diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /include | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Notes
Diffstat (limited to 'include')
1370 files changed, 31024 insertions, 13159 deletions
diff --git a/include/llvm-c/Analysis.h b/include/llvm-c/Analysis.h index 36dcb89e0e08..cb9e8ece3c53 100644 --- a/include/llvm-c/Analysis.h +++ b/include/llvm-c/Analysis.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Analysis.h - Analysis Library C Interface --------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h index d1fc302767ba..b307ee979f8a 100644 --- a/include/llvm-c/BitReader.h +++ b/include/llvm-c/BitReader.h @@ -1,9 +1,9 @@ /*===-- llvm-c/BitReader.h - BitReader Library C Interface ------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h index 797d03179ab3..187051555b9a 100644 --- a/include/llvm-c/BitWriter.h +++ b/include/llvm-c/BitWriter.h @@ -1,9 +1,9 @@ /*===-- llvm-c/BitWriter.h - BitWriter Library C Interface ------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Comdat.h b/include/llvm-c/Comdat.h index 499996d68a53..81fee3fc9a6b 100644 --- a/include/llvm-c/Comdat.h +++ b/include/llvm-c/Comdat.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Comdat.h - Module Comdat C Interface -------------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 06de058bdc58..cac2f297056d 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Core.h - Core Library C Interface ------------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -65,6 +65,7 @@ typedef enum { LLVMInvoke = 5, /* removed 6 due to API changes */ LLVMUnreachable = 7, + LLVMCallBr = 67, /* Standard Unary Operators */ LLVMFNeg = 66, @@ -2402,6 +2403,13 @@ LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn); 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() @@ -2612,52 +2620,138 @@ 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); /** - * @defgroup LLVMCCoreValueMetadata Metadata + * Obtain an iterator to the first GlobalIFunc in a Module. * - * @{ + * @see llvm::Module::ifunc_begin() */ +LLVMValueRef LLVMGetFirstGlobalIFunc(LLVMModuleRef M); /** - * Obtain a MDString value from a context. + * Obtain an iterator to the last GlobalIFunc in a Module. * - * The returned instance corresponds to the llvm::MDString class. + * @see llvm::Module::ifunc_end() + */ +LLVMValueRef LLVMGetLastGlobalIFunc(LLVMModuleRef M); + +/** + * Advance a GlobalIFunc iterator to the next GlobalIFunc. * - * The instance is specified by string data of a specified length. The - * string content is copied, so the backing memory can be freed after - * this function returns. + * Returns NULL if the iterator was already at the end and there are no more + * global aliases. */ -LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, - unsigned SLen); +LLVMValueRef LLVMGetNextGlobalIFunc(LLVMValueRef IFunc); /** - * Obtain a MDString value from the global context. + * 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 LLVMMDString(const char *Str, unsigned SLen); +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); /** - * Obtain a MDNode value from a context. + * Sets the resolver function associated with this indirect function. * - * The returned value corresponds to the llvm::MDNode class. + * @see llvm::GlobalIFunc::setResolver() */ -LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, - unsigned Count); +void LLVMSetGlobalIFuncResolver(LLVMValueRef IFunc, LLVMValueRef Resolver); /** - * Obtain a MDNode value from the global context. + * Remove a global indirect function from its parent module and delete it. + * + * @see llvm::GlobalIFunc::eraseFromParent() */ -LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); +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. @@ -2699,6 +2793,17 @@ unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V); */ 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); + /** * @} */ @@ -2812,6 +2917,24 @@ LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB); 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() @@ -3387,9 +3510,59 @@ void LLVMInsertIntoBuilderWithName(LLVMBuilderRef Builder, LLVMValueRef Instr, 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); -void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst); /* Terminators */ LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef); diff --git a/include/llvm-c/DataTypes.h b/include/llvm-c/DataTypes.h index 7081c83ffc2b..893b22b49ffc 100644 --- a/include/llvm-c/DataTypes.h +++ b/include/llvm-c/DataTypes.h @@ -1,9 +1,9 @@ /*===-- include/llvm-c/DataTypes.h - Define fixed size types ------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/DebugInfo.h b/include/llvm-c/DebugInfo.h index 87a72034b0e8..33c8110a863c 100644 --- a/include/llvm-c/DebugInfo.h +++ b/include/llvm-c/DebugInfo.h @@ -1,9 +1,8 @@ //===------------ DebugInfo.h - LLVM C API Debug Info API -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -51,13 +50,12 @@ typedef enum { LLVMDIFlagIntroducedVirtual = 1 << 18, LLVMDIFlagBitField = 1 << 19, LLVMDIFlagNoReturn = 1 << 20, - LLVMDIFlagMainSubprogram = 1 << 21, LLVMDIFlagTypePassByValue = 1 << 22, LLVMDIFlagTypePassByReference = 1 << 23, LLVMDIFlagEnumClass = 1 << 24, LLVMDIFlagFixedEnum = LLVMDIFlagEnumClass, // Deprecated. LLVMDIFlagThunk = 1 << 25, - LLVMDIFlagTrivial = 1 << 26, + LLVMDIFlagNonTrivial = 1 << 26, LLVMDIFlagBigEndian = 1 << 27, LLVMDIFlagLittleEndian = 1 << 28, LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), @@ -161,7 +159,8 @@ enum { LLVMDIObjCPropertyMetadataKind, LLVMDIImportedEntityMetadataKind, LLVMDIMacroMetadataKind, - LLVMDIMacroFileMetadataKind + LLVMDIMacroFileMetadataKind, + LLVMDICommonBlockMetadataKind }; typedef unsigned LLVMMetadataKind; @@ -453,6 +452,49 @@ unsigned LLVMDILocationGetColumn(LLVMMetadataRef Location); 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. @@ -480,6 +522,19 @@ LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder, LLVMDIFlags Flags); /** + * 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. @@ -1017,6 +1072,48 @@ LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( 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, @@ -1181,6 +1278,30 @@ LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func); 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() diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 5e80b95848cf..3adcc3c47a3f 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Disassembler.h - Disassembler Public C Interface ---*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/DisassemblerTypes.h b/include/llvm-c/DisassemblerTypes.h index e8754ac77055..389e5ee454a8 100644 --- a/include/llvm-c/DisassemblerTypes.h +++ b/include/llvm-c/DisassemblerTypes.h @@ -1,9 +1,9 @@ /*===-- llvm-c/DisassemblerTypedefs.h -----------------------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*/ diff --git a/include/llvm-c/Error.h b/include/llvm-c/Error.h index 71e84661222b..52943063c697 100644 --- a/include/llvm-c/Error.h +++ b/include/llvm-c/Error.h @@ -1,9 +1,9 @@ /*===------- llvm-c/Error.h - llvm::Error class C Interface -------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -60,7 +60,7 @@ void LLVMDisposeErrorMessage(char *ErrMsg); /** * Returns the type id for llvm StringError. */ -LLVMErrorTypeId LLVMGetStringErrorTypeId(); +LLVMErrorTypeId LLVMGetStringErrorTypeId(void); #ifdef __cplusplus } diff --git a/include/llvm-c/ErrorHandling.h b/include/llvm-c/ErrorHandling.h index 2059b3aeb158..4927349d8983 100644 --- a/include/llvm-c/ErrorHandling.h +++ b/include/llvm-c/ErrorHandling.h @@ -1,9 +1,9 @@ /*===-- llvm-c/ErrorHandling.h - Error Handling C Interface -------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index e8ebef9ab15d..ef714cd06384 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -1,9 +1,9 @@ /*===-- llvm-c/ExecutionEngine.h - ExecutionEngine Lib C Iface --*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/IRReader.h b/include/llvm-c/IRReader.h index 5b58d9921fb0..4d0b696e9583 100644 --- a/include/llvm-c/IRReader.h +++ b/include/llvm-c/IRReader.h @@ -1,9 +1,9 @@ /*===-- llvm-c/IRReader.h - IR Reader C Interface -----------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Initialization.h b/include/llvm-c/Initialization.h index e45eafb139f2..36c41dbd8d31 100644 --- a/include/llvm-c/Initialization.h +++ b/include/llvm-c/Initialization.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Initialization.h - Initialization C Interface ------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/LinkTimeOptimizer.h b/include/llvm-c/LinkTimeOptimizer.h index 8bcf59969ccb..19b4f5cf7491 100644 --- a/include/llvm-c/LinkTimeOptimizer.h +++ b/include/llvm-c/LinkTimeOptimizer.h @@ -1,9 +1,8 @@ //===-- llvm/LinkTimeOptimizer.h - LTO Public C Interface -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h index d02c37f94c86..908513041661 100644 --- a/include/llvm-c/Linker.h +++ b/include/llvm-c/Linker.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Linker.h - Module Linker C Interface -------------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index a2980e89fe3d..1e9b703a68ff 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/ /* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file is distributed under the University of Illinois Open Source */ -/* License. See LICENSE.TXT for details. */ +/* 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 */ /* */ /*===----------------------------------------------------------------------===*/ /* */ @@ -34,29 +34,140 @@ extern "C" { */ // Opaque type wrappers -typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef; typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef; typedef struct LLVMOpaqueSymbolIterator *LLVMSymbolIteratorRef; typedef struct LLVMOpaqueRelocationIterator *LLVMRelocationIteratorRef; -// ObjectFile creation -LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf); -void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile); +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); -// ObjectFile Section iterators -LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile); void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI); -LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, - LLVMSectionIteratorRef SI); + void LLVMMoveToNextSection(LLVMSectionIteratorRef SI); void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, LLVMSymbolIteratorRef Sym); // ObjectFile Symbol iterators -LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile); void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI); -LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile, - LLVMSymbolIteratorRef SI); void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI); // SectionRef accessors @@ -89,6 +200,28 @@ uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI); 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); /** * @} */ diff --git a/include/llvm-c/OptRemarks.h b/include/llvm-c/OptRemarks.h deleted file mode 100644 index 6a90394e711c..000000000000 --- a/include/llvm-c/OptRemarks.h +++ /dev/null @@ -1,204 +0,0 @@ -/*===-- llvm-c/OptRemarks.h - OptRemarks Public C Interface -------*- C -*-===*\ -|* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This header provides a public interface to an opt-remark library. *| -|* LLVM provides an implementation of this interface. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_C_OPT_REMARKS_H -#define LLVM_C_OPT_REMARKS_H - -#include "llvm-c/Core.h" -#include "llvm-c/Types.h" -#ifdef __cplusplus -#include <cstddef> -extern "C" { -#else -#include <stddef.h> -#endif /* !defined(__cplusplus) */ - -/** - * @defgroup LLVMCOPTREMARKS OptRemarks - * @ingroup LLVMC - * - * @{ - */ - -#define OPT_REMARKS_API_VERSION 0 - -/** - * String containing a buffer and a length. The buffer is not guaranteed to be - * zero-terminated. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -typedef struct { - const char *Str; - uint32_t Len; -} LLVMOptRemarkStringRef; - -/** - * DebugLoc containing File, Line and Column. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -typedef struct { - // File: - LLVMOptRemarkStringRef SourceFile; - // Line: - uint32_t SourceLineNumber; - // Column: - uint32_t SourceColumnNumber; -} LLVMOptRemarkDebugLoc; - -/** - * Element of the "Args" list. The key might give more information about what - * are the semantics of the value, e.g. "Callee" will tell you that the value - * is a symbol that names a function. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -typedef struct { - // e.g. "Callee" - LLVMOptRemarkStringRef Key; - // e.g. "malloc" - LLVMOptRemarkStringRef Value; - - // "DebugLoc": Optional - LLVMOptRemarkDebugLoc DebugLoc; -} LLVMOptRemarkArg; - -/** - * One remark entry. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -typedef struct { - // e.g. !Missed, !Passed - LLVMOptRemarkStringRef RemarkType; - // "Pass": Required - LLVMOptRemarkStringRef PassName; - // "Name": Required - LLVMOptRemarkStringRef RemarkName; - // "Function": Required - LLVMOptRemarkStringRef FunctionName; - - // "DebugLoc": Optional - LLVMOptRemarkDebugLoc DebugLoc; - // "Hotness": Optional - uint32_t Hotness; - // "Args": Optional. It is an array of `num_args` elements. - uint32_t NumArgs; - LLVMOptRemarkArg *Args; -} LLVMOptRemarkEntry; - -typedef struct LLVMOptRemarkOpaqueParser *LLVMOptRemarkParserRef; - -/** - * Creates a remark parser that can be used to read and parse the buffer located - * in \p Buf of size \p Size. - * - * \p Buf cannot be NULL. - * - * This function should be paired with LLVMOptRemarkParserDispose() to avoid - * leaking resources. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern LLVMOptRemarkParserRef LLVMOptRemarkParserCreate(const void *Buf, - uint64_t Size); - -/** - * Returns the next remark in the file. - * - * The value pointed to by the return value is invalidated by the next call to - * LLVMOptRemarkParserGetNext(). - * - * 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) LLVMOptRemarkParserHasError() will return `1`. - * - * 2) LLVMOptRemarkParserGetErrorMessage() will return a descriptive error - * message. - * - * An error may occur if: - * - * 1) An argument is invalid. - * - * 2) There is a YAML parsing error. This type of error aborts parsing - * immediately and returns `1`. It can occur on malformed YAML. - * - * 3) Remark parsing error. If this type of error occurs, the parser won't call - * the handler and will continue to the next one. It can occur on malformed - * remarks, like missing or extra fields in the file. - * - * Here is a quick example of the usage: - * - * ``` - * LLVMOptRemarkParserRef Parser = LLVMOptRemarkParserCreate(Buf, Size); - * LLVMOptRemarkEntry *Remark = NULL; - * while ((Remark == LLVMOptRemarkParserGetNext(Parser))) { - * // use Remark - * } - * bool HasError = LLVMOptRemarkParserHasError(Parser); - * LLVMOptRemarkParserDispose(Parser); - * ``` - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern LLVMOptRemarkEntry * -LLVMOptRemarkParserGetNext(LLVMOptRemarkParserRef Parser); - -/** - * Returns `1` if the parser encountered an error while parsing the buffer. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern LLVMBool LLVMOptRemarkParserHasError(LLVMOptRemarkParserRef 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 - * LLVMOptRemarkParserDispose() is called, the memory of the string will be - * released. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern const char * -LLVMOptRemarkParserGetErrorMessage(LLVMOptRemarkParserRef Parser); - -/** - * Releases all the resources used by \p Parser. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern void LLVMOptRemarkParserDispose(LLVMOptRemarkParserRef Parser); - -/** - * Returns the version of the opt-remarks dylib. - * - * \since OPT_REMARKS_API_VERSION=0 - */ -extern uint32_t LLVMOptRemarkVersion(void); - -/** - * @} // endgoup LLVMCOPTREMARKS - */ - -#ifdef __cplusplus -} -#endif /* !defined(__cplusplus) */ - -#endif /* LLVM_C_OPT_REMARKS_H */ diff --git a/include/llvm-c/OrcBindings.h b/include/llvm-c/OrcBindings.h index 570db87fee94..9e92371b5a3a 100644 --- a/include/llvm-c/OrcBindings.h +++ b/include/llvm-c/OrcBindings.h @@ -1,9 +1,9 @@ /*===----------- llvm-c/OrcBindings.h - Orc Lib C Iface ---------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Remarks.h b/include/llvm-c/Remarks.h new file mode 100644 index 000000000000..88eb5120c57c --- /dev/null +++ b/include/llvm-c/Remarks.h @@ -0,0 +1,329 @@ +/*===-- 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/Types.h" +#ifdef __cplusplus +#include <cstddef> +extern "C" { +#else +#include <stddef.h> +#endif /* !defined(__cplusplus) */ + +/** + * @defgroup LLVMCREMARKS Remarks + * @ingroup LLVMC + * + * @{ + */ + +#define REMARKS_API_VERSION 0 + +/** + * 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); + +/** + * 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 + */ + +#ifdef __cplusplus +} +#endif /* !defined(__cplusplus) */ + +#endif /* LLVM_C_REMARKS_H */ diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h index 37d5d72ff5dc..097f784246c5 100644 --- a/include/llvm-c/Support.h +++ b/include/llvm-c/Support.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Support.h - Support C Interface --------------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 03004ba5eec0..4ef641eaf232 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Target.h - Target Lib C Iface --------------------*- C++ -*-===*/ /* */ -/* The LLVM Compiler Infrastructure */ -/* */ -/* This file is distributed under the University of Illinois Open Source */ -/* License. See LICENSE.TXT for details. */ +/* 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 */ /* */ /*===----------------------------------------------------------------------===*/ /* */ @@ -22,10 +22,6 @@ #include "llvm-c/Types.h" #include "llvm/Config/llvm-config.h" -#if defined(_MSC_VER) && !defined(inline) -#define inline __inline -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index c06e9edc9aaf..28d7c096871e 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -1,9 +1,9 @@ /*===-- llvm-c/TargetMachine.h - Target Machine Library C Interface - C++ -*-=*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/AggressiveInstCombine.h b/include/llvm-c/Transforms/AggressiveInstCombine.h index 8756a22e917a..c0b0141c3da1 100644 --- a/include/llvm-c/Transforms/AggressiveInstCombine.h +++ b/include/llvm-c/Transforms/AggressiveInstCombine.h @@ -1,9 +1,9 @@ /*===-- AggressiveInstCombine.h ---------------------------------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/Coroutines.h b/include/llvm-c/Transforms/Coroutines.h index 827e30fb2d7c..227e7cf0a360 100644 --- a/include/llvm-c/Transforms/Coroutines.h +++ b/include/llvm-c/Transforms/Coroutines.h @@ -1,9 +1,9 @@ /*===-- Coroutines.h - Coroutines Library C Interface -----------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/IPO.h b/include/llvm-c/Transforms/IPO.h index 7705b1864dc3..7a82ed464141 100644 --- a/include/llvm-c/Transforms/IPO.h +++ b/include/llvm-c/Transforms/IPO.h @@ -1,9 +1,9 @@ /*===-- IPO.h - Interprocedural Transformations C Interface -----*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/InstCombine.h b/include/llvm-c/Transforms/InstCombine.h index e1c1572d53dc..166f278d9a69 100644 --- a/include/llvm-c/Transforms/InstCombine.h +++ b/include/llvm-c/Transforms/InstCombine.h @@ -1,9 +1,9 @@ /*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/PassManagerBuilder.h b/include/llvm-c/Transforms/PassManagerBuilder.h index 69786b341ab4..d164c00d49c5 100644 --- a/include/llvm-c/Transforms/PassManagerBuilder.h +++ b/include/llvm-c/Transforms/PassManagerBuilder.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Transform/PassManagerBuilder.h - PMB C Interface ---*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 3c3bb4eb9b82..031cf98b2df2 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -1,9 +1,9 @@ /*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Transforms/Utils.h b/include/llvm-c/Transforms/Utils.h index f171f7fbbe3e..63594abfa460 100644 --- a/include/llvm-c/Transforms/Utils.h +++ b/include/llvm-c/Transforms/Utils.h @@ -1,9 +1,9 @@ /*===-- Utils.h - Transformation Utils Library C Interface ------*- C++ -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -38,6 +38,9 @@ void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); +/** See llvm::createAddDiscriminatorsPass function. */ +void LLVMAddAddDiscriminatorsPass(LLVMPassManagerRef PM); + /** * @} */ diff --git a/include/llvm-c/Transforms/Vectorize.h b/include/llvm-c/Transforms/Vectorize.h index e3f9961acfb1..e383481fe4f4 100644 --- a/include/llvm-c/Transforms/Vectorize.h +++ b/include/llvm-c/Transforms/Vectorize.h @@ -1,10 +1,10 @@ /*===---------------------------Vectorize.h --------------------- -*- C -*-===*\ |*===----------- Vectorization Transformation Library C Interface ---------===*| |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| diff --git a/include/llvm-c/Types.h b/include/llvm-c/Types.h index ce1acf3e0421..612c7d3eff32 100644 --- a/include/llvm-c/Types.h +++ b/include/llvm-c/Types.h @@ -1,9 +1,9 @@ /*===-- llvm-c/Support.h - C Interface Types declarations ---------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -164,6 +164,11 @@ typedef struct LLVMOpaqueModuleFlagEntry LLVMModuleFlagEntry; typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef; /** + * @see llvm::object::Binary + */ +typedef struct LLVMOpaqueBinary *LLVMBinaryRef; + +/** * @} */ diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 090cd34af4e9..2467722b1954 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -1,9 +1,9 @@ /*===-- llvm-c/lto.h - LTO Public C Interface ---------------------*- C -*-===*\ |* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| +|* 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 *| |* *| |*===----------------------------------------------------------------------===*| |* *| @@ -44,7 +44,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 23 +#define LTO_API_VERSION 24 /** * \since prior to LTO_API_VERSION=3 @@ -846,7 +846,47 @@ thinlto_codegen_set_cache_size_megabytes(thinlto_code_gen_t cg, extern void thinlto_codegen_set_cache_size_files(thinlto_code_gen_t cg, unsigned max_size_files); - +/** 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); /** * @} // endgroup LLVMCTLTO_CACHING diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index c6fa5ad674f6..a9648d35cf5d 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -1,9 +1,8 @@ //===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -148,6 +147,17 @@ struct APFloatBase { /// \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; diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 6e106ff8bf5d..2381b75e08b1 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -2213,6 +2212,15 @@ Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C, // 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); -} // End of llvm namespace + +/// 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/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 7ee2c4c62fce..0f991826c457 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,6 +42,24 @@ public: /// \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)); diff --git a/include/llvm/ADT/AllocatorList.h b/include/llvm/ADT/AllocatorList.h index 178c6742a87b..405a2e4264df 100644 --- a/include/llvm/ADT/AllocatorList.h +++ b/include/llvm/ADT/AllocatorList.h @@ -1,9 +1,8 @@ //===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/Any.h b/include/llvm/ADT/Any.h index 7faa4c963d3d..5dcd6e73c54f 100644 --- a/include/llvm/ADT/Any.h +++ b/include/llvm/ADT/Any.h @@ -1,9 +1,8 @@ //===- Any.h - Generic type erased holder of any type -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 9cb25b09c6cb..773c88f7c9f9 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -1,9 +1,8 @@ //===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -431,7 +430,7 @@ namespace llvm { std::copy(Data.begin(), Data.end(), this->begin()); } - OwningArrayRef(OwningArrayRef &&Other) { *this = Other; } + OwningArrayRef(OwningArrayRef &&Other) { *this = std::move(Other); } OwningArrayRef &operator=(OwningArrayRef &&Other) { delete[] this->data(); @@ -526,12 +525,6 @@ namespace llvm { /// @} - // ArrayRefs can be treated like a POD type. - template <typename T> struct isPodLike; - template <typename T> struct isPodLike<ArrayRef<T>> { - static const bool value = true; - }; - template <typename T> hash_code hash_value(ArrayRef<T> S) { return hash_combine_range(S.begin(), S.end()); } diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 9ab1da7c6913..fabf5d9cd348 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/BitmaskEnum.h b/include/llvm/ADT/BitmaskEnum.h index 18c6ba5a3eb8..1a18bc721b21 100644 --- a/include/llvm/ADT/BitmaskEnum.h +++ b/include/llvm/ADT/BitmaskEnum.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/BitmaskEnum.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/BreadthFirstIterator.h b/include/llvm/ADT/BreadthFirstIterator.h index 6bc63c283b09..e97d76680db8 100644 --- a/include/llvm/ADT/BreadthFirstIterator.h +++ b/include/llvm/ADT/BreadthFirstIterator.h @@ -1,9 +1,8 @@ //===- llvm/ADT/BreadthFirstIterator.h - Breadth First iterator -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -125,7 +124,7 @@ public: const NodeRef &operator*() const { return VisitQueue.front()->first; } - // This is a nonstandard operator-> that dereferenfces the pointer an extra + // 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; } diff --git a/include/llvm/ADT/CachedHashString.h b/include/llvm/ADT/CachedHashString.h index d8f0e7afdd49..80144fb87e0e 100644 --- a/include/llvm/ADT/CachedHashString.h +++ b/include/llvm/ADT/CachedHashString.h @@ -1,9 +1,8 @@ //===- llvm/ADT/CachedHashString.h - Prehashed string/StringRef -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/DAGDeltaAlgorithm.h b/include/llvm/ADT/DAGDeltaAlgorithm.h index 41fdd43efb8a..d4cdc3c86048 100644 --- a/include/llvm/ADT/DAGDeltaAlgorithm.h +++ b/include/llvm/ADT/DAGDeltaAlgorithm.h @@ -1,9 +1,8 @@ //===- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h index 6becb2a60104..114b95499530 100644 --- a/include/llvm/ADT/DeltaAlgorithm.h +++ b/include/llvm/ADT/DeltaAlgorithm.h @@ -1,9 +1,8 @@ //===- DeltaAlgorithm.h - A Set Minimization Algorithm ---------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 1f50502fff92..a05cf8130d3c 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -1,9 +1,8 @@ //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -64,7 +63,7 @@ struct DenseMapPair : public std::pair<KeyT, ValueT> { template <typename AltPairT> DenseMapPair(AltPairT &&AltPair, typename std::enable_if<std::is_convertible< - AltPairT, std::pair<KeyT, ValueT>>::value>::type * = 0) + AltPairT, std::pair<KeyT, ValueT>>::value>::type * = nullptr) : std::pair<KeyT, ValueT>(std::forward<AltPairT>(AltPair)) {} KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } @@ -146,7 +145,8 @@ public: } const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); - if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) { + 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; @@ -422,7 +422,8 @@ protected: setNumEntries(other.getNumEntries()); setNumTombstones(other.getNumTombstones()); - if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) + if (is_trivially_copyable<KeyT>::value && + is_trivially_copyable<ValueT>::value) memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h index 5d12b424fb37..5ef6f3ad1b04 100644 --- a/include/llvm/ADT/DenseMapInfo.h +++ b/include/llvm/ADT/DenseMapInfo.h @@ -1,9 +1,8 @@ //===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/ScalableSize.h" #include <cassert> #include <cstddef> #include <cstdint> @@ -269,6 +269,21 @@ template <> struct DenseMapInfo<hash_code> { 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/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index e85a38587e41..9afb715ae1db 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -131,7 +130,7 @@ public: class ConstIterator { typename MapTy::const_iterator I; - friend class DenseSet; + friend class DenseSetImpl; friend class Iterator; public: diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 1f3766d3c9de..11967f5eefcc 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -1,9 +1,8 @@ //===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/EpochTracker.h b/include/llvm/ADT/EpochTracker.h index 49ef192364e8..a782b4756898 100644 --- a/include/llvm/ADT/EpochTracker.h +++ b/include/llvm/ADT/EpochTracker.h @@ -1,9 +1,8 @@ //===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index e3f48433c69f..2cb7108c0794 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -1,9 +1,8 @@ //===- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index e363e69d032a..d5837e51bcfc 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/FoldingSet.h - Uniquing Hash Set ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/FunctionExtras.h b/include/llvm/ADT/FunctionExtras.h index 2b75dc6ac219..121aa527a5da 100644 --- a/include/llvm/ADT/FunctionExtras.h +++ b/include/llvm/ADT/FunctionExtras.h @@ -1,9 +1,8 @@ //===- FunctionExtras.h - Function type erasure utilities -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h index d39b50fdc488..3ce91225d80d 100644 --- a/include/llvm/ADT/GraphTraits.h +++ b/include/llvm/ADT/GraphTraits.h @@ -1,9 +1,8 @@ //===- llvm/ADT/GraphTraits.h - Graph traits template -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index 9175c545b7c9..008188bfa210 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -192,7 +191,7 @@ inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) { 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 = len + (static_cast<uint32_t>(c) << 2); + uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2); return shift_mix(y * k2 ^ z * k3 ^ seed) * k2; } diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index 0541dc2566ed..c9ee494734e7 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -1,9 +1,8 @@ //==--- ImmutableList.h - Immutable (functional) list interface --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -242,10 +241,6 @@ template<typename T> struct DenseMapInfo<ImmutableList<T>> { } }; -template <typename T> struct isPodLike; -template <typename T> -struct isPodLike<ImmutableList<T>> { static const bool value = true; }; - } // end namespace llvm #endif // LLVM_ADT_IMMUTABLELIST_H diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index cbc27ff17ccf..86fd7fefaec3 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -1,9 +1,8 @@ //===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index b1d5f4ac42e4..587105431533 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -1,9 +1,8 @@ //===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h index 2ee80d2cde63..b44f16b91d76 100644 --- a/include/llvm/ADT/IndexedMap.h +++ b/include/llvm/ADT/IndexedMap.h @@ -1,9 +1,8 @@ //===- llvm/ADT/IndexedMap.h - An index map implementation ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/IntEqClasses.h b/include/llvm/ADT/IntEqClasses.h index 0baee2f11a79..08f46a3079ef 100644 --- a/include/llvm/ADT/IntEqClasses.h +++ b/include/llvm/ADT/IntEqClasses.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 2af61049e5af..12828c4cfdab 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -1,9 +1,8 @@ //===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index 430ef86afbd9..6d97fe15db8b 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -1,9 +1,8 @@ //==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 47b4987f210a..1de1124f4ea2 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/None.h b/include/llvm/ADT/None.h index 4b6bc1e005b5..004ca0ac50ac 100644 --- a/include/llvm/ADT/None.h +++ b/include/llvm/ADT/None.h @@ -1,9 +1,8 @@ //===-- None.h - Simple null value for implicit construction ------*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 76937d632ae1..b45a74002e10 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -1,9 +1,8 @@ //===- Optional.h - Simple variant for passing optional values --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,94 +16,197 @@ #define LLVM_ADT_OPTIONAL_H #include "llvm/ADT/None.h" -#include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" -#include <algorithm> #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 = isPodLike<T>::value> struct OptionalStorage { - AlignedCharArrayUnion<T> storage; - bool hasVal = false; +template <typename T, bool = is_trivially_copyable<T>::value> +class OptionalStorage { + union { + char empty; + T value; + }; + bool hasVal; - OptionalStorage() = default; +public: + ~OptionalStorage() { reset(); } - OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } - OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) { - if (hasVal) - new (storage.buffer) T(*O.getPointer()); + OptionalStorage() noexcept : empty(), hasVal(false) {} + + OptionalStorage(OptionalStorage const &other) : OptionalStorage() { + if (other.hasValue()) { + emplace(other.value); + } } - OptionalStorage(T &&y) : hasVal(true) { - new (storage.buffer) T(std::forward<T>(y)); + OptionalStorage(OptionalStorage &&other) : OptionalStorage() { + if (other.hasValue()) { + emplace(std::move(other.value)); + } } - OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) { - if (O.hasVal) { - new (storage.buffer) T(std::move(*O.getPointer())); + + 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; } } - OptionalStorage &operator=(T &&y) { - if (hasVal) - *getPointer() = std::move(y); - else { - new (storage.buffer) T(std::move(y)); + 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=(OptionalStorage &&O) { - if (!O.hasVal) - reset(); - else { - *this = std::move(*O.getPointer()); + OptionalStorage &operator=(T &&y) { + if (hasValue()) { + value = std::move(y); + } else { + ::new ((void *)std::addressof(value)) T(std::move(y)); + hasVal = true; } return *this; } - // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) - // could be made more efficient by passing by value, possibly unifying them - // with the rvalue versions above - but this could place a different set of - // requirements (notably: the existence of a default ctor) when implemented - // in that way. Careful SFINAE to avoid such pitfalls would be required. - OptionalStorage &operator=(const T &y) { - if (hasVal) - *getPointer() = y; - else { - new (storage.buffer) T(y); - hasVal = true; + 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=(const OptionalStorage &O) { - if (!O.hasVal) + + 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(); - else - *this = *O.getPointer(); + } return *this; } +}; - ~OptionalStorage() { reset(); } +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() { + void reset() noexcept { if (hasVal) { - (*getPointer()).~T(); + value.~T(); hasVal = false; } } - T *getPointer() { + bool hasValue() const noexcept { return hasVal; } + + T &getValue() LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); - return reinterpret_cast<T *>(storage.buffer); + return value; } - const T *getPointer() const { + T const &getValue() const LLVM_LVALUE_FUNCTION noexcept { assert(hasVal); - return reinterpret_cast<const T *>(storage.buffer); + 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; } }; @@ -119,10 +221,10 @@ public: constexpr Optional() {} constexpr Optional(NoneType) {} - Optional(const T &y) : Storage(y) {} + Optional(const T &y) : Storage(optional_detail::in_place_t{}, y) {} Optional(const Optional &O) = default; - Optional(T &&y) : Storage(std::forward<T>(y)) {} + Optional(T &&y) : Storage(optional_detail::in_place_t{}, std::move(y)) {} Optional(Optional &&O) = default; Optional &operator=(T &&y) { @@ -133,9 +235,7 @@ public: /// Create a new object by constructing it in place with the given arguments. template <typename... ArgTypes> void emplace(ArgTypes &&... Args) { - reset(); - Storage.hasVal = true; - new (getPointer()) T(std::forward<ArgTypes>(Args)...); + Storage.emplace(std::forward<ArgTypes>(Args)...); } static inline Optional create(const T *y) { @@ -150,23 +250,17 @@ public: void reset() { Storage.reset(); } - const T *getPointer() const { - assert(Storage.hasVal); - return reinterpret_cast<const T *>(Storage.storage.buffer); - } - T *getPointer() { - assert(Storage.hasVal); - return reinterpret_cast<T *>(Storage.storage.buffer); - } - const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); } - T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); } + 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 Storage.hasVal; } - bool hasValue() const { return Storage.hasVal; } + 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 *getPointer(); } - T &operator*() LLVM_LVALUE_FUNCTION { 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 { @@ -174,8 +268,8 @@ public: } #if LLVM_HAS_RVALUE_REFERENCE_THIS - T &&getValue() && { return std::move(*getPointer()); } - T &&operator*() && { return std::move(*getPointer()); } + T &&getValue() && { return std::move(Storage.getValue()); } + T &&operator*() && { return std::move(Storage.getValue()); } template <typename U> T getValueOr(U &&value) && { @@ -184,11 +278,6 @@ public: #endif }; -template <typename T> struct isPodLike<Optional<T>> { - // An Optional<T> is pod-like if T is. - static const bool value = isPodLike<T>::value; -}; - template <typename T, typename U> bool operator==(const Optional<T> &X, const Optional<U> &Y) { if (X && Y) @@ -323,6 +412,18 @@ 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/include/llvm/ADT/PackedVector.h b/include/llvm/ADT/PackedVector.h index 3d53c49536d0..ae7f8cc85743 100644 --- a/include/llvm/ADT/PackedVector.h +++ b/include/llvm/ADT/PackedVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PackedVector.h - Packed values vector -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/PointerEmbeddedInt.h b/include/llvm/ADT/PointerEmbeddedInt.h index ab4e1048a5bc..3eb6edb03430 100644 --- a/include/llvm/ADT/PointerEmbeddedInt.h +++ b/include/llvm/ADT/PointerEmbeddedInt.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PointerEmbeddedInt.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 6d1b53a90ad2..24a2bb67a36e 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_ADT_POINTERINTPAIR_H #include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <cstdint> #include <limits> @@ -126,6 +126,19 @@ public: } }; +// 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 < @@ -176,12 +189,6 @@ struct PointerIntPairInfo { } }; -template <typename T> struct isPodLike; -template <typename PointerTy, unsigned IntBits, typename IntType> -struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType>> { - static const bool value = true; -}; - // Provide specialization of DenseMapInfo for PointerIntPair. template <typename PointerTy, unsigned IntBits, typename IntType> struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType>> { diff --git a/include/llvm/ADT/PointerSumType.h b/include/llvm/ADT/PointerSumType.h index a19e45a46218..d467f83f58ac 100644 --- a/include/llvm/ADT/PointerSumType.h +++ b/include/llvm/ADT/PointerSumType.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PointerSumType.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 315e58336cba..2bcdf546c6e4 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -54,22 +53,98 @@ struct PointerUnionTypeSelectorReturn< typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return; }; -/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion -/// for the two template arguments. -template <typename PT1, typename PT2> class PointerUnionUIntTraits { -public: - static inline void *getAsVoidPointer(void *P) { return P; } - static inline void *getFromVoidPointer(void *P) { return P; } +namespace pointer_union_detail { + constexpr int constexprMin(int a, int b) { return a < b ? a : b; } + /// 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; + } + + // FIXME: In C++14, replace this with + // std::min({PointerLikeTypeTraits<Ts>::NumLowBitsAvailable...}) + template <typename T> constexpr int lowBitsAvailable() { + return PointerLikeTypeTraits<T>::NumLowBitsAvailable; + } + template <typename T1, typename T2, typename... Ts> + constexpr int lowBitsAvailable() { + return constexprMin(lowBitsAvailable<T1>(), lowBitsAvailable<T2, Ts...>()); + } - enum { - PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable), - PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable), - NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + /// 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 assigment 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; -/// A discriminated union of two pointer types, with the discriminator in the -/// low bit of the pointer. + 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. @@ -84,49 +159,44 @@ public: /// P = (float*)0; /// Y = P.get<float*>(); // ok. /// X = P.get<int*>(); // runtime assertion failure. -template <typename PT1, typename PT2> class PointerUnion { -public: - using ValTy = - PointerIntPair<void *, 1, bool, PointerUnionUIntTraits<PT1, PT2>>; - -private: - ValTy Val; - - struct IsPT1 { - static const int Num = 0; - }; - struct IsPT2 { - static const int Num = 1; - }; - template <typename T> struct UNION_DOESNT_CONTAIN_TYPE {}; +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 in some ways, 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(PT1 V) - : Val(const_cast<void *>( - PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {} - PointerUnion(PT2 V) - : Val(const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), - 1) {} + + 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 { // Convert from the void* to one of the pointer types, to make sure that // we recursively strip off low bits if we have a nested PointerUnion. - return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); + return !PointerLikeTypeTraits<First>::getFromVoidPointer( + 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 { - using Ty = typename ::llvm::PointerUnionTypeSelector< - PT1, T, IsPT1, - ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2, - UNION_DOESNT_CONTAIN_TYPE<T>>>::Return; - int TyNo = Ty::Num; - return static_cast<int>(Val.getInt()) == TyNo; + 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. @@ -134,7 +204,7 @@ public: /// If the specified pointer type is incorrect, assert. template <typename T> T get() const { assert(is<T>() && "Invalid accessor called"); - return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); + return PointerLikeTypeTraits<T>::getFromVoidPointer(this->Val.getPointer()); } /// Returns the current pointer if it is of the specified pointer type, @@ -147,342 +217,100 @@ public: /// If the union is set to the first pointer type get an address pointing to /// it. - PT1 const *getAddrOfPtr1() const { + 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. - PT1 *getAddrOfPtr1() { - assert(is<PT1>() && "Val is not the first pointer"); + First *getAddrOfPtr1() { + assert(is<First>() && "Val is not the first pointer"); assert( - get<PT1>() == Val.getPointer() && + get<First>() == this->Val.getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"); - return const_cast<PT1 *>( - reinterpret_cast<const PT1 *>(Val.getAddrOfPointer())); + 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) { - Val.initWithPointer(nullptr); + this->Val.initWithPointer(nullptr); return *this; } - /// Assignment operators - Allow assigning into this union from either - /// pointer type, setting the discriminator to remember what it came from. - const PointerUnion &operator=(const PT1 &RHS) { - Val.initWithPointer( - const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); - return *this; - } - const PointerUnion &operator=(const PT2 &RHS) { - Val.setPointerAndInt( - const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)), - 1); - return *this; - } + /// Assignment from elements of the union. + using Base::operator=; - void *getOpaqueValue() const { return Val.getOpaqueValue(); } + void *getOpaqueValue() const { return this->Val.getOpaqueValue(); } static inline PointerUnion getFromOpaqueValue(void *VP) { PointerUnion V; - V.Val = ValTy::getFromOpaqueValue(VP); + V.Val = decltype(V.Val)::getFromOpaqueValue(VP); return V; } }; -template <typename PT1, typename PT2> -bool operator==(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { +template <typename ...PTs> +bool operator==(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { return lhs.getOpaqueValue() == rhs.getOpaqueValue(); } -template <typename PT1, typename PT2> -bool operator!=(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { +template <typename ...PTs> +bool operator!=(PointerUnion<PTs...> lhs, PointerUnion<PTs...> rhs) { return lhs.getOpaqueValue() != rhs.getOpaqueValue(); } -template <typename PT1, typename PT2> -bool operator<(PointerUnion<PT1, PT2> lhs, PointerUnion<PT1, PT2> rhs) { +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 PT1, typename PT2> -struct PointerLikeTypeTraits<PointerUnion<PT1, PT2>> { - static inline void *getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { +template <typename ...PTs> +struct PointerLikeTypeTraits<PointerUnion<PTs...>> { + static inline void *getAsVoidPointer(const PointerUnion<PTs...> &P) { return P.getOpaqueValue(); } - static inline PointerUnion<PT1, PT2> getFromVoidPointer(void *P) { - return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); + static inline PointerUnion<PTs...> getFromVoidPointer(void *P) { + return PointerUnion<PTs...>::getFromOpaqueValue(P); } - // The number of bits available are the min of the two pointer types. - enum { - NumLowBitsAvailable = PointerLikeTypeTraits< - typename PointerUnion<PT1, PT2>::ValTy>::NumLowBitsAvailable - }; + // 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; }; /// A pointer union of three pointer types. See documentation for PointerUnion /// for usage. -template <typename PT1, typename PT2, typename PT3> class PointerUnion3 { -public: - using InnerUnion = PointerUnion<PT1, PT2>; - using ValTy = PointerUnion<InnerUnion, PT3>; - -private: - ValTy Val; - - struct IsInnerUnion { - ValTy Val; - - IsInnerUnion(ValTy val) : Val(val) {} - - template <typename T> int is() const { - return Val.template is<InnerUnion>() && - Val.template get<InnerUnion>().template is<T>(); - } - - template <typename T> T get() const { - return Val.template get<InnerUnion>().template get<T>(); - } - }; - - struct IsPT3 { - ValTy Val; - - IsPT3(ValTy val) : Val(val) {} - - template <typename T> int is() const { return Val.template is<T>(); } - template <typename T> T get() const { return Val.template get<T>(); } - }; - -public: - PointerUnion3() = default; - PointerUnion3(PT1 V) { Val = InnerUnion(V); } - PointerUnion3(PT2 V) { Val = InnerUnion(V); } - PointerUnion3(PT3 V) { Val = V; } - - /// Test if the pointer held in the union is null, regardless of - /// which type it is. - bool isNull() const { return Val.isNull(); } - explicit operator bool() const { return !isNull(); } - - /// Test if the Union currently holds the type matching T. - template <typename T> int is() const { - // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. - using Ty = typename ::llvm::PointerUnionTypeSelector< - PT1, T, IsInnerUnion, - ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return; - return Ty(Val).template is<T>(); - } - - /// 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"); - // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. - using Ty = typename ::llvm::PointerUnionTypeSelector< - PT1, T, IsInnerUnion, - ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3>>::Return; - return Ty(Val).template get<T>(); - } - - /// 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(); - } - - /// Assignment from nullptr which just clears the union. - const PointerUnion3 &operator=(std::nullptr_t) { - Val = nullptr; - return *this; - } - - /// Assignment operators - Allow assigning into this union from either - /// pointer type, setting the discriminator to remember what it came from. - const PointerUnion3 &operator=(const PT1 &RHS) { - Val = InnerUnion(RHS); - return *this; - } - const PointerUnion3 &operator=(const PT2 &RHS) { - Val = InnerUnion(RHS); - return *this; - } - const PointerUnion3 &operator=(const PT3 &RHS) { - Val = RHS; - return *this; - } - - void *getOpaqueValue() const { return Val.getOpaqueValue(); } - static inline PointerUnion3 getFromOpaqueValue(void *VP) { - PointerUnion3 V; - V.Val = ValTy::getFromOpaqueValue(VP); - return V; - } -}; - -// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has -// # low bits available = min(PT1bits,PT2bits,PT2bits)-2. template <typename PT1, typename PT2, typename PT3> -struct PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> { - static inline void *getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { - return P.getOpaqueValue(); - } - - static inline PointerUnion3<PT1, PT2, PT3> getFromVoidPointer(void *P) { - return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); - } - - // The number of bits available are the min of the two pointer types. - enum { - NumLowBitsAvailable = PointerLikeTypeTraits< - typename PointerUnion3<PT1, PT2, PT3>::ValTy>::NumLowBitsAvailable - }; -}; - -template <typename PT1, typename PT2, typename PT3> -bool operator<(PointerUnion3<PT1, PT2, PT3> lhs, - PointerUnion3<PT1, PT2, PT3> rhs) { - return lhs.getOpaqueValue() < rhs.getOpaqueValue(); -} +using PointerUnion3 = PointerUnion<PT1, PT2, PT3>; /// A pointer union of four pointer types. See documentation for PointerUnion /// for usage. template <typename PT1, typename PT2, typename PT3, typename PT4> -class PointerUnion4 { -public: - using InnerUnion1 = PointerUnion<PT1, PT2>; - using InnerUnion2 = PointerUnion<PT3, PT4>; - using ValTy = PointerUnion<InnerUnion1, InnerUnion2>; - -private: - ValTy Val; - -public: - PointerUnion4() = default; - PointerUnion4(PT1 V) { Val = InnerUnion1(V); } - PointerUnion4(PT2 V) { Val = InnerUnion1(V); } - PointerUnion4(PT3 V) { Val = InnerUnion2(V); } - PointerUnion4(PT4 V) { Val = InnerUnion2(V); } - - /// Test if the pointer held in the union is null, regardless of - /// which type it is. - bool isNull() const { return Val.isNull(); } - explicit operator bool() const { return !isNull(); } - - /// Test if the Union currently holds the type matching T. - template <typename T> int is() const { - // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. - using Ty = typename ::llvm::PointerUnionTypeSelector< - PT1, T, InnerUnion1, - ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, - InnerUnion2>>::Return; - return Val.template is<Ty>() && Val.template get<Ty>().template is<T>(); - } - - /// 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"); - // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. - using Ty = typename ::llvm::PointerUnionTypeSelector< - PT1, T, InnerUnion1, - ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, - InnerUnion2>>::Return; - return Val.template get<Ty>().template get<T>(); - } - - /// 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(); - } - - /// Assignment from nullptr which just clears the union. - const PointerUnion4 &operator=(std::nullptr_t) { - Val = nullptr; - return *this; - } - - /// Assignment operators - Allow assigning into this union from either - /// pointer type, setting the discriminator to remember what it came from. - const PointerUnion4 &operator=(const PT1 &RHS) { - Val = InnerUnion1(RHS); - return *this; - } - const PointerUnion4 &operator=(const PT2 &RHS) { - Val = InnerUnion1(RHS); - return *this; - } - const PointerUnion4 &operator=(const PT3 &RHS) { - Val = InnerUnion2(RHS); - return *this; - } - const PointerUnion4 &operator=(const PT4 &RHS) { - Val = InnerUnion2(RHS); - return *this; - } - - void *getOpaqueValue() const { return Val.getOpaqueValue(); } - static inline PointerUnion4 getFromOpaqueValue(void *VP) { - PointerUnion4 V; - V.Val = ValTy::getFromOpaqueValue(VP); - return V; - } -}; - -// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has -// # low bits available = min(PT1bits,PT2bits,PT2bits)-2. -template <typename PT1, typename PT2, typename PT3, typename PT4> -struct PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4>> { - static inline void * - getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { - return P.getOpaqueValue(); - } - - static inline PointerUnion4<PT1, PT2, PT3, PT4> getFromVoidPointer(void *P) { - return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); - } - - // The number of bits available are the min of the two pointer types. - enum { - NumLowBitsAvailable = PointerLikeTypeTraits< - typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>::NumLowBitsAvailable - }; -}; +using PointerUnion4 = PointerUnion<PT1, PT2, PT3, PT4>; // Teach DenseMap how to use PointerUnions as keys. -template <typename T, typename U> struct DenseMapInfo<PointerUnion<T, U>> { - using Pair = PointerUnion<T, U>; - using FirstInfo = DenseMapInfo<T>; - using SecondInfo = DenseMapInfo<U>; +template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> { + using Union = PointerUnion<PTs...>; + using FirstInfo = + DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>; - static inline Pair getEmptyKey() { return Pair(FirstInfo::getEmptyKey()); } + static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); } - static inline Pair getTombstoneKey() { - return Pair(FirstInfo::getTombstoneKey()); + static inline Union getTombstoneKey() { + return Union(FirstInfo::getTombstoneKey()); } - static unsigned getHashValue(const Pair &PairVal) { - intptr_t key = (intptr_t)PairVal.getOpaqueValue(); + static unsigned getHashValue(const Union &UnionVal) { + intptr_t key = (intptr_t)UnionVal.getOpaqueValue(); return DenseMapInfo<intptr_t>::getHashValue(key); } - static bool isEqual(const Pair &LHS, const Pair &RHS) { - return LHS.template is<T>() == RHS.template is<T>() && - (LHS.template is<T>() ? FirstInfo::isEqual(LHS.template get<T>(), - RHS.template get<T>()) - : SecondInfo::isEqual(LHS.template get<U>(), - RHS.template get<U>())); + static bool isEqual(const Union &LHS, const Union &RHS) { + return LHS == RHS; } }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index d77b12228cb1..2fe7447a8e77 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/PriorityQueue.h b/include/llvm/ADT/PriorityQueue.h index 8ba871e25304..cf79ee10ba7f 100644 --- a/include/llvm/ADT/PriorityQueue.h +++ b/include/llvm/ADT/PriorityQueue.h @@ -1,9 +1,8 @@ //===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/PriorityWorklist.h b/include/llvm/ADT/PriorityWorklist.h index aa531f3337d9..96d22c87557e 100644 --- a/include/llvm/ADT/PriorityWorklist.h +++ b/include/llvm/ADT/PriorityWorklist.h @@ -1,9 +1,8 @@ //===- PriorityWorklist.h - Worklist with insertion priority ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index ab1dc4613be0..eb1a5d0938cf 100644 --- a/include/llvm/ADT/SCCIterator.h +++ b/include/llvm/ADT/SCCIterator.h @@ -1,9 +1,8 @@ //===- ADT/SCCIterator.h - Strongly Connected Comp. Iter. -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index f66ca7c08a73..81dce0168c79 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -1,9 +1,8 @@ //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -241,6 +240,13 @@ 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]; @@ -1278,29 +1284,52 @@ auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { /// Provide wrappers to std::lower_bound which take ranges instead of having to /// pass begin/end explicitly. -template <typename R, typename ForwardIt> -auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { - return std::lower_bound(adl_begin(Range), adl_end(Range), I); +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 ForwardIt, typename Compare> -auto lower_bound(R &&Range, ForwardIt I, Compare C) +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), I, C); + 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 ForwardIt> -auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { - return std::upper_bound(adl_begin(Range), adl_end(Range), I); +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 ForwardIt, typename Compare> -auto upper_bound(R &&Range, ForwardIt I, Compare C) +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), I, C); + 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> @@ -1331,6 +1360,33 @@ 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> //===----------------------------------------------------------------------===// @@ -1418,6 +1474,9 @@ 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; @@ -1431,8 +1490,8 @@ template <typename R> struct result_pair { } std::size_t index() const { return Index; } - const ValueOfRange<R> &value() const { return *Iter; } - ValueOfRange<R> &value() { return *Iter; } + const value_reference value() const { return *Iter; } + value_reference value() { return *Iter; } private: std::size_t Index = std::numeric_limits<std::size_t>::max(); @@ -1577,6 +1636,19 @@ bool hasNItemsOrMore( 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/include/llvm/ADT/ScopeExit.h b/include/llvm/ADT/ScopeExit.h index bd13755fa999..712d91237739 100644 --- a/include/llvm/ADT/ScopeExit.h +++ b/include/llvm/ADT/ScopeExit.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ScopeExit.h - Execute code at scope exit --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 22b0c1bdaf4d..40c49ebc0be1 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -1,9 +1,8 @@ //===- ScopedHashTable.h - A simple scoped hash table -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/Sequence.h b/include/llvm/ADT/Sequence.h index 3d4a897bf9a9..8c505f2010dd 100644 --- a/include/llvm/ADT/Sequence.h +++ b/include/llvm/ADT/Sequence.h @@ -1,9 +1,8 @@ //===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/SetOperations.h b/include/llvm/ADT/SetOperations.h index 7c9f2fbe066e..037256a860b2 100644 --- a/include/llvm/ADT/SetOperations.h +++ b/include/llvm/ADT/SetOperations.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 3d6781041320..d0a0d28d1c81 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 0a73dbd60671..742450e6a951 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index db08e40257ba..913518230d2d 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index 5d84627714bc..6b128c2e2992 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index ff46e85ccb09..898be80d0324 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 0636abbb1fbf..17586904d212 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -42,8 +41,8 @@ protected: unsigned Size = 0, Capacity; SmallVectorBase() = delete; - SmallVectorBase(void *FirstEl, size_t Capacity) - : BeginX(FirstEl), Capacity(Capacity) {} + 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. @@ -64,9 +63,9 @@ public: /// 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 Size) { - assert(Size <= capacity()); - this->Size = Size; + void set_size(size_t N) { + assert(N <= capacity()); + Size = N; } }; @@ -125,13 +124,9 @@ public: using const_pointer = const T *; // forward iterator creation methods. - LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin() { return (iterator)this->BeginX; } - LLVM_ATTRIBUTE_ALWAYS_INLINE const_iterator begin() const { return (const_iterator)this->BeginX; } - LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end() { return begin() + size(); } - LLVM_ATTRIBUTE_ALWAYS_INLINE const_iterator end() const { return begin() + size(); } // reverse iterator creation methods. @@ -150,12 +145,10 @@ public: /// Return a pointer to the vector's buffer, even if empty(). const_pointer data() const { return const_pointer(begin()); } - LLVM_ATTRIBUTE_ALWAYS_INLINE reference operator[](size_type idx) { assert(idx < size()); return begin()[idx]; } - LLVM_ATTRIBUTE_ALWAYS_INLINE const_reference operator[](size_type idx) const { assert(idx < size()); return begin()[idx]; @@ -180,9 +173,9 @@ public: } }; -/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method +/// 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 = isPodLike<T>::value> +template <typename T, bool = is_trivially_copyable<T>::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { protected: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} @@ -236,8 +229,8 @@ public: }; // Define this out-of-line to dissuade the C++ compiler from inlining it. -template <typename T, bool isPodLike> -void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { +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"); @@ -260,9 +253,8 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { this->Capacity = NewCapacity; } - -/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method -/// implementations that are designed to work with POD-like T's. +/// 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: @@ -326,12 +318,13 @@ class SmallVectorImpl : public 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, isPodLike<T>::value>(N) {} + : SmallVectorTemplateBase<T>(N) {} public: SmallVectorImpl(const SmallVectorImpl &) = delete; @@ -393,22 +386,18 @@ public: 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); - // Grow allocated space if needed. if (NumInputs > this->capacity() - this->size()) this->grow(this->size()+NumInputs); - // Copy the new elements over. this->uninitialized_copy(in_start, in_end, this->end()); this->set_size(this->size() + NumInputs); } - /// Add the specified range to the end of the SmallVector. + /// Append \p NumInputs copies of \p Elt to the end. void append(size_type NumInputs, const T &Elt) { - // Grow allocated space if needed. if (NumInputs > this->capacity() - this->size()) this->grow(this->size()+NumInputs); - // Copy the new elements over. std::uninitialized_fill_n(this->end(), NumInputs, Elt); this->set_size(this->size() + NumInputs); } @@ -649,11 +638,12 @@ public: insert(I, IL.begin(), IL.end()); } - template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { + 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); diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 84e73bcbace8..12850e14f4ed 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index 3c8637621510..d9d3ff459267 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SparseMultiSet.h - Sparse multiset --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 74cc6dab8c74..a6eb9b942e80 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -1,9 +1,8 @@ //===- llvm/ADT/SparseSet.h - Sparse set ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h index 90c2eefceb6c..2ac59da596ef 100644 --- a/include/llvm/ADT/Statistic.h +++ b/include/llvm/ADT/Statistic.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 60a03633a8a6..16ac90bd6c89 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -1,9 +1,8 @@ //===- llvm/ADT/StringExtras.h - Useful string functions --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index a9f83d3f5091..8a586fc26709 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -1,9 +1,8 @@ //===- StringMap.h - String Hash table map interface ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -360,6 +359,11 @@ public: 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. diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index a5ba5b59b5a3..4661b1e68b2f 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -1,9 +1,8 @@ //===- StringRef.h - Constant String Reference Wrapper ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -63,7 +62,6 @@ namespace llvm { // Workaround memcmp issue with null pointers (undefined behavior) // by providing a specialized version - LLVM_ATTRIBUTE_ALWAYS_INLINE static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { if (Length == 0) { return 0; } return ::memcmp(Lhs,Rhs,Length); @@ -81,17 +79,14 @@ namespace llvm { StringRef(std::nullptr_t) = delete; /// Construct a string ref from a cstring. - LLVM_ATTRIBUTE_ALWAYS_INLINE /*implicit*/ StringRef(const char *Str) : Data(Str), Length(Str ? ::strlen(Str) : 0) {} /// Construct a string ref from a pointer and length. - LLVM_ATTRIBUTE_ALWAYS_INLINE /*implicit*/ constexpr StringRef(const char *data, size_t length) : Data(data), Length(length) {} /// Construct a string ref from an std::string. - LLVM_ATTRIBUTE_ALWAYS_INLINE /*implicit*/ StringRef(const std::string &Str) : Data(Str.data()), Length(Str.length()) {} @@ -124,17 +119,14 @@ namespace llvm { /// data - Get a pointer to the start of the string (which may not be null /// terminated). LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE const char *data() const { return Data; } /// empty - Check if the string is empty. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const { return Length == 0; } /// size - Get the string size. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const { return Length; } /// front - Get the first character in the string. @@ -165,7 +157,6 @@ namespace llvm { /// equals - Check for string equality, this is more efficient than /// compare() when the relative ordering of inequal strings isn't needed. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool equals(StringRef RHS) const { return (Length == RHS.Length && compareMemory(Data, RHS.Data, RHS.Length) == 0); @@ -180,7 +171,6 @@ namespace llvm { /// 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 - LLVM_ATTRIBUTE_ALWAYS_INLINE int compare(StringRef RHS) const { // Check the prefix for a mismatch. if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) @@ -263,7 +253,6 @@ namespace llvm { /// Check if this string starts with the given \p Prefix. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const { return Length >= Prefix.Length && compareMemory(Data, Prefix.Data, Prefix.Length) == 0; @@ -275,7 +264,6 @@ namespace llvm { /// Check if this string ends with the given \p Suffix. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool endswith(StringRef Suffix) const { return Length >= Suffix.Length && compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; @@ -294,7 +282,6 @@ namespace llvm { /// \returns The index of the first occurrence of \p C, or npos if not /// found. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE 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. @@ -317,7 +304,6 @@ namespace llvm { /// \returns The index of the first character satisfying \p F starting from /// \p From, or npos if not found. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find_if(function_ref<bool(char)> F, size_t From = 0) const { StringRef S = drop_front(From); while (!S.empty()) { @@ -333,7 +319,6 @@ namespace llvm { /// \returns The index of the first character not satisfying \p F starting /// from \p From, or npos if not found. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE 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); } @@ -444,19 +429,16 @@ namespace llvm { /// Return true if the given string is a substring of *this, and false /// otherwise. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool contains(StringRef Other) const { return find(Other) != npos; } /// Return true if the given character is contained in *this, and false /// otherwise. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE 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 - LLVM_ATTRIBUTE_ALWAYS_INLINE bool contains_lower(StringRef Other) const { return find_lower(Other) != npos; } @@ -464,7 +446,6 @@ namespace llvm { /// Return true if the given character is contained in *this, and false /// otherwise. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE bool contains_lower(char C) const { return find_lower(C) != npos; } /// @} @@ -594,7 +575,6 @@ namespace llvm { /// exceeds the number of characters remaining in the string, the string /// suffix (starting with \p Start) will be returned. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N = npos) const { Start = std::min(Start, Length); return StringRef(Data + Start, std::min(N, Length - Start)); @@ -604,7 +584,6 @@ namespace llvm { /// elements remaining. If \p N is greater than the length of the /// string, the entire string is returned. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_front(size_t N = 1) const { if (N >= size()) return *this; @@ -615,7 +594,6 @@ namespace llvm { /// elements remaining. If \p N is greater than the length of the /// string, the entire string is returned. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_back(size_t N = 1) const { if (N >= size()) return *this; @@ -625,7 +603,6 @@ namespace llvm { /// Return the longest prefix of 'this' such that every character /// in the prefix satisfies the given predicate. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_while(function_ref<bool(char)> F) const { return substr(0, find_if_not(F)); } @@ -633,7 +610,6 @@ namespace llvm { /// Return the longest prefix of 'this' such that no character in /// the prefix satisfies the given predicate. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef take_until(function_ref<bool(char)> F) const { return substr(0, find_if(F)); } @@ -641,7 +617,6 @@ namespace llvm { /// Return a StringRef equal to 'this' but with the first \p N elements /// dropped. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_front(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(N); @@ -650,7 +625,6 @@ namespace llvm { /// Return a StringRef equal to 'this' but with the last \p N elements /// dropped. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_back(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(0, size()-N); @@ -659,7 +633,6 @@ namespace llvm { /// Return a StringRef equal to 'this', but with all characters satisfying /// the given predicate dropped from the beginning of the string. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef drop_while(function_ref<bool(char)> F) const { return substr(find_if_not(F)); } @@ -667,14 +640,12 @@ namespace llvm { /// Return a StringRef equal to 'this', but with all characters not /// satisfying the given predicate dropped from the beginning of the string. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE 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. - LLVM_ATTRIBUTE_ALWAYS_INLINE bool consume_front(StringRef Prefix) { if (!startswith(Prefix)) return false; @@ -685,7 +656,6 @@ namespace llvm { /// Returns true if this StringRef has the given suffix and removes that /// suffix. - LLVM_ATTRIBUTE_ALWAYS_INLINE bool consume_back(StringRef Suffix) { if (!endswith(Suffix)) return false; @@ -706,7 +676,6 @@ namespace llvm { /// will be returned. If this is less than \p Start, an empty string will /// be returned. LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef slice(size_t Start, size_t End) const { Start = std::min(Start, Length); End = std::min(std::max(Start, End), Length); @@ -894,12 +863,10 @@ namespace llvm { /// @name StringRef Comparison Operators /// @{ - LLVM_ATTRIBUTE_ALWAYS_INLINE inline bool operator==(StringRef LHS, StringRef RHS) { return LHS.equals(RHS); } - LLVM_ATTRIBUTE_ALWAYS_INLINE inline bool operator!=(StringRef LHS, StringRef RHS) { return !(LHS == RHS); } inline bool operator<(StringRef LHS, StringRef RHS) { @@ -928,10 +895,6 @@ namespace llvm { LLVM_NODISCARD hash_code hash_value(StringRef S); - // StringRefs can be treated like a POD type. - template <typename T> struct isPodLike; - template <> struct isPodLike<StringRef> { static const bool value = true; }; - } // end namespace llvm #endif // LLVM_ADT_STRINGREF_H diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h index 9af44c07df79..af3a44a7b32c 100644 --- a/include/llvm/ADT/StringSet.h +++ b/include/llvm/ADT/StringSet.h @@ -1,9 +1,8 @@ //===- StringSet.h - The LLVM Compiler Driver -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -34,6 +33,7 @@ namespace llvm { for (StringRef X : S) insert(X); } + explicit StringSet(AllocatorTy A) : base(A) {} std::pair<typename base::iterator, bool> insert(StringRef Key) { assert(!Key.empty()); @@ -45,6 +45,12 @@ namespace llvm { for (auto It = Begin; It != End; ++It) base::insert(std::make_pair(*It, '\0')); } + + template <typename ValueTy> + std::pair<typename base::iterator, bool> + insert(const StringMapEntry<ValueTy> &MapEntry) { + return insert(MapEntry.getKey()); + } }; } // end namespace llvm diff --git a/include/llvm/ADT/StringSwitch.h b/include/llvm/ADT/StringSwitch.h index b7860b98ce5d..fea911f6928b 100644 --- a/include/llvm/ADT/StringSwitch.h +++ b/include/llvm/ADT/StringSwitch.h @@ -1,9 +1,8 @@ //===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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() @@ -49,7 +48,6 @@ class StringSwitch { Optional<T> Result; public: - LLVM_ATTRIBUTE_ALWAYS_INLINE explicit StringSwitch(StringRef S) : Str(S), Result() { } @@ -66,7 +64,6 @@ public: ~StringSwitch() = default; // Case-sensitive case matchers - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Case(StringLiteral S, T Value) { if (!Result && Str == S) { Result = std::move(Value); @@ -74,7 +71,6 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch& EndsWith(StringLiteral S, T Value) { if (!Result && Str.endswith(S)) { Result = std::move(Value); @@ -82,7 +78,6 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch& StartsWith(StringLiteral S, T Value) { if (!Result && Str.startswith(S)) { Result = std::move(Value); @@ -90,51 +85,43 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) { return Case(S0, Value).Case(S1, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return Case(S0, Value).Cases(S1, S2, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value) { return Case(S0, Value).Cases(S1, S2, S3, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE 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); } - LLVM_ATTRIBUTE_ALWAYS_INLINE 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); } - LLVM_ATTRIBUTE_ALWAYS_INLINE 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); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, @@ -142,7 +129,6 @@ public: return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, StringLiteral S4, StringLiteral S5, StringLiteral S6, StringLiteral S7, StringLiteral S8, @@ -151,7 +137,6 @@ public: } // Case-insensitive case matchers. - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(StringLiteral S, T Value) { if (!Result && Str.equals_lower(S)) Result = std::move(Value); @@ -159,7 +144,6 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(StringLiteral S, T Value) { if (!Result && Str.endswith_lower(S)) Result = Value; @@ -167,7 +151,6 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(StringLiteral S, T Value) { if (!Result && Str.startswith_lower(S)) Result = std::move(Value); @@ -175,31 +158,26 @@ public: return *this; } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) { return CaseLower(S0, Value).CaseLower(S1, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, T Value) { return CaseLower(S0, Value).CasesLower(S1, S2, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, StringLiteral S3, T Value) { return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value); } - LLVM_ATTRIBUTE_ALWAYS_INLINE 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 - LLVM_ATTRIBUTE_ALWAYS_INLINE R Default(T Value) { if (Result) return std::move(*Result); @@ -207,7 +185,6 @@ public: } LLVM_NODISCARD - LLVM_ATTRIBUTE_ALWAYS_INLINE operator R() { assert(Result && "Fell off the end of a string-switch"); return std::move(*Result); diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index 1b8e9aa658c3..ac82451a9b21 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index e06a68e27317..edeb31efab80 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -50,6 +49,7 @@ public: 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) @@ -109,6 +109,7 @@ public: ARMSubArch_v8r, ARMSubArch_v8m_baseline, ARMSubArch_v8m_mainline, + ARMSubArch_v8_1m_mainline, ARMSubArch_v7, ARMSubArch_v7em, ARMSubArch_v7m, @@ -187,7 +188,8 @@ public: HermitCore, // HermitCore Unikernel/Multikernel Hurd, // GNU/Hurd WASI, // Experimental WebAssembly OS - LastOSType = WASI + Emscripten, + LastOSType = Emscripten }; enum EnvironmentType { UnknownEnvironment, @@ -201,6 +203,8 @@ public: CODE16, EABI, EABIHF, + ELFv1, + ELFv2, Android, Musl, MuslEABI, @@ -210,8 +214,9 @@ public: Itanium, Cygnus, CoreCLR, - Simulator, // Simulator variants of other systems, e.g., Apple's iOS - LastEnvironmentType = Simulator + 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, @@ -220,6 +225,7 @@ public: ELF, MachO, Wasm, + XCOFF, }; private: @@ -415,7 +421,7 @@ public: if (LHS[1] != Minor) return LHS[1] < Minor; if (LHS[2] != Micro) - return LHS[1] < Micro; + return LHS[2] < Micro; return false; } @@ -480,6 +486,10 @@ public: return getEnvironment() == Triple::Simulator; } + bool isMacCatalystEnvironment() const { + return getEnvironment() == Triple::MacABI; + } + bool isOSNetBSD() const { return getOS() == Triple::NetBSD; } @@ -524,32 +534,36 @@ public: return getOS() == Triple::Haiku; } - /// Checks if the environment could be MSVC. - bool isWindowsMSVCEnvironment() const { - return getOS() == Triple::Win32 && - (getEnvironment() == Triple::UnknownEnvironment || - getEnvironment() == Triple::MSVC); + /// Tests whether the OS is Windows. + bool isOSWindows() const { + return getOS() == Triple::Win32; } /// Checks if the environment is MSVC. bool isKnownWindowsMSVCEnvironment() const { - return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC; + 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 getOS() == Triple::Win32 && getEnvironment() == Triple::CoreCLR; + return isOSWindows() && getEnvironment() == Triple::CoreCLR; } bool isWindowsItaniumEnvironment() const { - return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium; + return isOSWindows() && getEnvironment() == Triple::Itanium; } bool isWindowsCygwinEnvironment() const { - return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus; + return isOSWindows() && getEnvironment() == Triple::Cygnus; } bool isWindowsGNUEnvironment() const { - return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU; + return isOSWindows() && getEnvironment() == Triple::GNU; } /// Tests for either Cygwin or MinGW OS @@ -563,11 +577,6 @@ public: isWindowsItaniumEnvironment(); } - /// Tests whether the OS is Windows. - bool isOSWindows() const { - return getOS() == Triple::Win32; - } - /// Tests whether the OS is NaCl (Native Client) bool isOSNaCl() const { return getOS() == Triple::NaCl; @@ -593,6 +602,11 @@ public: 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 || @@ -600,6 +614,11 @@ public: !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; @@ -620,6 +639,11 @@ public: 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 && @@ -656,6 +680,11 @@ public: 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; @@ -691,6 +720,16 @@ public: 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 supports comdat bool supportsCOMDAT() const { return !isOSBinFormatMachO(); diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index b60fd0981398..4140c22aad3d 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -1,9 +1,8 @@ //===- Twine.h - Fast Temporary String Concatenation ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -274,6 +273,9 @@ namespace llvm { 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) { diff --git a/include/llvm/ADT/UniqueVector.h b/include/llvm/ADT/UniqueVector.h index c86bedd07687..bfea988f1702 100644 --- a/include/llvm/ADT/UniqueVector.h +++ b/include/llvm/ADT/UniqueVector.h @@ -1,9 +1,8 @@ //===- llvm/ADT/UniqueVector.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h index 9028abe4c72c..5aefb05ecdda 100644 --- a/include/llvm/ADT/VariadicFunction.h +++ b/include/llvm/ADT/VariadicFunction.h @@ -1,9 +1,8 @@ -//===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===// +//===- VariadicFunction.h - Variadic Functions ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/bit.h b/include/llvm/ADT/bit.h index a4aba7b6a9ee..a790d5ed2d21 100644 --- a/include/llvm/ADT/bit.h +++ b/include/llvm/ADT/bit.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -41,11 +40,11 @@ template <typename To, typename From , 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 isPodLike 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. +// 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 { diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h index b2e8ec5c3f6d..4f5134008692 100644 --- a/include/llvm/ADT/edit_distance.h +++ b/include/llvm/ADT/edit_distance.h @@ -1,9 +1,8 @@ //===-- llvm/ADT/edit_distance.h - Array edit distance function --- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/fallible_iterator.h b/include/llvm/ADT/fallible_iterator.h new file mode 100644 index 000000000000..6501ad2233cd --- /dev/null +++ b/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/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 00bb6d528175..06c7abff965f 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -1,9 +1,8 @@ //==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -66,9 +65,8 @@ template <typename NodeTy> struct ilist_callback_traits { void addNodeToList(NodeTy *) {} void removeNodeFromList(NodeTy *) {} - /// Callback before transferring nodes to this list. - /// - /// \pre \c this!=&OldList + /// 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*/) { @@ -287,8 +285,8 @@ private: if (position == last) return; - if (this != &L2) // Notify traits we moved the nodes... - this->transferNodesFromList(L2, first, last); + // Notify traits we moved the nodes... + this->transferNodesFromList(L2, first, last); base_list_type::splice(position, L2, first, last); } diff --git a/include/llvm/ADT/ilist_base.h b/include/llvm/ADT/ilist_base.h index 3d818a48d41d..b8c098b951ad 100644 --- a/include/llvm/ADT/ilist_base.h +++ b/include/llvm/ADT/ilist_base.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ilist_base.h - Intrusive List Base --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/ilist_iterator.h b/include/llvm/ADT/ilist_iterator.h index 671e644e0154..cbe5cefa96d1 100644 --- a/include/llvm/ADT/ilist_iterator.h +++ b/include/llvm/ADT/ilist_iterator.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index dd0e6b4ec2b9..e040d9630a1e 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ADT/ilist_node_base.h b/include/llvm/ADT/ilist_node_base.h index e5062ac4eaad..f6c518e6eed7 100644 --- a/include/llvm/ADT/ilist_node_base.h +++ b/include/llvm/ADT/ilist_node_base.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ilist_node_base.h - Intrusive List Node Base -----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/ilist_node_options.h b/include/llvm/ADT/ilist_node_options.h index 7ff4005f6757..9b95cdbe08c4 100644 --- a/include/llvm/ADT/ilist_node_options.h +++ b/include/llvm/ADT/ilist_node_options.h @@ -1,9 +1,8 @@ //===- llvm/ADT/ilist_node_options.h - ilist_node Options -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 40e490cf7864..467fd4c00ec5 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -1,9 +1,8 @@ //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index 2ba12866ecf3..774c7c4e3366 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -1,9 +1,8 @@ //===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ADT/simple_ilist.h b/include/llvm/ADT/simple_ilist.h index 4c7598a1acb4..9257b47b9cf8 100644 --- a/include/llvm/ADT/simple_ilist.h +++ b/include/llvm/ADT/simple_ilist.h @@ -1,9 +1,8 @@ //===- llvm/ADT/simple_ilist.h - Simple Intrusive List ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index e2a2ac0622e8..948341554f23 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -38,6 +37,7 @@ #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" @@ -286,6 +286,28 @@ 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 @@ -600,32 +622,8 @@ public: /// helpers above. ModRefInfo getModRefInfo(const Instruction *I, const Optional<MemoryLocation> &OptLoc) { - 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); - case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); - case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); - case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc); - case Instruction::AtomicCmpXchg: - return getModRefInfo((const AtomicCmpXchgInst*)I, Loc); - case Instruction::AtomicRMW: - return getModRefInfo((const AtomicRMWInst*)I, Loc); - case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); - case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); - case Instruction::CatchPad: - return getModRefInfo((const CatchPadInst *)I, Loc); - case Instruction::CatchRet: - return getModRefInfo((const CatchReturnInst *)I, Loc); - default: - return ModRefInfo::NoModRef; - } + AAQueryInfo AAQIP; + return getModRefInfo(I, OptLoc, AAQIP); } /// A convenience wrapper for constructing the memory location. @@ -692,6 +690,69 @@ public: } 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; @@ -703,6 +764,47 @@ private: 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 @@ -735,12 +837,12 @@ public: /// each other. This is the interface that must be implemented by specific /// alias analysis implementations. virtual AliasResult alias(const MemoryLocation &LocA, - const MemoryLocation &LocB) = 0; + 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, - bool OrLocal) = 0; + AAQueryInfo &AAQI, bool OrLocal) = 0; /// @} //===--------------------------------------------------------------------===// @@ -764,13 +866,14 @@ public: /// 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) = 0; + 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) = 0; + virtual ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) = 0; /// @} }; @@ -792,14 +895,14 @@ public: void setAAResults(AAResults *NewAAR) override { Result.setAAResults(NewAAR); } - AliasResult alias(const MemoryLocation &LocA, - const MemoryLocation &LocB) override { - return Result.alias(LocA, LocB); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) override { + return Result.alias(LocA, LocB, AAQI); } - bool pointsToConstantMemory(const MemoryLocation &Loc, + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, bool OrLocal) override { - return Result.pointsToConstantMemory(Loc, OrLocal); + return Result.pointsToConstantMemory(Loc, AAQI, OrLocal); } ModRefInfo getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) override { @@ -814,14 +917,14 @@ public: return Result.getModRefBehavior(F); } - ModRefInfo getModRefInfo(const CallBase *Call, - const MemoryLocation &Loc) override { - return Result.getModRefInfo(Call, Loc); + 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) override { - return Result.getModRefInfo(Call1, Call2); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) override { + return Result.getModRefInfo(Call1, Call2, AAQI); } }; @@ -867,13 +970,16 @@ protected: AAResultsProxy(AAResults *AAR, DerivedT &CurrentResult) : AAR(AAR), CurrentResult(CurrentResult) {} - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { - return AAR ? AAR->alias(LocA, LocB) : CurrentResult.alias(LocA, LocB); + 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, bool OrLocal) { - return AAR ? AAR->pointsToConstantMemory(Loc, OrLocal) - : CurrentResult.pointsToConstantMemory(Loc, OrLocal); + 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) { @@ -890,14 +996,16 @@ protected: return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F); } - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { - return AAR ? AAR->getModRefInfo(Call, Loc) - : CurrentResult.getModRefInfo(Call, Loc); + 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) { - return AAR ? AAR->getModRefInfo(Call1, Call2) - : CurrentResult.getModRefInfo(Call1, Call2); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) { + return AAR ? AAR->getModRefInfo(Call1, Call2, AAQI) + : CurrentResult.getModRefInfo(Call1, Call2, AAQI); } }; @@ -921,11 +1029,13 @@ protected: AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); } public: - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) { return MayAlias; } - bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) { + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal) { return false; } @@ -941,11 +1051,13 @@ public: return FMRB_UnknownModRefBehavior; } - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc) { + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI) { return ModRefInfo::ModRef; } - ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2) { + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI) { return ModRefInfo::ModRef; } }; @@ -984,6 +1096,11 @@ bool isIdentifiedFunctionLocal(const Value *V); /// This manager effectively wraps the AnalysisManager for registering alias /// analyses. When you register your alias analysis with this manager, it will /// ensure the analysis itself is registered with its AnalysisManager. +/// +/// 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; diff --git a/include/llvm/Analysis/AliasAnalysisEvaluator.h b/include/llvm/Analysis/AliasAnalysisEvaluator.h index 0941814a56c3..972eceaa3ba9 100644 --- a/include/llvm/Analysis/AliasAnalysisEvaluator.h +++ b/include/llvm/Analysis/AliasAnalysisEvaluator.h @@ -1,9 +1,8 @@ //===- AliasAnalysisEvaluator.h - Alias Analysis Accuracy Evaluator -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 7ed5cd5c4734..34a509b7f4bb 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -37,6 +36,8 @@ namespace llvm { class AliasSetTracker; class BasicBlock; class LoadInst; +class Loop; +class MemorySSA; class AnyMemSetInst; class AnyMemTransferInst; class raw_ostream; @@ -294,7 +295,8 @@ private: void removeFromTracker(AliasSetTracker &AST); void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size, - const AAMDNodes &AAInfo, bool KnownMustAlias = false); + const AAMDNodes &AAInfo, bool KnownMustAlias = false, + bool SkipSizeUpdate = false); void addUnknownInst(Instruction *I, AliasAnalysis &AA); void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { @@ -310,10 +312,10 @@ private: } public: - /// Return true if the specified pointer "may" (or must) alias one of the - /// members in the set. - bool aliasesPointer(const Value *Ptr, LocationSize Size, - const AAMDNodes &AAInfo, AliasAnalysis &AA) const; + /// 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; }; @@ -341,6 +343,8 @@ class AliasSetTracker { struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {}; AliasAnalysis &AA; + MemorySSA *MSSA; + Loop *L; ilist<AliasSet> AliasSets; using PointerMapType = DenseMap<ASTCallbackVH, AliasSet::PointerRec *, @@ -353,6 +357,8 @@ 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 @@ -377,6 +383,7 @@ public: 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(); @@ -439,7 +446,8 @@ private: AliasSet &addPointer(MemoryLocation Loc, AliasSet::AccessLattice E); AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size, - const AAMDNodes &AAInfo); + const AAMDNodes &AAInfo, + bool &MustAliasAll); /// Merge all alias sets into a single set that is considered to alias any /// pointer. diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index 46538b1fa86f..b42846472f2e 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -104,6 +103,10 @@ public: /// 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); @@ -209,6 +212,10 @@ public: /// 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; diff --git a/include/llvm/Analysis/BasicAliasAnalysis.h b/include/llvm/Analysis/BasicAliasAnalysis.h index 820d7ac0935a..22e8c4b474cb 100644 --- a/include/llvm/Analysis/BasicAliasAnalysis.h +++ b/include/llvm/Analysis/BasicAliasAnalysis.h @@ -1,9 +1,8 @@ //===- BasicAliasAnalysis.h - Stateless, local Alias Analysis ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -82,14 +81,18 @@ public: bool invalidate(Function &Fn, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv); - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); - ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); + 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, bool OrLocal); + 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); @@ -141,11 +144,6 @@ private: SmallVector<VariableGEPIndex, 4> VarIndices; }; - /// Track alias queries to guard against recursion. - using LocPair = std::pair<MemoryLocation, MemoryLocation>; - using AliasCacheTy = SmallDenseMap<LocPair, AliasResult, 8>; - AliasCacheTy AliasCache; - /// Tracks phi nodes we have visited. /// /// When interpret "Value" pointer equality as value equality we need to make @@ -200,22 +198,24 @@ private: AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size, const AAMDNodes &V1AAInfo, const Value *V2, LocationSize V2Size, const AAMDNodes &V2AAInfo, - const Value *UnderlyingV1, const Value *UnderlyingV2); + 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); + 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); + const Value *UnderV2, AAQueryInfo &AAQI); AliasResult aliasCheck(const Value *V1, LocationSize V1Size, AAMDNodes V1AATag, const Value *V2, LocationSize V2Size, AAMDNodes V2AATag, - const Value *O1 = nullptr, const Value *O2 = nullptr); + AAQueryInfo &AAQI, const Value *O1 = nullptr, + const Value *O2 = nullptr); }; /// Analysis pass providing a never-invalidated alias analysis result. diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index 0b2618735697..8bcfd7ff8f58 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,9 +1,8 @@ //===- BlockFrequencyInfo.h - Block Frequency Analysis ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -68,7 +67,8 @@ public: /// Returns the estimated profile count of \p BB. /// This computes the relative block frequency of \p BB and multiplies it by /// the enclosing function's count (if available) and returns the value. - Optional<uint64_t> getBlockProfileCount(const BasicBlock *BB) const; + 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 diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 25b2efd33c98..bfe4fb14a2b8 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -1,9 +1,8 @@ //==- BlockFrequencyInfoImpl.h - Block Frequency Implementation --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -160,10 +159,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, BlockMass X) { } // end namespace bfi_detail -template <> struct isPodLike<bfi_detail::BlockMass> { - static const bool value = true; -}; - /// Base class for BlockFrequencyInfoImpl /// /// BlockFrequencyInfoImplBase has supporting data structures and some @@ -187,9 +182,9 @@ public: struct BlockNode { using IndexType = uint32_t; - IndexType Index = std::numeric_limits<uint32_t>::max(); + IndexType Index; - BlockNode() = default; + BlockNode() : Index(std::numeric_limits<uint32_t>::max()) {} BlockNode(IndexType Index) : Index(Index) {} bool operator==(const BlockNode &X) const { return Index == X.Index; } @@ -525,9 +520,11 @@ public: BlockFrequency getBlockFreq(const BlockNode &Node) const; Optional<uint64_t> getBlockProfileCount(const Function &F, - const BlockNode &Node) const; + const BlockNode &Node, + bool AllowSynthetic = false) const; Optional<uint64_t> getProfileCountFromFreq(const Function &F, - uint64_t Freq) const; + uint64_t Freq, + bool AllowSynthetic = false) const; bool isIrrLoopHeader(const BlockNode &Node); void setBlockFreq(const BlockNode &Node, uint64_t Freq); @@ -973,13 +970,17 @@ public: } Optional<uint64_t> getBlockProfileCount(const Function &F, - const BlockT *BB) const { - return BlockFrequencyInfoImplBase::getBlockProfileCount(F, getNode(BB)); + const BlockT *BB, + bool AllowSynthetic = false) const { + return BlockFrequencyInfoImplBase::getBlockProfileCount(F, getNode(BB), + AllowSynthetic); } Optional<uint64_t> getProfileCountFromFreq(const Function &F, - uint64_t Freq) const { - return BlockFrequencyInfoImplBase::getProfileCountFromFreq(F, Freq); + uint64_t Freq, + bool AllowSynthetic = false) const { + return BlockFrequencyInfoImplBase::getProfileCountFromFreq(F, Freq, + AllowSynthetic); } bool isIrrLoopHeader(const BlockT *BB) { diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 45277db46090..97cb730d16c7 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -1,9 +1,8 @@ //===- BranchProbabilityInfo.h - Branch Probability Analysis ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h index caae0b6e2a8f..bb55e76ac86a 100644 --- a/include/llvm/Analysis/CFG.h +++ b/include/llvm/Analysis/CFG.h @@ -1,9 +1,8 @@ //===-- Analysis/CFG.h - BasicBlock Analyses --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -48,8 +47,8 @@ unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ); bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges = false); -/// Determine whether instruction 'To' is reachable from 'From', -/// returning true if uncertain. +/// 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 @@ -63,9 +62,10 @@ bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, /// 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 DominatorTree *DT = nullptr, - const LoopInfo *LI = nullptr); +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. @@ -89,6 +89,20 @@ bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist, 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 diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index 5996dd90bcfd..aaefc11653dd 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -1,9 +1,8 @@ //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CFLAliasAnalysisUtils.h b/include/llvm/Analysis/CFLAliasAnalysisUtils.h index 981a8ddc2289..02f999a5b913 100644 --- a/include/llvm/Analysis/CFLAliasAnalysisUtils.h +++ b/include/llvm/Analysis/CFLAliasAnalysisUtils.h @@ -1,9 +1,8 @@ //=- CFLAliasAnalysisUtils.h - Utilities for CFL Alias Analysis ----*- C++-*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/CFLAndersAliasAnalysis.h b/include/llvm/Analysis/CFLAndersAliasAnalysis.h index 8ae72553ab94..7c8b42b1d8d2 100644 --- a/include/llvm/Analysis/CFLAndersAliasAnalysis.h +++ b/include/llvm/Analysis/CFLAndersAliasAnalysis.h @@ -1,9 +1,8 @@ //==- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -61,7 +60,8 @@ public: const cflaa::AliasSummary *getAliasSummary(const Function &); AliasResult query(const MemoryLocation &, const MemoryLocation &); - AliasResult alias(const MemoryLocation &, const MemoryLocation &); + AliasResult alias(const MemoryLocation &, const MemoryLocation &, + AAQueryInfo &); private: /// Ensures that the given function is available in the cache. diff --git a/include/llvm/Analysis/CFLSteensAliasAnalysis.h b/include/llvm/Analysis/CFLSteensAliasAnalysis.h index 09e366f11e18..cc7a47cd9a5f 100644 --- a/include/llvm/Analysis/CFLSteensAliasAnalysis.h +++ b/include/llvm/Analysis/CFLSteensAliasAnalysis.h @@ -1,9 +1,8 @@ //==- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis -*- C++-*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -70,7 +69,8 @@ public: AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB); - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) { + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI) { if (LocA.Ptr == LocB.Ptr) return MustAlias; @@ -80,11 +80,11 @@ public: // 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); + return AAResultBase::alias(LocA, LocB, AAQI); AliasResult QueryResult = query(LocA, LocB); if (QueryResult == MayAlias) - return AAResultBase::alias(LocA, LocB); + return AAResultBase::alias(LocA, LocB, AAQI); return QueryResult; } diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 61b99f6c3e6b..8af5fb86995a 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -1,9 +1,8 @@ //===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -292,6 +291,21 @@ struct CGSCCUpdateResult { /// 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. @@ -339,175 +353,7 @@ public: } /// Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses 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, - 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; - } - - 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. - 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; - } + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); private: CGSCCPassT Pass; @@ -873,6 +719,210 @@ DevirtSCCRepeatedPass<PassT> createDevirtSCCRepeatedPass(PassT Pass, 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 diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index f109cf2fac4d..7a10183c4d91 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -1,9 +1,8 @@ //===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -48,8 +47,8 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/IR/CallSite.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" @@ -230,11 +229,11 @@ public: } /// Adds a function to the list of functions called by this one. - void addCalledFunction(CallSite CS, CallGraphNode *M) { - assert(!CS.getInstruction() || !CS.getCalledFunction() || - !CS.getCalledFunction()->isIntrinsic() || - !Intrinsic::isLeaf(CS.getCalledFunction()->getIntrinsicID())); - CalledFunctions.emplace_back(CS.getInstruction(), M); + 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(); } @@ -247,7 +246,7 @@ public: /// Removes the edge in the node for the specified call site. /// /// Note that this method takes linear time, so it should be used sparingly. - void removeCallEdgeFor(CallSite CS); + void removeCallEdgeFor(CallBase &Call); /// Removes all call edges from this node to the specified callee /// function. @@ -264,7 +263,8 @@ public: /// new one. /// /// Note that this method takes linear time, so it should be used sparingly. - void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode); + void replaceCallEdge(CallBase &Call, CallBase &NewCall, + CallGraphNode *NewNode); private: friend class CallGraph; diff --git a/include/llvm/Analysis/CallGraphSCCPass.h b/include/llvm/Analysis/CallGraphSCCPass.h index ace54607634c..1b5b7e2f039e 100644 --- a/include/llvm/Analysis/CallGraphSCCPass.h +++ b/include/llvm/Analysis/CallGraphSCCPass.h @@ -1,9 +1,8 @@ //===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CallPrinter.h b/include/llvm/Analysis/CallPrinter.h index 8b697d5aa149..8d4159f3ddc0 100644 --- a/include/llvm/Analysis/CallPrinter.h +++ b/include/llvm/Analysis/CallPrinter.h @@ -1,9 +1,8 @@ //===-- CallPrinter.h - Call graph printer external interface ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index aaaaff9ae252..ca7abd34fea2 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -1,9 +1,8 @@ //===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CmpInstAnalysis.h b/include/llvm/Analysis/CmpInstAnalysis.h index 0e9c6a96b0f4..3d34cd12aea4 100644 --- a/include/llvm/Analysis/CmpInstAnalysis.h +++ b/include/llvm/Analysis/CmpInstAnalysis.h @@ -1,9 +1,8 @@ //===-- CmpInstAnalysis.h - Utils to help fold compare insts ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 752902238522..1482b66a3080 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -1,9 +1,8 @@ //===- CodeMetrics.h - Code cost measurements -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,7 +16,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/IR/CallSite.h" namespace llvm { class AssumptionCache; @@ -29,14 +27,6 @@ class DataLayout; class TargetTransformInfo; class Value; -/// Check whether a call will lower to something small. -/// -/// This tests checks whether this callsite will lower to something -/// significantly cheaper than a traditional call, often a single -/// instruction. Note that if isInstructionFree(CS.getInstruction()) would -/// return true, so will this function. -bool callIsSmall(ImmutableCallSite CS); - /// Utility to calculate the size and a few similar metrics for a set /// of basic blocks. struct CodeMetrics { diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 192c1abddcd2..2385b6f09c40 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -1,9 +1,8 @@ //===-- ConstantFolding.h - Fold instructions into constants ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,7 +22,7 @@ namespace llvm { class APInt; template <typename T> class ArrayRef; -class CallSite; +class CallBase; class Constant; class ConstantExpr; class ConstantVector; @@ -31,7 +30,6 @@ class DataLayout; class Function; class GlobalValue; class Instruction; -class ImmutableCallSite; class TargetLibraryInfo; class Type; @@ -73,6 +71,12 @@ 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. @@ -139,11 +143,11 @@ Constant *ConstantFoldLoadThroughGEPIndices(Constant *C, /// canConstantFoldCallTo - Return true if its even possible to fold a call to /// the specified function. -bool canConstantFoldCallTo(ImmutableCallSite CS, const Function *F); +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(ImmutableCallSite CS, Function *F, +Constant *ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef<Constant *> Operands, const TargetLibraryInfo *TLI = nullptr); @@ -155,7 +159,7 @@ Constant *ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, /// Check whether the given call has no side-effects. /// Specifically checks for math routimes which sometimes set errno. -bool isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI); +bool isMathLibCallNoop(const CallBase *Call, const TargetLibraryInfo *TLI); } #endif diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index b7447a0547d5..0410a3314659 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -1,9 +1,8 @@ //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/DemandedBits.h b/include/llvm/Analysis/DemandedBits.h index 4c4e3f6c99e7..04db3eb57c18 100644 --- a/include/llvm/Analysis/DemandedBits.h +++ b/include/llvm/Analysis/DemandedBits.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/DemandedBits.h - Determine demanded bits ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 69d0e2c1513e..997013a5fc8e 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -1,9 +1,8 @@ //===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -275,6 +274,10 @@ template <typename T> class ArrayRef; 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. diff --git a/include/llvm/Analysis/DivergenceAnalysis.h b/include/llvm/Analysis/DivergenceAnalysis.h index d834862db095..3cfb9d13df94 100644 --- a/include/llvm/Analysis/DivergenceAnalysis.h +++ b/include/llvm/Analysis/DivergenceAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/DivergenceAnalysis.h - Divergence Analysis -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/DomPrinter.h b/include/llvm/Analysis/DomPrinter.h index 0ed28994995a..a177f877b295 100644 --- a/include/llvm/Analysis/DomPrinter.h +++ b/include/llvm/Analysis/DomPrinter.h @@ -1,9 +1,8 @@ //===-- DomPrinter.h - Dom printer external interface ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/DomTreeUpdater.h b/include/llvm/Analysis/DomTreeUpdater.h index e5bb092d21ca..5ccce2e064cc 100644 --- a/include/llvm/IR/DomTreeUpdater.h +++ b/include/llvm/Analysis/DomTreeUpdater.h @@ -1,9 +1,8 @@ //===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -12,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DOMTREEUPDATER_H -#define LLVM_DOMTREEUPDATER_H +#ifndef LLVM_ANALYSIS_DOMTREEUPDATER_H +#define LLVM_ANALYSIS_DOMTREEUPDATER_H #include "llvm/Analysis/PostDominators.h" #include "llvm/IR/Dominators.h" @@ -83,61 +82,114 @@ public: /// Returns false under Eager UpdateStrategy or PDT is nullptr. bool hasPendingPostDomTreeUpdates() const; - /// Apply updates on all available trees. Under Eager UpdateStrategy with - /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will - /// discard duplicated updates and self-dominance updates. If both DT and PDT - /// are nullptrs, this function discards all updates. The Eager Strategy - /// applies the updates immediately while the Lazy Strategy queues the - /// updates. It is required for the state of the LLVM IR to be updated - /// *before* applying the Updates because the internal update routine will - /// analyze the current state of the relationship between a pair of (From, To) - /// BasicBlocks to determine whether a single update needs to be discarded. - void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates, - bool ForceRemoveDuplicates = false); - - /// Notify all available trees on an edge insertion. If both DT and PDT are - /// nullptrs, this function discards the update. Under either Strategy, - /// self-dominance update will be removed. The Eager Strategy applies - /// the update immediately while the Lazy Strategy queues the update. - /// It is recommended to only use this method when you have exactly one - /// insertion (and no deletions). It is recommended to use applyUpdates() in - /// all other cases. This function has to be called *after* making the update - /// on the actual CFG. An internal functions checks if the edge exists in the + ///@{ + /// \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. - void insertEdge(BasicBlock *From, BasicBlock *To); - - /// Notify all available trees on an edge insertion. - /// Under either Strategy, the following updates will be discard silently - /// 1. Invalid - Inserting an edge that does not exist in the CFG. - /// 2. Self-dominance update. - /// 3. Both DT and PDT are nullptrs. - /// The Eager Strategy applies the update immediately while the Lazy Strategy - /// queues the update. It is recommended to only use this method when you have - /// exactly one insertion (and no deletions) and want to discard an invalid - /// update. - void insertEdgeRelaxed(BasicBlock *From, BasicBlock *To); - - /// Notify all available trees on an edge deletion. If both DT and PDT are - /// nullptrs, this function discards the update. Under either Strategy, - /// self-dominance update will be removed. The Eager Strategy applies - /// the update immediately while the Lazy Strategy queues the update. - /// It is recommended to only use this method when you have exactly one - /// deletion (and no insertions). It is recommended to use applyUpdates() in - /// all other cases. This function has to be called *after* making the update - /// on the actual CFG. An internal functions checks if the edge doesn't exist - /// in the CFG in DEBUG mode. - void deleteEdge(BasicBlock *From, BasicBlock *To); - - /// Notify all available trees on an edge deletion. - /// Under either Strategy, the following updates will be discard silently - /// 1. Invalid - Deleting an edge that still exists in the CFG. - /// 2. Self-dominance update. - /// 3. Both DT and PDT are nullptrs. - /// The Eager Strategy applies the update immediately while the Lazy Strategy - /// queues the update. It is recommended to only use this method when you have - /// exactly one deletion (and no insertions) and want to discard an invalid - /// update. - void deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To); + /// 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. @@ -159,27 +211,32 @@ public: void callbackDeleteBB(BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback); - /// Recalculate all available trees and flush all BasicBlocks - /// awaiting deletion immediately. - void recalculate(Function &F); + ///@} + + ///@{ + /// \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 also flush out of date updates applied by all available trees - /// and flush Deleted BBs if both trees are up-to-date. + /// 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 also flush out of date updates applied by all available trees - /// and flush Deleted BBs if both trees are up-to-date. + /// 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. - /// Does nothing under Eager UpdateStrategy. + void flush(); + ///@} + /// Debug method to help view the internal state of this class. LLVM_DUMP_METHOD void dump() const; @@ -221,11 +278,6 @@ private: /// Returns true if at least one BasicBlock is deleted. bool forceFlushDeletedBB(); - /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy - /// UpdateStrategy. Returns true if the update is queued for update. - bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From, - BasicBlock *To); - /// Helper function to apply all pending DomTree updates. void applyDomTreeUpdates(); @@ -254,4 +306,4 @@ private: }; } // namespace llvm -#endif // LLVM_DOMTREEUPDATER_H +#endif // LLVM_ANALYSIS_DOMTREEUPDATER_H diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index d94c420d7177..c0bf30e162dd 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 99224c0bf131..aa764be93b91 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/EHPersonalities.h b/include/llvm/Analysis/EHPersonalities.h index fe0e65b828ca..d89aa11617b5 100644 --- a/include/llvm/Analysis/EHPersonalities.h +++ b/include/llvm/Analysis/EHPersonalities.h @@ -1,9 +1,8 @@ //===- EHPersonalities.h - Compute EH-related information -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/GlobalsModRef.h b/include/llvm/Analysis/GlobalsModRef.h index 3a664ca6ef50..d3fcfc2d41ab 100644 --- a/include/llvm/Analysis/GlobalsModRef.h +++ b/include/llvm/Analysis/GlobalsModRef.h @@ -1,9 +1,8 @@ //===- GlobalsModRef.h - Simple Mod/Ref AA for Globals ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -85,10 +84,12 @@ public: //------------------------------------------------ // Implement the AliasAnalysis API // - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); using AAResultBase::getModRefInfo; - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); + 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 @@ -114,7 +115,7 @@ private: bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V); ModRefInfo getModRefInfoForArgument(const CallBase *Call, - const GlobalValue *GV); + const GlobalValue *GV, AAQueryInfo &AAQI); }; /// Analysis pass providing a never-invalidated alias analysis result. diff --git a/include/llvm/Analysis/GuardUtils.h b/include/llvm/Analysis/GuardUtils.h index 3b151eeafc81..41e7b7c06c75 100644 --- a/include/llvm/Analysis/GuardUtils.h +++ b/include/llvm/Analysis/GuardUtils.h @@ -1,9 +1,8 @@ //===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -15,12 +14,31 @@ namespace llvm { +class BasicBlock; class User; +class Value; -/// Returns true iff \p U has semantics of a guard. +/// 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 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); + } // llvm #endif // LLVM_ANALYSIS_GUARDUTILS_H - diff --git a/include/llvm/Analysis/IVDescriptors.h b/include/llvm/Analysis/IVDescriptors.h index 64b4ae23cc59..7be1fd3f5788 100644 --- a/include/llvm/Analysis/IVDescriptors.h +++ b/include/llvm/Analysis/IVDescriptors.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/IVDescriptors.h - IndVar Descriptors -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -90,10 +89,12 @@ public: RecurrenceDescriptor() = default; RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K, - MinMaxRecurrenceKind MK, Instruction *UAI, Type *RT, - bool Signed, SmallPtrSetImpl<Instruction *> &CI) - : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK), - UnsafeAlgebraInst(UAI), RecurrenceType(RT), IsSigned(Signed) { + 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()); } @@ -199,6 +200,8 @@ public: MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; } + FastMathFlags getFastMathFlags() { return FMF; } + TrackingVH<Value> getRecurrenceStartValue() { return StartValue; } Instruction *getLoopExitInstr() { return LoopExitInstr; } @@ -238,6 +241,9 @@ private: 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. @@ -309,12 +315,16 @@ public: /// not have the "fast-math" property. Such operation requires a relaxed FP /// mode. bool hasUnsafeAlgebra() { - return InductionBinOp && !cast<FPMathOperator>(InductionBinOp)->isFast(); + 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; diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index 035b974c5c1d..f8ea3bcca229 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/IndirectCallPromotionAnalysis.h b/include/llvm/Analysis/IndirectCallPromotionAnalysis.h index be3a28424cf5..8a05e913a910 100644 --- a/include/llvm/Analysis/IndirectCallPromotionAnalysis.h +++ b/include/llvm/Analysis/IndirectCallPromotionAnalysis.h @@ -1,9 +1,8 @@ //===- IndirectCallPromotionAnalysis.h - Indirect call analysis -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/IndirectCallVisitor.h b/include/llvm/Analysis/IndirectCallVisitor.h index d00cf63368f1..1d1f3f4cc5c0 100644 --- a/include/llvm/Analysis/IndirectCallVisitor.h +++ b/include/llvm/Analysis/IndirectCallVisitor.h @@ -1,9 +1,8 @@ //===-- IndirectCallVisitor.h - indirect call visitor ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 4c270354b0c4..611c9de24e47 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -1,9 +1,8 @@ //===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,7 +22,7 @@ namespace llvm { class AssumptionCacheTracker; class BlockFrequencyInfo; -class CallSite; +class CallBase; class DataLayout; class Function; class ProfileSummaryInfo; @@ -68,10 +67,10 @@ class InlineCost { }; /// The estimated cost of inlining this callsite. - const int Cost; + int Cost; /// The adjusted threshold against which this cost was computed. - const int Threshold; + int Threshold; /// Must be set for Always and Never instances. const char *Reason = nullptr; @@ -200,7 +199,7 @@ InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel); /// Return the cost associated with a callsite, including parameter passing /// and the call/return instruction. -int getCallsiteCost(CallSite CS, const DataLayout &DL); +int getCallsiteCost(CallBase &Call, const DataLayout &DL); /// Get an InlineCost object representing the cost of inlining this /// callsite. @@ -214,7 +213,7 @@ int getCallsiteCost(CallSite CS, const DataLayout &DL); /// Also note that calling this function *dynamically* computes the cost of /// inlining the callsite. It is an expensive, heavyweight call. InlineCost getInlineCost( - CallSite CS, const InlineParams &Params, TargetTransformInfo &CalleeTTI, + CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, std::function<AssumptionCache &(Function &)> &GetAssumptionCache, Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE = nullptr); @@ -225,14 +224,14 @@ InlineCost getInlineCost( /// parameter in all other respects. // InlineCost -getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params, +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. -bool isInlineViable(Function &Callee); +InlineResult isInlineViable(Function &Callee); } #endif diff --git a/include/llvm/Analysis/InstructionPrecedenceTracking.h b/include/llvm/Analysis/InstructionPrecedenceTracking.h index 073e6ec3b7f6..3c3981066a49 100644 --- a/include/llvm/Analysis/InstructionPrecedenceTracking.h +++ b/include/llvm/Analysis/InstructionPrecedenceTracking.h @@ -1,9 +1,8 @@ //===-- InstructionPrecedenceTracking.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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" @@ -93,7 +92,7 @@ public: /// 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) preceeding it. For example, this check is required if we +/// 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: diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 6662e91037e1..054ffca7215e 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -1,9 +1,8 @@ //===-- InstructionSimplify.h - Fold instrs into simpler forms --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -41,8 +40,8 @@ class Function; template <typename T, typename... TArgs> class AnalysisManager; template <class T> class ArrayRef; class AssumptionCache; +class CallBase; class DominatorTree; -class ImmutableCallSite; class DataLayout; class FastMathFlags; struct LoopStandardAnalysisResults; @@ -118,6 +117,10 @@ struct SimplifyQuery { // 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); @@ -228,6 +231,15 @@ Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask, 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 an FP UnaryOperator, fold the result or return null. +/// In contrast to SimplifyUnOp, try to use FastMathFlag when folding the +/// result. In case we don't need FastMathFlags, simply fall to SimplifyUnOp. +Value *SimplifyFPUnOp(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); @@ -239,16 +251,7 @@ Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS, FastMathFlags FMF, const SimplifyQuery &Q); /// Given a callsite, fold the result or return null. -Value *SimplifyCall(ImmutableCallSite CS, const SimplifyQuery &Q); - -/// Given a function and iterators over arguments, fold the result or return -/// null. -Value *SimplifyCall(ImmutableCallSite CS, Value *V, User::op_iterator ArgBegin, - User::op_iterator ArgEnd, const SimplifyQuery &Q); - -/// Given a function and set of arguments, fold the result or return null. -Value *SimplifyCall(ImmutableCallSite CS, Value *V, ArrayRef<Value *> Args, - const SimplifyQuery &Q); +Value *SimplifyCall(CallBase *Call, const SimplifyQuery &Q); /// See if we can compute a simplified version of this instruction. If not, /// return null. diff --git a/include/llvm/Analysis/Interval.h b/include/llvm/Analysis/Interval.h index f3714dddedd5..5c9a4535bc7f 100644 --- a/include/llvm/Analysis/Interval.h +++ b/include/llvm/Analysis/Interval.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 6ffcae592e98..efaaf9715b3d 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -1,9 +1,8 @@ //===- IntervalIterator.h - Interval Iterator Declaration -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/IntervalPartition.h b/include/llvm/Analysis/IntervalPartition.h index 50335165711f..5b127c25a2b8 100644 --- a/include/llvm/Analysis/IntervalPartition.h +++ b/include/llvm/Analysis/IntervalPartition.h @@ -1,9 +1,8 @@ //===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h index 3083db75b81c..7c826780c318 100644 --- a/include/llvm/Analysis/IteratedDominanceFrontier.h +++ b/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -1,101 +1,89 @@ //===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// Compute iterated dominance frontiers using a linear time algorithm. -/// -/// The algorithm used here is based on: -/// -/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes. -/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of -/// Programming Languages -/// POPL '95. ACM, New York, NY, 62-73. -/// -/// It has been modified to not explicitly use the DJ graph data structure and -/// to directly compute pruned SSA using per-variable liveness 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_IDF_H #define LLVM_ANALYSIS_IDF_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFGDiff.h" -#include "llvm/IR/Dominators.h" +#include "llvm/Support/GenericIteratedDominanceFrontier.h" namespace llvm { -/// Determine the iterated dominance frontier, given a set of defining -/// blocks, and optionally, a set of live-in blocks. -/// -/// In turn, the results can be used to place phi nodes. -/// -/// This algorithm is a linear time computation of Iterated Dominance Frontiers, -/// pruned using the live-in set. -/// By default, liveness is not used to prune the IDF computation. -/// The template parameters should be either BasicBlock* or Inverse<BasicBlock -/// *>, depending on if you want the forward or reverse IDF. -template <class NodeTy, bool IsPostDom> -class IDFCalculator { - public: - IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT) - : DT(DT), GD(nullptr), useLiveIn(false) {} - - IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT, - const GraphDiff<BasicBlock *, IsPostDom> *GD) - : DT(DT), GD(GD), useLiveIn(false) {} - - /// Give the IDF calculator the set of blocks in which the value is - /// defined. This is equivalent to the set of starting blocks it should be - /// calculating the IDF for (though later gets pruned based on liveness). - /// - /// Note: This set *must* live for the entire lifetime of the IDF calculator. - void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { - DefBlocks = &Blocks; - } - - /// Give the IDF calculator the set of blocks in which the value is - /// live on entry to the block. This is used to prune the IDF calculation to - /// not include blocks where any phi insertion would be dead. - /// - /// Note: This set *must* live for the entire lifetime of the IDF calculator. - - void setLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { - LiveInBlocks = &Blocks; - useLiveIn = true; - } +class BasicBlock; - /// Reset the live-in block set to be empty, and tell the IDF - /// calculator to not use liveness anymore. - void resetLiveInBlocks() { - LiveInBlocks = nullptr; - useLiveIn = false; +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); } - /// Calculate iterated dominance frontiers - /// - /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in - /// the file-level comment. It performs DF->IDF pruning using the live-in - /// set, to avoid computing the IDF for blocks where an inserted PHI node - /// would be dead. - void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks); - -private: - DominatorTreeBase<BasicBlock, IsPostDom> &DT; - const GraphDiff<BasicBlock *, IsPostDom> *GD; - bool useLiveIn; - const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks; - const SmallPtrSetImpl<BasicBlock *> *DefBlocks; + ChildrenTy get(const NodeRef &N); + + const GraphDiff<BasicBlock *, IsPostDom> *GD = nullptr; }; -typedef IDFCalculator<BasicBlock *, false> ForwardIDFCalculator; -typedef IDFCalculator<Inverse<BasicBlock *>, true> ReverseIDFCalculator; + +} // 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/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/include/llvm/Analysis/LazyBlockFrequencyInfo.h index d1afb63d7e08..0e7dc943bacf 100644 --- a/include/llvm/Analysis/LazyBlockFrequencyInfo.h +++ b/include/llvm/Analysis/LazyBlockFrequencyInfo.h @@ -1,9 +1,8 @@ //===- LazyBlockFrequencyInfo.h - Lazy Block Frequency Analysis -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/include/llvm/Analysis/LazyBranchProbabilityInfo.h index 9e6bcfedcbb9..cae0778cd16d 100644 --- a/include/llvm/Analysis/LazyBranchProbabilityInfo.h +++ b/include/llvm/Analysis/LazyBranchProbabilityInfo.h @@ -1,9 +1,8 @@ //===- LazyBranchProbabilityInfo.h - Lazy Branch Probability ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index d1ec6a9dcc55..2d83929211e2 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -1,9 +1,8 @@ //===- LazyCallGraph.h - Analysis of a Module's call graph ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -39,6 +38,7 @@ #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" @@ -1083,12 +1083,26 @@ public: 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)) { - // 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 (Visited.insert(BA->getFunction()).second) - Worklist.push_back(BA->getFunction()); + // 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; } diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 1a4fdb591427..570a5044f6f8 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -1,9 +1,8 @@ //===- LazyValueInfo.h - Value constraint analysis --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/LegacyDivergenceAnalysis.h b/include/llvm/Analysis/LegacyDivergenceAnalysis.h index fc426ad7fb64..0a338b816640 100644 --- a/include/llvm/Analysis/LegacyDivergenceAnalysis.h +++ b/include/llvm/Analysis/LegacyDivergenceAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LegacyDivergenceAnalysis.h - KernelDivergence Analysis -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/Lint.h b/include/llvm/Analysis/Lint.h index db5919fd91c7..0fea81e215c9 100644 --- a/include/llvm/Analysis/Lint.h +++ b/include/llvm/Analysis/Lint.h @@ -1,9 +1,8 @@ //===-- llvm/Analysis/Lint.h - LLVM IR Lint ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index f110c28bfc6d..5df6bb02308d 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -1,9 +1,8 @@ //===- Loads.h - Local load analysis --------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -26,7 +25,8 @@ class MDNode; /// Return true if this is always a dereferenceable pointer. If the context /// instruction is specified perform context-sensitive analysis and return true /// if the pointer is dereferenceable at the specified instruction. -bool isDereferenceablePointer(const Value *V, const DataLayout &DL, +bool isDereferenceablePointer(const Value *V, Type *Ty, + const DataLayout &DL, const Instruction *CtxI = nullptr, const DominatorTree *DT = nullptr); @@ -34,8 +34,8 @@ bool isDereferenceablePointer(const Value *V, const DataLayout &DL, /// greater or equal than requested. If the context instruction is specified /// performs context-sensitive analysis and returns true if the pointer is /// dereferenceable at the specified instruction. -bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, - const DataLayout &DL, +bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, + unsigned Align, const DataLayout &DL, const Instruction *CtxI = nullptr, const DominatorTree *DT = nullptr); @@ -56,7 +56,20 @@ bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, /// If it is not obviously safe to load from the specified pointer, we do a /// quick local scan of the basic block containing ScanFrom, to determine if /// the address is already accessed. -bool isSafeToLoadUnconditionally(Value *V, unsigned Align, +bool isSafeToLoadUnconditionally(Value *V, unsigned Align, APInt &Size, + const DataLayout &DL, + Instruction *ScanFrom = 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, Type *Ty, unsigned Align, const DataLayout &DL, Instruction *ScanFrom = nullptr, const DominatorTree *DT = nullptr); diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 4ed00e207753..9e9aaa32c64f 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -523,6 +522,11 @@ public: /// 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(); } @@ -643,6 +647,7 @@ private: /// Cache the result of analyzeLoop. bool CanVecMem; + bool HasConvergentOp; /// Indicator that there are non vectorizable stores to a uniform address. bool HasDependenceInvolvingLoopInvariantAddress; diff --git a/include/llvm/Analysis/LoopAnalysisManager.h b/include/llvm/Analysis/LoopAnalysisManager.h index 00e562c4f31f..368a810cfa67 100644 --- a/include/llvm/Analysis/LoopAnalysisManager.h +++ b/include/llvm/Analysis/LoopAnalysisManager.h @@ -1,9 +1,8 @@ //===- LoopAnalysisManager.h - Loop analysis management ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -62,9 +61,6 @@ struct LoopStandardAnalysisResults { MemorySSA *MSSA; }; -/// Enables memory ssa as a dependency for loop passes. -extern cl::opt<bool> EnableMSSALoopDependency; - /// Extern template declaration for the analysis set for this IR unit. extern template class AllAnalysesOn<Loop>; diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 72873546a068..584eb3a8c854 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -55,8 +54,11 @@ 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; @@ -199,9 +201,10 @@ public: } /// True if terminator in the block can branch to another block that is - /// outside of the current loop. + /// 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; @@ -267,16 +270,20 @@ public: /// Return all unique successor blocks of this loop. /// These are the blocks _outside of the current loop_ which are branched to. - /// This assumes that loop exits are in canonical form, i.e. all exits are - /// dedicated exits. 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<const BlockT *, const BlockT *> Edge; + typedef std::pair<BlockT *, BlockT *> Edge; /// Return all pairs of (_inside_block_,_outside_block_). void getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const; @@ -309,6 +316,40 @@ public: 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 // @@ -471,7 +512,7 @@ public: public: LocRange() {} - LocRange(DebugLoc Start) : Start(std::move(Start)), End(std::move(Start)) {} + LocRange(DebugLoc Start) : Start(Start), End(Start) {} LocRange(DebugLoc Start, DebugLoc End) : Start(std::move(Start)), End(std::move(End)) {} @@ -499,7 +540,8 @@ public: /// 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) const; + 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. @@ -511,7 +553,8 @@ public: /// If null, the terminator of the loop preheader is used. /// bool makeLoopInvariant(Instruction *I, bool &Changed, - Instruction *InsertPt = nullptr) const; + 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 @@ -522,6 +565,170 @@ public: /// 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 loop bounds and induction variable, and + /// check if a given phinode is an auxiliary induction variable, as well as + /// checking 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 + /// - 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 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; @@ -1015,6 +1222,26 @@ MDNode *findOptionMDForLoop(const Loop *TheLoop, StringRef Name); /// 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/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 2b807919fedf..4c33dac9e21e 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -96,49 +95,36 @@ bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const { 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 { - typedef GraphTraits<BlockT *> BlockTraits; - typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits; - - assert(hasDedicatedExits() && - "getUniqueExitBlocks assumes the loop has canonical form exits!"); - - SmallVector<BlockT *, 32> SwitchExitBlocks; - for (BlockT *Block : this->blocks()) { - SwitchExitBlocks.clear(); - for (BlockT *Successor : children<BlockT *>(Block)) { - // If block is inside the loop then it is not an exit block. - if (contains(Successor)) - continue; - - BlockT *FirstPred = *InvBlockTraits::child_begin(Successor); - - // If current basic block is this exit block's first predecessor then only - // insert exit block in to the output ExitBlocks vector. This ensures that - // same exit block is not inserted twice into ExitBlocks vector. - if (Block != FirstPred) - continue; - - // If a terminator has more then two successors, for example SwitchInst, - // then it is possible that there are multiple edges from current block to - // one exit block. - if (std::distance(BlockTraits::child_begin(Block), - BlockTraits::child_end(Block)) <= 2) { - ExitBlocks.push_back(Successor); - continue; - } + getUniqueExitBlocksHelper(this, ExitBlocks, + [](const BlockT *BB) { return true; }); +} - // In case of multiple edges from current block to exit block, collect - // only one edge in ExitBlocks. Use switchExitBlocks to keep track of - // duplicate edges. - if (!is_contained(SwitchExitBlocks, Successor)) { - SwitchExitBlocks.push_back(Successor); - ExitBlocks.push_back(Successor); - } - } - } +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> @@ -588,16 +574,9 @@ SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() { // FIXME: If we change the order of LoopInfo we will want to remove the // reverse here. for (LoopT *RootL : reverse(*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 append them in reverse order. - PreOrderWorklist.append(L->rbegin(), L->rend()); - PreOrderLoops.push_back(L); - } while (!PreOrderWorklist.empty()); + auto PreOrderLoopsInRootL = RootL->getLoopsInPreorder(); + PreOrderLoops.append(PreOrderLoopsInRootL.begin(), + PreOrderLoopsInRootL.end()); } return PreOrderLoops; diff --git a/include/llvm/Analysis/LoopIterator.h b/include/llvm/Analysis/LoopIterator.h index 91c54b23029b..fa4da4283f55 100644 --- a/include/llvm/Analysis/LoopIterator.h +++ b/include/llvm/Analysis/LoopIterator.h @@ -1,9 +1,8 @@ //===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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. diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 86cfecd9df11..9215ab34ec6d 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -1,9 +1,8 @@ //===- LoopPass.h - LoopPass class ----------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/LoopUnrollAnalyzer.h b/include/llvm/Analysis/LoopUnrollAnalyzer.h index f45bf0b223b8..5f332e3cac16 100644 --- a/include/llvm/Analysis/LoopUnrollAnalyzer.h +++ b/include/llvm/Analysis/LoopUnrollAnalyzer.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LoopUnrollAnalyzer.h - Loop Unroll Analyzer-*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 5418128f16ef..49f9e58ffad7 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -1,9 +1,8 @@ //==- llvm/Analysis/MemoryBuiltins.h - Calls to memory builtins --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #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" @@ -84,6 +84,15 @@ bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, 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); + //===----------------------------------------------------------------------===// // malloc Call Utility Functions. // @@ -135,6 +144,9 @@ inline CallInst *extractCallocCall(Value *I, const TargetLibraryInfo *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); @@ -178,14 +190,13 @@ 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. -ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize, - const DataLayout &DL, - const TargetLibraryInfo *TLI, - bool MustSucceed); +/// 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>; @@ -252,7 +263,7 @@ using SizeOffsetEvalType = std::pair<Value *, Value *>; /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { - using BuilderTy = IRBuilder<TargetFolder>; + using BuilderTy = IRBuilder<TargetFolder, IRBuilderCallbackInserter>; using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>; using CacheMapTy = DenseMap<const Value *, WeakEvalType>; using PtrSetTy = SmallPtrSet<const Value *, 8>; @@ -265,17 +276,18 @@ class ObjectSizeOffsetEvaluator Value *Zero; CacheMapTy CacheMap; PtrSetTy SeenVals; - bool RoundToAlign; - - SizeOffsetEvalType unknown() { - return std::make_pair(nullptr, nullptr); - } + 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, bool RoundToAlign = false); + LLVMContext &Context, ObjectSizeOpts EvalOpts = {}); SizeOffsetEvalType compute(Value *V); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 958d4fe4b832..e2669c2fa601 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -382,7 +381,8 @@ public: /// /// See the class comment for more details. It is illegal to call this on /// non-memory instructions. - MemDepResult getDependency(Instruction *QueryInst); + 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. @@ -448,14 +448,14 @@ public: BasicBlock::iterator ScanIt, BasicBlock *BB, Instruction *QueryInst = nullptr, - unsigned *Limit = nullptr); - - MemDepResult getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, - bool isLoad, - BasicBlock::iterator ScanIt, - BasicBlock *BB, - Instruction *QueryInst, - unsigned *Limit = 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 diff --git a/include/llvm/Analysis/MemoryLocation.h b/include/llvm/Analysis/MemoryLocation.h index fca18c1b5999..7c26353e618b 100644 --- a/include/llvm/Analysis/MemoryLocation.h +++ b/include/llvm/Analysis/MemoryLocation.h @@ -1,9 +1,8 @@ //===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h index 17e2d0c73977..b7730be75354 100644 --- a/include/llvm/Analysis/MemorySSA.h +++ b/include/llvm/Analysis/MemorySSA.h @@ -1,9 +1,8 @@ //===- MemorySSA.h - Build Memory SSA ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -105,6 +104,9 @@ namespace llvm { +/// Enables memory ssa as a dependency for loop passes. +extern cl::opt<bool> EnableMSSALoopDependency; + class Function; class Instruction; class MemoryAccess; @@ -701,6 +703,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess) 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(); @@ -776,9 +783,6 @@ public: /// all uses, uses appear in the right places). This is used by unit tests. void verifyMemorySSA() const; - /// Check clobber sanity for an access. - void checkClobberSanityAccess(const MemoryAccess *MA) const; - /// Used in various insertion functions to specify whether we are talking /// about the beginning or end of a block. enum InsertionPlace { Beginning, End }; @@ -793,7 +797,6 @@ protected: void verifyDomination(Function &F) const; void verifyOrdering(Function &F) const; void verifyDominationNumbers(const Function &F) const; - void verifyClobberSanity(const Function &F) const; // This is used by the use optimizer and updater. AccessList *getWritableBlockAccesses(const BasicBlock *BB) const { @@ -830,13 +833,13 @@ protected: const MemoryUseOrDef *Template = nullptr); private: - class ClobberWalkerBase; - class CachingWalker; - class SkipSelfWalker; + template <class AliasAnalysisType> class ClobberWalkerBase; + template <class AliasAnalysisType> class CachingWalker; + template <class AliasAnalysisType> class SkipSelfWalker; class OptimizeUses; - CachingWalker *getWalkerImpl(); - void buildMemorySSA(); + CachingWalker<AliasAnalysis> *getWalkerImpl(); + void buildMemorySSA(BatchAAResults &BAA); void optimizeUses(); void prepareForMoveTo(MemoryAccess *, BasicBlock *); @@ -850,7 +853,8 @@ private: void markUnreachableAsLiveOnEntry(BasicBlock *BB); bool dominatesUse(const MemoryAccess *, const MemoryAccess *) const; MemoryPhi *createMemoryPhi(BasicBlock *BB); - MemoryUseOrDef *createNewAccess(Instruction *, + template <typename AliasAnalysisType> + MemoryUseOrDef *createNewAccess(Instruction *, AliasAnalysisType *, const MemoryUseOrDef *Template = nullptr); MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace); void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &); @@ -886,9 +890,9 @@ private: mutable DenseMap<const MemoryAccess *, unsigned long> BlockNumbering; // Memory SSA building info - std::unique_ptr<ClobberWalkerBase> WalkerBase; - std::unique_ptr<CachingWalker> Walker; - std::unique_ptr<SkipSelfWalker> SkipWalker; + std::unique_ptr<ClobberWalkerBase<AliasAnalysis>> WalkerBase; + std::unique_ptr<CachingWalker<AliasAnalysis>> Walker; + std::unique_ptr<SkipSelfWalker<AliasAnalysis>> SkipWalker; unsigned NextID; }; @@ -932,6 +936,9 @@ public: 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); @@ -1044,8 +1051,6 @@ public: /// the walker it uses or returns. virtual void invalidateInfo(MemoryAccess *) {} - virtual void verify(const MemorySSA *MSSA) { assert(MSSA == this->MSSA); } - protected: friend class MemorySSA; // For updating MSSA pointer in MemorySSA move // constructor. @@ -1101,15 +1106,15 @@ public: 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 (MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) + if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) return MP->getIncomingValue(ArgNo); return cast<MemoryUseOrDef>(Access)->getDefiningAccess(); } using BaseT::operator++; - memoryaccess_def_iterator &operator++() { + memoryaccess_def_iterator_base &operator++() { assert(Access && "Hit end of iterator"); - if (MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) { + if (const MemoryPhi *MP = dyn_cast<MemoryPhi>(Access)) { if (++ArgNo >= MP->getNumIncomingValues()) { ArgNo = 0; Access = nullptr; diff --git a/include/llvm/Analysis/MemorySSAUpdater.h b/include/llvm/Analysis/MemorySSAUpdater.h index 169d5bd9fa8b..d4d8040c1ff6 100644 --- a/include/llvm/Analysis/MemorySSAUpdater.h +++ b/include/llvm/Analysis/MemorySSAUpdater.h @@ -1,9 +1,8 @@ //===- MemorySSAUpdater.h - Memory SSA Updater-------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -32,6 +31,7 @@ #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" @@ -106,7 +106,12 @@ public: /// 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(BasicBlock *From, BasicBlock *To); + 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 @@ -222,14 +227,14 @@ public: /// 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 *); + 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) { + void removeMemoryAccess(const Instruction *I, bool OptimizePhis = false) { if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) - removeMemoryAccess(MA); + removeMemoryAccess(MA, OptimizePhis); } /// Remove all MemoryAcceses in a set of BasicBlocks about to be deleted. @@ -239,7 +244,17 @@ public: /// 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 SmallPtrSetImpl<BasicBlock *> &DeadBlocks); + 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; } @@ -262,6 +277,7 @@ private: MemoryAccess *recursePhi(MemoryAccess *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 @@ -272,8 +288,14 @@ private: // 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); + const ValueToValueMapTy &VMap, PhiToDefMap &MPhiMap, + bool CloneWasSimplified = false); template <typename Iter> void privateUpdateExitBlocksForClonedLoop(ArrayRef<BasicBlock *> ExitBlocks, Iter ValuesBegin, Iter ValuesEnd, diff --git a/include/llvm/Analysis/ModuleSummaryAnalysis.h b/include/llvm/Analysis/ModuleSummaryAnalysis.h index 9af7859cb4bf..1572a49e3384 100644 --- a/include/llvm/Analysis/ModuleSummaryAnalysis.h +++ b/include/llvm/Analysis/ModuleSummaryAnalysis.h @@ -1,9 +1,8 @@ //===- ModuleSummaryAnalysis.h - Module summary index builder ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/MustExecute.h b/include/llvm/Analysis/MustExecute.h index ad3222c17e62..3ef539c89d97 100644 --- a/include/llvm/Analysis/MustExecute.h +++ b/include/llvm/Analysis/MustExecute.h @@ -1,9 +1,8 @@ //===- MustExecute.h - Is an instruction known to execute--------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/include/llvm/Analysis/ObjCARCAliasAnalysis.h index 58a67042ea2d..b4f4e5f29768 100644 --- a/include/llvm/Analysis/ObjCARCAliasAnalysis.h +++ b/include/llvm/Analysis/ObjCARCAliasAnalysis.h @@ -1,9 +1,8 @@ //===- ObjCARCAliasAnalysis.h - ObjC ARC Alias Analysis ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -53,14 +52,17 @@ public: return false; } - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); - bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal); + 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); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); }; /// Analysis pass providing a never-invalidated alias analysis result. diff --git a/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/include/llvm/Analysis/ObjCARCAnalysisUtils.h index 1f497fab35da..522abd756c9f 100644 --- a/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ b/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -1,9 +1,8 @@ //===- ObjCARCAnalysisUtils.h - ObjC ARC Analysis Utilities -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Analysis/ObjCARCInstKind.h b/include/llvm/Analysis/ObjCARCInstKind.h index 018ea1f851be..dc6093a7b86c 100644 --- a/include/llvm/Analysis/ObjCARCInstKind.h +++ b/include/llvm/Analysis/ObjCARCInstKind.h @@ -1,9 +1,8 @@ //===- ObjCARCInstKind.h - ARC instruction equivalence classes --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -75,6 +74,10 @@ bool IsForwarding(ARCInstKind Class); /// 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); diff --git a/include/llvm/Analysis/OptimizationRemarkEmitter.h b/include/llvm/Analysis/OptimizationRemarkEmitter.h index fa838696e2f8..7b8404404ce7 100644 --- a/include/llvm/Analysis/OptimizationRemarkEmitter.h +++ b/include/llvm/Analysis/OptimizationRemarkEmitter.h @@ -1,9 +1,8 @@ //===- OptimizationRemarkEmitter.h - Optimization Diagnostic ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -78,7 +77,7 @@ public: // 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().getDiagnosticsOutputFile() || + if (F->getContext().getRemarkStreamer() || F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { auto R = RemarkBuilder(); emit((DiagnosticInfoOptimizationBase &)R); @@ -93,7 +92,7 @@ public: /// provide more context so that non-trivial false positives can be quickly /// detected by the user. bool allowExtraAnalysis(StringRef PassName) const { - return (F->getContext().getDiagnosticsOutputFile() || + return (F->getContext().getRemarkStreamer() || F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); } diff --git a/include/llvm/Analysis/OrderedBasicBlock.h b/include/llvm/Analysis/OrderedBasicBlock.h index 0776aa626005..ae64c0189f5e 100644 --- a/include/llvm/Analysis/OrderedBasicBlock.h +++ b/include/llvm/Analysis/OrderedBasicBlock.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -60,6 +59,14 @@ public: /// 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 diff --git a/include/llvm/Analysis/OrderedInstructions.h b/include/llvm/Analysis/OrderedInstructions.h index 7e3850b87c57..967b146b52de 100644 --- a/include/llvm/Analysis/OrderedInstructions.h +++ b/include/llvm/Analysis/OrderedInstructions.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils/OrderedInstructions.h -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 0a335b6be6c7..54a07f053478 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -1,9 +1,8 @@ //===- PHITransAddr.h - PHI Translation for Addresses -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 081dd5000835..d9c97dff8c6e 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -1,9 +1,8 @@ //===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/PhiValues.h b/include/llvm/Analysis/PhiValues.h index 76204ac1bc6c..124fa2191694 100644 --- a/include/llvm/Analysis/PhiValues.h +++ b/include/llvm/Analysis/PhiValues.h @@ -1,9 +1,8 @@ //===- PhiValues.h - Phi Value Analysis -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index f2dc8d135d71..87d2e0318d0a 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -1,9 +1,8 @@ //=- llvm/Analysis/PostDominators.h - Post Dominator Calculation --*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/ProfileSummaryInfo.h b/include/llvm/Analysis/ProfileSummaryInfo.h index 3aef4be72d71..f309d344b8d1 100644 --- a/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/include/llvm/Analysis/ProfileSummaryInfo.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -74,6 +73,12 @@ public: 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 @@ -87,7 +92,8 @@ public: /// Returns the profile count for \p CallInst. Optional<uint64_t> getProfileCount(const Instruction *CallInst, - BlockFrequencyInfo *BFI); + BlockFrequencyInfo *BFI, + bool AllowSynthetic = false); /// Returns true if the working set size of the code is considered huge. bool hasHugeWorkingSetSize(); /// Returns true if \p F has hot function entry. diff --git a/include/llvm/Analysis/PtrUseVisitor.h b/include/llvm/Analysis/PtrUseVisitor.h index b34b25c75040..fbf04c841d30 100644 --- a/include/llvm/Analysis/PtrUseVisitor.h +++ b/include/llvm/Analysis/PtrUseVisitor.h @@ -1,9 +1,8 @@ //===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -257,6 +256,10 @@ protected: enqueueUsers(BC); } + void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) { + enqueueUsers(ASC); + } + void visitPtrToIntInst(PtrToIntInst &I) { PI.setEscaped(&I); } diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 27f6cc197927..8bcc3e851200 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -1,9 +1,8 @@ //===- RegionInfo.h - SESE region analysis ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index 5904214aa925..c59c09dd2095 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -1,9 +1,8 @@ //===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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. diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 4fd92fcde20b..72bc5bbcb506 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -1,9 +1,8 @@ //===- RegionIterator.h - Iterators to iteratate over Regions ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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. diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index b3da91c89cbd..5b1864a37629 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -1,9 +1,8 @@ //===- RegionPass.h - RegionPass class --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/RegionPrinter.h b/include/llvm/Analysis/RegionPrinter.h index e132eaea5674..154ac35c486a 100644 --- a/include/llvm/Analysis/RegionPrinter.h +++ b/include/llvm/Analysis/RegionPrinter.h @@ -1,9 +1,8 @@ //===-- RegionPrinter.h - Region printer external interface -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 8f4200b07e5c..0bd98ef37e7a 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -85,6 +84,9 @@ class SCEV : public FoldingSetNode { 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; @@ -116,8 +118,9 @@ public: NoWrapMask = (1 << 3) - 1 }; - explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) - : FastID(ID), SCEVType(SCEVTy) {} + 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; @@ -138,6 +141,19 @@ public: /// 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; @@ -521,7 +537,7 @@ public: 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); + 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); @@ -582,6 +598,8 @@ public: /// \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); @@ -619,11 +637,13 @@ public: /// 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); + 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); + 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 @@ -726,9 +746,12 @@ public: unsigned getSmallConstantTripMultiple(const Loop *L, BasicBlock *ExitingBlock); - /// Get the expression for the number of loop iterations for which this loop - /// is guaranteed not to exit via ExitingBlock. Otherwise return - /// SCEVCouldNotCompute. + /// 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); /// If the specified loop has a predictable backedge-taken count, return it, @@ -764,6 +787,13 @@ public: /// 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 @@ -1273,7 +1303,7 @@ private: using EdgeExitInfo = std::pair<BasicBlock *, ExitLimit>; /// Initialize BackedgeTakenInfo from a list of exact exit counts. - BackedgeTakenInfo(SmallVectorImpl<EdgeExitInfo> &&ExitCounts, bool Complete, + BackedgeTakenInfo(ArrayRef<EdgeExitInfo> ExitCounts, bool Complete, const SCEV *MaxCount, bool MaxOrZero); /// Test whether this BackedgeTakenInfo contains any computed information, @@ -1826,15 +1856,15 @@ private: bool NoWrap); /// Get add expr already created or create a new one. - const SCEV *getOrCreateAddExpr(SmallVectorImpl<const SCEV *> &Ops, + const SCEV *getOrCreateAddExpr(ArrayRef<const SCEV *> Ops, SCEV::NoWrapFlags Flags); /// Get mul expr already created or create a new one. - const SCEV *getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops, + const SCEV *getOrCreateMulExpr(ArrayRef<const SCEV *> Ops, SCEV::NoWrapFlags Flags); // Get addrec expr already created or create a new one. - const SCEV *getOrCreateAddRecExpr(SmallVectorImpl<const SCEV *> &Ops, + 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. @@ -1853,6 +1883,16 @@ private: /// 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; diff --git a/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h b/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h index 329be51e5eac..98d53237d4a0 100644 --- a/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h +++ b/include/llvm/Analysis/ScalarEvolutionAliasAnalysis.h @@ -1,9 +1,8 @@ //===- ScalarEvolutionAliasAnalysis.h - SCEV-based AA -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -31,7 +30,8 @@ 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); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); private: Value *GetBaseValue(const SCEV *S); diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 58d42680d6bc..a519f93216b3 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -1,9 +1,8 @@ //===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -316,8 +315,10 @@ namespace llvm { SmallPtrSetImpl<const SCEV *> &Processed); /// Insert the specified binary operator, doing a small amount of work to - /// avoid inserting an obviously redundant operation. - Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); + /// 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 @@ -368,6 +369,10 @@ namespace llvm { Value *visitUMaxExpr(const SCEVUMaxExpr *S); + Value *visitSMinExpr(const SCEVSMinExpr *S); + + Value *visitUMinExpr(const SCEVUMinExpr *S); + Value *visitUnknown(const SCEVUnknown *S) { return S->getValue(); } diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 42e76094eb2b..d008af7b7e6f 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -40,7 +39,7 @@ class Type; // These should be ordered in terms of increasing complexity to make the // folders simpler. scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, - scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, + scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, scUMinExpr, scSMinExpr, scUnknown, scCouldNotCompute }; @@ -51,7 +50,7 @@ class Type; ConstantInt *V; SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) : - SCEV(ID, scConstant), V(v) {} + SCEV(ID, scConstant, 1), V(v) {} public: ConstantInt *getValue() const { return V; } @@ -65,6 +64,13 @@ class Type; } }; + 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: @@ -142,9 +148,10 @@ class Type; const SCEV *const *Operands; size_t NumOperands; - SCEVNAryExpr(const FoldingSetNodeIDRef ID, - enum SCEVTypes T, const SCEV *const *O, size_t N) - : SCEV(ID, T), Operands(O), NumOperands(N) {} + 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; } @@ -183,10 +190,9 @@ class Type; /// 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 || + return S->getSCEVType() == scAddExpr || S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || S->getSCEVType() == scUMaxExpr || + S->getSCEVType() == scSMinExpr || S->getSCEVType() == scUMinExpr || S->getSCEVType() == scAddRecExpr; } }; @@ -201,10 +207,9 @@ class Type; 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; + 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. @@ -258,7 +263,8 @@ class Type; const SCEV *RHS; SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs) - : SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {} + : SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})), LHS(lhs), + RHS(rhs) {} public: const SCEV *getLHS() const { return LHS; } @@ -358,18 +364,54 @@ class Type; } }; - /// This class represents a signed maximum selection. - class SCEVSMaxExpr : public SCEVCommutativeExpr { + /// This node is the base class min/max selections. + class SCEVMinMaxExpr : public SCEVCommutativeExpr { friend class ScalarEvolution; - SCEVSMaxExpr(const FoldingSetNodeIDRef ID, - const SCEV *const *O, size_t N) - : SCEVCommutativeExpr(ID, scSMaxExpr, O, N) { - // Max never overflows. + 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; @@ -377,15 +419,11 @@ class Type; }; /// This class represents an unsigned maximum selection. - class SCEVUMaxExpr : public SCEVCommutativeExpr { + class SCEVUMaxExpr : public SCEVMinMaxExpr { friend class ScalarEvolution; - SCEVUMaxExpr(const FoldingSetNodeIDRef ID, - const SCEV *const *O, size_t N) - : SCEVCommutativeExpr(ID, scUMaxExpr, O, N) { - // Max never overflows. - setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW)); - } + 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: @@ -394,6 +432,34 @@ class Type; } }; + /// 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. @@ -411,7 +477,7 @@ class Type; SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, ScalarEvolution *se, SCEVUnknown *next) : - SCEV(ID, scUnknown), CallbackVH(V), SE(se), Next(next) {} + SCEV(ID, scUnknown, 1), CallbackVH(V), SE(se), Next(next) {} // Implement CallbackVH. void deleted() override; @@ -466,6 +532,10 @@ class Type; 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: @@ -519,6 +589,8 @@ class Type; case scMulExpr: case scSMaxExpr: case scUMaxExpr: + case scSMinExpr: + case scUMinExpr: case scAddRecExpr: for (const auto *Op : cast<SCEVNAryExpr>(S)->operands()) push(Op); @@ -681,6 +753,26 @@ class Type; 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; } diff --git a/include/llvm/Analysis/ScalarEvolutionNormalization.h b/include/llvm/Analysis/ScalarEvolutionNormalization.h index 51c92121c8f0..1a05594a46ec 100644 --- a/include/llvm/Analysis/ScalarEvolutionNormalization.h +++ b/include/llvm/Analysis/ScalarEvolutionNormalization.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/ScalarEvolutionNormalization.h - See below -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/ScopedNoAliasAA.h b/include/llvm/Analysis/ScopedNoAliasAA.h index 1356c6e9198a..dae733bd2015 100644 --- a/include/llvm/Analysis/ScopedNoAliasAA.h +++ b/include/llvm/Analysis/ScopedNoAliasAA.h @@ -1,9 +1,8 @@ //===- ScopedNoAliasAA.h - Scoped No-Alias Alias Analysis -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -40,9 +39,12 @@ public: return false; } - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); - ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); + 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; diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 02a2e64268b7..fac92e4a25a4 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -1,9 +1,8 @@ //===- SparsePropagation.h - Sparse Conditional Property Propagation ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -330,12 +329,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors( return; } - if (TI.isExceptionalTerminator()) { - Succs.assign(Succs.size(), true); - return; - } - - if (isa<IndirectBrInst>(TI)) { + if (TI.isExceptionalTerminator() || + TI.isIndirectTerminator()) { Succs.assign(Succs.size(), true); return; } diff --git a/include/llvm/Analysis/StackSafetyAnalysis.h b/include/llvm/Analysis/StackSafetyAnalysis.h index 8a151650a34c..f9d8b08ac142 100644 --- a/include/llvm/Analysis/StackSafetyAnalysis.h +++ b/include/llvm/Analysis/StackSafetyAnalysis.h @@ -1,9 +1,8 @@ //===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/SyncDependenceAnalysis.h b/include/llvm/Analysis/SyncDependenceAnalysis.h index df693d9d8e8c..099403b47757 100644 --- a/include/llvm/Analysis/SyncDependenceAnalysis.h +++ b/include/llvm/Analysis/SyncDependenceAnalysis.h @@ -1,9 +1,8 @@ //===- SyncDependenceAnalysis.h - Divergent Branch Dependence -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/SyntheticCountsUtils.h b/include/llvm/Analysis/SyntheticCountsUtils.h index db80bef001e2..b9b4c98bfc35 100644 --- a/include/llvm/Analysis/SyntheticCountsUtils.h +++ b/include/llvm/Analysis/SyntheticCountsUtils.h @@ -1,9 +1,8 @@ //===- SyntheticCountsUtils.h - utilities for count propagation--*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index ae75d3773362..7ab6562be440 100644 --- a/include/llvm/Analysis/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -1,9 +1,8 @@ //====- TargetFolder.h - Constant folding helper ---------------*- C++ -*-====// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -125,6 +124,10 @@ public: return Fold(ConstantExpr::getNot(C)); } + Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { + return Fold(ConstantExpr::get(Opc, C)); + } + //===--------------------------------------------------------------------===// // Memory Instructions //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def index 518a85ee1a01..afed404f04c0 100644 --- a/include/llvm/Analysis/TargetLibraryInfo.def +++ b/include/llvm/Analysis/TargetLibraryInfo.def @@ -1,9 +1,8 @@ //===-- TargetLibraryInfo.def - Library information -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,6 +11,15 @@ // 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) @@ -330,6 +338,10 @@ TLI_DEFINE_STRING_INTERNAL("__logf_finite") /// long double __logl_finite(long double x); TLI_DEFINE_ENUM_INTERNAL(logl_finite) TLI_DEFINE_STRING_INTERNAL("__logl_finite") +/// void *__memccpy_chk(void *dst, const void *src, int c, size_t n, +/// size_t dstsize) +TLI_DEFINE_ENUM_INTERNAL(memccpy_chk) +TLI_DEFINE_STRING_INTERNAL("__memccpy_chk") /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(memcpy_chk) TLI_DEFINE_STRING_INTERNAL("__memcpy_chk") @@ -373,6 +385,23 @@ TLI_DEFINE_STRING_INTERNAL("__sinpi") /// float __sinpif(float x); TLI_DEFINE_ENUM_INTERNAL(sinpif) TLI_DEFINE_STRING_INTERNAL("__sinpif") +/// int __small_fprintf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(small_fprintf) +TLI_DEFINE_STRING_INTERNAL("__small_fprintf") +/// int __small_printf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(small_printf) +TLI_DEFINE_STRING_INTERNAL("__small_printf") +/// int __small_sprintf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(small_sprintf) +TLI_DEFINE_STRING_INTERNAL("__small_sprintf") +/// int __snprintf_chk(char *s, size_t n, int flags, size_t slen, +/// const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(snprintf_chk) +TLI_DEFINE_STRING_INTERNAL("__snprintf_chk") +/// int __sprintf_chk(char *str, int flags, size_t str_len, +/// const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(sprintf_chk) +TLI_DEFINE_STRING_INTERNAL("__sprintf_chk") /// double __sqrt_finite(double x); TLI_DEFINE_ENUM_INTERNAL(sqrt_finite) TLI_DEFINE_STRING_INTERNAL("__sqrt_finite") @@ -388,12 +417,26 @@ TLI_DEFINE_STRING_INTERNAL("__stpcpy_chk") /// char *__stpncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(stpncpy_chk) TLI_DEFINE_STRING_INTERNAL("__stpncpy_chk") +/// char *__strcat_chk(char *s1, const char *s2, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strcat_chk) +TLI_DEFINE_STRING_INTERNAL("__strcat_chk") /// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(strcpy_chk) TLI_DEFINE_STRING_INTERNAL("__strcpy_chk") /// char * __strdup(const char *s); TLI_DEFINE_ENUM_INTERNAL(dunder_strdup) TLI_DEFINE_STRING_INTERNAL("__strdup") +/// size_t __strlcat_chk(char *dst, const char *src, size_t size, +/// size_t dstsize); +TLI_DEFINE_ENUM_INTERNAL(strlcat_chk) +TLI_DEFINE_STRING_INTERNAL("__strlcat_chk") +/// size_t __strlcpy_chk(char *dst, const char *src, size_t size, +/// size_t dstsize); +TLI_DEFINE_ENUM_INTERNAL(strlcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__strlcpy_chk") +/// char *strncat_chk(char *s1, const char *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strncat_chk) +TLI_DEFINE_STRING_INTERNAL("__strncat_chk") /// char *__strncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); TLI_DEFINE_ENUM_INTERNAL(strncpy_chk) TLI_DEFINE_STRING_INTERNAL("__strncpy_chk") @@ -403,6 +446,14 @@ TLI_DEFINE_STRING_INTERNAL("__strndup") /// char * __strtok_r(char *s, const char *delim, char **save_ptr); TLI_DEFINE_ENUM_INTERNAL(dunder_strtok_r) TLI_DEFINE_STRING_INTERNAL("__strtok_r") +/// int __vsnprintf_chk(char *s, size_t n, int flags, size_t slen, +/// const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsnprintf_chk) +TLI_DEFINE_STRING_INTERNAL("__vsnprintf_chk") +/// int __vsprintf_chk(char *s, int flags, size_t slen, const char *format, +/// va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsprintf_chk) +TLI_DEFINE_STRING_INTERNAL("__vsprintf_chk") /// int abs(int j); TLI_DEFINE_ENUM_INTERNAL(abs) TLI_DEFINE_STRING_INTERNAL("abs") @@ -1192,6 +1243,12 @@ TLI_DEFINE_STRING_INTERNAL("strcspn") /// char *strdup(const char *s1); TLI_DEFINE_ENUM_INTERNAL(strdup) TLI_DEFINE_STRING_INTERNAL("strdup") +/// size_t strlcat(char *dst, const char *src, size_t size); +TLI_DEFINE_ENUM_INTERNAL(strlcat) +TLI_DEFINE_STRING_INTERNAL("strlcat") +/// size_t strlcpy(char *dst, const char *src, size_t size); +TLI_DEFINE_ENUM_INTERNAL(strlcpy) +TLI_DEFINE_STRING_INTERNAL("strlcpy") /// size_t strlen(const char *s); TLI_DEFINE_ENUM_INTERNAL(strlen) TLI_DEFINE_STRING_INTERNAL("strlen") diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h index a3fe834022f7..4b5200f5a838 100644 --- a/include/llvm/Analysis/TargetLibraryInfo.h +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -1,9 +1,8 @@ //===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -87,6 +86,7 @@ public: enum VectorLibrary { NoLibrary, // Don't use any vector library. Accelerate, // Use Accelerate framework. + MASSV, // IBM MASS vector library. SVML // Intel short vector math library. }; @@ -281,9 +281,9 @@ public: case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl: case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l: case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l: - case LibFunc_memcmp: case LibFunc_strcmp: case LibFunc_strcpy: - case LibFunc_stpcpy: case LibFunc_strlen: case LibFunc_strnlen: - case LibFunc_memchr: case LibFunc_mempcpy: + case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp: + case LibFunc_strcpy: case LibFunc_stpcpy: case LibFunc_strlen: + case LibFunc_strnlen: case LibFunc_memchr: case LibFunc_mempcpy: return true; } return false; diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 223175d17c2d..7574b811bc1c 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -1,9 +1,8 @@ //===- TargetTransformInfo.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -28,6 +27,10 @@ #include "llvm/Pass.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/AssumptionCache.h" #include <functional> namespace llvm { @@ -36,6 +39,8 @@ namespace Intrinsic { enum ID : unsigned; } +class AssumptionCache; +class BranchInst; class Function; class GlobalValue; class IntrinsicInst; @@ -45,6 +50,7 @@ class SCEV; class ScalarEvolution; class StoreInst; class SwitchInst; +class TargetLibraryInfo; class Type; class User; class Value; @@ -73,6 +79,30 @@ struct MemIntrinsicInfo { } }; +/// Attributes of a target dependent hardware loop. +struct HardwareLoopInfo { + HardwareLoopInfo() = delete; + HardwareLoopInfo(Loop *L) : L(L) {} + Loop *L = nullptr; + BasicBlock *ExitBlock = nullptr; + BranchInst *ExitBranch = nullptr; + const SCEV *ExitCount = nullptr; + IntegerType *CountType = nullptr; + Value *LoopDecrement = nullptr; // Decrement the loop counter by this + // value in every iteration. + bool IsNestingLegal = false; // Can a hardware loop be a parent to + // another hardware loop? + bool CounterInReg = false; // Should loop counter be updated in + // the loop via a phi? + bool PerformEntryTest = false; // Generate the intrinsic which also performs + // icmp ne zero on the loop counter value and + // produces an i1 to guard the loop entry. + bool isHardwareLoopCandidate(ScalarEvolution &SE, LoopInfo &LI, + DominatorTree &DT, bool ForceNestedLoop = false, + bool ForceHardwareLoopPHI = false); + bool canAnalyze(LoopInfo &LI); +}; + /// This pass provides access to the codegen interfaces that are needed /// for IR-level transformations. class TargetTransformInfo { @@ -81,7 +111,7 @@ public: /// API below. /// /// This is used by targets to construct a TTI wrapping their target-specific - /// implementaion that encodes appropriate costs for their target. + /// implementation that encodes appropriate costs for their target. template <typename T> TargetTransformInfo(T Impl); /// Construct a baseline TTI object using a minimal implementation of @@ -209,18 +239,21 @@ public: /// This is the most basic query for estimating call cost: it only knows the /// function type and (potentially) the number of arguments at the call site. /// The latter is only interesting for varargs function types. - int getCallCost(FunctionType *FTy, int NumArgs = -1) const; + int getCallCost(FunctionType *FTy, int NumArgs = -1, + const User *U = nullptr) const; /// Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. - int getCallCost(const Function *F, int NumArgs = -1) const; + int getCallCost(const Function *F, int NumArgs = -1, + const User *U = nullptr) const; /// Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. - int getCallCost(const Function *F, ArrayRef<const Value *> Arguments) const; + int getCallCost(const Function *F, ArrayRef<const Value *> Arguments, + const User *U = nullptr) const; /// \returns A value by which our inlining threshold should be multiplied. /// This is primarily used to bump up the inlining threshold wholesale on @@ -230,17 +263,35 @@ public: /// individual classes of instructions would be better. unsigned getInliningThresholdMultiplier() const; + /// \returns Vector bonus in percent. + /// + /// Vector bonuses: We want to more aggressively inline vector-dense kernels + /// and apply this bonus based on the percentage of vector instructions. A + /// bonus is applied if the vector instructions exceed 50% and half that amount + /// is applied if it exceeds 10%. Note that these bonuses are some what + /// arbitrary and evolved over time by accident as much as because they are + /// principled bonuses. + /// FIXME: It would be nice to base the bonus values on something more + /// scientific. A target may has no bonus on vector instructions. + int getInlinerVectorBonusPercent() const; + /// Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) const; + ArrayRef<Type *> ParamTys, + const User *U = nullptr) const; /// Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) const; + ArrayRef<const Value *> Arguments, + const User *U = nullptr) const; + + /// \return the expected cost of a memcpy, which could e.g. depend on the + /// source/destination type and alignment and the number of bytes copied. + int getMemcpyCost(const Instruction *I) const; /// \return The estimated number of case clusters when lowering \p 'SI'. /// \p JTSize Set a jump table size only when \p SI is suitable for a jump @@ -296,7 +347,7 @@ public: // Returns true for the target specific // set of operations which produce uniform result - // even taking non-unform arguments + // even taking non-uniform arguments bool isAlwaysUniform(const Value *V) const; /// Returns the address space ID for a target's 'flat' address space. Note @@ -437,6 +488,13 @@ public: void getUnrollingPreferences(Loop *L, ScalarEvolution &, UnrollingPreferences &UP) const; + /// Query the target whether it would be profitable to convert the given loop + /// into a hardware loop. + bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) const; + /// @} /// \name Scalar Target Information @@ -483,21 +541,40 @@ public: /// calculation for the instructions in a loop. bool canMacroFuseCmp() const; + /// Return true if the target can save a compare for loop count, for example + /// hardware loop saves a compare. + bool canSaveCmp(Loop *L, BranchInst **BI, ScalarEvolution *SE, LoopInfo *LI, + DominatorTree *DT, AssumptionCache *AC, + TargetLibraryInfo *LibInfo) const; + /// \return True is LSR should make efforts to create/preserve post-inc /// addressing mode expressions. bool shouldFavorPostInc() const; - /// Return true if the target supports masked load/store - /// AVX2 and AVX-512 targets allow masks for consecutive load and store + /// Return true if LSR should make efforts to generate indexed addressing + /// modes that operate across loop iterations. + bool shouldFavorBackedgeIndex(const Loop *L) const; + + /// Return true if the target supports masked load. bool isLegalMaskedStore(Type *DataType) const; + /// Return true if the target supports masked store. bool isLegalMaskedLoad(Type *DataType) const; - /// Return true if the target supports masked gather/scatter - /// AVX-512 fully supports gather and scatter for vectors with 32 and 64 - /// bits scalar type. + /// Return true if the target supports nontemporal store. + bool isLegalNTStore(Type *DataType, unsigned Alignment) const; + /// Return true if the target supports nontemporal load. + bool isLegalNTLoad(Type *DataType, unsigned Alignment) const; + + /// Return true if the target supports masked scatter. bool isLegalMaskedScatter(Type *DataType) const; + /// Return true if the target supports masked gather. bool isLegalMaskedGather(Type *DataType) const; + /// Return true if the target supports masked compress store. + bool isLegalMaskedCompressStore(Type *DataType) const; + /// Return true if the target supports masked expand load. + bool isLegalMaskedExpandLoad(Type *DataType) const; + /// Return true if the target has a unified operation to calculate division /// and remainder. If so, the additional implicit multiplication and /// subtraction required to calculate a remainder from division are free. This @@ -576,17 +653,35 @@ public: /// Don't restrict interleaved unrolling to small loops. bool enableAggressiveInterleaving(bool LoopHasReductions) const; - /// If not nullptr, enable inline expansion of memcmp. IsZeroCmp is - /// true if this is the expansion of memcmp(p1, p2, s) == 0. + /// Returns options for expansion of memcmp. IsZeroCmp is + // true if this is the expansion of memcmp(p1, p2, s) == 0. struct MemCmpExpansionOptions { + // Return true if memcmp expansion is enabled. + operator bool() const { return MaxNumLoads > 0; } + + // Maximum number of load operations. + unsigned MaxNumLoads = 0; + // The list of available load sizes (in bytes), sorted in decreasing order. SmallVector<unsigned, 8> LoadSizes; + + // For memcmp expansion when the memcmp result is only compared equal or + // not-equal to 0, allow up to this number of load pairs per block. As an + // example, this may allow 'memcmp(a, b, 3) == 0' in a single block: + // a0 = load2bytes &a[0] + // b0 = load2bytes &b[0] + // a2 = load1byte &a[2] + // b2 = load1byte &b[2] + // r = cmp eq (a0 ^ b0 | a2 ^ b2), 0 + unsigned NumLoadsPerBlock = 1; + // Set to true to allow overlapping loads. For example, 7-byte compares can // be done with two 4-byte compares instead of 4+2+1-byte compares. This // requires all loads in LoadSizes to be doable in an unaligned way. bool AllowOverlappingLoads = false; }; - const MemCmpExpansionOptions *enableMemCmpExpansion(bool IsZeroCmp) const; + MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, + bool IsZeroCmp) const; /// Enable matching of interleaved access groups. bool enableInterleavedAccessVectorization() const; @@ -700,7 +795,7 @@ public: bool shouldMaximizeVectorBandwidth(bool OptSize) const; /// \return The minimum vectorization factor for types of given element - /// bit width, or 0 if there is no mimimum VF. The returned value only + /// bit width, or 0 if there is no minimum VF. The returned value only /// applies when shouldMaximizeVectorBandwidth returns true. unsigned getMinimumVF(unsigned ElemWidth) const; @@ -1005,6 +1100,11 @@ public: /// \returns True if the target wants to expand the given reduction intrinsic /// into a shuffle sequence. bool shouldExpandReduction(const IntrinsicInst *II) const; + + /// \returns the size cost of rematerializing a GlobalValue address relative + /// to a stack reload. + unsigned getGISelRematGlobalCost() const; + /// @} private: @@ -1035,15 +1135,18 @@ public: virtual int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands) = 0; virtual int getExtCost(const Instruction *I, const Value *Src) = 0; - virtual int getCallCost(FunctionType *FTy, int NumArgs) = 0; - virtual int getCallCost(const Function *F, int NumArgs) = 0; + virtual int getCallCost(FunctionType *FTy, int NumArgs, const User *U) = 0; + virtual int getCallCost(const Function *F, int NumArgs, const User *U) = 0; virtual int getCallCost(const Function *F, - ArrayRef<const Value *> Arguments) = 0; + ArrayRef<const Value *> Arguments, const User *U) = 0; virtual unsigned getInliningThresholdMultiplier() = 0; + virtual int getInlinerVectorBonusPercent() = 0; virtual int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) = 0; + ArrayRef<Type *> ParamTys, const User *U) = 0; virtual int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) = 0; + ArrayRef<const Value *> Arguments, + const User *U) = 0; + virtual int getMemcpyCost(const Instruction *I) = 0; virtual unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, unsigned &JTSize) = 0; virtual int @@ -1055,6 +1158,10 @@ public: virtual bool isLoweredToCall(const Function *F) = 0; virtual void getUnrollingPreferences(Loop *L, ScalarEvolution &, UnrollingPreferences &UP) = 0; + virtual bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) = 0; virtual bool isLegalAddImmediate(int64_t Imm) = 0; virtual bool isLegalICmpImmediate(int64_t Imm) = 0; virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, @@ -1065,11 +1172,19 @@ public: virtual bool isLSRCostLess(TargetTransformInfo::LSRCost &C1, TargetTransformInfo::LSRCost &C2) = 0; virtual bool canMacroFuseCmp() = 0; + virtual bool canSaveCmp(Loop *L, BranchInst **BI, ScalarEvolution *SE, + LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC, + TargetLibraryInfo *LibInfo) = 0; virtual bool shouldFavorPostInc() const = 0; + virtual bool shouldFavorBackedgeIndex(const Loop *L) const = 0; virtual bool isLegalMaskedStore(Type *DataType) = 0; virtual bool isLegalMaskedLoad(Type *DataType) = 0; + virtual bool isLegalNTStore(Type *DataType, unsigned Alignment) = 0; + virtual bool isLegalNTLoad(Type *DataType, unsigned Alignment) = 0; virtual bool isLegalMaskedScatter(Type *DataType) = 0; virtual bool isLegalMaskedGather(Type *DataType) = 0; + virtual bool isLegalMaskedCompressStore(Type *DataType) = 0; + virtual bool isLegalMaskedExpandLoad(Type *DataType) = 0; virtual bool hasDivRemOp(Type *DataType, bool IsSigned) = 0; virtual bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) = 0; virtual bool prefersVectorizedAddressing() = 0; @@ -1092,8 +1207,8 @@ public: unsigned VF) = 0; virtual bool supportsEfficientVectorElementLoadStore() = 0; virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0; - virtual const MemCmpExpansionOptions *enableMemCmpExpansion( - bool IsZeroCmp) const = 0; + virtual MemCmpExpansionOptions + enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const = 0; virtual bool enableInterleavedAccessVectorization() = 0; virtual bool enableMaskedInterleavedAccessVectorization() = 0; virtual bool isFPVectorizationPotentiallyUnsafe() = 0; @@ -1210,6 +1325,7 @@ public: virtual bool useReductionIntrinsic(unsigned Opcode, Type *Ty, ReductionFlags) const = 0; virtual bool shouldExpandReduction(const IntrinsicInst *II) const = 0; + virtual unsigned getGISelRematGlobalCost() const = 0; virtual int getInstructionLatency(const Instruction *I) = 0; }; @@ -1235,26 +1351,33 @@ public: int getExtCost(const Instruction *I, const Value *Src) override { return Impl.getExtCost(I, Src); } - int getCallCost(FunctionType *FTy, int NumArgs) override { - return Impl.getCallCost(FTy, NumArgs); + int getCallCost(FunctionType *FTy, int NumArgs, const User *U) override { + return Impl.getCallCost(FTy, NumArgs, U); } - int getCallCost(const Function *F, int NumArgs) override { - return Impl.getCallCost(F, NumArgs); + int getCallCost(const Function *F, int NumArgs, const User *U) override { + return Impl.getCallCost(F, NumArgs, U); } int getCallCost(const Function *F, - ArrayRef<const Value *> Arguments) override { - return Impl.getCallCost(F, Arguments); + ArrayRef<const Value *> Arguments, const User *U) override { + return Impl.getCallCost(F, Arguments, U); } unsigned getInliningThresholdMultiplier() override { return Impl.getInliningThresholdMultiplier(); } + int getInlinerVectorBonusPercent() override { + return Impl.getInlinerVectorBonusPercent(); + } int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) override { - return Impl.getIntrinsicCost(IID, RetTy, ParamTys); + ArrayRef<Type *> ParamTys, const User *U = nullptr) override { + return Impl.getIntrinsicCost(IID, RetTy, ParamTys, U); } int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) override { - return Impl.getIntrinsicCost(IID, RetTy, Arguments); + ArrayRef<const Value *> Arguments, + const User *U = nullptr) override { + return Impl.getIntrinsicCost(IID, RetTy, Arguments, U); + } + int getMemcpyCost(const Instruction *I) override { + return Impl.getMemcpyCost(I); } int getUserCost(const User *U, ArrayRef<const Value *> Operands) override { return Impl.getUserCost(U, Operands); @@ -1279,6 +1402,12 @@ public: UnrollingPreferences &UP) override { return Impl.getUnrollingPreferences(L, SE, UP); } + bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) override { + return Impl.isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo); + } bool isLegalAddImmediate(int64_t Imm) override { return Impl.isLegalAddImmediate(Imm); } @@ -1299,21 +1428,42 @@ public: bool canMacroFuseCmp() override { return Impl.canMacroFuseCmp(); } + bool canSaveCmp(Loop *L, BranchInst **BI, + ScalarEvolution *SE, + LoopInfo *LI, DominatorTree *DT, AssumptionCache *AC, + TargetLibraryInfo *LibInfo) override { + return Impl.canSaveCmp(L, BI, SE, LI, DT, AC, LibInfo); + } bool shouldFavorPostInc() const override { return Impl.shouldFavorPostInc(); } + bool shouldFavorBackedgeIndex(const Loop *L) const override { + return Impl.shouldFavorBackedgeIndex(L); + } bool isLegalMaskedStore(Type *DataType) override { return Impl.isLegalMaskedStore(DataType); } bool isLegalMaskedLoad(Type *DataType) override { return Impl.isLegalMaskedLoad(DataType); } + bool isLegalNTStore(Type *DataType, unsigned Alignment) override { + return Impl.isLegalNTStore(DataType, Alignment); + } + bool isLegalNTLoad(Type *DataType, unsigned Alignment) override { + return Impl.isLegalNTLoad(DataType, Alignment); + } bool isLegalMaskedScatter(Type *DataType) override { return Impl.isLegalMaskedScatter(DataType); } bool isLegalMaskedGather(Type *DataType) override { return Impl.isLegalMaskedGather(DataType); } + bool isLegalMaskedCompressStore(Type *DataType) override { + return Impl.isLegalMaskedCompressStore(DataType); + } + bool isLegalMaskedExpandLoad(Type *DataType) override { + return Impl.isLegalMaskedExpandLoad(DataType); + } bool hasDivRemOp(Type *DataType, bool IsSigned) override { return Impl.hasDivRemOp(DataType, IsSigned); } @@ -1368,9 +1518,9 @@ public: bool enableAggressiveInterleaving(bool LoopHasReductions) override { return Impl.enableAggressiveInterleaving(LoopHasReductions); } - const MemCmpExpansionOptions *enableMemCmpExpansion( - bool IsZeroCmp) const override { - return Impl.enableMemCmpExpansion(IsZeroCmp); + MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, + bool IsZeroCmp) const override { + return Impl.enableMemCmpExpansion(OptSize, IsZeroCmp); } bool enableInterleavedAccessVectorization() override { return Impl.enableInterleavedAccessVectorization(); @@ -1617,6 +1767,11 @@ public: bool shouldExpandReduction(const IntrinsicInst *II) const override { return Impl.shouldExpandReduction(II); } + + unsigned getGISelRematGlobalCost() const override { + return Impl.getGISelRematGlobalCost(); + } + int getInstructionLatency(const Instruction *I) override { return Impl.getInstructionLatency(I); } diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index c9a234deeb7d..b99e1eb9adf0 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1,9 +1,8 @@ //===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -124,7 +123,7 @@ public: return TTI::TCC_Basic; } - unsigned getCallCost(FunctionType *FTy, int NumArgs) { + unsigned getCallCost(FunctionType *FTy, int NumArgs, const User *U) { assert(FTy && "FunctionType must be provided to this routine."); // The target-independent implementation just measures the size of the @@ -141,45 +140,10 @@ public: unsigned getInliningThresholdMultiplier() { return 1; } - unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) { - switch (IID) { - default: - // Intrinsics rarely (if ever) have normal argument setup constraints. - // Model them as having a basic instruction cost. - // FIXME: This is wrong for libc intrinsics. - return TTI::TCC_Basic; + int getInlinerVectorBonusPercent() { return 150; } - case Intrinsic::annotation: - case Intrinsic::assume: - case Intrinsic::sideeffect: - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - case Intrinsic::dbg_label: - case Intrinsic::invariant_start: - case Intrinsic::invariant_end: - case Intrinsic::launder_invariant_group: - case Intrinsic::strip_invariant_group: - case Intrinsic::is_constant: - case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - case Intrinsic::objectsize: - case Intrinsic::ptr_annotation: - case Intrinsic::var_annotation: - case Intrinsic::experimental_gc_result: - case Intrinsic::experimental_gc_relocate: - case Intrinsic::coro_alloc: - case Intrinsic::coro_begin: - case Intrinsic::coro_free: - case Intrinsic::coro_end: - case Intrinsic::coro_frame: - case Intrinsic::coro_size: - case Intrinsic::coro_suspend: - case Intrinsic::coro_param: - case Intrinsic::coro_subfn_addr: - // These intrinsics don't actually represent code after lowering. - return TTI::TCC_Free; - } + unsigned getMemcpyCost(const Instruction *I) { + return TTI::TCC_Expensive; } bool hasBranchDivergence() { return false; } @@ -228,6 +192,13 @@ public: return true; } + bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) { + return false; + } + void getUnrollingPreferences(Loop *, ScalarEvolution &, TTI::UnrollingPreferences &) {} @@ -252,16 +223,42 @@ public: bool canMacroFuseCmp() { return false; } + bool canSaveCmp(Loop *L, BranchInst **BI, ScalarEvolution *SE, LoopInfo *LI, + DominatorTree *DT, AssumptionCache *AC, + TargetLibraryInfo *LibInfo) { + return false; + } + bool shouldFavorPostInc() const { return false; } + bool shouldFavorBackedgeIndex(const Loop *L) const { return false; } + bool isLegalMaskedStore(Type *DataType) { return false; } bool isLegalMaskedLoad(Type *DataType) { return false; } + bool isLegalNTStore(Type *DataType, unsigned Alignment) { + // By default, assume nontemporal memory stores are available for stores + // that are aligned and have a size that is a power of 2. + unsigned DataSize = DL.getTypeStoreSize(DataType); + return Alignment >= DataSize && isPowerOf2_32(DataSize); + } + + bool isLegalNTLoad(Type *DataType, unsigned Alignment) { + // By default, assume nontemporal memory loads are available for loads that + // are aligned and have a size that is a power of 2. + unsigned DataSize = DL.getTypeStoreSize(DataType); + return Alignment >= DataSize && isPowerOf2_32(DataSize); + } + bool isLegalMaskedScatter(Type *DataType) { return false; } bool isLegalMaskedGather(Type *DataType) { return false; } + bool isLegalMaskedCompressStore(Type *DataType) { return false; } + + bool isLegalMaskedExpandLoad(Type *DataType) { return false; } + bool hasDivRemOp(Type *DataType, bool IsSigned) { return false; } bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) { return false; } @@ -307,9 +304,9 @@ public: bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; } - const TTI::MemCmpExpansionOptions *enableMemCmpExpansion( - bool IsZeroCmp) const { - return nullptr; + TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, + bool IsZeroCmp) const { + return {}; } bool enableInterleavedAccessVectorization() { return false; } @@ -583,6 +580,10 @@ public: return true; } + unsigned getGISelRematGlobalCost() const { + return 1; + } + protected: // Obtain the minimum required size to hold the value (without the sign) // In case of a vector it returns the min required size for one element. @@ -679,7 +680,7 @@ protected: public: using BaseT::getCallCost; - unsigned getCallCost(const Function *F, int NumArgs) { + unsigned getCallCost(const Function *F, int NumArgs, const User *U) { assert(F && "A concrete function must be provided to this routine."); if (NumArgs < 0) @@ -691,35 +692,34 @@ public: FunctionType *FTy = F->getFunctionType(); SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end()); return static_cast<T *>(this) - ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys); + ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys, U); } if (!static_cast<T *>(this)->isLoweredToCall(F)) return TTI::TCC_Basic; // Give a basic cost if it will be lowered // directly. - return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs); + return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs, U); } - unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) { + unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments, + const User *U) { // Simply delegate to generic handling of the call. // FIXME: We should use instsimplify or something else to catch calls which // will constant fold with these arguments. - return static_cast<T *>(this)->getCallCost(F, Arguments.size()); + return static_cast<T *>(this)->getCallCost(F, Arguments.size(), U); } using BaseT::getGEPCost; int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands) { - const GlobalValue *BaseGV = nullptr; - if (Ptr != nullptr) { - // TODO: will remove this when pointers have an opaque type. - assert(Ptr->getType()->getScalarType()->getPointerElementType() == - PointeeType && - "explicit pointee type doesn't match operand's pointee type"); - BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts()); - } + assert(PointeeType && Ptr && "can't get GEPCost of nullptr"); + // TODO: will remove this when pointers have an opaque type. + assert(Ptr->getType()->getScalarType()->getPointerElementType() == + PointeeType && + "explicit pointee type doesn't match operand's pointee type"); + auto *BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts()); bool HasBaseReg = (BaseGV == nullptr); auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType()); @@ -762,21 +762,60 @@ public: } } - // Assumes the address space is 0 when Ptr is nullptr. - unsigned AS = - (Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace()); - if (static_cast<T *>(this)->isLegalAddressingMode( TargetType, const_cast<GlobalValue *>(BaseGV), - BaseOffset.sextOrTrunc(64).getSExtValue(), HasBaseReg, Scale, AS)) + BaseOffset.sextOrTrunc(64).getSExtValue(), HasBaseReg, Scale, + Ptr->getType()->getPointerAddressSpace())) return TTI::TCC_Free; return TTI::TCC_Basic; } - using BaseT::getIntrinsicCost; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys, const User *U) { + switch (IID) { + default: + // Intrinsics rarely (if ever) have normal argument setup constraints. + // Model them as having a basic instruction cost. + return TTI::TCC_Basic; + + // TODO: other libc intrinsics. + case Intrinsic::memcpy: + return static_cast<T *>(this)->getMemcpyCost(dyn_cast<Instruction>(U)); + + case Intrinsic::annotation: + case Intrinsic::assume: + case Intrinsic::sideeffect: + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + case Intrinsic::dbg_label: + case Intrinsic::invariant_start: + case Intrinsic::invariant_end: + case Intrinsic::launder_invariant_group: + case Intrinsic::strip_invariant_group: + case Intrinsic::is_constant: + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::objectsize: + case Intrinsic::ptr_annotation: + case Intrinsic::var_annotation: + case Intrinsic::experimental_gc_result: + case Intrinsic::experimental_gc_relocate: + case Intrinsic::coro_alloc: + case Intrinsic::coro_begin: + case Intrinsic::coro_free: + case Intrinsic::coro_end: + case Intrinsic::coro_frame: + case Intrinsic::coro_size: + case Intrinsic::coro_suspend: + case Intrinsic::coro_param: + case Intrinsic::coro_subfn_addr: + // These intrinsics don't actually represent code after lowering. + return TTI::TCC_Free; + } + } unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) { + ArrayRef<const Value *> Arguments, const User *U) { // Delegate to the generic intrinsic handling code. This mostly provides an // opportunity for targets to (for example) special case the cost of // certain intrinsics based on constants used as arguments. @@ -784,7 +823,7 @@ public: ParamTys.reserve(Arguments.size()); for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx) ParamTys.push_back(Arguments[Idx]->getType()); - return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys); + return static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys, U); } unsigned getUserCost(const User *U, ArrayRef<const Value *> Operands) { @@ -808,22 +847,18 @@ public: // Just use the called value type. Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); return static_cast<T *>(this) - ->getCallCost(cast<FunctionType>(FTy), CS.arg_size()); + ->getCallCost(cast<FunctionType>(FTy), CS.arg_size(), U); } SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end()); - return static_cast<T *>(this)->getCallCost(F, Arguments); + return static_cast<T *>(this)->getCallCost(F, Arguments, U); } - if (const CastInst *CI = dyn_cast<CastInst>(U)) { - // Result of a cmp instruction is often extended (to be used by other - // cmp instructions, logical or return instructions). These are usually - // nop on most sane targets. - if (isa<CmpInst>(CI->getOperand(0))) - return TTI::TCC_Free; - if (isa<SExtInst>(CI) || isa<ZExtInst>(CI) || isa<FPExtInst>(CI)) - return static_cast<T *>(this)->getExtCost(CI, Operands.back()); - } + if (isa<SExtInst>(U) || isa<ZExtInst>(U) || isa<FPExtInst>(U)) + // The old behaviour of generally treating extensions of icmp to be free + // has been removed. A target that needs it should override getUserCost(). + return static_cast<T *>(this)->getExtCost(cast<Instruction>(U), + Operands.back()); return static_cast<T *>(this)->getOperationCost( Operator::getOpcode(U), U->getType(), diff --git a/include/llvm/Analysis/Trace.h b/include/llvm/Analysis/Trace.h index b05d384ab1a3..a1ffd03c4053 100644 --- a/include/llvm/Analysis/Trace.h +++ b/include/llvm/Analysis/Trace.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/Trace.h - Represent one trace of LLVM code -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/TypeBasedAliasAnalysis.h b/include/llvm/Analysis/TypeBasedAliasAnalysis.h index d2e6df22425e..344f26806618 100644 --- a/include/llvm/Analysis/TypeBasedAliasAnalysis.h +++ b/include/llvm/Analysis/TypeBasedAliasAnalysis.h @@ -1,9 +1,8 @@ //===- TypeBasedAliasAnalysis.h - Type-Based Alias Analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -41,12 +40,16 @@ public: return false; } - AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); - bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal); + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB, + AAQueryInfo &AAQI); + bool pointsToConstantMemory(const MemoryLocation &Loc, AAQueryInfo &AAQI, + bool OrLocal); FunctionModRefBehavior getModRefBehavior(const CallBase *Call); FunctionModRefBehavior getModRefBehavior(const Function *F); - ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc); - ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2); + ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc, + AAQueryInfo &AAQI); + ModRefInfo getModRefInfo(const CallBase *Call1, const CallBase *Call2, + AAQueryInfo &AAQI); private: bool Aliases(const MDNode *A, const MDNode *B) const; diff --git a/include/llvm/Analysis/TypeMetadataUtils.h b/include/llvm/Analysis/TypeMetadataUtils.h index 3bf9c5d20741..82cf8efeea54 100644 --- a/include/llvm/Analysis/TypeMetadataUtils.h +++ b/include/llvm/Analysis/TypeMetadataUtils.h @@ -1,9 +1,8 @@ //===- TypeMetadataUtils.h - Utilities related to type metadata --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/Utils/Local.h b/include/llvm/Analysis/Utils/Local.h index b4141bbff28d..acbdf5dca32c 100644 --- a/include/llvm/Analysis/Utils/Local.h +++ b/include/llvm/Analysis/Utils/Local.h @@ -1,9 +1,8 @@ //===- Local.h - Functions to perform local transformations -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/ValueLattice.h b/include/llvm/Analysis/ValueLattice.h index 0744ca617e48..56519d7d0857 100644 --- a/include/llvm/Analysis/ValueLattice.h +++ b/include/llvm/Analysis/ValueLattice.h @@ -1,9 +1,8 @@ //===- ValueLattice.h - Value constraint analysis ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/ValueLatticeUtils.h b/include/llvm/Analysis/ValueLatticeUtils.h index 02072672e56e..a3bbb96129bf 100644 --- a/include/llvm/Analysis/ValueLatticeUtils.h +++ b/include/llvm/Analysis/ValueLatticeUtils.h @@ -1,9 +1,8 @@ //===-- ValueLatticeUtils.h - Utils for solving lattices --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index f46fdfcb608e..fa7e0e0eef7e 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/ValueTracking.h - Walk computations --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,8 +16,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Intrinsics.h" #include <cassert> @@ -29,10 +30,10 @@ namespace llvm { class AddOperator; class APInt; class AssumptionCache; -class DataLayout; class DominatorTree; class GEPOperator; class IntrinsicInst; +class WithOverflowInst; struct KnownBits; class Loop; class LoopInfo; @@ -223,7 +224,7 @@ class Value; /// 0.0 etc. If the value can't be handled with a repeated byte store (e.g. /// i16 0x1234), return null. If the value is entirely undef and padding, /// return undef. - Value *isBytewiseValue(Value *V); + Value *isBytewiseValue(Value *V, const DataLayout &DL); /// Given an aggregrate and an sequence of indices, see if the scalar value /// indexed is already around as a register, for example if it were inserted @@ -237,8 +238,18 @@ class Value; /// Analyze the specified pointer to see if it can be expressed as a base /// pointer plus a constant offset. Return the base and offset to the caller. - Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, - const DataLayout &DL); + /// + /// This is a wrapper around Value::stripAndAccumulateConstantOffsets that + /// creates and later unpacks the required APInt. + inline Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const DataLayout &DL) { + APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0); + Value *Base = + Ptr->stripAndAccumulateConstantOffsets(DL, OffsetAPInt, + /* AllowNonInbounds */ true); + Offset = OffsetAPInt.getSExtValue(); + return Base; + } inline const Value *GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, const DataLayout &DL) { @@ -351,7 +362,8 @@ class Value; /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects /// should not assume that Curr and Prev share the same underlying object thus /// it shouldn't look through the phi above. - void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects, + void GetUnderlyingObjects(const Value *V, + SmallVectorImpl<const Value *> &Objects, const DataLayout &DL, LoopInfo *LI = nullptr, unsigned MaxLookup = 6); @@ -411,7 +423,16 @@ class Value; bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, const DominatorTree *DT = nullptr); - enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; + enum class OverflowResult { + /// Always overflows in the direction of signed/unsigned min value. + AlwaysOverflowsLow, + /// Always overflows in the direction of signed/unsigned max value. + AlwaysOverflowsHigh, + /// May or may not overflow. + MayOverflow, + /// Never overflows. + NeverOverflows, + }; OverflowResult computeOverflowForUnsignedMul(const Value *LHS, const Value *RHS, @@ -455,12 +476,17 @@ class Value; const Instruction *CxtI, const DominatorTree *DT); - /// Returns true if the arithmetic part of the \p II 's result is + /// Returns true if the arithmetic part of the \p WO 's result is /// used only along the paths control dependent on the computation - /// not overflowing, \p II being an <op>.with.overflow intrinsic. - bool isOverflowIntrinsicNoWrap(const IntrinsicInst *II, + /// not overflowing, \p WO being an <op>.with.overflow intrinsic. + bool isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, const DominatorTree &DT); + + /// Determine the possible constant range of an integer or vector of integer + /// value. This is intended as a cheap, non-recursive check. + ConstantRange computeConstantRange(const Value *V, bool UseInstrInfo = true); + /// Return true if this function can prove that the instruction I will /// always transfer execution to one of its successors (including the next /// instruction that follows within a basic block). E.g. this is not @@ -506,6 +532,12 @@ class Value; /// value (all bits poison). const Value *getGuaranteedNonFullPoisonOp(const Instruction *I); + /// Return true if the given instruction must trigger undefined behavior. + /// when I is executed with any operands which appear in KnownPoison holding + /// a full-poison value at the point of execution. + bool mustTriggerUB(const Instruction *I, + const SmallSet<const Value *, 16>& KnownPoison); + /// Return true if this function can prove that if PoisonI is executed /// and yields a full-poison value (all bits poison), then that will /// trigger undefined behavior. @@ -584,6 +616,12 @@ class Value; return Result; } + /// Determine the pattern that a select with the given compare as its + /// predicate and given values as its true/false operands would match. + SelectPatternResult matchDecomposedSelectPattern( + CmpInst *CmpI, Value *TrueVal, Value *FalseVal, Value *&LHS, Value *&RHS, + Instruction::CastOps *CastOp = nullptr, unsigned Depth = 0); + /// Return the canonical comparison predicate for the specified /// minimum/maximum flavor. CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF, diff --git a/include/llvm/Analysis/VecFuncs.def b/include/llvm/Analysis/VecFuncs.def new file mode 100644 index 000000000000..4c9206266d9a --- /dev/null +++ b/include/llvm/Analysis/VecFuncs.def @@ -0,0 +1,250 @@ +//===-- VecFuncs.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 create mappings from scalar math functions to vector +// functions along with their vectorization factor. The current support includes +// such mappings for Accelerate framework, MASS vector library, and SVML library. + +#if !(defined(TLI_DEFINE_VECFUNC)) +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF) {SCAL, VEC, VF}, +#endif + +#if defined(TLI_DEFINE_ACCELERATE_VECFUNCS) +// Accelerate framework's Vector Functions + +// Floating-Point Arithmetic and Auxiliary Functions +TLI_DEFINE_VECFUNC("ceilf", "vceilf", 4) +TLI_DEFINE_VECFUNC("fabsf", "vfabsf", 4) +TLI_DEFINE_VECFUNC("llvm.fabs.f32", "vfabsf", 4) +TLI_DEFINE_VECFUNC("floorf", "vfloorf", 4) +TLI_DEFINE_VECFUNC("sqrtf", "vsqrtf", 4) +TLI_DEFINE_VECFUNC("llvm.sqrt.f32", "vsqrtf", 4) + +// Exponential and Logarithmic Functions +TLI_DEFINE_VECFUNC("expf", "vexpf", 4) +TLI_DEFINE_VECFUNC("llvm.exp.f32", "vexpf", 4) +TLI_DEFINE_VECFUNC("expm1f", "vexpm1f", 4) +TLI_DEFINE_VECFUNC("logf", "vlogf", 4) +TLI_DEFINE_VECFUNC("llvm.log.f32", "vlogf", 4) +TLI_DEFINE_VECFUNC("log1pf", "vlog1pf", 4) +TLI_DEFINE_VECFUNC("log10f", "vlog10f", 4) +TLI_DEFINE_VECFUNC("llvm.log10.f32", "vlog10f", 4) +TLI_DEFINE_VECFUNC("logbf", "vlogbf", 4) + +// Trigonometric Functions +TLI_DEFINE_VECFUNC("sinf", "vsinf", 4) +TLI_DEFINE_VECFUNC("llvm.sin.f32", "vsinf", 4) +TLI_DEFINE_VECFUNC("cosf", "vcosf", 4) +TLI_DEFINE_VECFUNC("llvm.cos.f32", "vcosf", 4) +TLI_DEFINE_VECFUNC("tanf", "vtanf", 4) +TLI_DEFINE_VECFUNC("asinf", "vasinf", 4) +TLI_DEFINE_VECFUNC("acosf", "vacosf", 4) +TLI_DEFINE_VECFUNC("atanf", "vatanf", 4) + +// Hyperbolic Functions +TLI_DEFINE_VECFUNC("sinhf", "vsinhf", 4) +TLI_DEFINE_VECFUNC("coshf", "vcoshf", 4) +TLI_DEFINE_VECFUNC("tanhf", "vtanhf", 4) +TLI_DEFINE_VECFUNC("asinhf", "vasinhf", 4) +TLI_DEFINE_VECFUNC("acoshf", "vacoshf", 4) +TLI_DEFINE_VECFUNC("atanhf", "vatanhf", 4) + + +#elif defined(TLI_DEFINE_MASSV_VECFUNCS) +// IBM MASS library's vector Functions + +// Floating-Point Arithmetic and Auxiliary Functions +TLI_DEFINE_VECFUNC("cbrt", "__cbrtd2_massv", 2) +TLI_DEFINE_VECFUNC("cbrtf", "__cbrtf4_massv", 4) +TLI_DEFINE_VECFUNC("pow", "__powd2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.pow.f64", "__powd2_massv", 2) +TLI_DEFINE_VECFUNC("powf", "__powf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.pow.f32", "__powf4_massv", 4) +TLI_DEFINE_VECFUNC("sqrt", "__sqrtd2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.sqrt.f64", "__sqrtd2_massv", 2) +TLI_DEFINE_VECFUNC("sqrtf", "__sqrtf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.sqrt.f32", "__sqrtf4_massv", 4) + +// Exponential and Logarithmic Functions +TLI_DEFINE_VECFUNC("exp", "__expd2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.exp.f64", "__expd2_massv", 2) +TLI_DEFINE_VECFUNC("expf", "__expf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.exp.f32", "__expf4_massv", 4) +TLI_DEFINE_VECFUNC("exp2", "__exp2d2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.exp2.f64", "__exp2d2_massv", 2) +TLI_DEFINE_VECFUNC("exp2f", "__exp2f4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.exp2.f32", "__exp2f4_massv", 4) +TLI_DEFINE_VECFUNC("expm1", "__expm1d2_massv", 2) +TLI_DEFINE_VECFUNC("expm1f", "__expm1f4_massv", 4) +TLI_DEFINE_VECFUNC("log", "__logd2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.log.f64", "__logd2_massv", 2) +TLI_DEFINE_VECFUNC("logf", "__logf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.log.f32", "__logf4_massv", 4) +TLI_DEFINE_VECFUNC("log1p", "__log1pd2_massv", 2) +TLI_DEFINE_VECFUNC("log1pf", "__log1pf4_massv", 4) +TLI_DEFINE_VECFUNC("log10", "__log10d2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.log10.f64", "__log10d2_massv", 2) +TLI_DEFINE_VECFUNC("log10f", "__log10f4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.log10.f32", "__log10f4_massv", 4) +TLI_DEFINE_VECFUNC("log2", "__log2d2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.log2.f64", "__log2d2_massv", 2) +TLI_DEFINE_VECFUNC("log2f", "__log2f4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.log2.f32", "__log2f4_massv", 4) + +// Trigonometric Functions +TLI_DEFINE_VECFUNC("sin", "__sind2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.sin.f64", "__sind2_massv", 2) +TLI_DEFINE_VECFUNC("sinf", "__sinf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.sin.f32", "__sinf4_massv", 4) +TLI_DEFINE_VECFUNC("cos", "__cosd2_massv", 2) +TLI_DEFINE_VECFUNC("llvm.cos.f64", "__cosd2_massv", 2) +TLI_DEFINE_VECFUNC("cosf", "__cosf4_massv", 4) +TLI_DEFINE_VECFUNC("llvm.cos.f32", "__cosf4_massv", 4) +TLI_DEFINE_VECFUNC("tan", "__tand2_massv", 2) +TLI_DEFINE_VECFUNC("tanf", "__tanf4_massv", 4) +TLI_DEFINE_VECFUNC("asin", "__asind2_massv", 2) +TLI_DEFINE_VECFUNC("asinf", "__asinf4_massv", 4) +TLI_DEFINE_VECFUNC("acos", "__acosd2_massv", 2) +TLI_DEFINE_VECFUNC("acosf", "__acosf4_massv", 4) +TLI_DEFINE_VECFUNC("atan", "__atand2_massv", 2) +TLI_DEFINE_VECFUNC("atanf", "__atanf4_massv", 4) +TLI_DEFINE_VECFUNC("atan2", "__atan2d2_massv", 2) +TLI_DEFINE_VECFUNC("atan2f", "__atan2f4_massv", 4) + +// Hyperbolic Functions +TLI_DEFINE_VECFUNC("sinh", "__sinhd2_massv", 2) +TLI_DEFINE_VECFUNC("sinhf", "__sinhf4_massv", 4) +TLI_DEFINE_VECFUNC("cosh", "__coshd2_massv", 2) +TLI_DEFINE_VECFUNC("coshf", "__coshf4_massv", 4) +TLI_DEFINE_VECFUNC("tanh", "__tanhd2_massv", 2) +TLI_DEFINE_VECFUNC("tanhf", "__tanhf4_massv", 4) +TLI_DEFINE_VECFUNC("asinh", "__asinhd2_massv", 2) +TLI_DEFINE_VECFUNC("asinhf", "__asinhf4_massv", 4) +TLI_DEFINE_VECFUNC("acosh", "__acoshd2_massv", 2) +TLI_DEFINE_VECFUNC("acoshf", "__acoshf4_massv", 4) +TLI_DEFINE_VECFUNC("atanh", "__atanhd2_massv", 2) +TLI_DEFINE_VECFUNC("atanhf", "__atanhf4_massv", 4) + + +#elif defined(TLI_DEFINE_SVML_VECFUNCS) +// Intel SVM library's Vector Functions + +TLI_DEFINE_VECFUNC("sin", "__svml_sin2", 2) +TLI_DEFINE_VECFUNC("sin", "__svml_sin4", 4) +TLI_DEFINE_VECFUNC("sin", "__svml_sin8", 8) + +TLI_DEFINE_VECFUNC("sinf", "__svml_sinf4", 4) +TLI_DEFINE_VECFUNC("sinf", "__svml_sinf8", 8) +TLI_DEFINE_VECFUNC("sinf", "__svml_sinf16", 16) + +TLI_DEFINE_VECFUNC("llvm.sin.f64", "__svml_sin2", 2) +TLI_DEFINE_VECFUNC("llvm.sin.f64", "__svml_sin4", 4) +TLI_DEFINE_VECFUNC("llvm.sin.f64", "__svml_sin8", 8) + +TLI_DEFINE_VECFUNC("llvm.sin.f32", "__svml_sinf4", 4) +TLI_DEFINE_VECFUNC("llvm.sin.f32", "__svml_sinf8", 8) +TLI_DEFINE_VECFUNC("llvm.sin.f32", "__svml_sinf16", 16) + +TLI_DEFINE_VECFUNC("cos", "__svml_cos2", 2) +TLI_DEFINE_VECFUNC("cos", "__svml_cos4", 4) +TLI_DEFINE_VECFUNC("cos", "__svml_cos8", 8) + +TLI_DEFINE_VECFUNC("cosf", "__svml_cosf4", 4) +TLI_DEFINE_VECFUNC("cosf", "__svml_cosf8", 8) +TLI_DEFINE_VECFUNC("cosf", "__svml_cosf16", 16) + +TLI_DEFINE_VECFUNC("llvm.cos.f64", "__svml_cos2", 2) +TLI_DEFINE_VECFUNC("llvm.cos.f64", "__svml_cos4", 4) +TLI_DEFINE_VECFUNC("llvm.cos.f64", "__svml_cos8", 8) + +TLI_DEFINE_VECFUNC("llvm.cos.f32", "__svml_cosf4", 4) +TLI_DEFINE_VECFUNC("llvm.cos.f32", "__svml_cosf8", 8) +TLI_DEFINE_VECFUNC("llvm.cos.f32", "__svml_cosf16", 16) + +TLI_DEFINE_VECFUNC("pow", "__svml_pow2", 2) +TLI_DEFINE_VECFUNC("pow", "__svml_pow4", 4) +TLI_DEFINE_VECFUNC("pow", "__svml_pow8", 8) + +TLI_DEFINE_VECFUNC("powf", "__svml_powf4", 4) +TLI_DEFINE_VECFUNC("powf", "__svml_powf8", 8) +TLI_DEFINE_VECFUNC("powf", "__svml_powf16", 16) + +TLI_DEFINE_VECFUNC("__pow_finite", "__svml_pow2", 2) +TLI_DEFINE_VECFUNC("__pow_finite", "__svml_pow4", 4) +TLI_DEFINE_VECFUNC("__pow_finite", "__svml_pow8", 8) + +TLI_DEFINE_VECFUNC("__powf_finite", "__svml_powf4", 4) +TLI_DEFINE_VECFUNC("__powf_finite", "__svml_powf8", 8) +TLI_DEFINE_VECFUNC("__powf_finite", "__svml_powf16", 16) + +TLI_DEFINE_VECFUNC("llvm.pow.f64", "__svml_pow2", 2) +TLI_DEFINE_VECFUNC("llvm.pow.f64", "__svml_pow4", 4) +TLI_DEFINE_VECFUNC("llvm.pow.f64", "__svml_pow8", 8) + +TLI_DEFINE_VECFUNC("llvm.pow.f32", "__svml_powf4", 4) +TLI_DEFINE_VECFUNC("llvm.pow.f32", "__svml_powf8", 8) +TLI_DEFINE_VECFUNC("llvm.pow.f32", "__svml_powf16", 16) + +TLI_DEFINE_VECFUNC("exp", "__svml_exp2", 2) +TLI_DEFINE_VECFUNC("exp", "__svml_exp4", 4) +TLI_DEFINE_VECFUNC("exp", "__svml_exp8", 8) + +TLI_DEFINE_VECFUNC("expf", "__svml_expf4", 4) +TLI_DEFINE_VECFUNC("expf", "__svml_expf8", 8) +TLI_DEFINE_VECFUNC("expf", "__svml_expf16", 16) + +TLI_DEFINE_VECFUNC("__exp_finite", "__svml_exp2", 2) +TLI_DEFINE_VECFUNC("__exp_finite", "__svml_exp4", 4) +TLI_DEFINE_VECFUNC("__exp_finite", "__svml_exp8", 8) + +TLI_DEFINE_VECFUNC("__expf_finite", "__svml_expf4", 4) +TLI_DEFINE_VECFUNC("__expf_finite", "__svml_expf8", 8) +TLI_DEFINE_VECFUNC("__expf_finite", "__svml_expf16", 16) + +TLI_DEFINE_VECFUNC("llvm.exp.f64", "__svml_exp2", 2) +TLI_DEFINE_VECFUNC("llvm.exp.f64", "__svml_exp4", 4) +TLI_DEFINE_VECFUNC("llvm.exp.f64", "__svml_exp8", 8) + +TLI_DEFINE_VECFUNC("llvm.exp.f32", "__svml_expf4", 4) +TLI_DEFINE_VECFUNC("llvm.exp.f32", "__svml_expf8", 8) +TLI_DEFINE_VECFUNC("llvm.exp.f32", "__svml_expf16", 16) + +TLI_DEFINE_VECFUNC("log", "__svml_log2", 2) +TLI_DEFINE_VECFUNC("log", "__svml_log4", 4) +TLI_DEFINE_VECFUNC("log", "__svml_log8", 8) + +TLI_DEFINE_VECFUNC("logf", "__svml_logf4", 4) +TLI_DEFINE_VECFUNC("logf", "__svml_logf8", 8) +TLI_DEFINE_VECFUNC("logf", "__svml_logf16", 16) + +TLI_DEFINE_VECFUNC("__log_finite", "__svml_log2", 2) +TLI_DEFINE_VECFUNC("__log_finite", "__svml_log4", 4) +TLI_DEFINE_VECFUNC("__log_finite", "__svml_log8", 8) + +TLI_DEFINE_VECFUNC("__logf_finite", "__svml_logf4", 4) +TLI_DEFINE_VECFUNC("__logf_finite", "__svml_logf8", 8) +TLI_DEFINE_VECFUNC("__logf_finite", "__svml_logf16", 16) + +TLI_DEFINE_VECFUNC("llvm.log.f64", "__svml_log2", 2) +TLI_DEFINE_VECFUNC("llvm.log.f64", "__svml_log4", 4) +TLI_DEFINE_VECFUNC("llvm.log.f64", "__svml_log8", 8) + +TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf4", 4) +TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf8", 8) +TLI_DEFINE_VECFUNC("llvm.log.f32", "__svml_logf16", 16) + + +#else +#error "Must choose which vector library functions are to be defined." +#endif + +#undef TLI_DEFINE_VECFUNC +#undef TLI_DEFINE_ACCELERATE_VECFUNCS +#undef TLI_DEFINE_MASSV_VECFUNCS +#undef TLI_DEFINE_SVML_VECFUNCS + diff --git a/include/llvm/Analysis/VectorUtils.h b/include/llvm/Analysis/VectorUtils.h index be4d4f17b9ad..d93d2bc4570b 100644 --- a/include/llvm/Analysis/VectorUtils.h +++ b/include/llvm/Analysis/VectorUtils.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/VectorUtils.h - Vector utilities -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/Support/CheckedArithmetic.h" namespace llvm { @@ -36,13 +36,12 @@ enum ID : unsigned; } /// Identify if the intrinsic is trivially vectorizable. -/// This method returns true if the intrinsic's argument types are all -/// scalars for the scalar form of the intrinsic and all vectors for -/// the vector form of the intrinsic. +/// This method returns true if the intrinsic's argument types are all scalars +/// for the scalar form of the intrinsic and all vectors (or scalars handled by +/// hasVectorInstrinsicScalarOpd) for the vector form of the intrinsic. bool isTriviallyVectorizable(Intrinsic::ID ID); -/// Identifies if the intrinsic has a scalar operand. It checks for -/// ctlz,cttz and powi special intrinsics whose argument is scalar. +/// Identifies if the vector form of the intrinsic has a scalar operand. bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx); /// Returns intrinsic ID for call. @@ -78,6 +77,12 @@ Value *findScalarElement(Value *V, unsigned EltNo); /// a sequence of instructions that broadcast a single value into a vector. const Value *getSplatValue(const Value *V); +/// Return true if the input value is known to be a vector with all identical +/// elements (potentially including undefined elements). +/// This may be more powerful than the related getSplatValue() because it is +/// not limited by finding a scalar source value to a splatted vector. +bool isSplatValue(const Value *V, unsigned Depth = 0); + /// Compute a map of integer instructions to their minimum legal type /// size. /// @@ -223,6 +228,20 @@ Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start, /// elements, it will be padded with undefs. Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs); +/// Given a mask vector of the form <Y x i1>, Return true if all of the +/// elements of this predicate mask are false or undef. That is, return true +/// if all lanes can be assumed inactive. +bool maskIsAllZeroOrUndef(Value *Mask); + +/// Given a mask vector of the form <Y x i1>, Return true if all of the +/// elements of this predicate mask are true or undef. That is, return true +/// if all lanes can be assumed active. +bool maskIsAllOneOrUndef(Value *Mask); + +/// Given a mask vector of the form <Y x i1>, return an APInt (of bitwidth Y) +/// for each lane which may be active. +APInt possiblyDemandedEltsInMask(Value *Mask); + /// The group of interleaved loads/stores sharing the same stride and /// close to each other. /// @@ -251,10 +270,10 @@ Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs); /// the interleaved store group doesn't allow gaps. template <typename InstTy> class InterleaveGroup { public: - InterleaveGroup(unsigned Factor, bool Reverse, unsigned Align) + InterleaveGroup(uint32_t Factor, bool Reverse, uint32_t Align) : Factor(Factor), Reverse(Reverse), Align(Align), InsertPos(nullptr) {} - InterleaveGroup(InstTy *Instr, int Stride, unsigned Align) + InterleaveGroup(InstTy *Instr, int32_t Stride, uint32_t Align) : Align(Align), InsertPos(Instr) { assert(Align && "The alignment should be non-zero"); @@ -266,19 +285,23 @@ public: } bool isReverse() const { return Reverse; } - unsigned getFactor() const { return Factor; } - unsigned getAlignment() const { return Align; } - unsigned getNumMembers() const { return Members.size(); } + uint32_t getFactor() const { return Factor; } + uint32_t getAlignment() const { return Align; } + uint32_t getNumMembers() const { return Members.size(); } /// Try to insert a new member \p Instr with index \p Index and /// alignment \p NewAlign. The index is related to the leader and it could be /// negative if it is the new leader. /// /// \returns false if the instruction doesn't belong to the group. - bool insertMember(InstTy *Instr, int Index, unsigned NewAlign) { + bool insertMember(InstTy *Instr, int32_t Index, uint32_t NewAlign) { assert(NewAlign && "The new member's alignment should be non-zero"); - int Key = Index + SmallestKey; + // Make sure the key fits in an int32_t. + Optional<int32_t> MaybeKey = checkedAdd(Index, SmallestKey); + if (!MaybeKey) + return false; + int32_t Key = *MaybeKey; // Skip if there is already a member with the same index. if (Members.find(Key) != Members.end()) @@ -286,13 +309,19 @@ public: if (Key > LargestKey) { // The largest index is always less than the interleave factor. - if (Index >= static_cast<int>(Factor)) + if (Index >= static_cast<int32_t>(Factor)) return false; LargestKey = Key; } else if (Key < SmallestKey) { + + // Make sure the largest index fits in an int32_t. + Optional<int32_t> MaybeLargestIndex = checkedSub(LargestKey, Key); + if (!MaybeLargestIndex) + return false; + // The largest index is always less than the interleave factor. - if (LargestKey - Key >= static_cast<int>(Factor)) + if (*MaybeLargestIndex >= static_cast<int64_t>(Factor)) return false; SmallestKey = Key; @@ -307,8 +336,8 @@ public: /// Get the member with the given index \p Index /// /// \returns nullptr if contains no such member. - InstTy *getMember(unsigned Index) const { - int Key = SmallestKey + Index; + InstTy *getMember(uint32_t Index) const { + int32_t Key = SmallestKey + Index; auto Member = Members.find(Key); if (Member == Members.end()) return nullptr; @@ -318,7 +347,7 @@ public: /// Get the index for the given member. Unlike the key in the member /// map, the index starts from 0. - unsigned getIndex(const InstTy *Instr) const { + uint32_t getIndex(const InstTy *Instr) const { for (auto I : Members) { if (I.second == Instr) return I.first - SmallestKey; @@ -356,12 +385,12 @@ public: } private: - unsigned Factor; // Interleave Factor. + uint32_t Factor; // Interleave Factor. bool Reverse; - unsigned Align; - DenseMap<int, InstTy *> Members; - int SmallestKey = 0; - int LargestKey = 0; + uint32_t Align; + DenseMap<int32_t, InstTy *> Members; + int32_t SmallestKey = 0; + int32_t LargestKey = 0; // To avoid breaking dependences, vectorized instructions of an interleave // group should be inserted at either the first load or the last store in diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h index 285a7c022a24..b0c603497805 100644 --- a/include/llvm/AsmParser/Parser.h +++ b/include/llvm/AsmParser/Parser.h @@ -1,9 +1,8 @@ //===-- Parser.h - Parser for LLVM IR text assembly files -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/AsmParser/SlotMapping.h b/include/llvm/AsmParser/SlotMapping.h index bd7e8fcad8bc..0e95eb816b4c 100644 --- a/include/llvm/AsmParser/SlotMapping.h +++ b/include/llvm/AsmParser/SlotMapping.h @@ -1,9 +1,8 @@ //===-- SlotMapping.h - Slot number mapping for unnamed values --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h b/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h index de44f41720ed..7332b2a7ea89 100644 --- a/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h +++ b/include/llvm/BinaryFormat/AMDGPUMetadataVerifier.h @@ -1,9 +1,8 @@ //===- AMDGPUMetadataVerifier.h - MsgPack Types -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,7 +16,7 @@ #ifndef LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H #define LLVM_BINARYFORMAT_AMDGPUMETADATAVERIFIER_H -#include "llvm/BinaryFormat/MsgPackTypes.h" +#include "llvm/BinaryFormat/MsgPackDocument.h" namespace llvm { namespace AMDGPU { @@ -34,22 +33,22 @@ namespace V3 { class MetadataVerifier { bool Strict; - bool verifyScalar(msgpack::Node &Node, msgpack::ScalarNode::ScalarKind SKind, - function_ref<bool(msgpack::ScalarNode &)> verifyValue = {}); - bool verifyInteger(msgpack::Node &Node); - bool verifyArray(msgpack::Node &Node, - function_ref<bool(msgpack::Node &)> verifyNode, + bool verifyScalar(msgpack::DocNode &Node, msgpack::Type SKind, + function_ref<bool(msgpack::DocNode &)> verifyValue = {}); + bool verifyInteger(msgpack::DocNode &Node); + bool verifyArray(msgpack::DocNode &Node, + function_ref<bool(msgpack::DocNode &)> verifyNode, Optional<size_t> Size = None); - bool verifyEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required, - function_ref<bool(msgpack::Node &)> verifyNode); + bool verifyEntry(msgpack::MapDocNode &MapNode, StringRef Key, bool Required, + function_ref<bool(msgpack::DocNode &)> verifyNode); bool - verifyScalarEntry(msgpack::MapNode &MapNode, StringRef Key, bool Required, - msgpack::ScalarNode::ScalarKind SKind, - function_ref<bool(msgpack::ScalarNode &)> verifyValue = {}); - bool verifyIntegerEntry(msgpack::MapNode &MapNode, StringRef Key, + verifyScalarEntry(msgpack::MapDocNode &MapNode, StringRef Key, bool Required, + msgpack::Type SKind, + function_ref<bool(msgpack::DocNode &)> verifyValue = {}); + bool verifyIntegerEntry(msgpack::MapDocNode &MapNode, StringRef Key, bool Required); - bool verifyKernelArgs(msgpack::Node &Node); - bool verifyKernel(msgpack::Node &Node); + bool verifyKernelArgs(msgpack::DocNode &Node); + bool verifyKernel(msgpack::DocNode &Node); public: /// Construct a MetadataVerifier, specifying whether it will operate in \p @@ -59,7 +58,7 @@ public: /// Verify given HSA metadata. /// /// \returns True when successful, false when metadata is invalid. - bool verify(msgpack::Node &HSAMetadataRoot); + bool verify(msgpack::DocNode &HSAMetadataRoot); }; } // end namespace V3 diff --git a/include/llvm/BinaryFormat/COFF.h b/include/llvm/BinaryFormat/COFF.h index 7b973c03cc80..0fe38a437725 100644 --- a/include/llvm/BinaryFormat/COFF.h +++ b/include/llvm/BinaryFormat/COFF.h @@ -1,9 +1,8 @@ //===-- llvm/BinaryFormat/COFF.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -371,13 +370,15 @@ enum RelocationTypesARM : unsigned { IMAGE_REL_ARM_TOKEN = 0x0005, IMAGE_REL_ARM_BLX24 = 0x0008, IMAGE_REL_ARM_BLX11 = 0x0009, + IMAGE_REL_ARM_REL32 = 0x000A, IMAGE_REL_ARM_SECTION = 0x000E, IMAGE_REL_ARM_SECREL = 0x000F, IMAGE_REL_ARM_MOV32A = 0x0010, IMAGE_REL_ARM_MOV32T = 0x0011, IMAGE_REL_ARM_BRANCH20T = 0x0012, IMAGE_REL_ARM_BRANCH24T = 0x0014, - IMAGE_REL_ARM_BLX23T = 0x0015 + IMAGE_REL_ARM_BLX23T = 0x0015, + IMAGE_REL_ARM_PAIR = 0x0016, }; enum RelocationTypesARM64 : unsigned { @@ -398,9 +399,10 @@ enum RelocationTypesARM64 : unsigned { IMAGE_REL_ARM64_ADDR64 = 0x000E, IMAGE_REL_ARM64_BRANCH19 = 0x000F, IMAGE_REL_ARM64_BRANCH14 = 0x0010, + IMAGE_REL_ARM64_REL32 = 0x0011, }; -enum COMDATType : unsigned { +enum COMDATType : uint8_t { IMAGE_COMDAT_SELECT_NODUPLICATES = 1, IMAGE_COMDAT_SELECT_ANY, IMAGE_COMDAT_SELECT_SAME_SIZE, diff --git a/include/llvm/BinaryFormat/Dwarf.def b/include/llvm/BinaryFormat/Dwarf.def index 6ad3cb57f62f..b0f78d0fd61f 100644 --- a/include/llvm/BinaryFormat/Dwarf.def +++ b/include/llvm/BinaryFormat/Dwarf.def @@ -1,9 +1,8 @@ //===- llvm/Support/Dwarf.def - Dwarf definitions ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -355,7 +354,13 @@ HANDLE_DW_AT(0x2107, GNU_vector, 0, GNU) HANDLE_DW_AT(0x2110, GNU_template_name, 0, GNU) HANDLE_DW_AT(0x210f, GNU_odr_signature, 0, GNU) HANDLE_DW_AT(0x2111, GNU_call_site_value, 0, GNU) +HANDLE_DW_AT (0x2112, GNU_call_site_data_value, 0, GNU) +HANDLE_DW_AT (0x2113, GNU_call_site_target, 0, GNU) +HANDLE_DW_AT (0x2114, GNU_call_site_target_clobbered, 0, GNU) +HANDLE_DW_AT (0x2115, GNU_tail_call, 0, GNU) +HANDLE_DW_AT (0x2116, GNU_all_tail_call_sites, 0, GNU) HANDLE_DW_AT(0x2117, GNU_all_call_sites, 0, GNU) +HANDLE_DW_AT (0x2118, GNU_all_source_call_sites, 0, GNU) HANDLE_DW_AT(0x2119, GNU_macros, 0, GNU) // Extensions for Fission proposal. HANDLE_DW_AT(0x2130, GNU_dwo_name, 0, GNU) @@ -387,6 +392,7 @@ HANDLE_DW_AT(0x3b31, BORLAND_closure, 0, BORLAND) HANDLE_DW_AT(0x3e00, LLVM_include_path, 0, LLVM) HANDLE_DW_AT(0x3e01, LLVM_config_macros, 0, LLVM) HANDLE_DW_AT(0x3e02, LLVM_isysroot, 0, LLVM) +HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM) // Apple extensions. HANDLE_DW_AT(0x3fe1, APPLE_optimized, 0, APPLE) HANDLE_DW_AT(0x3fe2, APPLE_flags, 0, APPLE) @@ -627,6 +633,8 @@ HANDLE_DW_OP(0xa9, reinterpret, 5, DWARF) // Vendor extensions: // Extensions for GNU-style thread-local storage. HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU) +// The GNU entry value extension. +HANDLE_DW_OP(0xf3, GNU_entry_value, 0, GNU) // Extensions for Fission proposal. HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU) HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU) diff --git a/include/llvm/BinaryFormat/Dwarf.h b/include/llvm/BinaryFormat/Dwarf.h index 525a04d5e6cf..76d9c365c0a8 100644 --- a/include/llvm/BinaryFormat/Dwarf.h +++ b/include/llvm/BinaryFormat/Dwarf.h @@ -1,9 +1,8 @@ //===-- llvm/BinaryFormat/Dwarf.h ---Dwarf Constants-------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -130,7 +129,9 @@ enum LocationAtom { #include "llvm/BinaryFormat/Dwarf.def" DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, - DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata. + DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata. + DW_OP_LLVM_convert = 0x1001, ///< Only used in LLVM metadata. + DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata. }; enum TypeKind : uint8_t { diff --git a/include/llvm/BinaryFormat/DynamicTags.def b/include/llvm/BinaryFormat/DynamicTags.def index 2e15cc30fca7..aec408bd2d72 100644 --- a/include/llvm/BinaryFormat/DynamicTags.def +++ b/include/llvm/BinaryFormat/DynamicTags.def @@ -6,6 +6,11 @@ // such as DT_HIOS, etc. to allow using this file to in other contexts. // For example we can use it to generate a stringification switch statement. +#ifndef AARCH64_DYNAMIC_TAG +#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define AARCH64_DYNAMIC_TAG_DEFINED +#endif + #ifndef HEXAGON_DYNAMIC_TAG #define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) #define HEXAGON_DYNAMIC_TAG_DEFINED @@ -16,6 +21,11 @@ #define MIPS_DYNAMIC_TAG_DEFINED #endif +#ifndef PPC_DYNAMIC_TAG +#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define PPC_DYNAMIC_TAG_DEFINED +#endif + #ifndef PPC64_DYNAMIC_TAG #define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) #define PPC64_DYNAMIC_TAG_DEFINED @@ -107,6 +117,10 @@ DYNAMIC_TAG(VERNEED, 0X6FFFFFFE) // The address of the version dependency // table. DYNAMIC_TAG(VERNEEDNUM, 0X6FFFFFFF) // The number of entries in DT_VERNEED. +// AArch64 specific dynamic table entries +AARCH64_DYNAMIC_TAG(AARCH64_BTI_PLT, 0x70000001) +AARCH64_DYNAMIC_TAG(AARCH64_PAC_PLT, 0x70000003) + // Hexagon specific dynamic table entries HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000) HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001) @@ -190,17 +204,27 @@ MIPS_DYNAMIC_TAG(MIPS_RWPLT, 0x70000034) // Points to the base MIPS_DYNAMIC_TAG(MIPS_RLD_MAP_REL, 0x70000035) // Relative offset of run time loader // map, used for debugging. +// PPC specific dynamic table entries. +PPC_DYNAMIC_TAG(PPC_GOT, 0x70000000) // Uses Secure PLT ABI. +PPC_DYNAMIC_TAG(PPC_OPT, 0x70000001) // Has TLS optimization. + // PPC64 specific dynamic table entries. PPC64_DYNAMIC_TAG(PPC64_GLINK, 0x70000000) // Address of 32 bytes before the // first glink lazy resolver stub. // Sun machine-independent extensions. DYNAMIC_TAG(AUXILIARY, 0x7FFFFFFD) // Shared object to load before self +DYNAMIC_TAG(USED, 0x7FFFFFFE) // Same as DT_NEEDED DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from #ifdef DYNAMIC_TAG_MARKER_DEFINED #undef DYNAMIC_TAG_MARKER +#undef DYNAMIC_TAG_MARKER_DEFINED +#endif +#ifdef AARCH64_DYNAMIC_TAG_DEFINED +#undef AARCH64_DYNAMIC_TAG +#undef AARCH64_DYNAMIC_TAG_DEFINED #endif #ifdef MIPS_DYNAMIC_TAG_DEFINED #undef MIPS_DYNAMIC_TAG @@ -210,6 +234,10 @@ DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from #undef HEXAGON_DYNAMIC_TAG #undef HEXAGON_DYNAMIC_TAG_DEFINED #endif +#ifdef PPC_DYNAMIC_TAG_DEFINED +#undef PPC_DYNAMIC_TAG +#undef PPC_DYNAMIC_TAG_DEFINED +#endif #ifdef PPC64_DYNAMIC_TAG_DEFINED #undef PPC64_DYNAMIC_TAG #undef PPC64_DYNAMIC_TAG_DEFINED diff --git a/include/llvm/BinaryFormat/ELF.h b/include/llvm/BinaryFormat/ELF.h index ce35d127d433..2bd711137845 100644 --- a/include/llvm/BinaryFormat/ELF.h +++ b/include/llvm/BinaryFormat/ELF.h @@ -1,9 +1,8 @@ //===- llvm/BinaryFormat/ELF.h - ELF constants and structures ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -703,15 +702,20 @@ enum : unsigned { EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, + // AMDGCN GFX10. + EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, + EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, + EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, // Reserved for AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027, - EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x030, + EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x032, // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX909, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX1012, // Indicates if the "xnack" target feature is enabled for all code contained // in the object. @@ -839,6 +843,10 @@ enum : unsigned { SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile. SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols // for safe ICF. + SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04, // LLVM Dependent Library Specifiers. + SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. + SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. + SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. @@ -1340,6 +1348,14 @@ enum { NT_FREEBSD_PROCSTAT_AUXV = 16, }; +// Generic note types +enum : unsigned { + NT_VERSION = 1, + NT_ARCH = 2, + NT_GNU_BUILD_ATTRIBUTE_OPEN = 0x100, + NT_GNU_BUILD_ATTRIBUTE_FUNC = 0x101, +}; + enum { NT_GNU_ABI_TAG = 1, NT_GNU_HWCAP = 2, @@ -1352,13 +1368,65 @@ enum { enum : unsigned { GNU_PROPERTY_STACK_SIZE = 1, GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2, - GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002 + GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000, + GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002, + GNU_PROPERTY_X86_ISA_1_NEEDED = 0xc0008000, + GNU_PROPERTY_X86_FEATURE_2_NEEDED = 0xc0008001, + GNU_PROPERTY_X86_ISA_1_USED = 0xc0010000, + GNU_PROPERTY_X86_FEATURE_2_USED = 0xc0010001, }; -// CET properties -enum { +// aarch64 processor feature bits. +enum : unsigned { + GNU_PROPERTY_AARCH64_FEATURE_1_BTI = 1 << 0, + GNU_PROPERTY_AARCH64_FEATURE_1_PAC = 1 << 1, +}; + +// x86 processor feature bits. +enum : unsigned { GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0, - GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1 + GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1, + + GNU_PROPERTY_X86_ISA_1_CMOV = 1 << 0, + GNU_PROPERTY_X86_ISA_1_SSE = 1 << 1, + GNU_PROPERTY_X86_ISA_1_SSE2 = 1 << 2, + GNU_PROPERTY_X86_ISA_1_SSE3 = 1 << 3, + GNU_PROPERTY_X86_ISA_1_SSSE3 = 1 << 4, + GNU_PROPERTY_X86_ISA_1_SSE4_1 = 1 << 5, + GNU_PROPERTY_X86_ISA_1_SSE4_2 = 1 << 6, + GNU_PROPERTY_X86_ISA_1_AVX = 1 << 7, + GNU_PROPERTY_X86_ISA_1_AVX2 = 1 << 8, + GNU_PROPERTY_X86_ISA_1_FMA = 1 << 9, + GNU_PROPERTY_X86_ISA_1_AVX512F = 1 << 10, + GNU_PROPERTY_X86_ISA_1_AVX512CD = 1 << 11, + GNU_PROPERTY_X86_ISA_1_AVX512ER = 1 << 12, + GNU_PROPERTY_X86_ISA_1_AVX512PF = 1 << 13, + GNU_PROPERTY_X86_ISA_1_AVX512VL = 1 << 14, + GNU_PROPERTY_X86_ISA_1_AVX512DQ = 1 << 15, + GNU_PROPERTY_X86_ISA_1_AVX512BW = 1 << 16, + GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS = 1 << 17, + GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW = 1 << 18, + GNU_PROPERTY_X86_ISA_1_AVX512_BITALG = 1 << 19, + GNU_PROPERTY_X86_ISA_1_AVX512_IFMA = 1 << 20, + GNU_PROPERTY_X86_ISA_1_AVX512_VBMI = 1 << 21, + GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2 = 1 << 22, + GNU_PROPERTY_X86_ISA_1_AVX512_VNNI = 1 << 23, + + GNU_PROPERTY_X86_FEATURE_2_X86 = 1 << 0, + GNU_PROPERTY_X86_FEATURE_2_X87 = 1 << 1, + GNU_PROPERTY_X86_FEATURE_2_MMX = 1 << 2, + GNU_PROPERTY_X86_FEATURE_2_XMM = 1 << 3, + GNU_PROPERTY_X86_FEATURE_2_YMM = 1 << 4, + GNU_PROPERTY_X86_FEATURE_2_ZMM = 1 << 5, + GNU_PROPERTY_X86_FEATURE_2_FXSR = 1 << 6, + GNU_PROPERTY_X86_FEATURE_2_XSAVE = 1 << 7, + GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT = 1 << 8, + GNU_PROPERTY_X86_FEATURE_2_XSAVEC = 1 << 9, +}; + +// AMDGPU-specific section indices. +enum { + SHN_AMDGPU_LDS = 0xff00, // Variable in LDS; symbol encoded like SHN_COMMON }; // AMD specific notes. (Code Object V2) diff --git a/include/llvm/BinaryFormat/ELFRelocs/ARM.def b/include/llvm/BinaryFormat/ELFRelocs/ARM.def index 730fc5b8836c..e0709fb81813 100644 --- a/include/llvm/BinaryFormat/ELFRelocs/ARM.def +++ b/include/llvm/BinaryFormat/ELFRelocs/ARM.def @@ -135,4 +135,7 @@ ELF_RELOC(R_ARM_PRIVATE_15, 0x7f) ELF_RELOC(R_ARM_ME_TOO, 0x80) ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81) ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82) +ELF_RELOC(R_ARM_THM_BF16, 0x88) +ELF_RELOC(R_ARM_THM_BF12, 0x89) +ELF_RELOC(R_ARM_THM_BF18, 0x8a) ELF_RELOC(R_ARM_IRELATIVE, 0xa0) diff --git a/include/llvm/BinaryFormat/ELFRelocs/PowerPC.def b/include/llvm/BinaryFormat/ELFRelocs/PowerPC.def index e4f8ee0ebe2b..28036889cca6 100644 --- a/include/llvm/BinaryFormat/ELFRelocs/PowerPC.def +++ b/include/llvm/BinaryFormat/ELFRelocs/PowerPC.def @@ -27,9 +27,25 @@ #undef R_PPC_GOT16_HI #undef R_PPC_GOT16_HA #undef R_PPC_PLTREL24 +#undef R_PPC_COPY +#undef R_PPC_GLOB_DAT #undef R_PPC_JMP_SLOT +#undef R_PPC_RELATIVE #undef R_PPC_LOCAL24PC +#undef R_PPC_UADDR32 +#undef R_PPC_UADDR16 #undef R_PPC_REL32 +#undef R_PPC_PLT32 +#undef R_PPC_PLTREL32 +#undef R_PPC_PLT16_LO +#undef R_PPC_PLT16_HI +#undef R_PPC_PLT16_HA +#undef R_PPC_SDAREL16 +#undef R_PPC_SECTOFF +#undef R_PPC_SECTOFF_LO +#undef R_PPC_SECTOFF_HI +#undef R_PPC_SECTOFF_HA +#undef R_PPC_ADDR30 #undef R_PPC_TLS #undef R_PPC_DTPMOD32 #undef R_PPC_TPREL16 @@ -84,9 +100,25 @@ ELF_RELOC(R_PPC_GOT16_LO, 15) ELF_RELOC(R_PPC_GOT16_HI, 16) ELF_RELOC(R_PPC_GOT16_HA, 17) ELF_RELOC(R_PPC_PLTREL24, 18) +ELF_RELOC(R_PPC_COPY, 19) +ELF_RELOC(R_PPC_GLOB_DAT, 20) ELF_RELOC(R_PPC_JMP_SLOT, 21) +ELF_RELOC(R_PPC_RELATIVE, 22) ELF_RELOC(R_PPC_LOCAL24PC, 23) +ELF_RELOC(R_PPC_UADDR32, 24) +ELF_RELOC(R_PPC_UADDR16, 25) ELF_RELOC(R_PPC_REL32, 26) +ELF_RELOC(R_PPC_PLT32, 27) +ELF_RELOC(R_PPC_PLTREL32, 28) +ELF_RELOC(R_PPC_PLT16_LO, 29) +ELF_RELOC(R_PPC_PLT16_HI, 30) +ELF_RELOC(R_PPC_PLT16_HA, 31) +ELF_RELOC(R_PPC_SDAREL16, 32) +ELF_RELOC(R_PPC_SECTOFF, 33) +ELF_RELOC(R_PPC_SECTOFF_LO, 34) +ELF_RELOC(R_PPC_SECTOFF_HI, 35) +ELF_RELOC(R_PPC_SECTOFF_HA, 36) +ELF_RELOC(R_PPC_ADDR30, 37) ELF_RELOC(R_PPC_TLS, 67) ELF_RELOC(R_PPC_DTPMOD32, 68) ELF_RELOC(R_PPC_TPREL16, 69) @@ -117,6 +149,7 @@ ELF_RELOC(R_PPC_GOT_DTPREL16_HI, 93) ELF_RELOC(R_PPC_GOT_DTPREL16_HA, 94) ELF_RELOC(R_PPC_TLSGD, 95) ELF_RELOC(R_PPC_TLSLD, 96) +ELF_RELOC(R_PPC_IRELATIVE, 248) ELF_RELOC(R_PPC_REL16, 249) ELF_RELOC(R_PPC_REL16_LO, 250) ELF_RELOC(R_PPC_REL16_HI, 251) diff --git a/include/llvm/BinaryFormat/MachO.def b/include/llvm/BinaryFormat/MachO.def index 95de48d2b19e..76dcc58ba048 100644 --- a/include/llvm/BinaryFormat/MachO.def +++ b/include/llvm/BinaryFormat/MachO.def @@ -1,9 +1,8 @@ //,,,-- llvm/Support/MachO.def - The MachO file definitions -----*- C++ -*-,,,// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //,,,----------------------------------------------------------------------,,,// // diff --git a/include/llvm/BinaryFormat/MachO.h b/include/llvm/BinaryFormat/MachO.h index b3d60984249f..a01393a3b303 100644 --- a/include/llvm/BinaryFormat/MachO.h +++ b/include/llvm/BinaryFormat/MachO.h @@ -1,9 +1,8 @@ //===-- llvm/BinaryFormat/MachO.h - The MachO file format -------*- C++/-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -335,6 +334,7 @@ enum { N_WEAK_DEF = 0x0080u, N_SYMBOL_RESOLVER = 0x0100u, N_ALT_ENTRY = 0x0200u, + N_COLD_FUNC = 0x0400u, // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL() // as these are in the top 8 bits. SELF_LIBRARY_ORDINAL = 0x0, @@ -487,6 +487,7 @@ enum PlatformType { PLATFORM_TVOS = 3, PLATFORM_WATCHOS = 4, PLATFORM_BRIDGEOS = 5, + PLATFORM_MACCATALYST = 6, PLATFORM_IOSSIMULATOR = 7, PLATFORM_TVOSSIMULATOR = 8, PLATFORM_WATCHOSSIMULATOR = 9 @@ -942,8 +943,13 @@ struct fat_arch_64 { // Structs from <mach-o/reloc.h> struct relocation_info { int32_t r_address; +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) + uint32_t r_type : 4, r_extern : 1, r_length : 2, r_pcrel : 1, + r_symbolnum : 24; +#else uint32_t r_symbolnum : 24, r_pcrel : 1, r_length : 2, r_extern : 1, r_type : 4; +#endif }; struct scattered_relocation_info { @@ -1396,7 +1402,8 @@ inline void SET_COMM_ALIGN(uint16_t &n_desc, uint8_t align) { enum : uint32_t { // Capability bits used in the definition of cpu_type. CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits - CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI + CPU_ARCH_ABI64 = 0x01000000, // 64 bit ABI + CPU_ARCH_ABI64_32 = 0x02000000, // ILP32 ABI on 64-bit hardware }; // Constants for the cputype field. @@ -1409,6 +1416,7 @@ enum CPUType { CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC CPU_TYPE_ARM = 12, CPU_TYPE_ARM64 = CPU_TYPE_ARM | CPU_ARCH_ABI64, + CPU_TYPE_ARM64_32 = CPU_TYPE_ARM | CPU_ARCH_ABI64_32, CPU_TYPE_SPARC = 14, CPU_TYPE_POWERPC = 18, CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 @@ -1477,7 +1485,12 @@ enum CPUSubTypeARM { CPU_SUBTYPE_ARM_V7EM = 16 }; -enum CPUSubTypeARM64 { CPU_SUBTYPE_ARM64_ALL = 0 }; +enum CPUSubTypeARM64 { + CPU_SUBTYPE_ARM64_ALL = 0, + CPU_SUBTYPE_ARM64E = 2, +}; + +enum CPUSubTypeARM64_32 { CPU_SUBTYPE_ARM64_32_V8 = 1 }; enum CPUSubTypeSPARC { CPU_SUBTYPE_SPARC_ALL = 0 }; diff --git a/include/llvm/BinaryFormat/Magic.h b/include/llvm/BinaryFormat/Magic.h index 04801f810be3..cd9833ec4d22 100644 --- a/include/llvm/BinaryFormat/Magic.h +++ b/include/llvm/BinaryFormat/Magic.h @@ -1,9 +1,8 @@ //===- llvm/BinaryFormat/Magic.h - File magic identification ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -40,11 +39,14 @@ struct file_magic { macho_dsym_companion, ///< Mach-O dSYM companion file macho_kext_bundle, ///< Mach-O kext bundle file macho_universal_binary, ///< Mach-O universal binary + minidump, ///< Windows minidump file coff_cl_gl_object, ///< Microsoft cl.exe's intermediate code file coff_object, ///< COFF object file coff_import_library, ///< COFF import library pecoff_executable, ///< PECOFF executable file windows_resource, ///< Windows compiled resource file (.res) + xcoff_object_32, ///< 32-bit XCOFF object file + xcoff_object_64, ///< 64-bit XCOFF object file wasm_object, ///< WebAssembly Object file pdb, ///< Windows PDB debug info file }; diff --git a/include/llvm/BinaryFormat/Minidump.h b/include/llvm/BinaryFormat/Minidump.h new file mode 100644 index 000000000000..65c17d1eb00c --- /dev/null +++ b/include/llvm/BinaryFormat/Minidump.h @@ -0,0 +1,203 @@ +//===- Minidump.h - Minidump constants and structures -----------*- 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 constants and data structures pertaining to the Windows Minidump +// core file format. +// +// Reference: +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx +// https://chromium.googlesource.com/breakpad/breakpad/ +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_MINIDUMP_H +#define LLVM_BINARYFORMAT_MINIDUMP_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace minidump { + +/// The minidump header is the first part of a minidump file. It identifies the +/// file as a minidump file, and gives the location of the stream directory. +struct Header { + static constexpr uint32_t MagicSignature = 0x504d444d; // PMDM + static constexpr uint16_t MagicVersion = 0xa793; + + support::ulittle32_t Signature; + // The high 16 bits of version field are implementation specific. The low 16 + // bits should be MagicVersion. + support::ulittle32_t Version; + support::ulittle32_t NumberOfStreams; + support::ulittle32_t StreamDirectoryRVA; + support::ulittle32_t Checksum; + support::ulittle32_t TimeDateStamp; + support::ulittle64_t Flags; +}; +static_assert(sizeof(Header) == 32, ""); + +/// The type of a minidump stream identifies its contents. Streams numbers after +/// LastReserved are for application-defined data streams. +enum class StreamType : uint32_t { +#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) NAME = CODE, +#include "llvm/BinaryFormat/MinidumpConstants.def" + Unused = 0, + LastReserved = 0x0000ffff, +}; + +/// Specifies the location (and size) of various objects in the minidump file. +/// The location is relative to the start of the file. +struct LocationDescriptor { + support::ulittle32_t DataSize; + support::ulittle32_t RVA; +}; +static_assert(sizeof(LocationDescriptor) == 8, ""); + +/// Describes a single memory range (both its VM address and where to find it in +/// the file) of the process from which this minidump file was generated. +struct MemoryDescriptor { + support::ulittle64_t StartOfMemoryRange; + LocationDescriptor Memory; +}; +static_assert(sizeof(MemoryDescriptor) == 16, ""); + +/// Specifies the location and type of a single stream in the minidump file. The +/// minidump stream directory is an array of entries of this type, with its size +/// given by Header.NumberOfStreams. +struct Directory { + support::little_t<StreamType> Type; + LocationDescriptor Location; +}; +static_assert(sizeof(Directory) == 12, ""); + +/// The processor architecture of the system that generated this minidump. Used +/// in the ProcessorArch field of the SystemInfo stream. +enum class ProcessorArchitecture : uint16_t { +#define HANDLE_MDMP_ARCH(CODE, NAME) NAME = CODE, +#include "llvm/BinaryFormat/MinidumpConstants.def" +}; + +/// The OS Platform of the system that generated this minidump. Used in the +/// PlatformId field of the SystemInfo stream. +enum class OSPlatform : uint32_t { +#define HANDLE_MDMP_PLATFORM(CODE, NAME) NAME = CODE, +#include "llvm/BinaryFormat/MinidumpConstants.def" +}; + +/// Detailed information about the processor of the system that generated this +/// minidump. Its interpretation depends on the ProcessorArchitecture enum. +union CPUInfo { + struct X86Info { + char VendorID[12]; // cpuid 0: ebx, edx, ecx + support::ulittle32_t VersionInfo; // cpuid 1: eax + support::ulittle32_t FeatureInfo; // cpuid 1: edx + support::ulittle32_t AMDExtendedFeatures; // cpuid 0x80000001, ebx + } X86; + struct ArmInfo { + support::ulittle32_t CPUID; + support::ulittle32_t ElfHWCaps; // linux specific, 0 otherwise + } Arm; + struct OtherInfo { + uint8_t ProcessorFeatures[16]; + } Other; +}; +static_assert(sizeof(CPUInfo) == 24, ""); + +/// The SystemInfo stream, containing various information about the system where +/// this minidump was generated. +struct SystemInfo { + support::little_t<ProcessorArchitecture> ProcessorArch; + support::ulittle16_t ProcessorLevel; + support::ulittle16_t ProcessorRevision; + + uint8_t NumberOfProcessors; + uint8_t ProductType; + + support::ulittle32_t MajorVersion; + support::ulittle32_t MinorVersion; + support::ulittle32_t BuildNumber; + support::little_t<OSPlatform> PlatformId; + support::ulittle32_t CSDVersionRVA; + + support::ulittle16_t SuiteMask; + support::ulittle16_t Reserved; + + CPUInfo CPU; +}; +static_assert(sizeof(SystemInfo) == 56, ""); + +struct VSFixedFileInfo { + support::ulittle32_t Signature; + support::ulittle32_t StructVersion; + support::ulittle32_t FileVersionHigh; + support::ulittle32_t FileVersionLow; + support::ulittle32_t ProductVersionHigh; + support::ulittle32_t ProductVersionLow; + support::ulittle32_t FileFlagsMask; + support::ulittle32_t FileFlags; + support::ulittle32_t FileOS; + support::ulittle32_t FileType; + support::ulittle32_t FileSubtype; + support::ulittle32_t FileDateHigh; + support::ulittle32_t FileDateLow; +}; +static_assert(sizeof(VSFixedFileInfo) == 52, ""); + +inline bool operator==(const VSFixedFileInfo &LHS, const VSFixedFileInfo &RHS) { + return memcmp(&LHS, &RHS, sizeof(VSFixedFileInfo)) == 0; +} + +struct Module { + support::ulittle64_t BaseOfImage; + support::ulittle32_t SizeOfImage; + support::ulittle32_t Checksum; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ModuleNameRVA; + VSFixedFileInfo VersionInfo; + LocationDescriptor CvRecord; + LocationDescriptor MiscRecord; + support::ulittle64_t Reserved0; + support::ulittle64_t Reserved1; +}; +static_assert(sizeof(Module) == 108, ""); + +/// Describes a single thread in the minidump file. Part of the ThreadList +/// stream. +struct Thread { + support::ulittle32_t ThreadId; + support::ulittle32_t SuspendCount; + support::ulittle32_t PriorityClass; + support::ulittle32_t Priority; + support::ulittle64_t EnvironmentBlock; + MemoryDescriptor Stack; + LocationDescriptor Context; +}; +static_assert(sizeof(Thread) == 48, ""); + +} // namespace minidump + +template <> struct DenseMapInfo<minidump::StreamType> { + static minidump::StreamType getEmptyKey() { return minidump::StreamType(-1); } + + static minidump::StreamType getTombstoneKey() { + return minidump::StreamType(-2); + } + + static unsigned getHashValue(minidump::StreamType Val) { + return DenseMapInfo<uint32_t>::getHashValue(static_cast<uint32_t>(Val)); + } + + static bool isEqual(minidump::StreamType LHS, minidump::StreamType RHS) { + return LHS == RHS; + } +}; + +} // namespace llvm + +#endif // LLVM_BINARYFORMAT_MINIDUMP_H diff --git a/include/llvm/BinaryFormat/MinidumpConstants.def b/include/llvm/BinaryFormat/MinidumpConstants.def new file mode 100644 index 000000000000..d4f13dd99217 --- /dev/null +++ b/include/llvm/BinaryFormat/MinidumpConstants.def @@ -0,0 +1,107 @@ +//===- MinidumpConstants.def - Iteration over minidump 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 +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_MDMP_STREAM_TYPE || defined HANDLE_MDMP_ARCH || \ + defined HANDLE_MDMP_PLATFORM) +#error "Missing HANDLE_MDMP definition" +#endif + +#ifndef HANDLE_MDMP_STREAM_TYPE +#define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) +#endif + +#ifndef HANDLE_MDMP_ARCH +#define HANDLE_MDMP_ARCH(CODE, NAME) +#endif + +#ifndef HANDLE_MDMP_PLATFORM +#define HANDLE_MDMP_PLATFORM(CODE, NAME) +#endif + +HANDLE_MDMP_STREAM_TYPE(0x0003, ThreadList) +HANDLE_MDMP_STREAM_TYPE(0x0004, ModuleList) +HANDLE_MDMP_STREAM_TYPE(0x0005, MemoryList) +HANDLE_MDMP_STREAM_TYPE(0x0006, Exception) +HANDLE_MDMP_STREAM_TYPE(0x0007, SystemInfo) +HANDLE_MDMP_STREAM_TYPE(0x0008, ThreadExList) +HANDLE_MDMP_STREAM_TYPE(0x0009, Memory64List) +HANDLE_MDMP_STREAM_TYPE(0x000a, CommentA) +HANDLE_MDMP_STREAM_TYPE(0x000b, CommentW) +HANDLE_MDMP_STREAM_TYPE(0x000c, HandleData) +HANDLE_MDMP_STREAM_TYPE(0x000d, FunctionTable) +HANDLE_MDMP_STREAM_TYPE(0x000e, UnloadedModuleList) +HANDLE_MDMP_STREAM_TYPE(0x000f, MiscInfo) +HANDLE_MDMP_STREAM_TYPE(0x0010, MemoryInfoList) +HANDLE_MDMP_STREAM_TYPE(0x0011, ThreadInfoList) +HANDLE_MDMP_STREAM_TYPE(0x0012, HandleOperationList) +HANDLE_MDMP_STREAM_TYPE(0x0013, Token) +HANDLE_MDMP_STREAM_TYPE(0x0014, JavascriptData) +HANDLE_MDMP_STREAM_TYPE(0x0015, SystemMemoryInfo) +HANDLE_MDMP_STREAM_TYPE(0x0016, ProcessVMCounters) +// Breakpad extension types. 0x4767 = "Gg" +HANDLE_MDMP_STREAM_TYPE(0x47670001, BreakpadInfo) +HANDLE_MDMP_STREAM_TYPE(0x47670002, AssertionInfo) +// These are additional minidump stream values which are specific to the linux +// breakpad implementation. +HANDLE_MDMP_STREAM_TYPE(0x47670003, LinuxCPUInfo) // /proc/cpuinfo +HANDLE_MDMP_STREAM_TYPE(0x47670004, LinuxProcStatus) // /proc/$x/status +HANDLE_MDMP_STREAM_TYPE(0x47670005, LinuxLSBRelease) // /etc/lsb-release +HANDLE_MDMP_STREAM_TYPE(0x47670006, LinuxCMDLine) // /proc/$x/cmdline +HANDLE_MDMP_STREAM_TYPE(0x47670007, LinuxEnviron) // /proc/$x/environ +HANDLE_MDMP_STREAM_TYPE(0x47670008, LinuxAuxv) // /proc/$x/auxv +HANDLE_MDMP_STREAM_TYPE(0x47670009, LinuxMaps) // /proc/$x/maps +HANDLE_MDMP_STREAM_TYPE(0x4767000A, LinuxDSODebug) +HANDLE_MDMP_STREAM_TYPE(0x4767000B, LinuxProcStat) // /proc/$x/stat +HANDLE_MDMP_STREAM_TYPE(0x4767000C, LinuxProcUptime) // uptime +HANDLE_MDMP_STREAM_TYPE(0x4767000D, LinuxProcFD) // /proc/$x/fd +// Facebook-defined stream types +HANDLE_MDMP_STREAM_TYPE(0xFACE1CA7, FacebookLogcat) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFA, FacebookAppCustomData) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFB, FacebookBuildID) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFC, FacebookAppVersionName) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFD, FacebookJavaStack) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFE, FacebookDalvikInfo) +HANDLE_MDMP_STREAM_TYPE(0xFACECAFF, FacebookUnwindSymbols) +HANDLE_MDMP_STREAM_TYPE(0xFACECB00, FacebookDumpErrorLog) +HANDLE_MDMP_STREAM_TYPE(0xFACECCCC, FacebookAppStateLog) +HANDLE_MDMP_STREAM_TYPE(0xFACEDEAD, FacebookAbortReason) +HANDLE_MDMP_STREAM_TYPE(0xFACEE000, FacebookThreadName) + +HANDLE_MDMP_ARCH(0x0000, X86) // PROCESSOR_ARCHITECTURE_INTEL +HANDLE_MDMP_ARCH(0x0001, MIPS) // PROCESSOR_ARCHITECTURE_MIPS +HANDLE_MDMP_ARCH(0x0002, Alpha) // PROCESSOR_ARCHITECTURE_ALPHA +HANDLE_MDMP_ARCH(0x0003, PPC) // PROCESSOR_ARCHITECTURE_PPC +HANDLE_MDMP_ARCH(0x0004, SHX) // PROCESSOR_ARCHITECTURE_SHX (Super-H) +HANDLE_MDMP_ARCH(0x0005, ARM) // PROCESSOR_ARCHITECTURE_ARM +HANDLE_MDMP_ARCH(0x0006, IA64) // PROCESSOR_ARCHITECTURE_IA64 +HANDLE_MDMP_ARCH(0x0007, Alpha64) // PROCESSOR_ARCHITECTURE_ALPHA64 +HANDLE_MDMP_ARCH(0x0008, MSIL) // PROCESSOR_ARCHITECTURE_MSIL +HANDLE_MDMP_ARCH(0x0009, AMD64) // PROCESSOR_ARCHITECTURE_AMD64 +HANDLE_MDMP_ARCH(0x000a, X86Win64) // PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 +HANDLE_MDMP_ARCH(0x8001, SPARC) // Breakpad-defined value for SPARC +HANDLE_MDMP_ARCH(0x8002, PPC64) // Breakpad-defined value for PPC64 +HANDLE_MDMP_ARCH(0x8003, ARM64) // Breakpad-defined value for ARM64 +HANDLE_MDMP_ARCH(0x8004, MIPS64) // Breakpad-defined value for MIPS64 + +HANDLE_MDMP_PLATFORM(0x0000, Win32S) // Win32 on Windows 3.1 +HANDLE_MDMP_PLATFORM(0x0001, Win32Windows) // Windows 95-98-Me +HANDLE_MDMP_PLATFORM(0x0002, Win32NT) // Windows NT, 2000+ +HANDLE_MDMP_PLATFORM(0x0003, Win32CE) // Windows CE, Windows Mobile, "Handheld" +// Breakpad-defined values. +HANDLE_MDMP_PLATFORM(0x8000, Unix) // Generic Unix-ish +HANDLE_MDMP_PLATFORM(0x8101, MacOSX) // Mac OS X/Darwin +HANDLE_MDMP_PLATFORM(0x8102, IOS) // iOS +HANDLE_MDMP_PLATFORM(0x8201, Linux) // Linux +HANDLE_MDMP_PLATFORM(0x8202, Solaris) // Solaris +HANDLE_MDMP_PLATFORM(0x8203, Android) // Android +HANDLE_MDMP_PLATFORM(0x8204, PS3) // PS3 +HANDLE_MDMP_PLATFORM(0x8205, NaCl) // Native Client (NaCl) + +#undef HANDLE_MDMP_STREAM_TYPE +#undef HANDLE_MDMP_ARCH +#undef HANDLE_MDMP_PLATFORM diff --git a/include/llvm/BinaryFormat/MsgPack.def b/include/llvm/BinaryFormat/MsgPack.def index 781b49f46aeb..7ad83ff21c42 100644 --- a/include/llvm/BinaryFormat/MsgPack.def +++ b/include/llvm/BinaryFormat/MsgPack.def @@ -1,9 +1,8 @@ //===- MsgPack.def - MessagePack definitions --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/BinaryFormat/MsgPack.h b/include/llvm/BinaryFormat/MsgPack.h index d431912a53e5..9fda14b21c71 100644 --- a/include/llvm/BinaryFormat/MsgPack.h +++ b/include/llvm/BinaryFormat/MsgPack.h @@ -1,9 +1,8 @@ //===-- MsgPack.h - MessagePack Constants -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/BinaryFormat/MsgPackDocument.h b/include/llvm/BinaryFormat/MsgPackDocument.h new file mode 100644 index 000000000000..824ecc353207 --- /dev/null +++ b/include/llvm/BinaryFormat/MsgPackDocument.h @@ -0,0 +1,385 @@ +//===-- MsgPackDocument.h - MsgPack Document --------------------*- 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 a class that exposes a simple in-memory representation +/// of a document of MsgPack objects, that can be read from MsgPack, written to +/// MsgPack, and inspected and modified in memory. This is intended to be a +/// lighter-weight (in terms of memory allocations) replacement for +/// MsgPackTypes. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H +#define LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H + +#include "llvm/BinaryFormat/MsgPackReader.h" +#include <map> + +namespace llvm { +namespace msgpack { + +class ArrayDocNode; +class Document; +class MapDocNode; + +/// The kind of a DocNode and its owning Document. +struct KindAndDocument { + Document *Doc; + Type Kind; +}; + +/// A node in a MsgPack Document. This is a simple copyable and +/// passable-by-value type that does not own any memory. +class DocNode { + friend Document; + +public: + typedef std::map<DocNode, DocNode> MapTy; + typedef std::vector<DocNode> ArrayTy; + +private: + // Using KindAndDocument allows us to squeeze Kind and a pointer to the + // owning Document into the same word. Having a pointer to the owning + // Document makes the API of DocNode more convenient, and allows its use in + // YAMLIO. + const KindAndDocument *KindAndDoc; + +protected: + // The union of different values. + union { + int64_t Int; + uint64_t UInt; + bool Bool; + double Float; + StringRef Raw; + ArrayTy *Array; + MapTy *Map; + }; + +public: + DocNode() : KindAndDoc(nullptr) {} + + // Type methods + bool isMap() const { return getKind() == Type::Map; } + bool isArray() const { return getKind() == Type::Array; } + bool isScalar() const { return !isMap() && !isArray(); } + bool isString() const { return getKind() == Type::String; } + + // Accessors + bool isEmpty() const { return !KindAndDoc; } + Type getKind() const { return KindAndDoc->Kind; } + Document *getDocument() const { return KindAndDoc->Doc; } + + int64_t &getInt() { + assert(getKind() == Type::Int); + return Int; + } + + uint64_t &getUInt() { + assert(getKind() == Type::UInt); + return UInt; + } + + bool &getBool() { + assert(getKind() == Type::Boolean); + return Bool; + } + + double &getFloat() { + assert(getKind() == Type::Float); + return Float; + } + + int64_t getInt() const { + assert(getKind() == Type::Int); + return Int; + } + + uint64_t getUInt() const { + assert(getKind() == Type::UInt); + return UInt; + } + + bool getBool() const { + assert(getKind() == Type::Boolean); + return Bool; + } + + double getFloat() const { + assert(getKind() == Type::Float); + return Float; + } + + StringRef getString() const { + assert(getKind() == Type::String); + return Raw; + } + + /// Get an ArrayDocNode for an array node. If Convert, convert the node to an + /// array node if necessary. + ArrayDocNode &getArray(bool Convert = false) { + if (getKind() != Type::Array) { + assert(Convert); + convertToArray(); + } + // This could be a static_cast, except ArrayDocNode is a forward reference. + return *reinterpret_cast<ArrayDocNode *>(this); + } + + /// Get a MapDocNode for a map node. If Convert, convert the node to a map + /// node if necessary. + MapDocNode &getMap(bool Convert = false) { + if (getKind() != Type::Map) { + assert(Convert); + convertToMap(); + } + // This could be a static_cast, except MapDocNode is a forward reference. + return *reinterpret_cast<MapDocNode *>(this); + } + + /// Comparison operator, used for map keys. + friend bool operator<(const DocNode &Lhs, const DocNode &Rhs) { + // This has to cope with one or both of the nodes being default-constructed, + // such that KindAndDoc is not set. + if (Lhs.KindAndDoc != Rhs.KindAndDoc) { + if (!Rhs.KindAndDoc) + return false; + if (!Lhs.KindAndDoc) + return true; + return (unsigned)Lhs.getKind() < (unsigned)Rhs.getKind(); + } + switch (Lhs.getKind()) { + case Type::Int: + return Lhs.Int < Rhs.Int; + case Type::UInt: + return Lhs.UInt < Rhs.UInt; + case Type::Nil: + return false; + case Type::Boolean: + return Lhs.Bool < Rhs.Bool; + case Type::Float: + return Lhs.Float < Rhs.Float; + case Type::String: + case Type::Binary: + return Lhs.Raw < Rhs.Raw; + default: + llvm_unreachable("bad map key type"); + } + } + + /// Equality operator + friend bool operator==(const DocNode &Lhs, const DocNode &Rhs) { + return !(Lhs < Rhs) && !(Rhs < Lhs); + } + + /// Convert this node to a string, assuming it is scalar. + std::string toString() const; + + /// Convert the StringRef and use it to set this DocNode (assuming scalar). If + /// it is a string, copy the string into the Document's strings list so we do + /// not rely on S having a lifetime beyond this call. Tag is "" or a YAML tag. + StringRef fromString(StringRef S, StringRef Tag = ""); + +private: + // Private constructor setting KindAndDoc, used by methods in Document. + DocNode(const KindAndDocument *KindAndDoc) : KindAndDoc(KindAndDoc) {} + + void convertToArray(); + void convertToMap(); +}; + +/// A DocNode that is a map. +class MapDocNode : public DocNode { +public: + MapDocNode() {} + MapDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Map); } + + // Map access methods. + size_t size() const { return Map->size(); } + bool empty() const { return !size(); } + MapTy::iterator begin() { return Map->begin(); } + MapTy::iterator end() { return Map->end(); } + MapTy::iterator find(DocNode Key) { return Map->find(Key); } + MapTy::iterator find(StringRef Key); + /// Member access. The string data must remain valid for the lifetime of the + /// Document. + DocNode &operator[](StringRef S); + /// Member access. + DocNode &operator[](DocNode Key); +}; + +/// A DocNode that is an array. +class ArrayDocNode : public DocNode { +public: + ArrayDocNode() {} + ArrayDocNode(DocNode &N) : DocNode(N) { assert(getKind() == Type::Array); } + + // Array access methods. + size_t size() const { return Array->size(); } + bool empty() const { return !size(); } + ArrayTy::iterator begin() { return Array->begin(); } + ArrayTy::iterator end() { return Array->end(); } + void push_back(DocNode N) { + assert(N.getDocument() == getDocument()); + Array->push_back(N); + } + + /// Element access. This extends the array if necessary. + DocNode &operator[](size_t Index); +}; + +/// Simple in-memory representation of a document of msgpack objects with +/// ability to find and create array and map elements. Does not currently cope +/// with any extension types. +class Document { + // Maps, arrays and strings used by nodes in the document. No attempt is made + // to free unused ones. + std::vector<std::unique_ptr<DocNode::MapTy>> Maps; + std::vector<std::unique_ptr<DocNode::ArrayTy>> Arrays; + std::vector<std::unique_ptr<char[]>> Strings; + + // The root node of the document. + DocNode Root; + + // The KindAndDocument structs pointed to by nodes in the document. + KindAndDocument KindAndDocs[size_t(Type::Extension) + 1]; + + // Whether YAML output uses hex for UInt. + bool HexMode = false; + +public: + Document() { + clear(); + for (unsigned T = 0; T != size_t(Type::Extension) + 1; ++T) + KindAndDocs[T] = {this, Type(T)}; + } + + /// Get ref to the document's root element. + DocNode &getRoot() { return Root; } + + /// Restore the Document to an empty state. + void clear() { getRoot() = getNode(); } + + /// Create a nil node associated with this Document. + DocNode getNode() { + auto N = DocNode(&KindAndDocs[size_t(Type::Nil)]); + return N; + } + + /// Create an Int node associated with this Document. + DocNode getNode(int64_t V) { + auto N = DocNode(&KindAndDocs[size_t(Type::Int)]); + N.Int = V; + return N; + } + + /// Create an Int node associated with this Document. + DocNode getNode(int V) { + auto N = DocNode(&KindAndDocs[size_t(Type::Int)]); + N.Int = V; + return N; + } + + /// Create a UInt node associated with this Document. + DocNode getNode(uint64_t V) { + auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]); + N.UInt = V; + return N; + } + + /// Create a UInt node associated with this Document. + DocNode getNode(unsigned V) { + auto N = DocNode(&KindAndDocs[size_t(Type::UInt)]); + N.UInt = V; + return N; + } + + /// Create a Boolean node associated with this Document. + DocNode getNode(bool V) { + auto N = DocNode(&KindAndDocs[size_t(Type::Boolean)]); + N.Bool = V; + return N; + } + + /// Create a Float node associated with this Document. + DocNode getNode(double V) { + auto N = DocNode(&KindAndDocs[size_t(Type::Float)]); + N.Float = V; + return N; + } + + /// Create a String node associated with this Document. If !Copy, the passed + /// string must remain valid for the lifetime of the Document. + DocNode getNode(StringRef V, bool Copy = false) { + if (Copy) + V = addString(V); + auto N = DocNode(&KindAndDocs[size_t(Type::String)]); + N.Raw = V; + return N; + } + + /// Create a String node associated with this Document. If !Copy, the passed + /// string must remain valid for the lifetime of the Document. + DocNode getNode(const char *V, bool Copy = false) { + return getNode(StringRef(V), Copy); + } + + /// Create an empty Map node associated with this Document. + MapDocNode getMapNode() { + auto N = DocNode(&KindAndDocs[size_t(Type::Map)]); + Maps.push_back(std::unique_ptr<DocNode::MapTy>(new DocNode::MapTy)); + N.Map = Maps.back().get(); + return N.getMap(); + } + + /// Create an empty Array node associated with this Document. + ArrayDocNode getArrayNode() { + auto N = DocNode(&KindAndDocs[size_t(Type::Array)]); + Arrays.push_back(std::unique_ptr<DocNode::ArrayTy>(new DocNode::ArrayTy)); + N.Array = Arrays.back().get(); + return N.getArray(); + } + + /// Read a MsgPack document from a binary MsgPack blob. + /// The blob data must remain valid for the lifetime of this Document (because + /// a string object in the document contains a StringRef into the original + /// blob). + /// If Multi, then this sets root to an array and adds top-level objects to + /// it. If !Multi, then it only reads a single top-level object, even if there + /// are more, and sets root to that. + /// Returns false if failed due to illegal format. + bool readFromBlob(StringRef Blob, bool Multi); + + /// Write a MsgPack document to a binary MsgPack blob. + void writeToBlob(std::string &Blob); + + /// Copy a string into the Document's strings list, and return the copy that + /// is owned by the Document. + StringRef addString(StringRef S) { + Strings.push_back(std::unique_ptr<char[]>(new char[S.size()])); + memcpy(&Strings.back()[0], S.data(), S.size()); + return StringRef(&Strings.back()[0], S.size()); + } + + /// Set whether YAML output uses hex for UInt. Default off. + void setHexMode(bool Val = true) { HexMode = Val; } + + /// Get Hexmode flag. + bool getHexMode() const { return HexMode; } + + /// Convert MsgPack Document to YAML text. + void toYAML(raw_ostream &OS); + + /// Read YAML text into the MsgPack document. Returns false on failure. + bool fromYAML(StringRef S); +}; + +} // namespace msgpack +} // namespace llvm + +#endif // LLVM_BINARYFORMAT_MSGPACKDOCUMENT_H diff --git a/include/llvm/BinaryFormat/MsgPackReader.h b/include/llvm/BinaryFormat/MsgPackReader.h index 511c31407455..2d332f531b23 100644 --- a/include/llvm/BinaryFormat/MsgPackReader.h +++ b/include/llvm/BinaryFormat/MsgPackReader.h @@ -1,9 +1,8 @@ //===- MsgPackReader.h - Simple MsgPack reader ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/BinaryFormat/MsgPackTypes.h b/include/llvm/BinaryFormat/MsgPackTypes.h deleted file mode 100644 index f96cd4c338fd..000000000000 --- a/include/llvm/BinaryFormat/MsgPackTypes.h +++ /dev/null @@ -1,372 +0,0 @@ -//===- MsgPackTypes.h - MsgPack Types ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This is a data structure for representing MessagePack "documents", with -/// methods to go to and from MessagePack. The types also specialize YAMLIO -/// traits in order to go to and from YAML. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Optional.h" -#include "llvm/BinaryFormat/MsgPackReader.h" -#include "llvm/BinaryFormat/MsgPackWriter.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/YAMLTraits.h" -#include <vector> - -#ifndef LLVM_BINARYFORMAT_MSGPACKTYPES_H -#define LLVM_BINARYFORMAT_MSGPACKTYPES_H - -namespace llvm { -namespace msgpack { - -class Node; - -/// Short-hand for a Node pointer. -using NodePtr = std::shared_ptr<Node>; - -/// Short-hand for an Optional Node pointer. -using OptNodePtr = Optional<NodePtr>; - -/// Abstract base-class which can be any MessagePack type. -class Node { -public: - enum NodeKind { - NK_Scalar, - NK_Array, - NK_Map, - }; - -private: - virtual void anchor() = 0; - const NodeKind Kind; - - static Expected<OptNodePtr> readArray(Reader &MPReader, size_t Length); - static Expected<OptNodePtr> readMap(Reader &MPReader, size_t Length); - -public: - NodeKind getKind() const { return Kind; } - - /// Construct a Node. Used by derived classes to track kind information. - Node(NodeKind Kind) : Kind(Kind) {} - - virtual ~Node() = default; - - /// Read from a MessagePack reader \p MPReader, returning an error if one is - /// encountered, or None if \p MPReader is at the end of stream, or some Node - /// pointer if some type is read. - static Expected<OptNodePtr> read(Reader &MPReader); - - /// Write to a MessagePack writer \p MPWriter. - virtual void write(Writer &MPWriter) = 0; -}; - -/// A MessagePack scalar. -class ScalarNode : public Node { -public: - enum ScalarKind { - SK_Int, - SK_UInt, - SK_Nil, - SK_Boolean, - SK_Float, - SK_String, - SK_Binary, - }; - -private: - void anchor() override; - - void destroy(); - - ScalarKind SKind; - - union { - int64_t IntValue; - uint64_t UIntValue; - bool BoolValue; - double FloatValue; - std::string StringValue; - }; - -public: - /// Construct an Int ScalarNode. - ScalarNode(int64_t IntValue); - /// Construct an Int ScalarNode. - ScalarNode(int32_t IntValue); - /// Construct an UInt ScalarNode. - ScalarNode(uint64_t UIntValue); - /// Construct an UInt ScalarNode. - ScalarNode(uint32_t UIntValue); - /// Construct a Nil ScalarNode. - ScalarNode(); - /// Construct a Boolean ScalarNode. - ScalarNode(bool BoolValue); - /// Construct a Float ScalarNode. - ScalarNode(double FloatValue); - /// Construct a String ScalarNode. - ScalarNode(StringRef StringValue); - /// Construct a String ScalarNode. - ScalarNode(const char *StringValue); - /// Construct a String ScalarNode. - ScalarNode(std::string &&StringValue); - /// Construct a Binary ScalarNode. - ScalarNode(MemoryBufferRef BinaryValue); - - ~ScalarNode(); - - ScalarNode &operator=(const ScalarNode &RHS) = delete; - /// A ScalarNode can only be move assigned. - ScalarNode &operator=(ScalarNode &&RHS); - - /// Change the kind of this ScalarNode, zero initializing it to the new type. - void setScalarKind(ScalarKind SKind) { - switch (SKind) { - case SK_Int: - *this = int64_t(0); - break; - case SK_UInt: - *this = uint64_t(0); - break; - case SK_Boolean: - *this = false; - break; - case SK_Float: - *this = 0.0; - break; - case SK_String: - *this = StringRef(); - break; - case SK_Binary: - *this = MemoryBufferRef("", ""); - break; - case SK_Nil: - *this = ScalarNode(); - break; - } - } - - /// Get the current kind of ScalarNode. - ScalarKind getScalarKind() { return SKind; } - - /// Get the value of an Int scalar. - /// - /// \warning Assumes getScalarKind() == SK_Int - int64_t getInt() { - assert(SKind == SK_Int); - return IntValue; - } - - /// Get the value of a UInt scalar. - /// - /// \warning Assumes getScalarKind() == SK_UInt - uint64_t getUInt() { - assert(SKind == SK_UInt); - return UIntValue; - } - - /// Get the value of an Boolean scalar. - /// - /// \warning Assumes getScalarKind() == SK_Boolean - bool getBool() { - assert(SKind == SK_Boolean); - return BoolValue; - } - - /// Get the value of an Float scalar. - /// - /// \warning Assumes getScalarKind() == SK_Float - double getFloat() { - assert(SKind == SK_Float); - return FloatValue; - } - - /// Get the value of a String scalar. - /// - /// \warning Assumes getScalarKind() == SK_String - StringRef getString() { - assert(SKind == SK_String); - return StringValue; - } - - /// Get the value of a Binary scalar. - /// - /// \warning Assumes getScalarKind() == SK_Binary - StringRef getBinary() { - assert(SKind == SK_Binary); - return StringValue; - } - - static bool classof(const Node *N) { return N->getKind() == NK_Scalar; } - - void write(Writer &MPWriter) override; - - /// Parse a YAML scalar of the current ScalarKind from \p ScalarStr. - /// - /// \returns An empty string on success, otherwise an error message. - StringRef inputYAML(StringRef ScalarStr); - - /// Output a YAML scalar of the current ScalarKind into \p OS. - void outputYAML(raw_ostream &OS) const; - - /// Determine which YAML quoting type the current value would need when - /// output. - yaml::QuotingType mustQuoteYAML(StringRef ScalarStr) const; - - /// Get the YAML tag for the current ScalarKind. - StringRef getYAMLTag() const; - - /// Flag which affects how the type handles YAML tags when reading and - /// writing. - /// - /// When false, tags are used when reading and writing. When reading, the tag - /// is used to decide the ScalarKind before parsing. When writing, the tag is - /// output along with the value. - /// - /// When true, tags are ignored when reading and writing. When reading, the - /// ScalarKind is always assumed to be String. When writing, the tag is not - /// output. - bool IgnoreTag = false; - - static const char *IntTag; - static const char *NilTag; - static const char *BooleanTag; - static const char *FloatTag; - static const char *StringTag; - static const char *BinaryTag; -}; - -class ArrayNode : public Node, public std::vector<NodePtr> { - void anchor() override; - -public: - ArrayNode() : Node(NK_Array) {} - static bool classof(const Node *N) { return N->getKind() == NK_Array; } - - void write(Writer &MPWriter) override { - MPWriter.writeArraySize(this->size()); - for (auto &N : *this) - N->write(MPWriter); - } -}; - -class MapNode : public Node, public StringMap<NodePtr> { - void anchor() override; - -public: - MapNode() : Node(NK_Map) {} - static bool classof(const Node *N) { return N->getKind() == NK_Map; } - - void write(Writer &MPWriter) override { - MPWriter.writeMapSize(this->size()); - for (auto &N : *this) { - MPWriter.write(N.first()); - N.second->write(MPWriter); - } - } -}; - -} // end namespace msgpack - -namespace yaml { - -template <> struct PolymorphicTraits<msgpack::NodePtr> { - static NodeKind getKind(const msgpack::NodePtr &N) { - if (isa<msgpack::ScalarNode>(*N)) - return NodeKind::Scalar; - if (isa<msgpack::MapNode>(*N)) - return NodeKind::Map; - if (isa<msgpack::ArrayNode>(*N)) - return NodeKind::Sequence; - llvm_unreachable("NodeKind not supported"); - } - static msgpack::ScalarNode &getAsScalar(msgpack::NodePtr &N) { - if (!N || !isa<msgpack::ScalarNode>(*N)) - N.reset(new msgpack::ScalarNode()); - return *cast<msgpack::ScalarNode>(N.get()); - } - static msgpack::MapNode &getAsMap(msgpack::NodePtr &N) { - if (!N || !isa<msgpack::MapNode>(*N)) - N.reset(new msgpack::MapNode()); - return *cast<msgpack::MapNode>(N.get()); - } - static msgpack::ArrayNode &getAsSequence(msgpack::NodePtr &N) { - if (!N || !isa<msgpack::ArrayNode>(*N)) - N.reset(new msgpack::ArrayNode()); - return *cast<msgpack::ArrayNode>(N.get()); - } -}; - -template <> struct TaggedScalarTraits<msgpack::ScalarNode> { - static void output(const msgpack::ScalarNode &S, void *Ctxt, - raw_ostream &ScalarOS, raw_ostream &TagOS) { - if (!S.IgnoreTag) - TagOS << S.getYAMLTag(); - S.outputYAML(ScalarOS); - } - - static StringRef input(StringRef ScalarStr, StringRef Tag, void *Ctxt, - msgpack::ScalarNode &S) { - if (Tag == msgpack::ScalarNode::IntTag) { - S.setScalarKind(msgpack::ScalarNode::SK_UInt); - if (S.inputYAML(ScalarStr) == StringRef()) - return StringRef(); - S.setScalarKind(msgpack::ScalarNode::SK_Int); - return S.inputYAML(ScalarStr); - } - - if (S.IgnoreTag || Tag == msgpack::ScalarNode::StringTag || - Tag == "tag:yaml.org,2002:str") - S.setScalarKind(msgpack::ScalarNode::SK_String); - else if (Tag == msgpack::ScalarNode::NilTag) - S.setScalarKind(msgpack::ScalarNode::SK_Nil); - else if (Tag == msgpack::ScalarNode::BooleanTag) - S.setScalarKind(msgpack::ScalarNode::SK_Boolean); - else if (Tag == msgpack::ScalarNode::FloatTag) - S.setScalarKind(msgpack::ScalarNode::SK_Float); - else if (Tag == msgpack::ScalarNode::StringTag) - S.setScalarKind(msgpack::ScalarNode::SK_String); - else if (Tag == msgpack::ScalarNode::BinaryTag) - S.setScalarKind(msgpack::ScalarNode::SK_Binary); - else - return "Unsupported messagepack tag"; - - return S.inputYAML(ScalarStr); - } - - static QuotingType mustQuote(const msgpack::ScalarNode &S, StringRef Str) { - return S.mustQuoteYAML(Str); - } -}; - -template <> struct CustomMappingTraits<msgpack::MapNode> { - static void inputOne(IO &IO, StringRef Key, msgpack::MapNode &M) { - IO.mapRequired(Key.str().c_str(), M[Key]); - } - static void output(IO &IO, msgpack::MapNode &M) { - for (auto &N : M) - IO.mapRequired(N.getKey().str().c_str(), N.getValue()); - } -}; - -template <> struct SequenceTraits<msgpack::ArrayNode> { - static size_t size(IO &IO, msgpack::ArrayNode &A) { return A.size(); } - static msgpack::NodePtr &element(IO &IO, msgpack::ArrayNode &A, - size_t Index) { - if (Index >= A.size()) - A.resize(Index + 1); - return A[Index]; - } -}; - -} // end namespace yaml -} // end namespace llvm - -#endif // LLVM_BINARYFORMAT_MSGPACKTYPES_H diff --git a/include/llvm/BinaryFormat/MsgPackWriter.h b/include/llvm/BinaryFormat/MsgPackWriter.h index 98af422c9f19..3b610b774f77 100644 --- a/include/llvm/BinaryFormat/MsgPackWriter.h +++ b/include/llvm/BinaryFormat/MsgPackWriter.h @@ -1,9 +1,8 @@ //===- MsgPackWriter.h - Simple MsgPack writer ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/BinaryFormat/Wasm.h b/include/llvm/BinaryFormat/Wasm.h index d9f0f94b298d..0f22bfe610c6 100644 --- a/include/llvm/BinaryFormat/Wasm.h +++ b/include/llvm/BinaryFormat/Wasm.h @@ -1,9 +1,8 @@ //===- Wasm.h - Wasm object file format -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,6 +42,17 @@ struct WasmDylinkInfo { std::vector<StringRef> Needed; // Shared library depenedencies }; +struct WasmProducerInfo { + std::vector<std::pair<std::string, std::string>> Languages; + std::vector<std::pair<std::string, std::string>> Tools; + std::vector<std::pair<std::string, std::string>> SDKs; +}; + +struct WasmFeatureEntry { + uint8_t Prefix; + std::string Name; +}; + struct WasmExport { StringRef Name; uint8_t Kind; @@ -126,12 +136,13 @@ struct WasmFunction { }; struct WasmDataSegment { - uint32_t MemoryIndex; - WasmInitExpr Offset; + uint32_t InitFlags; + uint32_t MemoryIndex; // present if InitFlags & WASM_SEGMENT_HAS_MEMINDEX + WasmInitExpr Offset; // present if InitFlags & WASM_SEGMENT_IS_PASSIVE == 0 ArrayRef<uint8_t> Content; StringRef Name; // from the "segment info" section uint32_t Alignment; - uint32_t Flags; + uint32_t LinkerFlags; uint32_t Comdat; // from the "comdat info" section }; @@ -165,7 +176,8 @@ struct WasmSymbolInfo { StringRef Name; uint8_t Kind; uint32_t Flags; - StringRef Module; // For undefined symbols the module name of the import + StringRef ImportModule; // For undefined symbols the module of the import + StringRef ImportName; // For undefined symbols the name of the import union { // For function or global symbols, the index in function or global index // space. @@ -212,7 +224,7 @@ enum : unsigned { WASM_TYPE_F64 = 0x7C, WASM_TYPE_V128 = 0x7B, WASM_TYPE_FUNCREF = 0x70, - WASM_TYPE_EXCEPT_REF = 0x68, + WASM_TYPE_EXNREF = 0x68, WASM_TYPE_FUNC = 0x60, WASM_TYPE_NORESULT = 0x40, // for blocks with no result values }; @@ -229,11 +241,19 @@ enum : unsigned { // Opcodes used in initializer expressions. enum : unsigned { WASM_OPCODE_END = 0x0b, + WASM_OPCODE_CALL = 0x10, + WASM_OPCODE_LOCAL_GET = 0x20, WASM_OPCODE_GLOBAL_GET = 0x23, + WASM_OPCODE_GLOBAL_SET = 0x24, + WASM_OPCODE_I32_STORE = 0x36, WASM_OPCODE_I32_CONST = 0x41, WASM_OPCODE_I64_CONST = 0x42, WASM_OPCODE_F32_CONST = 0x43, WASM_OPCODE_F64_CONST = 0x44, + WASM_OPCODE_I32_ADD = 0x6a, + WASM_OPCODE_MISC_PREFIX = 0xfc, + WASM_OPCODE_MEMORY_INIT = 0x08, + WASM_OPCODE_DATA_DROP = 0x09, }; enum : unsigned { @@ -241,6 +261,18 @@ enum : unsigned { WASM_LIMITS_FLAG_IS_SHARED = 0x2, }; +enum : unsigned { + WASM_SEGMENT_IS_PASSIVE = 0x01, + WASM_SEGMENT_HAS_MEMINDEX = 0x02, +}; + +// Feature policy prefixes used in the custom "target_features" section +enum : uint8_t { + WASM_FEATURE_PREFIX_USED = '+', + WASM_FEATURE_PREFIX_REQUIRED = '=', + WASM_FEATURE_PREFIX_DISALLOWED = '-', +}; + // Kind codes used in the custom "name" section enum : unsigned { WASM_NAMES_FUNCTION = 0x1, @@ -284,6 +316,8 @@ const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; const unsigned WASM_SYMBOL_UNDEFINED = 0x10; +const unsigned WASM_SYMBOL_EXPORTED = 0x20; +const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; #define WASM_RELOC(name, value) name = value, @@ -300,17 +334,17 @@ enum class ValType { F32 = WASM_TYPE_F32, F64 = WASM_TYPE_F64, V128 = WASM_TYPE_V128, - EXCEPT_REF = WASM_TYPE_EXCEPT_REF, + EXNREF = WASM_TYPE_EXNREF, }; struct WasmSignature { - SmallVector<wasm::ValType, 1> Returns; - SmallVector<wasm::ValType, 4> Params; + SmallVector<ValType, 1> Returns; + SmallVector<ValType, 4> Params; // Support empty and tombstone instances, needed by DenseMap. enum { Plain, Empty, Tombstone } State = Plain; - WasmSignature(SmallVector<wasm::ValType, 1> &&InReturns, - SmallVector<wasm::ValType, 4> &&InParams) + WasmSignature(SmallVector<ValType, 1> &&InReturns, + SmallVector<ValType, 4> &&InParams) : Returns(InReturns), Params(InParams) {} WasmSignature() = default; }; @@ -333,8 +367,9 @@ inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { return !(LHS == RHS); } -std::string toString(wasm::WasmSymbolType type); +std::string toString(WasmSymbolType type); std::string relocTypetoString(uint32_t type); +bool relocTypeHasAddend(uint32_t type); } // end namespace wasm } // end namespace llvm diff --git a/include/llvm/BinaryFormat/WasmRelocs.def b/include/llvm/BinaryFormat/WasmRelocs.def index b3a08e70c1d5..00dacf72abb0 100644 --- a/include/llvm/BinaryFormat/WasmRelocs.def +++ b/include/llvm/BinaryFormat/WasmRelocs.def @@ -2,14 +2,16 @@ #error "WASM_RELOC must be defined" #endif -WASM_RELOC(R_WEBASSEMBLY_FUNCTION_INDEX_LEB, 0) -WASM_RELOC(R_WEBASSEMBLY_TABLE_INDEX_SLEB, 1) -WASM_RELOC(R_WEBASSEMBLY_TABLE_INDEX_I32, 2) -WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_LEB, 3) -WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_SLEB, 4) -WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_I32, 5) -WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6) -WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7) -WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8) -WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9) -WASM_RELOC(R_WEBASSEMBLY_EVENT_INDEX_LEB, 10) +WASM_RELOC(R_WASM_FUNCTION_INDEX_LEB, 0) +WASM_RELOC(R_WASM_TABLE_INDEX_SLEB, 1) +WASM_RELOC(R_WASM_TABLE_INDEX_I32, 2) +WASM_RELOC(R_WASM_MEMORY_ADDR_LEB, 3) +WASM_RELOC(R_WASM_MEMORY_ADDR_SLEB, 4) +WASM_RELOC(R_WASM_MEMORY_ADDR_I32, 5) +WASM_RELOC(R_WASM_TYPE_INDEX_LEB, 6) +WASM_RELOC(R_WASM_GLOBAL_INDEX_LEB, 7) +WASM_RELOC(R_WASM_FUNCTION_OFFSET_I32, 8) +WASM_RELOC(R_WASM_SECTION_OFFSET_I32, 9) +WASM_RELOC(R_WASM_EVENT_INDEX_LEB, 10) +WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB, 11) +WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB, 12) diff --git a/include/llvm/BinaryFormat/XCOFF.h b/include/llvm/BinaryFormat/XCOFF.h new file mode 100644 index 000000000000..7774ab3ed24a --- /dev/null +++ b/include/llvm/BinaryFormat/XCOFF.h @@ -0,0 +1,145 @@ +//===-- llvm/BinaryFormat/XCOFF.h - The XCOFF file format -------*- 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 manifest constants for the XCOFF object file format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINARYFORMAT_XCOFF_H +#define LLVM_BINARYFORMAT_XCOFF_H + +#include <cstdint> + +namespace llvm { +namespace XCOFF { + +// Constants used in the XCOFF definition. +enum { SectionNameSize = 8, SymbolNameSize = 8 }; +enum ReservedSectionNum { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 }; + +// x_smclas field of x_csect from system header: /usr/include/syms.h +/// Storage Mapping Class definitions. +enum StorageMappingClass { + // READ ONLY CLASSES + XMC_PR = 0, ///< Program Code + XMC_RO = 1, ///< Read Only Constant + XMC_DB = 2, ///< Debug Dictionary Table + XMC_GL = 6, ///< Global Linkage (Interfile Interface Code) + XMC_XO = 7, ///< Extended Operation (Pseudo Machine Instruction) + XMC_SV = 8, ///< Supervisor Call (32-bit process only) + XMC_SV64 = 17, ///< Supervisor Call for 64-bit process + XMC_SV3264 = 18, ///< Supervisor Call for both 32- and 64-bit processes + XMC_TI = 12, ///< Traceback Index csect + XMC_TB = 13, ///< Traceback Table csect + + // READ WRITE CLASSES + XMC_RW = 5, ///< Read Write Data + XMC_TC0 = 15, ///< TOC Anchor for TOC Addressability + XMC_TC = 3, ///< General TOC item + XMC_TD = 16, ///< Scalar data item in the TOC + XMC_DS = 10, ///< Descriptor csect + XMC_UA = 4, ///< Unclassified - Treated as Read Write + XMC_BS = 9, ///< BSS class (uninitialized static internal) + XMC_UC = 11, ///< Un-named Fortran Common + + XMC_TL = 20, ///< Initialized thread-local variable + XMC_UL = 21, ///< Uninitialized thread-local variable + XMC_TE = 22 ///< Symbol mapped at the end of TOC +}; + +// Flags for defining the section type. Used for the s_flags field of +// the section header structure. Defined in the system header `scnhdr.h`. +enum SectionTypeFlags { + STYP_PAD = 0x0008, + STYP_DWARF = 0x0010, + STYP_TEXT = 0x0020, + STYP_DATA = 0x0040, + STYP_BSS = 0x0080, + STYP_EXCEPT = 0x0100, + STYP_INFO = 0x0200, + STYP_TDATA = 0x0400, + STYP_TBSS = 0x0800, + STYP_LOADER = 0x1000, + STYP_DEBUG = 0x2000, + STYP_TYPCHK = 0x4000, + STYP_OVRFLO = 0x8000 +}; + +// STORAGE CLASSES, n_sclass field of syment. +// The values come from `storclass.h` and `dbxstclass.h`. +enum StorageClass : uint8_t { + // Storage classes used for symbolic debugging symbols. + C_FILE = 103, // File name + C_BINCL = 108, // Beginning of include file + C_EINCL = 109, // Ending of include file + C_GSYM = 128, // Global variable + C_STSYM = 133, // Statically allocated symbol + C_BCOMM = 135, // Beginning of common block + C_ECOMM = 137, // End of common block + C_ENTRY = 141, // Alternate entry + C_BSTAT = 143, // Beginning of static block + C_ESTAT = 144, // End of static block + C_GTLS = 145, // Global thread-local variable + C_STTLS = 146, // Static thread-local variable + + // Storage classes used for DWARF symbols. + C_DWARF = 112, // DWARF section symbol + + // Storage classes used for absolute symbols. + C_LSYM = 129, // Automatic variable allocated on stack + C_PSYM = 130, // Argument to subroutine allocated on stack + C_RSYM = 131, // Register variable + C_RPSYM = 132, // Argument to function or procedure stored in register + C_ECOML = 136, // Local member of common block + C_FUN = 142, // Function or procedure + + // Storage classes used for undefined external symbols or + // symbols of general sections. + C_EXT = 2, // External symbol + C_WEAKEXT = 111, // Weak external symbol + + // Storage classes used for symbols of general sections. + C_NULL = 0, + C_STAT = 3, // Static + C_BLOCK = 100, // ".bb" or ".eb" + C_FCN = 101, // ".bf" or ".ef" + C_HIDEXT = 107, // Un-named external symbol + C_INFO = 110, // Comment string in .info section + C_DECL = 140, // Declaration of object (type) + + // Storage classes - Obsolete/Undocumented. + C_AUTO = 1, // Automatic variable + C_REG = 4, // Register variable + C_EXTDEF = 5, // External definition + C_LABEL = 6, // Label + C_ULABEL = 7, // Undefined label + C_MOS = 8, // Member of structure + C_ARG = 9, // Function argument + C_STRTAG = 10, // Structure tag + C_MOU = 11, // Member of union + C_UNTAG = 12, // Union tag + C_TPDEF = 13, // Type definition + C_USTATIC = 14, // Undefined static + C_ENTAG = 15, // Enumeration tag + C_MOE = 16, // Member of enumeration + C_REGPARM = 17, // Register parameter + C_FIELD = 18, // Bit field + C_EOS = 102, // End of structure + C_LINE = 104, + C_ALIAS = 105, // Duplicate tag + C_HIDDEN = 106, // Special storage class for external + C_EFCN = 255, // Physical end of function + + // Storage classes - reserved + C_TCSYM = 134 // Reserved +}; + +} // end namespace XCOFF +} // end namespace llvm + +#endif diff --git a/include/llvm/Bitcode/BitcodeAnalyzer.h b/include/llvm/Bitcode/BitcodeAnalyzer.h new file mode 100644 index 000000000000..cfdebd6fe6cb --- /dev/null +++ b/include/llvm/Bitcode/BitcodeAnalyzer.h @@ -0,0 +1,103 @@ +//===- llvm/Bitcode/BitcodeAnalyzer.h - Bitcode 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 header defines interfaces to analyze LLVM bitcode files/streams. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODE_ANALYZER_H +#define LLVM_BITCODE_BITCODE_ANALYZER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitstream/BitstreamReader.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" +#include <map> +#include <vector> + +namespace llvm { + +/// CurStreamTypeType - A type for CurStreamType +enum CurStreamTypeType { + UnknownBitstream, + LLVMIRBitstream, + ClangSerializedASTBitstream, + ClangSerializedDiagnosticsBitstream, +}; + +struct BCDumpOptions { + /// The stream. + raw_ostream &OS; + /// Print per-code histogram. + bool Histogram = false; + /// Don't emit numeric info in dump if symbolic info is available. + bool Symbolic = false; + /// Print binary blobs using hex escapes. + bool ShowBinaryBlobs = false; + + BCDumpOptions(raw_ostream &OS) : OS(OS) {} +}; + +class BitcodeAnalyzer { + BitstreamCursor Stream; + BitstreamBlockInfo BlockInfo; + CurStreamTypeType CurStreamType; + Optional<BitstreamCursor> BlockInfoStream; + unsigned NumTopBlocks = 0; + + struct PerRecordStats { + unsigned NumInstances; + unsigned NumAbbrev; + uint64_t TotalBits; + PerRecordStats() : NumInstances(0), NumAbbrev(0), TotalBits(0) {} + }; + + struct PerBlockIDStats { + /// NumInstances - This the number of times this block ID has been seen. + unsigned NumInstances; + /// NumBits - The total size in bits of all of these blocks. + uint64_t NumBits; + /// NumSubBlocks - The total number of blocks these blocks contain. + unsigned NumSubBlocks; + /// NumAbbrevs - The total number of abbreviations. + unsigned NumAbbrevs; + /// NumRecords - The total number of records these blocks contain, and the + /// number that are abbreviated. + unsigned NumRecords, NumAbbreviatedRecords; + /// CodeFreq - Keep track of the number of times we see each code. + std::vector<PerRecordStats> CodeFreq; + PerBlockIDStats() + : NumInstances(0), NumBits(0), NumSubBlocks(0), NumAbbrevs(0), + NumRecords(0), NumAbbreviatedRecords(0) {} + }; + + std::map<unsigned, PerBlockIDStats> BlockIDStats; + +public: + BitcodeAnalyzer(StringRef Buffer, Optional<StringRef> BlockInfoBuffer = None); + /// Analyze the bitcode file. + Error analyze(Optional<BCDumpOptions> O = None, + Optional<StringRef> CheckHash = None); + /// Print stats about the bitcode file. + void printStats(BCDumpOptions O, Optional<StringRef> Filename = None); + +private: + /// Read a block, updating statistics, etc. + Error parseBlock(unsigned BlockID, unsigned IndentLevel, + Optional<BCDumpOptions> O = None, + Optional<StringRef> CheckHash = None); + + Error decodeMetadataStringsBlob(StringRef Indent, ArrayRef<uint64_t> Record, + StringRef Blob, raw_ostream &OS); +}; + +} // end namespace llvm + +#endif // LLVM_BITCODE_BITCODE_ANALYZER_H diff --git a/include/llvm/Bitcode/BitcodeReader.h b/include/llvm/Bitcode/BitcodeReader.h index 0d7cc141f2ce..ba61da733bea 100644 --- a/include/llvm/Bitcode/BitcodeReader.h +++ b/include/llvm/Bitcode/BitcodeReader.h @@ -1,9 +1,8 @@ //===- llvm/Bitcode/BitcodeReader.h - Bitcode reader ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,7 +15,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Bitstream/BitCodes.h" #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" diff --git a/include/llvm/Bitcode/BitcodeWriter.h b/include/llvm/Bitcode/BitcodeWriter.h index 0010cf6c0544..39061e09cda5 100644 --- a/include/llvm/Bitcode/BitcodeWriter.h +++ b/include/llvm/Bitcode/BitcodeWriter.h @@ -1,9 +1,8 @@ //===- llvm/Bitcode/BitcodeWriter.h - Bitcode writers -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index 05044c9ae11c..1773d1b9f11b 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -1,9 +1,8 @@ //===-- BitcodeWriterPass.h - Bitcode writing pass --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index f0d11e9c1689..decd4dd3a965 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -1,9 +1,8 @@ //===- LLVMBitCodes.h - Enum values for the LLVM bitcode format -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,7 +17,7 @@ #ifndef LLVM_BITCODE_LLVMBITCODES_H #define LLVM_BITCODE_LLVMBITCODES_H -#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Bitstream/BitCodes.h" namespace llvm { namespace bitc { @@ -264,10 +263,31 @@ enum GlobalValueSummarySymtabCodes { // Index-wide flags FS_FLAGS = 20, // Maps type identifier to summary information for that type identifier. + // Produced by the thin link (only lives in combined index). // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits, // n x (typeid, kind, name, numrba, // numrba x (numarg, numarg x arg, kind, info, byte, bit))] FS_TYPE_ID = 21, + // For background see overview at https://llvm.org/docs/TypeMetadata.html. + // The type metadata includes both the type identifier and the offset of + // the address point of the type (the address held by objects of that type + // which may not be the beginning of the virtual table). Vtable definitions + // are decorated with type metadata for the types they are compatible with. + // + // Maps type identifier to summary information for that type identifier + // computed from type metadata: the valueid of each vtable definition + // decorated with a type metadata for that identifier, and the offset from + // the corresponding type metadata. + // Exists in the per-module summary to provide information to thin link + // for index-based whole program devirtualization. + // TYPE_ID_METADATA: [typeid, n x (valueid, offset)] + FS_TYPE_ID_METADATA = 22, + // Summarizes vtable definition for use in index-based whole program + // devirtualization during the thin link. + // PERMODULE_VTABLE_GLOBALVAR_INIT_REFS: [valueid, flags, varflags, + // numrefs, numrefs x valueid, + // n x (valueid, offset)] + FS_PERMODULE_VTABLE_GLOBALVAR_INIT_REFS = 23, }; enum MetadataCodes { @@ -311,6 +331,7 @@ enum MetadataCodes { METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] METADATA_LABEL = 40, // [distinct, scope, name, file, line] + METADATA_COMMON_BLOCK = 44, // [distinct, scope, name, variable,...] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -407,7 +428,9 @@ enum RMWOperations { RMW_MAX = 7, RMW_MIN = 8, RMW_UMAX = 9, - RMW_UMIN = 10 + RMW_UMIN = 10, + RMW_FADD = 11, + RMW_FSUB = 12 }; /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing @@ -534,6 +557,8 @@ enum FunctionCodes { // 54 is unused. FUNC_CODE_OPERAND_BUNDLE = 55, // OPERAND_BUNDLE: [tag#, value...] FUNC_CODE_INST_UNOP = 56, // UNOP: [opcode, ty, opval] + FUNC_CODE_INST_CALLBR = 57, // CALLBR: [attr, cc, norm, transfs, + // fnty, fnid, args...] }; enum UseListCodes { @@ -602,6 +627,11 @@ enum AttributeKindCodes { ATTR_KIND_OPT_FOR_FUZZING = 57, ATTR_KIND_SHADOWCALLSTACK = 58, ATTR_KIND_SPECULATIVE_LOAD_HARDENING = 59, + ATTR_KIND_IMMARG = 60, + ATTR_KIND_WILLRETURN = 61, + ATTR_KIND_NOFREE = 62, + ATTR_KIND_NOSYNC = 63, + ATTR_KIND_SANITIZE_MEMTAG = 64, }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitstream/BitCodes.h index bf21e146e771..adf54ba96396 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitstream/BitCodes.h @@ -1,13 +1,12 @@ -//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===// +//===- BitCodes.h - Enum values for the bitstream format --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 Bitcode enum values. +// This header defines bitstream enum values. // // The enum values defined in this file should be considered permanent. If // new features are added, they should have values added at the end of the @@ -15,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_BITCODES_H -#define LLVM_BITCODE_BITCODES_H +#ifndef LLVM_BITSTREAM_BITCODES_H +#define LLVM_BITSTREAM_BITCODES_H #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" @@ -24,13 +23,15 @@ #include <cassert> namespace llvm { -/// Offsets of the 32-bit fields of bitcode wrapper header. -static const unsigned BWH_MagicField = 0 * 4; -static const unsigned BWH_VersionField = 1 * 4; -static const unsigned BWH_OffsetField = 2 * 4; -static const unsigned BWH_SizeField = 3 * 4; -static const unsigned BWH_CPUTypeField = 4 * 4; -static const unsigned BWH_HeaderSize = 5 * 4; +/// Offsets of the 32-bit fields of bitstream wrapper header. +enum BitstreamWrapperHeader : unsigned { + BWH_MagicField = 0 * 4, + BWH_VersionField = 1 * 4, + BWH_OffsetField = 2 * 4, + BWH_SizeField = 3 * 4, + BWH_CPUTypeField = 4 * 4, + BWH_HeaderSize = 5 * 4 +}; namespace bitc { enum StandardWidths { @@ -160,8 +161,6 @@ public: }; -template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; }; - /// BitCodeAbbrev - This class represents an abbreviation record. An /// abbreviation allows a complex record that has redundancy to be stored in a /// specialized format instead of the fully-general, fully-vbr, format. diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitstream/BitstreamReader.h index 72e7619d9e1c..ee82e7ec1ba2 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitstream/BitstreamReader.h @@ -1,9 +1,8 @@ //===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -12,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_BITSTREAMREADER_H -#define LLVM_BITCODE_BITSTREAMREADER_H +#ifndef LLVM_BITSTREAM_BITSTREAMREADER_H +#define LLVM_BITSTREAM_BITSTREAMREADER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Bitstream/BitCodes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -98,14 +97,13 @@ private: unsigned BitsInCurWord = 0; public: - static const size_t MaxChunkSize = sizeof(word_t) * 8; + static const constexpr size_t MaxChunkSize = sizeof(word_t) * 8; SimpleBitstreamCursor() = default; explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes) : BitcodeBytes(BitcodeBytes) {} explicit SimpleBitstreamCursor(StringRef BitcodeBytes) - : BitcodeBytes(reinterpret_cast<const uint8_t *>(BitcodeBytes.data()), - BitcodeBytes.size()) {} + : BitcodeBytes(arrayRefFromStringRef(BitcodeBytes)) {} explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes) : SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {} @@ -129,7 +127,7 @@ public: ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; } /// Reset the stream to the specified bit number. - void JumpToBit(uint64_t BitNo) { + Error JumpToBit(uint64_t BitNo) { size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); assert(canSkipToPos(ByteNo) && "Invalid location"); @@ -139,8 +137,14 @@ public: BitsInCurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) - Read(WordBitNo); + if (WordBitNo) { + if (Expected<word_t> Res = Read(WordBitNo)) + return Error::success(); + else + return Res.takeError(); + } + + return Error::success(); } /// Get a pointer into the bitstream at the specified byte offset. @@ -156,9 +160,11 @@ public: return getPointerToByte(BitNo / 8, NumBytes); } - void fillCurWord() { + Error fillCurWord() { if (NextChar >= BitcodeBytes.size()) - report_fatal_error("Unexpected end of file"); + return createStringError(std::errc::io_error, + "Unexpected end of file reading %u of %u bytes", + NextChar, BitcodeBytes.size()); // Read the next word from the stream. const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar; @@ -177,9 +183,10 @@ public: } NextChar += BytesRead; BitsInCurWord = BytesRead * 8; + return Error::success(); } - word_t Read(unsigned NumBits) { + Expected<word_t> Read(unsigned NumBits) { static const unsigned BitsInWord = MaxChunkSize; assert(NumBits && NumBits <= BitsInWord && @@ -201,11 +208,14 @@ public: word_t R = BitsInCurWord ? CurWord : 0; unsigned BitsLeft = NumBits - BitsInCurWord; - fillCurWord(); + if (Error fillResult = fillCurWord()) + return std::move(fillResult); // If we run out of data, abort. if (BitsLeft > BitsInCurWord) - report_fatal_error("Unexpected end of file"); + return createStringError(std::errc::io_error, + "Unexpected end of file reading %u of %u bits", + BitsInCurWord, BitsLeft); word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); @@ -219,8 +229,12 @@ public: return R; } - uint32_t ReadVBR(unsigned NumBits) { - uint32_t Piece = Read(NumBits); + Expected<uint32_t> ReadVBR(unsigned NumBits) { + Expected<unsigned> MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + uint32_t Piece = MaybeRead.get(); + if ((Piece & (1U << (NumBits-1))) == 0) return Piece; @@ -233,14 +247,21 @@ public: return Result; NextBit += NumBits-1; - Piece = Read(NumBits); + MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + Piece = MaybeRead.get(); } } // Read a VBR that may have a value up to 64-bits in size. The chunk size of // the VBR must still be <= 32 bits though. - uint64_t ReadVBR64(unsigned NumBits) { - uint32_t Piece = Read(NumBits); + Expected<uint64_t> ReadVBR64(unsigned NumBits) { + Expected<uint64_t> MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + uint32_t Piece = MaybeRead.get(); + if ((Piece & (1U << (NumBits-1))) == 0) return uint64_t(Piece); @@ -253,7 +274,10 @@ public: return Result; NextBit += NumBits-1; - Piece = Read(NumBits); + MaybeRead = Read(NumBits); + if (!MaybeRead) + return MaybeRead; + Piece = MaybeRead.get(); } } @@ -270,6 +294,9 @@ public: BitsInCurWord = 0; } + /// Return the size of the stream in bytes. + size_t SizeInBytes() const { return BitcodeBytes.size(); } + /// Skip to the end of the file. void skipToEnd() { NextChar = BitcodeBytes.size(); } }; @@ -340,17 +367,18 @@ public: explicit BitstreamCursor(MemoryBufferRef BitcodeBytes) : SimpleBitstreamCursor(BitcodeBytes) {} - using SimpleBitstreamCursor::canSkipToPos; using SimpleBitstreamCursor::AtEndOfStream; + using SimpleBitstreamCursor::canSkipToPos; + using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::getBitcodeBytes; using SimpleBitstreamCursor::GetCurrentBitNo; using SimpleBitstreamCursor::getCurrentByteNo; using SimpleBitstreamCursor::getPointerToByte; using SimpleBitstreamCursor::JumpToBit; - using SimpleBitstreamCursor::fillCurWord; using SimpleBitstreamCursor::Read; using SimpleBitstreamCursor::ReadVBR; using SimpleBitstreamCursor::ReadVBR64; + using SimpleBitstreamCursor::SizeInBytes; /// Return the number of bits used to encode an abbrev #. unsigned getAbbrevIDWidth() const { return CurCodeSize; } @@ -367,12 +395,16 @@ public: }; /// Advance the current bitstream, returning the next entry in the stream. - BitstreamEntry advance(unsigned Flags = 0) { + Expected<BitstreamEntry> advance(unsigned Flags = 0) { while (true) { if (AtEndOfStream()) return BitstreamEntry::getError(); - unsigned Code = ReadCode(); + Expected<unsigned> MaybeCode = ReadCode(); + if (!MaybeCode) + return MaybeCode.takeError(); + unsigned Code = MaybeCode.get(); + if (Code == bitc::END_BLOCK) { // Pop the end of the block unless Flags tells us not to. if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) @@ -380,14 +412,19 @@ public: return BitstreamEntry::getEndBlock(); } - if (Code == bitc::ENTER_SUBBLOCK) - return BitstreamEntry::getSubBlock(ReadSubBlockID()); + if (Code == bitc::ENTER_SUBBLOCK) { + if (Expected<unsigned> MaybeSubBlock = ReadSubBlockID()) + return BitstreamEntry::getSubBlock(MaybeSubBlock.get()); + else + return MaybeSubBlock.takeError(); + } if (Code == bitc::DEFINE_ABBREV && !(Flags & AF_DontAutoprocessAbbrevs)) { // We read and accumulate abbrev's, the client can't do anything with // them anyway. - ReadAbbrevRecord(); + if (Error Err = ReadAbbrevRecord()) + return std::move(Err); continue; } @@ -397,53 +434,66 @@ public: /// This is a convenience function for clients that don't expect any /// subblocks. This just skips over them automatically. - BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { + Expected<BitstreamEntry> advanceSkippingSubblocks(unsigned Flags = 0) { while (true) { // If we found a normal entry, return it. - BitstreamEntry Entry = advance(Flags); + Expected<BitstreamEntry> MaybeEntry = advance(Flags); + if (!MaybeEntry) + return MaybeEntry; + BitstreamEntry Entry = MaybeEntry.get(); + if (Entry.Kind != BitstreamEntry::SubBlock) return Entry; // If we found a sub-block, just skip over it and check the next entry. - if (SkipBlock()) - return BitstreamEntry::getError(); + if (Error Err = SkipBlock()) + return std::move(Err); } } - unsigned ReadCode() { - return Read(CurCodeSize); - } + Expected<unsigned> ReadCode() { return Read(CurCodeSize); } // Block header: // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. - unsigned ReadSubBlockID() { - return ReadVBR(bitc::BlockIDWidth); - } + Expected<unsigned> ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); } /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body - /// of this block. If the block record is malformed, return true. - bool SkipBlock() { - // Read and ignore the codelen value. Since we are skipping this block, we - // don't care what code widths are used inside of it. - ReadVBR(bitc::CodeLenWidth); + /// of this block. + Error SkipBlock() { + // Read and ignore the codelen value. + if (Expected<uint32_t> Res = ReadVBR(bitc::CodeLenWidth)) + ; // Since we are skipping this block, we don't care what code widths are + // used inside of it. + else + return Res.takeError(); + SkipToFourByteBoundary(); - size_t NumFourBytes = Read(bitc::BlockSizeWidth); + Expected<unsigned> MaybeNum = Read(bitc::BlockSizeWidth); + if (!MaybeNum) + return MaybeNum.takeError(); + size_t NumFourBytes = MaybeNum.get(); // Check that the block wasn't partially defined, and that the offset isn't // bogus. - size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; - if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) - return true; - - JumpToBit(SkipTo); - return false; + size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8; + if (AtEndOfStream()) + return createStringError(std::errc::illegal_byte_sequence, + "can't skip block: already at end of stream"); + if (!canSkipToPos(SkipTo / 8)) + return createStringError(std::errc::illegal_byte_sequence, + "can't skip to bit %zu from %" PRIu64, SkipTo, + GetCurrentBitNo()); + + if (Error Res = JumpToBit(SkipTo)) + return Res; + + return Error::success(); } - /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true - /// if the block has an error. - bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); + /// Having read the ENTER_SUBBLOCK abbrevid, and enter the block. + Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); bool ReadBlockEnd() { if (BlockScope.empty()) return true; @@ -478,22 +528,23 @@ public: } /// Read the current record and discard it, returning the code for the record. - unsigned skipRecord(unsigned AbbrevID); + Expected<unsigned> skipRecord(unsigned AbbrevID); - unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, - StringRef *Blob = nullptr); + Expected<unsigned> readRecord(unsigned AbbrevID, + SmallVectorImpl<uint64_t> &Vals, + StringRef *Blob = nullptr); //===--------------------------------------------------------------------===// // Abbrev Processing //===--------------------------------------------------------------------===// - void ReadAbbrevRecord(); + Error ReadAbbrevRecord(); /// Read and return a block info block from the bitstream. If an error was /// encountered, return None. /// /// \param ReadBlockInfoNames Whether to read block/record name information in /// the BlockInfo block. Only llvm-bcanalyzer uses this. - Optional<BitstreamBlockInfo> + Expected<Optional<BitstreamBlockInfo>> ReadBlockInfoBlock(bool ReadBlockInfoNames = false); /// Set the block info to be used by this BitstreamCursor to interpret @@ -503,4 +554,4 @@ public: } // end llvm namespace -#endif // LLVM_BITCODE_BITSTREAMREADER_H +#endif // LLVM_BITSTREAM_BITSTREAMREADER_H diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitstream/BitstreamWriter.h index c854769e0622..c0ead19dc71d 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitstream/BitstreamWriter.h @@ -1,9 +1,8 @@ //===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -12,14 +11,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_BITSTREAMWRITER_H -#define LLVM_BITCODE_BITSTREAMWRITER_H +#ifndef LLVM_BITSTREAM_BITSTREAMWRITER_H +#define LLVM_BITSTREAM_BITSTREAMWRITER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Bitstream/BitCodes.h" #include "llvm/Support/Endian.h" #include <vector> @@ -487,10 +486,8 @@ private: } public: - /// EmitAbbrev - This emits an abbreviation to the stream. Note that this - /// method takes ownership of the specified abbrev. + /// Emits the abbreviation \p Abbv to the stream. unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) { - // Emit the abbreviation as a record. EncodeAbbrev(*Abbv); CurAbbrevs.push_back(std::move(Abbv)); return static_cast<unsigned>(CurAbbrevs.size())-1 + diff --git a/include/llvm/CodeGen/AccelTable.h b/include/llvm/CodeGen/AccelTable.h index 13928582f2dd..734531a65d50 100644 --- a/include/llvm/CodeGen/AccelTable.h +++ b/include/llvm/CodeGen/AccelTable.h @@ -1,9 +1,8 @@ //==- include/llvm/CodeGen/AccelTable.h - Accelerator Tables -----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -327,14 +326,8 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -352,16 +345,10 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -376,14 +363,8 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; @@ -407,16 +388,10 @@ public: void emit(AsmPrinter *Asm) const override; -#ifndef _MSC_VER - // The line below is rejected by older versions (TBD) of MSVC. static constexpr Atom Atoms[] = { Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; -#else - // FIXME: Erase this path once the minimum MSCV version has been bumped. - static const SmallVector<Atom, 4> Atoms; -#endif #ifndef NDEBUG void print(raw_ostream &OS) const override; diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index d77aee66ed76..0be0ac22a74d 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -1,9 +1,8 @@ //===- CodeGen/Analysis.h - CodeGen LLVM IR Analysis Utilities --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -26,6 +25,7 @@ namespace llvm { class GlobalValue; +class LLT; class MachineBasicBlock; class MachineFunction; class TargetLoweringBase; @@ -74,6 +74,25 @@ void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl<uint64_t> *Offsets = nullptr, uint64_t StartingOffset = 0); +/// Variant of ComputeValueVTs that also produces the memory VTs. +void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, + SmallVectorImpl<EVT> &ValueVTs, + SmallVectorImpl<EVT> *MemVTs, + SmallVectorImpl<uint64_t> *Offsets = nullptr, + uint64_t StartingOffset = 0); + +/// computeValueLLTs - Given an LLVM IR type, compute a sequence of +/// LLTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// If Offsets is non-null, it points to a vector to be filled in +/// with the in-memory offsets of each of the individual values. +/// +void computeValueLLTs(const DataLayout &DL, Type &Ty, + SmallVectorImpl<LLT> &ValueTys, + SmallVectorImpl<uint64_t> *Offsets = nullptr, + uint64_t StartingOffset = 0); + /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. GlobalValue *ExtractTypeInfo(Value *V); diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 413901d218f9..d110f8b01cb5 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" @@ -33,7 +33,6 @@ namespace llvm { -class AsmPrinterHandler; class BasicBlock; class BlockAddress; class Constant; @@ -122,9 +121,6 @@ public: using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>; MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs; - /// Enable print [latency:throughput] in output. - bool EnablePrintSchedInfo = false; - private: MCSymbol *CurrentFnBegin = nullptr; MCSymbol *CurrentFnEnd = nullptr; @@ -142,16 +138,16 @@ protected: /// Protected struct HandlerInfo and Handlers permit target extended /// AsmPrinter adds their own handlers. struct HandlerInfo { - AsmPrinterHandler *Handler; + std::unique_ptr<AsmPrinterHandler> Handler; const char *TimerName; const char *TimerDescription; const char *TimerGroupName; const char *TimerGroupDescription; - HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName, - const char *TimerDescription, const char *TimerGroupName, - const char *TimerGroupDescription) - : Handler(Handler), TimerName(TimerName), + HandlerInfo(std::unique_ptr<AsmPrinterHandler> Handler, + const char *TimerName, const char *TimerDescription, + const char *TimerGroupName, const char *TimerGroupDescription) + : Handler(std::move(Handler)), TimerName(TimerName), TimerDescription(TimerDescription), TimerGroupName(TimerGroupName), TimerGroupDescription(TimerGroupDescription) {} }; @@ -227,6 +223,9 @@ public: void EmitToStreamer(MCStreamer &S, const MCInst &Inst); + /// Emits inital debug location directive. + void emitInitialRawDwarfLocDirective(const MachineFunction &MF); + /// Return the current section we are emitting to. const MCSection *getCurrentSection() const; @@ -316,6 +315,8 @@ public: void emitStackSizeSection(const MachineFunction &MF); + void emitRemarksSection(Module &M); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves() const; @@ -511,7 +512,7 @@ public: void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const; /// Emit the specified unsigned leb128 value. - void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const; + void EmitULEB128(uint64_t Value, const char *Desc = nullptr, unsigned PadTo = 0) const; /// Emit a .byte 42 directive that corresponds to an encoding. If verbose /// assembly output is enabled, we output comments describing the encoding. @@ -542,6 +543,12 @@ public: emitDwarfStringOffset(S.getEntry()); } + /// Emit reference to a call site with a specified encoding + void EmitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Encoding) const; + /// Emit an integer value corresponding to the call site encoding + void EmitCallSiteValue(uint64_t Value, unsigned Encoding) const; + /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } @@ -589,20 +596,22 @@ public: virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, const char *Code) const; + /// Print the MachineOperand as a symbol. Targets with complex handling of + /// symbol references should override the base implementation. + virtual void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS); + /// Print the specified operand of MI, an INLINEASM instruction, using the /// specified assembler variant. Targets should override this to format as /// appropriate. This method can return true if the operand is erroneous. virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); /// Print the specified operand of MI, an INLINEASM instruction, using the /// specified assembler variant as an address. Targets should override this to /// format as appropriate. This method can return true if the operand is /// erroneous. virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS); + const char *ExtraCode, raw_ostream &OS); /// Let the target do anything it needs to do before emitting inlineasm. /// \p StartInfo - the subtarget info before parsing inline asm @@ -617,6 +626,15 @@ public: virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo) const; + /// This emits visibility information about symbol, if this is supported by + /// the target. + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; + + /// This emits linkage information about \p GVSym based on \p GV, if this is + /// supported by the target. + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; + private: /// Private state for PrintSpecial() // Assign a unique ID to this machine instruction. @@ -647,13 +665,6 @@ private: // Internal Implementation Details //===------------------------------------------------------------------===// - /// This emits visibility information about symbol, if this is supported by - /// the target. - void EmitVisibility(MCSymbol *Sym, unsigned Visibility, - bool IsDefinition = true) const; - - void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; - void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid) const; void EmitLLVMUsedList(const ConstantArray *InitList); diff --git a/include/llvm/CodeGen/AsmPrinterHandler.h b/include/llvm/CodeGen/AsmPrinterHandler.h index a8b13200dd4e..affb558f2fa6 100644 --- a/include/llvm/CodeGen/AsmPrinterHandler.h +++ b/include/llvm/CodeGen/AsmPrinterHandler.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/AsmPrinterHandler.h -----------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/AtomicExpandUtils.h b/include/llvm/CodeGen/AtomicExpandUtils.h index b1adf66e7ff4..8a46c6e00d22 100644 --- a/include/llvm/CodeGen/AtomicExpandUtils.h +++ b/include/llvm/CodeGen/AtomicExpandUtils.h @@ -1,9 +1,8 @@ //===- AtomicExpandUtils.h - Utilities for expanding atomic instructions --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index f105d887c397..70bf670fdf0b 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -1,9 +1,8 @@ //===- BasicTTIImpl.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -197,11 +196,12 @@ protected: public: /// \name Scalar TTI Implementations /// @{ - bool allowsMisalignedMemoryAccesses(LLVMContext &Context, - unsigned BitWidth, unsigned AddressSpace, - unsigned Alignment, bool *Fast) const { + bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, + unsigned AddressSpace, unsigned Alignment, + bool *Fast) const { EVT E = EVT::getIntegerVT(Context, BitWidth); - return getTLI()->allowsMisalignedMemoryAccesses(E, AddressSpace, Alignment, Fast); + return getTLI()->allowsMisalignedMemoryAccesses( + E, AddressSpace, Alignment, MachineMemOperand::MONone, Fast); } bool hasBranchDivergence() { return false; } @@ -293,12 +293,12 @@ public: } unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) { - return BaseT::getIntrinsicCost(IID, RetTy, Arguments); + ArrayRef<const Value *> Arguments, const User *U) { + return BaseT::getIntrinsicCost(IID, RetTy, Arguments, U); } unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) { + ArrayRef<Type *> ParamTys, const User *U) { if (IID == Intrinsic::cttz) { if (getTLI()->isCheapToSpeculateCttz()) return TargetTransformInfo::TCC_Basic; @@ -311,7 +311,7 @@ public: return TargetTransformInfo::TCC_Expensive; } - return BaseT::getIntrinsicCost(IID, RetTy, ParamTys); + return BaseT::getIntrinsicCost(IID, RetTy, ParamTys, U); } unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, @@ -414,6 +414,12 @@ public: if (TLI->isZExtFree(OpTy, Ty)) return TargetTransformInfo::TCC_Free; return TargetTransformInfo::TCC_Basic; + + case Instruction::AddrSpaceCast: + if (TLI->isFreeAddrSpaceCast(OpTy->getPointerAddressSpace(), + Ty->getPointerAddressSpace())) + return TargetTransformInfo::TCC_Free; + return TargetTransformInfo::TCC_Basic; } return BaseT::getOperationCost(Opcode, Ty, OpTy); @@ -421,6 +427,8 @@ public: unsigned getInliningThresholdMultiplier() { return 1; } + int getInlinerVectorBonusPercent() { return 150; } + void getUnrollingPreferences(Loop *L, ScalarEvolution &SE, TTI::UnrollingPreferences &UP) { // This unrolling functionality is target independent, but to provide some @@ -486,6 +494,13 @@ public: UP.BEInsns = 2; } + bool isHardwareLoopProfitable(Loop *L, ScalarEvolution &SE, + AssumptionCache &AC, + TargetLibraryInfo *LibInfo, + HardwareLoopInfo &HWLoopInfo) { + return BaseT::isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo); + } + int getInstructionLatency(const Instruction *I) { if (isa<LoadInst>(I)) return getST()->getSchedModel().DefaultLoadLatency; @@ -657,7 +672,7 @@ public: return 0; if (Opcode == Instruction::AddrSpaceCast && - TLI->isNoopAddrSpaceCast(Src->getPointerAddressSpace(), + TLI->isFreeAddrSpaceCast(Src->getPointerAddressSpace(), Dst->getPointerAddressSpace())) return 0; @@ -997,7 +1012,7 @@ public: // inside the loop. if (UseMaskForGaps) Cost += static_cast<T *>(this)->getArithmeticInstrCost( - BinaryOperator::And, MaskVT); + BinaryOperator::And, MaskVT); return Cost; } @@ -1058,8 +1073,8 @@ public: case Intrinsic::experimental_vector_reduce_and: case Intrinsic::experimental_vector_reduce_or: case Intrinsic::experimental_vector_reduce_xor: - case Intrinsic::experimental_vector_reduce_fadd: - case Intrinsic::experimental_vector_reduce_fmul: + case Intrinsic::experimental_vector_reduce_v2_fadd: + case Intrinsic::experimental_vector_reduce_v2_fmul: case Intrinsic::experimental_vector_reduce_smax: case Intrinsic::experimental_vector_reduce_smin: case Intrinsic::experimental_vector_reduce_fmax: @@ -1116,6 +1131,9 @@ public: unsigned getIntrinsicInstrCost( Intrinsic::ID IID, Type *RetTy, ArrayRef<Type *> Tys, FastMathFlags FMF, unsigned ScalarizationCostPassed = std::numeric_limits<unsigned>::max()) { + unsigned RetVF = (RetTy->isVectorTy() ? RetTy->getVectorNumElements() : 1); + auto *ConcreteTTI = static_cast<T *>(this); + SmallVector<unsigned, 2> ISDs; unsigned SingleCallCost = 10; // Library call cost. Make it expensive. switch (IID) { @@ -1144,8 +1162,8 @@ public: if (ScalarCalls == 1) return 1; // Return cost of a scalar intrinsic. Assume it to be cheap. - unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( - IID, ScalarRetTy, ScalarTys, FMF); + unsigned ScalarCost = + ConcreteTTI->getIntrinsicInstrCost(IID, ScalarRetTy, ScalarTys, FMF); return ScalarCalls * ScalarCost + ScalarizationCost; } @@ -1227,44 +1245,181 @@ public: case Intrinsic::sideeffect: return 0; case Intrinsic::masked_store: - return static_cast<T *>(this) - ->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, 0); + return ConcreteTTI->getMaskedMemoryOpCost(Instruction::Store, Tys[0], 0, + 0); case Intrinsic::masked_load: - return static_cast<T *>(this) - ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + return ConcreteTTI->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); case Intrinsic::experimental_vector_reduce_add: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Add, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Add, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_mul: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Mul, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Mul, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_and: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::And, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::And, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_or: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Or, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Or, Tys[0], + /*IsPairwiseForm=*/false); case Intrinsic::experimental_vector_reduce_xor: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::Xor, Tys[0], /*IsPairwiseForm=*/false); - case Intrinsic::experimental_vector_reduce_fadd: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::FAdd, Tys[0], /*IsPairwiseForm=*/false); - case Intrinsic::experimental_vector_reduce_fmul: - return static_cast<T *>(this)->getArithmeticReductionCost( - Instruction::FMul, Tys[0], /*IsPairwiseForm=*/false); + return ConcreteTTI->getArithmeticReductionCost(Instruction::Xor, Tys[0], + /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_v2_fadd: + return ConcreteTTI->getArithmeticReductionCost( + Instruction::FAdd, Tys[0], + /*IsPairwiseForm=*/false); // FIXME: Add new flag for cost of strict + // reductions. + case Intrinsic::experimental_vector_reduce_v2_fmul: + return ConcreteTTI->getArithmeticReductionCost( + Instruction::FMul, Tys[0], + /*IsPairwiseForm=*/false); // FIXME: Add new flag for cost of strict + // reductions. case Intrinsic::experimental_vector_reduce_smax: case Intrinsic::experimental_vector_reduce_smin: case Intrinsic::experimental_vector_reduce_fmax: case Intrinsic::experimental_vector_reduce_fmin: - return static_cast<T *>(this)->getMinMaxReductionCost( + return ConcreteTTI->getMinMaxReductionCost( Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, - /*IsSigned=*/true); + /*IsUnsigned=*/true); case Intrinsic::experimental_vector_reduce_umax: case Intrinsic::experimental_vector_reduce_umin: - return static_cast<T *>(this)->getMinMaxReductionCost( + return ConcreteTTI->getMinMaxReductionCost( Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, - /*IsSigned=*/false); + /*IsUnsigned=*/false); + case Intrinsic::sadd_sat: + case Intrinsic::ssub_sat: { + Type *CondTy = Type::getInt1Ty(RetTy->getContext()); + if (RetVF > 1) + CondTy = VectorType::get(CondTy, RetVF); + + Type *OpTy = StructType::create({RetTy, CondTy}); + Intrinsic::ID OverflowOp = IID == Intrinsic::sadd_sat + ? Intrinsic::sadd_with_overflow + : Intrinsic::ssub_with_overflow; + + // SatMax -> Overflow && SumDiff < 0 + // SatMin -> Overflow && SumDiff >= 0 + unsigned Cost = 0; + Cost += ConcreteTTI->getIntrinsicInstrCost( + OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, RetTy, + CondTy, nullptr); + Cost += 2 * ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy, + CondTy, nullptr); + return Cost; + } + case Intrinsic::uadd_sat: + case Intrinsic::usub_sat: { + Type *CondTy = Type::getInt1Ty(RetTy->getContext()); + if (RetVF > 1) + CondTy = VectorType::get(CondTy, RetVF); + + Type *OpTy = StructType::create({RetTy, CondTy}); + Intrinsic::ID OverflowOp = IID == Intrinsic::uadd_sat + ? Intrinsic::uadd_with_overflow + : Intrinsic::usub_with_overflow; + + unsigned Cost = 0; + Cost += ConcreteTTI->getIntrinsicInstrCost( + OverflowOp, OpTy, {RetTy, RetTy}, FMF, ScalarizationCostPassed); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::Select, RetTy, + CondTy, nullptr); + return Cost; + } + case Intrinsic::smul_fix: + case Intrinsic::umul_fix: { + unsigned ExtSize = RetTy->getScalarSizeInBits() * 2; + Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize); + if (RetVF > 1) + ExtTy = VectorType::get(ExtTy, RetVF); + + unsigned ExtOp = + IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + + unsigned Cost = 0; + Cost += 2 * ConcreteTTI->getCastInstrCost(ExtOp, ExtTy, RetTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Mul, ExtTy); + Cost += + 2 * ConcreteTTI->getCastInstrCost(Instruction::Trunc, RetTy, ExtTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::LShr, RetTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Shl, RetTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Or, RetTy); + return Cost; + } + case Intrinsic::sadd_with_overflow: + case Intrinsic::ssub_with_overflow: { + Type *SumTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned Opcode = IID == Intrinsic::sadd_with_overflow + ? BinaryOperator::Add + : BinaryOperator::Sub; + + // LHSSign -> LHS >= 0 + // RHSSign -> RHS >= 0 + // SumSign -> Sum >= 0 + // + // Add: + // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) + // Sub: + // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) + unsigned Cost = 0; + Cost += ConcreteTTI->getArithmeticInstrCost(Opcode, SumTy); + Cost += 3 * ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, + OverflowTy, nullptr); + Cost += 2 * ConcreteTTI->getCmpSelInstrCost( + BinaryOperator::ICmp, OverflowTy, OverflowTy, nullptr); + Cost += + ConcreteTTI->getArithmeticInstrCost(BinaryOperator::And, OverflowTy); + return Cost; + } + case Intrinsic::uadd_with_overflow: + case Intrinsic::usub_with_overflow: { + Type *SumTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned Opcode = IID == Intrinsic::uadd_with_overflow + ? BinaryOperator::Add + : BinaryOperator::Sub; + + unsigned Cost = 0; + Cost += ConcreteTTI->getArithmeticInstrCost(Opcode, SumTy); + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, SumTy, + OverflowTy, nullptr); + return Cost; + } + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: { + Type *MulTy = RetTy->getContainedType(0); + Type *OverflowTy = RetTy->getContainedType(1); + unsigned ExtSize = MulTy->getScalarSizeInBits() * 2; + Type *ExtTy = Type::getIntNTy(RetTy->getContext(), ExtSize); + if (MulTy->isVectorTy()) + ExtTy = VectorType::get(ExtTy, MulTy->getVectorNumElements() ); + + unsigned ExtOp = + IID == Intrinsic::smul_fix ? Instruction::SExt : Instruction::ZExt; + + unsigned Cost = 0; + Cost += 2 * ConcreteTTI->getCastInstrCost(ExtOp, ExtTy, MulTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::Mul, ExtTy); + Cost += + 2 * ConcreteTTI->getCastInstrCost(Instruction::Trunc, MulTy, ExtTy); + Cost += ConcreteTTI->getArithmeticInstrCost(Instruction::LShr, MulTy, + TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + + if (IID == Intrinsic::smul_with_overflow) + Cost += ConcreteTTI->getArithmeticInstrCost( + Instruction::AShr, MulTy, TTI::OK_AnyValue, + TTI::OK_UniformConstantValue); + + Cost += ConcreteTTI->getCmpSelInstrCost(BinaryOperator::ICmp, MulTy, + OverflowTy, nullptr); + return Cost; + } case Intrinsic::ctpop: ISDs.push_back(ISD::CTPOP); // In case of legalization use TCC_Expensive. This is cheaper than a @@ -1305,17 +1460,16 @@ public: if (MinLegalCostI != LegalCost.end()) return *MinLegalCostI; - auto MinCustomCostI = std::min_element(CustomCost.begin(), CustomCost.end()); + auto MinCustomCostI = + std::min_element(CustomCost.begin(), CustomCost.end()); if (MinCustomCostI != CustomCost.end()) return *MinCustomCostI; // If we can't lower fmuladd into an FMA estimate the cost as a floating // point mul followed by an add. if (IID == Intrinsic::fmuladd) - return static_cast<T *>(this) - ->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + - static_cast<T *>(this) - ->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); + return ConcreteTTI->getArithmeticInstrCost(BinaryOperator::FMul, RetTy) + + ConcreteTTI->getArithmeticInstrCost(BinaryOperator::FAdd, RetTy); // Else, assume that we need to scalarize this intrinsic. For math builtins // this will emit a costly libcall, adding call overhead and spills. Make it @@ -1333,7 +1487,7 @@ public: Ty = Ty->getScalarType(); ScalarTys.push_back(Ty); } - unsigned ScalarCost = static_cast<T *>(this)->getIntrinsicInstrCost( + unsigned ScalarCost = ConcreteTTI->getIntrinsicInstrCost( IID, RetTy->getScalarType(), ScalarTys, FMF); for (unsigned i = 0, ie = Tys.size(); i != ie; ++i) { if (Tys[i]->isVectorTy()) { diff --git a/include/llvm/CodeGen/BuiltinGCs.h b/include/llvm/CodeGen/BuiltinGCs.h index 1767922fb5ac..d44183dab0f7 100644 --- a/include/llvm/CodeGen/BuiltinGCs.h +++ b/include/llvm/CodeGen/BuiltinGCs.h @@ -1,9 +1,8 @@ //===-- BuiltinGCs.h - Garbage collector linkage hacks --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/CSEConfigBase.h b/include/llvm/CodeGen/CSEConfigBase.h new file mode 100644 index 000000000000..70b5e5c17eb1 --- /dev/null +++ b/include/llvm/CodeGen/CSEConfigBase.h @@ -0,0 +1,28 @@ +//===- CSEConfigBase.h - A CSEConfig 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CSECONFIG_BASE_H +#define LLVM_CODEGEN_CSECONFIG_BASE_H + +namespace llvm { +// Class representing some configuration that can be done during GlobalISel's +// CSEInfo analysis. We define it here because TargetPassConfig can't depend on +// the GlobalISel library, and so we use this in the interface between them +// so that the derived classes in GISel can reference generic opcodes. +class CSEConfigBase { +public: + virtual ~CSEConfigBase() = default; + // Hook for defining which Generic instructions should be CSEd. + // GISelCSEInfo currently only calls this hook when dealing with generic + // opcodes. + virtual bool shouldCSEOpc(unsigned Opc) { return false; } +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_CSECONFIG_BASE_H diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index f85767f1fc11..9b8b7324f30a 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/CalcSpillWeights.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index efcf80ba0b4e..aa339e1cc913 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -1,9 +1,8 @@ //===- llvm/CallingConvLower.h - Calling Conventions ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -146,7 +145,7 @@ public: bool needsCustom() const { return isCustom; } - unsigned getLocReg() const { assert(isRegLoc()); return Loc; } + Register getLocReg() const { assert(isRegLoc()); return Loc; } unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } unsigned getExtraInfo() const { return Loc; } MVT getLocVT() const { return LocVT; } @@ -557,7 +556,7 @@ public: // Sort the locations of the arguments according to their original position. SmallVector<CCValAssign, 16> TmpArgLocs; - std::swap(TmpArgLocs, Locs); + TmpArgLocs.swap(Locs); auto B = TmpArgLocs.begin(), E = TmpArgLocs.end(); std::merge(B, B + NumFirstPassLocs, B + NumFirstPassLocs, E, std::back_inserter(Locs), diff --git a/include/llvm/CodeGen/CommandFlags.inc b/include/llvm/CodeGen/CommandFlags.inc index 568d329a5e8c..cb69e9f61405 100644 --- a/include/llvm/CodeGen/CommandFlags.inc +++ b/include/llvm/CodeGen/CommandFlags.inc @@ -1,9 +1,8 @@ //===-- CommandFlags.h - Command Line Flags Interface -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -272,6 +271,11 @@ static cl::opt<bool> EnableAddrsig("addrsig", cl::desc("Emit an address-significance table"), cl::init(false)); +static cl::opt<bool> + EnableDebugEntryValues("debug-entry-values", + cl::desc("Emit debug info about parameter's entry values"), + cl::init(false)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -301,6 +305,7 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.ExceptionModel = ExceptionModel; Options.EmitStackSizeSection = EnableStackSizeSection; Options.EmitAddrsig = EnableAddrsig; + Options.EnableDebugEntryValues = EnableDebugEntryValues; Options.MCOptions = InitMCTargetOptionsFromFlags(); diff --git a/include/llvm/CodeGen/CostTable.h b/include/llvm/CodeGen/CostTable.h index 48ad76971520..52f3bfaea180 100644 --- a/include/llvm/CodeGen/CostTable.h +++ b/include/llvm/CodeGen/CostTable.h @@ -1,9 +1,8 @@ //===-- CostTable.h - Instruction Cost Table handling -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/CodeGen/DAGCombine.h b/include/llvm/CodeGen/DAGCombine.h index 8b5919005451..944187341455 100644 --- a/include/llvm/CodeGen/DAGCombine.h +++ b/include/llvm/CodeGen/DAGCombine.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/DAGCombine.h ------- SelectionDAG Nodes ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index d3aabe22f216..cf58ee0cabea 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DFAPacketizer.h - DFA Packetizer for VLIW ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 class implements a deterministic finite automaton (DFA) based diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index 7d486b1df56d..684f9e40ca5a 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/DIE.h - DWARF Info Entries -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -39,6 +38,7 @@ namespace llvm { class AsmPrinter; class DIE; class DIEUnit; +class DwarfCompileUnit; class MCExpr; class MCSection; class MCSymbol; @@ -231,6 +231,25 @@ public: }; //===--------------------------------------------------------------------===// +/// A BaseTypeRef DIE. +class DIEBaseTypeRef { + const DwarfCompileUnit *CU; + const uint64_t Index; + static constexpr unsigned ULEB128PadSize = 4; + +public: + explicit DIEBaseTypeRef(const DwarfCompileUnit *TheCU, uint64_t Idx) + : CU(TheCU), Index(Idx) {} + + /// EmitValue - Emit base type reference. + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + /// SizeOf - Determine size of the base type reference in bytes. + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; + + void print(raw_ostream &O) const; +}; + +//===--------------------------------------------------------------------===// /// A simple label difference DIE. /// class DIEDelta { @@ -350,7 +369,7 @@ private: /// should be stored by reference instead of by value. using ValTy = AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel, DIEDelta *, DIEEntry, DIEBlock *, - DIELoc *, DIELocList>; + DIELoc *, DIELocList, DIEBaseTypeRef *>; static_assert(sizeof(ValTy) <= sizeof(uint64_t) || sizeof(ValTy) <= sizeof(void *), @@ -502,6 +521,18 @@ struct IntrusiveBackListBase { } Last = &N; } + + void push_front(Node &N) { + assert(N.Next.getPointer() == &N && "Expected unlinked node"); + assert(N.Next.getInt() == true && "Expected unlinked node"); + + if (Last) { + N.Next.setPointerAndInt(Last->Next.getPointer(), false); + Last->Next.setPointerAndInt(&N, true); + } else { + Last = &N; + } + } }; template <class T> class IntrusiveBackList : IntrusiveBackListBase { @@ -509,8 +540,15 @@ public: using IntrusiveBackListBase::empty; void push_back(T &N) { IntrusiveBackListBase::push_back(N); } + void push_front(T &N) { IntrusiveBackListBase::push_front(N); } T &back() { return *static_cast<T *>(Last); } const T &back() const { return *static_cast<T *>(Last); } + T &front() { + return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr); + } + const T &front() const { + return *static_cast<T *>(Last ? Last->Next.getPointer() : nullptr); + } class const_iterator; class iterator @@ -760,7 +798,7 @@ public: /// /// \returns the DIEUnit that represents the compile or type unit that owns /// this DIE, or NULL if this DIE hasn't been added to a unit DIE. - const DIEUnit *getUnit() const; + DIEUnit *getUnit() const; void setOffset(unsigned O) { Offset = O; } void setSize(unsigned S) { Size = S; } @@ -773,6 +811,13 @@ public: return Children.back(); } + DIE &addChildFront(DIE *Child) { + assert(!Child->getParent() && "Child should be orphaned"); + Child->Owner = this; + Children.push_front(*Child); + return Children.front(); + } + /// Find a value in the DIE with the attribute given. /// /// Returns a default-constructed DIEValue (where \a DIEValue::getType() @@ -800,7 +845,7 @@ class DIEUnit { const uint16_t Version; /// The Dwarf version number for this unit. const uint8_t AddrSize; /// The size in bytes of an address for this unit. protected: - ~DIEUnit() = default; + virtual ~DIEUnit() = default; public: DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag); diff --git a/include/llvm/CodeGen/DIEValue.def b/include/llvm/CodeGen/DIEValue.def index a3fce9b1d20c..92afeb3868b4 100644 --- a/include/llvm/CodeGen/DIEValue.def +++ b/include/llvm/CodeGen/DIEValue.def @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DIEValue.def - DIEValue types ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,6 +34,7 @@ HANDLE_DIEVALUE_SMALL(Integer) HANDLE_DIEVALUE_SMALL(String) HANDLE_DIEVALUE_SMALL(Expr) HANDLE_DIEVALUE_SMALL(Label) +HANDLE_DIEVALUE_LARGE(BaseTypeRef) HANDLE_DIEVALUE_LARGE(Delta) HANDLE_DIEVALUE_SMALL(Entry) HANDLE_DIEVALUE_LARGE(Block) diff --git a/include/llvm/CodeGen/DbgEntityHistoryCalculator.h b/include/llvm/CodeGen/DbgEntityHistoryCalculator.h index befc28f084e7..7eec75bc81bf 100644 --- a/include/llvm/CodeGen/DbgEntityHistoryCalculator.h +++ b/include/llvm/CodeGen/DbgEntityHistoryCalculator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DbgEntityHistoryCalculator.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define LLVM_CODEGEN_DBGVALUEHISTORYCALCULATOR_H #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DebugInfoMetadata.h" #include <utility> @@ -22,35 +22,76 @@ class MachineFunction; class MachineInstr; class TargetRegisterInfo; -// For each user variable, keep a list of instruction ranges where this variable -// is accessible. The variables are listed in order of appearance. +/// For each user variable, keep a list of instruction ranges where this +/// variable is accessible. The variables are listed in order of appearance. class DbgValueHistoryMap { - // Each instruction range starts with a DBG_VALUE instruction, specifying the - // location of a variable, which is assumed to be valid until the end of the - // range. If end is not specified, location is valid until the start - // instruction of the next instruction range, or until the end of the - // function. public: - using InstrRange = std::pair<const MachineInstr *, const MachineInstr *>; - using InstrRanges = SmallVector<InstrRange, 4>; + /// Index in the entry vector. + typedef size_t EntryIndex; + + /// Special value to indicate that an entry is valid until the end of the + /// function. + static const EntryIndex NoEntry = std::numeric_limits<EntryIndex>::max(); + + /// Specifies a change in a variable's debug value history. + /// + /// There exist two types of entries: + /// + /// * Debug value entry: + /// + /// A new debug value becomes live. If the entry's \p EndIndex is \p NoEntry, + /// the value is valid until the end of the function. For other values, the + /// index points to the entry in the entry vector that ends this debug + /// value. The ending entry can either be an overlapping debug value, or + /// an instruction that clobbers the value. + /// + /// * Clobbering entry: + /// + /// This entry's instruction clobbers one or more preceding + /// register-described debug values that have their end index + /// set to this entry's position in the entry vector. + class Entry { + public: + enum EntryKind { DbgValue, Clobber }; + + Entry(const MachineInstr *Instr, EntryKind Kind) + : Instr(Instr, Kind), EndIndex(NoEntry) {} + + const MachineInstr *getInstr() const { return Instr.getPointer(); } + EntryIndex getEndIndex() const { return EndIndex; } + EntryKind getEntryKind() const { return Instr.getInt(); } + + bool isClobber() const { return getEntryKind() == Clobber; } + bool isDbgValue() const { return getEntryKind() == DbgValue; } + bool isClosed() const { return EndIndex != NoEntry; } + + void endEntry(EntryIndex EndIndex); + + private: + PointerIntPair<const MachineInstr *, 1, EntryKind> Instr; + EntryIndex EndIndex; + }; + using Entries = SmallVector<Entry, 4>; using InlinedEntity = std::pair<const DINode *, const DILocation *>; - using InstrRangesMap = MapVector<InlinedEntity, InstrRanges>; + using EntriesMap = MapVector<InlinedEntity, Entries>; private: - InstrRangesMap VarInstrRanges; + EntriesMap VarEntries; public: - void startInstrRange(InlinedEntity Var, const MachineInstr &MI); - void endInstrRange(InlinedEntity Var, const MachineInstr &MI); - - // Returns register currently describing @Var. If @Var is currently - // unaccessible or is not described by a register, returns 0. - unsigned getRegisterForVar(InlinedEntity Var) const; - - bool empty() const { return VarInstrRanges.empty(); } - void clear() { VarInstrRanges.clear(); } - InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); } - InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); } + bool startDbgValue(InlinedEntity Var, const MachineInstr &MI, + EntryIndex &NewIndex); + EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI); + + Entry &getEntry(InlinedEntity Var, EntryIndex Index) { + auto &Entries = VarEntries[Var]; + return Entries[Index]; + } + + bool empty() const { return VarEntries.empty(); } + void clear() { VarEntries.clear(); } + EntriesMap::const_iterator begin() const { return VarEntries.begin(); } + EntriesMap::const_iterator end() const { return VarEntries.end(); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const; diff --git a/include/llvm/CodeGen/DebugHandlerBase.h b/include/llvm/CodeGen/DebugHandlerBase.h index 4f0d14d317f2..4008d597395e 100644 --- a/include/llvm/CodeGen/DebugHandlerBase.h +++ b/include/llvm/CodeGen/DebugHandlerBase.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/DebugHandlerBase.h -----------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -130,7 +129,7 @@ public: const MCExpr *getFunctionLocalOffsetAfterInsn(const MachineInstr *MI); /// If this type is derived from a base type then return base type size. - static uint64_t getBaseTypeSize(const DITypeRef TyRef); + static uint64_t getBaseTypeSize(const DIType *Ty); }; } diff --git a/include/llvm/CodeGen/DwarfStringPoolEntry.h b/include/llvm/CodeGen/DwarfStringPoolEntry.h index 8b1a7af17bbf..e189352a7b2d 100644 --- a/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h index c31fad246c96..28cdf54e0575 100644 --- a/include/llvm/CodeGen/EdgeBundles.h +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -1,9 +1,8 @@ //===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ExecutionDomainFix.h b/include/llvm/CodeGen/ExecutionDomainFix.h index 338c214dd073..6836678e2101 100644 --- a/include/llvm/CodeGen/ExecutionDomainFix.h +++ b/include/llvm/CodeGen/ExecutionDomainFix.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ExpandReductions.h b/include/llvm/CodeGen/ExpandReductions.h index c6aaaad967b3..5dbed07873c1 100644 --- a/include/llvm/CodeGen/ExpandReductions.h +++ b/include/llvm/CodeGen/ExpandReductions.h @@ -1,9 +1,8 @@ //===----- ExpandReductions.h - Expand experimental reduction intrinsics --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 865d8a88b8cc..f09b59daf4dd 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -1,9 +1,8 @@ //===- FastISel.h - Definition of the FastISel class ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -528,7 +527,7 @@ protected: /// Select and emit code for a binary operator instruction, which has /// an opcode which directly corresponds to the given ISD opcode. bool selectBinaryOp(const User *I, unsigned ISDOpcode); - bool selectFNeg(const User *I); + bool selectFNeg(const User *I, const Value *In); bool selectGetElementPtr(const User *I); bool selectStackmap(const CallInst *I); bool selectPatchpoint(const CallInst *I); diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h index 55e25c9823b1..a1e2349c413e 100644 --- a/include/llvm/CodeGen/FaultMaps.h +++ b/include/llvm/CodeGen/FaultMaps.h @@ -1,9 +1,8 @@ //===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 7c658515de09..fb60191abd3a 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -1,9 +1,8 @@ //===- FunctionLoweringInfo.h - Lower functions from LLVM IR ---*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,13 +13,14 @@ #ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H #define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H - #include "llvm/ADT/APInt.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LegacyDivergenceAnalysis.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -57,6 +57,7 @@ public: const TargetLowering *TLI; MachineRegisterInfo *RegInfo; BranchProbabilityInfo *BPI; + const LegacyDivergenceAnalysis *DA; /// CanLowerReturn - true iff the function's return value can be lowered to /// registers. bool CanLowerReturn; @@ -71,48 +72,6 @@ public: /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. DenseMap<const BasicBlock*, MachineBasicBlock *> MBBMap; - /// A map from swifterror value in a basic block to the virtual register it is - /// currently represented by. - DenseMap<std::pair<const MachineBasicBlock *, const Value *>, unsigned> - SwiftErrorVRegDefMap; - - /// A list of upward exposed vreg uses that need to be satisfied by either a - /// copy def or a phi node at the beginning of the basic block representing - /// the predecessor(s) swifterror value. - DenseMap<std::pair<const MachineBasicBlock *, const Value *>, unsigned> - SwiftErrorVRegUpwardsUse; - - /// A map from instructions that define/use a swifterror value to the virtual - /// register that represents that def/use. - llvm::DenseMap<PointerIntPair<const Instruction *, 1, bool>, unsigned> - SwiftErrorVRegDefUses; - - /// The swifterror argument of the current function. - const Value *SwiftErrorArg; - - using SwiftErrorValues = SmallVector<const Value*, 1>; - /// A function can only have a single swifterror argument. And if it does - /// have a swifterror argument, it must be the first entry in - /// SwiftErrorVals. - SwiftErrorValues SwiftErrorVals; - - /// Get or create the swifterror value virtual register in - /// SwiftErrorVRegDefMap for this basic block. - unsigned getOrCreateSwiftErrorVReg(const MachineBasicBlock *, - const Value *); - - /// Set the swifterror virtual register in the SwiftErrorVRegDefMap for this - /// basic block. - void setCurrentSwiftErrorVReg(const MachineBasicBlock *MBB, const Value *, - unsigned); - - /// Get or create the swifterror value virtual register for a def of a - /// swifterror by an instruction. - std::pair<unsigned, bool> getOrCreateSwiftErrorVRegDefAt(const Instruction *); - std::pair<unsigned, bool> - getOrCreateSwiftErrorVRegUseAt(const Instruction *, const MachineBasicBlock *, - const Value *); - /// ValueMap - Since we emit code for the function a basic block at a time, /// we must remember which virtual registers hold the values for /// cross-basic-block values. @@ -175,6 +134,10 @@ public: /// function arguments that are inserted after scheduling is completed. SmallVector<MachineInstr*, 8> ArgDbgValues; + /// Bitvector with a bit set if corresponding argument is described in + /// ArgDbgValues. Using arg numbers according to Argument numbering. + BitVector DescribedArgs; + /// RegFixups - Registers which need to be replaced after isel is done. DenseMap<unsigned, unsigned> RegFixups; @@ -236,9 +199,11 @@ public: return ValueMap.count(V); } - unsigned CreateReg(MVT VT); + unsigned CreateReg(MVT VT, bool isDivergent = false); + + unsigned CreateRegs(const Value *V); - unsigned CreateRegs(Type *Ty); + unsigned CreateRegs(Type *Ty, bool isDivergent = false); unsigned InitializeRegForValue(const Value *V) { // Tokens never live in vregs. @@ -247,7 +212,7 @@ public: unsigned &R = ValueMap[V]; assert(R == 0 && "Already initialized this value register!"); assert(VirtReg2Value.empty()); - return R = CreateRegs(V->getType()); + return R = CreateRegs(V); } /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 7fb27202c122..77cd356c49dd 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -1,9 +1,8 @@ //===- GCMetadata.h - Garbage collector metadata ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 5f1efb2ce02c..f9527c9f8752 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 5a60cd7cb823..c5731528da4e 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GCStrategy.h - Garbage collection -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/include/llvm/CodeGen/GlobalISel/CSEInfo.h index ce2d285a99e5..5a44e67992ad 100644 --- a/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ b/include/llvm/CodeGen/GlobalISel/CSEInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H #include "llvm/ADT/FoldingSet.h" +#include "llvm/CodeGen/CSEConfigBase.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/GISelWorkList.h" #include "llvm/CodeGen/GlobalISel/Utils.h" @@ -37,25 +37,27 @@ public: void Profile(FoldingSetNodeID &ID); }; -// Class representing some configuration that can be done during CSE analysis. -// Currently it only supports shouldCSE method that each pass can set. -class CSEConfig { +// A CSE config for fully optimized builds. +class CSEConfigFull : public CSEConfigBase { public: - virtual ~CSEConfig() = default; - // Hook for defining which Generic instructions should be CSEd. - // GISelCSEInfo currently only calls this hook when dealing with generic - // opcodes. - virtual bool shouldCSEOpc(unsigned Opc); + virtual ~CSEConfigFull() = default; + virtual bool shouldCSEOpc(unsigned Opc) override; }; -// TODO: Find a better place for this. // Commonly used for O0 config. -class CSEConfigConstantOnly : public CSEConfig { +class CSEConfigConstantOnly : public CSEConfigBase { public: virtual ~CSEConfigConstantOnly() = default; virtual bool shouldCSEOpc(unsigned Opc) override; }; +// Returns the standard expected CSEConfig for the given optimization level. +// We have this logic here so targets can make use of it from their derived +// TargetPassConfig, but can't put this logic into TargetPassConfig directly +// because the CodeGen library can't depend on GlobalISel. +std::unique_ptr<CSEConfigBase> +getStandardCSEConfigForOpt(CodeGenOpt::Level Level); + /// The CSE Analysis object. /// This installs itself as a delegate to the MachineFunction to track /// new instructions as well as deletions. It however will not be able to @@ -74,7 +76,7 @@ class GISelCSEInfo : public GISelChangeObserver { FoldingSet<UniqueMachineInstr> CSEMap; MachineRegisterInfo *MRI = nullptr; MachineFunction *MF = nullptr; - std::unique_ptr<CSEConfig> CSEOpt; + std::unique_ptr<CSEConfigBase> CSEOpt; /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel, /// often instructions are mutated (while their ID has completely changed). /// Whenever mutation happens, invalidate the UniqueMachineInstr for the @@ -139,7 +141,9 @@ public: void releaseMemory(); - void setCSEConfig(std::unique_ptr<CSEConfig> Opt) { CSEOpt = std::move(Opt); } + void setCSEConfig(std::unique_ptr<CSEConfigBase> Opt) { + CSEOpt = std::move(Opt); + } bool shouldCSE(unsigned Opc) const; @@ -199,11 +203,12 @@ class GISelCSEAnalysisWrapper { bool AlreadyComputed = false; public: - /// Takes a CSEConfig object that defines what opcodes get CSEd. + /// Takes a CSEConfigBase object that defines what opcodes get CSEd. /// If CSEConfig is already set, and the CSE Analysis has been preserved, /// it will not use the new CSEOpt(use Recompute to force using the new /// CSEOpt). - GISelCSEInfo &get(std::unique_ptr<CSEConfig> CSEOpt, bool ReCompute = false); + GISelCSEInfo &get(std::unique_ptr<CSEConfigBase> CSEOpt, + bool ReCompute = false); void setMF(MachineFunction &MFunc) { MF = &MFunc; } void setComputed(bool Computed) { AlreadyComputed = Computed; } void releaseMemory() { Info.releaseMemory(); } diff --git a/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h b/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h index a8fb736ebbb5..4f95335db74b 100644 --- a/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/CodeGen/GlobalISel/CallLowering.h b/include/llvm/CodeGen/GlobalISel/CallLowering.h index ab498e8f070b..d717121ad78e 100644 --- a/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CallLowering.h - Call lowering ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -16,6 +15,7 @@ #define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/IR/CallSite.h" @@ -27,6 +27,7 @@ namespace llvm { +class CCState; class DataLayout; class Function; class MachineIRBuilder; @@ -43,14 +44,19 @@ class CallLowering { virtual void anchor(); public: struct ArgInfo { - unsigned Reg; + SmallVector<Register, 4> Regs; Type *Ty; ISD::ArgFlagsTy Flags; bool IsFixed; - ArgInfo(unsigned Reg, Type *Ty, ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, - bool IsFixed = true) - : Reg(Reg), Ty(Ty), Flags(Flags), IsFixed(IsFixed) {} + ArgInfo(ArrayRef<Register> Regs, Type *Ty, + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy{}, bool IsFixed = true) + : Regs(Regs.begin(), Regs.end()), Ty(Ty), Flags(Flags), + IsFixed(IsFixed) { + // FIXME: We should have just one way of saying "no register". + assert((Ty->isVoidTy() == (Regs.empty() || Regs[0] == 0)) && + "only void types should have no register"); + } }; /// Argument handling is mostly uniform between the four places that @@ -66,24 +72,28 @@ public: virtual ~ValueHandler() = default; + /// Returns true if the handler is dealing with formal arguments, + /// not with return values etc. + virtual bool isArgumentHandler() const { return false; } + /// Materialize a VReg containing the address of the specified /// stack-based object. This is either based on a FrameIndex or /// direct SP manipulation, depending on the context. \p MPO /// should be initialized to an appropriate description of the /// address created. - virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, + virtual Register getStackAddress(uint64_t Size, int64_t Offset, MachinePointerInfo &MPO) = 0; /// The specified value has been assigned to a physical register, /// handle the appropriate COPY (either to or from) and mark any /// relevant uses/defines as needed. - virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg, + virtual void assignValueToReg(Register ValVReg, Register PhysReg, CCValAssign &VA) = 0; /// The specified value has been assigned to a stack /// location. Load or store it there, with appropriate extension /// if necessary. - virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, + virtual void assignValueToAddress(Register ValVReg, Register Addr, uint64_t Size, MachinePointerInfo &MPO, CCValAssign &VA) = 0; @@ -98,7 +108,7 @@ public: llvm_unreachable("Custom values not supported"); } - unsigned extendRegister(unsigned ValReg, CCValAssign &VA); + Register extendRegister(Register ValReg, CCValAssign &VA); virtual bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, const ArgInfo &Info, @@ -130,39 +140,83 @@ protected: void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; + /// Generate instructions for packing \p SrcRegs into one big register + /// corresponding to the aggregate type \p PackedTy. + /// + /// \param SrcRegs should contain one virtual register for each base type in + /// \p PackedTy, as returned by computeValueLLTs. + /// + /// \return The packed register. + Register packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy, + MachineIRBuilder &MIRBuilder) const; + + /// Generate instructions for unpacking \p SrcReg into the \p DstRegs + /// corresponding to the aggregate type \p PackedTy. + /// + /// \param DstRegs should contain one virtual register for each base type in + /// \p PackedTy, as returned by computeValueLLTs. + void unpackRegs(ArrayRef<Register> DstRegs, Register SrcReg, Type *PackedTy, + MachineIRBuilder &MIRBuilder) const; + /// Invoke Handler::assignArg on each of the given \p Args and then use /// \p Callback to move them to the assigned locations. /// /// \return True if everything has succeeded, false otherwise. bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, ValueHandler &Handler) const; - + bool handleAssignments(CCState &CCState, + SmallVectorImpl<CCValAssign> &ArgLocs, + MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, + ValueHandler &Handler) const; public: CallLowering(const TargetLowering *TLI) : TLI(TLI) {} virtual ~CallLowering() = default; + /// \return true if the target is capable of handling swifterror values that + /// have been promoted to a specified register. The extended versions of + /// lowerReturn and lowerCall should be implemented. + virtual bool supportSwiftError() const { + return false; + } + /// This hook must be implemented to lower outgoing return values, described /// by \p Val, into the specified virtual registers \p VRegs. /// This hook is used by GlobalISel. /// + /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter + /// that needs to be implicitly returned. + /// /// \return True if the lowering succeeds, false otherwise. virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef<unsigned> VRegs) const { + ArrayRef<Register> VRegs, + Register SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); + return lowerReturn(MIRBuilder, Val, VRegs); + } + return false; + } + + /// This hook behaves as the extended lowerReturn function, but for targets + /// that do not support swifterror value promotion. + virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, + ArrayRef<Register> VRegs) const { return false; } /// This hook must be implemented to lower the incoming (formal) - /// arguments, described by \p Args, for GlobalISel. Each argument - /// must end up in the related virtual register described by VRegs. - /// In other words, the first argument should end up in VRegs[0], - /// the second in VRegs[1], and so on. + /// arguments, described by \p VRegs, for GlobalISel. Each argument + /// must end up in the related virtual registers described by \p VRegs. + /// In other words, the first argument should end up in \c VRegs[0], + /// the second in \c VRegs[1], and so on. For each argument, there will be one + /// register for each non-aggregate type, as returned by \c computeValueLLTs. /// \p MIRBuilder is set to the proper insertion for the argument /// lowering. /// /// \return True if the lowering succeeded, false otherwise. virtual bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, - ArrayRef<unsigned> VRegs) const { + ArrayRef<ArrayRef<Register>> VRegs) const { return false; } @@ -174,20 +228,31 @@ public: /// \p Callee is the destination of the call. It should be either a register, /// globaladdress, or externalsymbol. /// - /// \p ResTy is the type returned by the function - /// - /// \p ResReg is the generic virtual register that the returned - /// value should be lowered into. + /// \p OrigRet is a descriptor for the return type of the function. /// - /// \p ArgTys is a list of the types each member of \p ArgRegs has; used by - /// the target to decide which register/stack slot should be allocated. + /// \p OrigArgs is a list of descriptors of the arguments passed to the + /// function. /// - /// \p ArgRegs is a list of virtual registers containing each argument that - /// needs to be passed. + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. /// /// \return true if the lowering succeeded, false otherwise. virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs, + Register SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "trying to use unsupported swifterror"); + return lowerCall(MIRBuilder, CallConv, Callee, OrigRet, OrigArgs); + } + return false; + } + + /// This hook behaves as the extended lowerCall function, but for targets that + /// do not support swifterror value promotion. + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, ArrayRef<ArgInfo> OrigArgs) const { return false; } @@ -197,11 +262,18 @@ public: /// /// \p CI is the call/invoke instruction. /// - /// \p ResReg is a register where the call's return value should be stored (or - /// 0 if there is no return value). + /// \p ResRegs are the registers where the call's return value should be + /// stored (or 0 if there is no return value). There will be one register for + /// each non-aggregate type, as returned by \c computeValueLLTs. + /// + /// \p ArgRegs is a list of lists of virtual registers containing each + /// argument that needs to be passed (argument \c i should be placed in \c + /// ArgRegs[i]). For each argument, there will be one register for each + /// non-aggregate type, as returned by \c computeValueLLTs. /// - /// \p ArgRegs is a list of virtual registers containing each argument that - /// needs to be passed. + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. /// /// \p GetCalleeReg is a callback to materialize a register for the callee if /// the target determines it cannot jump to the destination based purely on \p @@ -210,7 +282,8 @@ public: /// /// \return true if the lowering succeeded, false otherwise. bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, - unsigned ResReg, ArrayRef<unsigned> ArgRegs, + ArrayRef<Register> ResRegs, + ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg, std::function<unsigned()> GetCalleeReg) const; }; diff --git a/include/llvm/CodeGen/GlobalISel/Combiner.h b/include/llvm/CodeGen/GlobalISel/Combiner.h index b097c7817762..efe8bdf93664 100644 --- a/include/llvm/CodeGen/GlobalISel/Combiner.h +++ b/include/llvm/CodeGen/GlobalISel/Combiner.h @@ -1,9 +1,8 @@ -//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == // +//== ----- llvm/CodeGen/GlobalISel/Combiner.h -------------------*- C++ -*-== // // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 6e9ac01c1ee2..0c50c9c5e0cf 100644 --- a/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/CombinerHelper.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===--------------------------------------------------------------------===// // @@ -18,6 +17,9 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H #define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H +#include "llvm/CodeGen/LowLevelType.h" +#include "llvm/CodeGen/Register.h" + namespace llvm { class GISelChangeObserver; @@ -26,6 +28,12 @@ class MachineRegisterInfo; class MachineInstr; class MachineOperand; +struct PreferredTuple { + LLT Ty; // The result type of the extend. + unsigned ExtendOpcode; // G_ANYEXT/G_SEXT/G_ZEXT + MachineInstr *MI; +}; + class CombinerHelper { MachineIRBuilder &Builder; MachineRegisterInfo &MRI; @@ -35,20 +43,27 @@ public: CombinerHelper(GISelChangeObserver &Observer, MachineIRBuilder &B); /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes - void replaceRegWith(MachineRegisterInfo &MRI, unsigned FromReg, unsigned ToReg) const; + void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const; /// Replace a single register operand with a new register and inform the /// observer of the changes. void replaceRegOpWith(MachineRegisterInfo &MRI, MachineOperand &FromRegOp, - unsigned ToReg) const; + Register ToReg) const; /// If \p MI is COPY, try to combine it. /// Returns true if MI changed. bool tryCombineCopy(MachineInstr &MI); + bool matchCombineCopy(MachineInstr &MI); + void applyCombineCopy(MachineInstr &MI); /// If \p MI is extend that consumes the result of a load, try to combine it. /// Returns true if MI changed. bool tryCombineExtendingLoads(MachineInstr &MI); + bool matchCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); + void applyCombineExtendingLoads(MachineInstr &MI, PreferredTuple &MatchInfo); + + bool matchCombineBr(MachineInstr &MI); + bool tryCombineBr(MachineInstr &MI); /// Try to transform \p MI by using all of the above /// combine functions. Returns true if changed. diff --git a/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/include/llvm/CodeGen/GlobalISel/CombinerInfo.h index d21aa3f725d9..3b09a8e2b479 100644 --- a/include/llvm/CodeGen/GlobalISel/CombinerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h index 220a571b21db..e817d9b4550e 100644 --- a/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h b/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h index c8e8a7a5a7cb..e5691cb35174 100644 --- a/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h +++ b/include/llvm/CodeGen/GlobalISel/GISelChangeObserver.h @@ -1,9 +1,8 @@ -//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h ------------------===// +//===----- llvm/CodeGen/GlobalISel/GISelChangeObserver.h --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -34,10 +33,17 @@ public: /// An instruction is about to be erased. virtual void erasingInstr(MachineInstr &MI) = 0; - /// An instruction was created and inserted into the function. + + /// An instruction has been created and inserted into the function. + /// Note that the instruction might not be a fully fledged instruction at this + /// point and won't be if the MachineFunction::Delegate is calling it. This is + /// because the delegate only sees the construction of the MachineInstr before + /// operands have been added. virtual void createdInstr(MachineInstr &MI) = 0; + /// This instruction is about to be mutated in some way. virtual void changingInstr(MachineInstr &MI) = 0; + /// This instruction was mutated in some way. virtual void changedInstr(MachineInstr &MI) = 0; diff --git a/include/llvm/CodeGen/GlobalISel/GISelWorkList.h b/include/llvm/CodeGen/GlobalISel/GISelWorkList.h index 1571841a208d..b0bb519283b1 100644 --- a/include/llvm/CodeGen/GlobalISel/GISelWorkList.h +++ b/include/llvm/CodeGen/GlobalISel/GISelWorkList.h @@ -1,9 +1,8 @@ //===- GISelWorkList.h - Worklist for GISel passes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,23 +32,61 @@ class GISelWorkList { SmallVector<MachineInstr *, N> Worklist; DenseMap<MachineInstr *, unsigned> WorklistMap; +#ifndef NDEBUG + bool Finalized = true; +#endif + public: - GISelWorkList() {} + GISelWorkList() : WorklistMap(N) {} bool empty() const { return WorklistMap.empty(); } unsigned size() const { return WorklistMap.size(); } + // Since we don't know ahead of time how many instructions we're going to add + // to the worklist, and migrating densemap's elements is quite expensive + // everytime we resize, only insert to the smallvector (typically during the + // initial phase of populating lists). Before the worklist can be used, + // finalize should be called. Also assert with NDEBUG if list is ever used + // without finalizing. Note that unlike insert, we won't check for duplicates + // - so the ideal place to use this is during the initial prepopulating phase + // of most passes. + void deferred_insert(MachineInstr *I) { + Worklist.push_back(I); +#ifndef NDEBUG + Finalized = false; +#endif + } + + // This should only be called when using deferred_insert. + // This asserts that the WorklistMap is empty, and then + // inserts all the elements in the Worklist into the map. + // It also asserts if there are any duplicate elements found. + void finalize() { + assert(WorklistMap.empty() && "Expecting empty worklistmap"); + if (Worklist.size() > N) + WorklistMap.reserve(Worklist.size()); + for (unsigned i = 0; i < Worklist.size(); ++i) + if (!WorklistMap.try_emplace(Worklist[i], i).second) + llvm_unreachable("Duplicate elements in the list"); +#ifndef NDEBUG + Finalized = true; +#endif + } + /// Add the specified instruction to the worklist if it isn't already in it. void insert(MachineInstr *I) { + assert(Finalized && "GISelWorkList used without finalizing"); if (WorklistMap.try_emplace(I, Worklist.size()).second) Worklist.push_back(I); } /// Remove I from the worklist if it exists. void remove(const MachineInstr *I) { + assert((Finalized || WorklistMap.empty()) && "Neither finalized nor empty"); auto It = WorklistMap.find(I); - if (It == WorklistMap.end()) return; // Not in worklist. + if (It == WorklistMap.end()) + return; // Not in worklist. // Don't bother moving everything down, just null out the slot. Worklist[It->second] = nullptr; @@ -63,6 +100,7 @@ public: } MachineInstr *pop_back_val() { + assert(Finalized && "GISelWorkList used without finalizing"); MachineInstr *I; do { I = Worklist.pop_back_val(); diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index d1770bf6e4ce..8654ba83f08d 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/IRTranslator.h - IRTranslator ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -23,7 +22,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Types.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SwitchLoweringUtils.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Allocator.h" #include <memory> @@ -37,6 +38,7 @@ class CallInst; class CallLowering; class Constant; class DataLayout; +class FunctionLoweringInfo; class Instruction; class MachineBasicBlock; class MachineFunction; @@ -69,7 +71,7 @@ private: public: ValueToVRegInfo() = default; - using VRegListT = SmallVector<unsigned, 1>; + using VRegListT = SmallVector<Register, 1>; using OffsetListT = SmallVector<uint64_t, 1>; using const_vreg_iterator = @@ -164,6 +166,8 @@ private: /// this function. DenseMap<const AllocaInst *, int> FrameIndices; + SwiftErrorValueTracking SwiftError; + /// \name Methods for translating form LLVM IR to MachineInstr. /// \see ::translate for general information on the translate methods. /// @{ @@ -196,7 +200,7 @@ private: /// the function. /// /// \return true if the materialization succeeded. - bool translate(const Constant &C, unsigned Reg); + bool translate(const Constant &C, Register Reg); /// Translate an LLVM bitcast into generic IR. Either a COPY or a G_BITCAST is /// emitted. @@ -212,24 +216,27 @@ private: bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, unsigned ID); - void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder); + void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, MachineIRBuilder &MIRBuilder); + /// Helper function for translateSimpleIntrinsic. + /// \return The generic opcode for \p IntrinsicID if \p IntrinsicID is a + /// simple intrinsic (ceil, fabs, etc.). Otherwise, returns + /// Intrinsic::not_intrinsic. + unsigned getSimpleIntrinsicOpcode(Intrinsic::ID ID); + + /// Translates the intrinsics defined in getSimpleIntrinsicOpcode. + /// \return true if the translation succeeded. + bool translateSimpleIntrinsic(const CallInst &CI, Intrinsic::ID ID, + MachineIRBuilder &MIRBuilder); + bool translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder); bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); - // FIXME: temporary function to expose previous interface to call lowering - // until it is refactored. - /// Combines all component registers of \p V into a single scalar with size - /// "max(Offsets) + last size". - unsigned packRegs(const Value &V, MachineIRBuilder &MIRBuilder); - - void unpackRegs(const Value &V, unsigned Src, MachineIRBuilder &MIRBuilder); - /// Returns true if the value should be split into multiple LLTs. /// If \p Offsets is given then the split type's offsets will be stored in it. /// If \p Offsets is not empty it will be cleared first. @@ -242,6 +249,8 @@ private: bool translateInvoke(const User &U, MachineIRBuilder &MIRBuilder); + bool translateCallBr(const User &U, MachineIRBuilder &MIRBuilder); + bool translateLandingPad(const User &U, MachineIRBuilder &MIRBuilder); /// Translate one of LLVM's cast instructions into MachineInstrs, with the @@ -278,7 +287,42 @@ private: /// \pre \p U is a branch instruction. bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); + // Begin switch lowering functions. + bool emitJumpTableHeader(SwitchCG::JumpTable &JT, + SwitchCG::JumpTableHeader &JTH, + MachineBasicBlock *HeaderBB); + void emitJumpTable(SwitchCG::JumpTable &JT, MachineBasicBlock *MBB); + + void emitSwitchCase(SwitchCG::CaseBlock &CB, MachineBasicBlock *SwitchBB, + MachineIRBuilder &MIB); + + bool lowerJumpTableWorkItem(SwitchCG::SwitchWorkListItem W, + MachineBasicBlock *SwitchMBB, + MachineBasicBlock *CurMBB, + MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB, + MachineFunction::iterator BBI, + BranchProbability UnhandledProbs, + SwitchCG::CaseClusterIt I, + MachineBasicBlock *Fallthrough, + bool FallthroughUnreachable); + + bool lowerSwitchRangeWorkItem(SwitchCG::CaseClusterIt I, + Value *Cond, + MachineBasicBlock *Fallthrough, + bool FallthroughUnreachable, + BranchProbability UnhandledProbs, + MachineBasicBlock *CurMBB, + MachineIRBuilder &MIB, + MachineBasicBlock *SwitchMBB); + + bool lowerSwitchWorkItem(SwitchCG::SwitchWorkListItem W, Value *Cond, + MachineBasicBlock *SwitchMBB, + MachineBasicBlock *DefaultMBB, + MachineIRBuilder &MIB); + bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); + // End switch lowering section. bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder); @@ -404,6 +448,7 @@ private: bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder); bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder); + bool translateFence(const User &U, MachineIRBuilder &MIRBuilder); // Stubs to keep the compiler happy while we implement the rest of the // translation. @@ -419,9 +464,6 @@ private: bool translateCatchSwitch(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateFence(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) { return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder); } @@ -466,19 +508,50 @@ private: /// Current optimization remark emitter. Used to report failures. std::unique_ptr<OptimizationRemarkEmitter> ORE; + FunctionLoweringInfo FuncInfo; + + // True when either the Target Machine specifies no optimizations or the + // function has the optnone attribute. + bool EnableOpts = false; + + /// Switch analysis and optimization. + class GISelSwitchLowering : public SwitchCG::SwitchLowering { + public: + GISelSwitchLowering(IRTranslator *irt, FunctionLoweringInfo &funcinfo) + : SwitchLowering(funcinfo), IRT(irt) { + assert(irt && "irt is null!"); + } + + virtual void addSuccessorWithProb( + MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob = BranchProbability::getUnknown()) override { + IRT->addSuccessorWithProb(Src, Dst, Prob); + } + + virtual ~GISelSwitchLowering() = default; + + private: + IRTranslator *IRT; + }; + + std::unique_ptr<GISelSwitchLowering> SL; + // * Insert all the code needed to materialize the constants // at the proper place. E.g., Entry block or dominator block // of each constant depending on how fancy we want to be. // * Clear the different maps. void finalizeFunction(); + // Handle emitting jump tables for each basic block. + void finalizeBasicBlock(); + /// Get the VRegs that represent \p Val. /// Non-aggregate types have just one corresponding VReg and the list can be /// used as a single "unsigned". Aggregates get flattened. If such VRegs do /// not exist, they are created. - ArrayRef<unsigned> getOrCreateVRegs(const Value &Val); + ArrayRef<Register> getOrCreateVRegs(const Value &Val); - unsigned getOrCreateVReg(const Value &Val) { + Register getOrCreateVReg(const Value &Val) { auto Regs = getOrCreateVRegs(Val); if (Regs.empty()) return 0; @@ -522,6 +595,14 @@ private: return SmallVector<MachineBasicBlock *, 4>(1, &getMBB(*Edge.first)); } + /// Return branch probability calculated by BranchProbabilityInfo for IR + /// blocks. + BranchProbability getEdgeProbability(const MachineBasicBlock *Src, + const MachineBasicBlock *Dst) const; + + void addSuccessorWithProb(MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob); + public: // Ctor, nothing fancy. IRTranslator(); diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelect.h b/include/llvm/CodeGen/GlobalISel/InstructionSelect.h index 01521c46ab6a..1af46e0a9e76 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelect.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelect.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/InstructionSelect.h -----------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 describes the interface of the MachineFunctionPass diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 471def7f45a3..e9b93be76754 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/InstructionSelector.h ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -139,6 +138,16 @@ enum { /// - MMOIdx - MMO index /// - Size - The size in bytes of the memory access GIM_CheckMemorySizeEqualTo, + + /// Check the address space of the memory access for the given machine memory + /// operand. + /// - InsnID - Instruction ID + /// - MMOIdx - MMO index + /// - NumAddrSpace - Number of valid address spaces + /// - AddrSpaceN - An allowed space of the memory access + /// - AddrSpaceN+1 ... + GIM_CheckMemoryAddressSpace, + /// Check the size of the memory access for the given machine memory operand /// against the size of an operand. /// - InsnID - Instruction ID diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index 2003a79f6b20..e8ee4af0cb0b 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -371,6 +370,45 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckMemoryAddressSpace: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t MMOIdx = MatchTable[CurrentIdx++]; + // This accepts a list of possible address spaces. + const int NumAddrSpace = MatchTable[CurrentIdx++]; + + if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + + // Need to still jump to the end of the list of address spaces if we find + // a match earlier. + const uint64_t LastIdx = CurrentIdx + NumAddrSpace; + + const MachineMemOperand *MMO + = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); + const unsigned MMOAddrSpace = MMO->getAddrSpace(); + + bool Success = false; + for (int I = 0; I != NumAddrSpace; ++I) { + unsigned AddrSpace = MatchTable[CurrentIdx++]; + DEBUG_WITH_TYPE( + TgtInstructionSelector::getName(), + dbgs() << "addrspace(" << MMOAddrSpace << ") vs " + << AddrSpace << '\n'); + + if (AddrSpace == MMOAddrSpace) { + Success = true; + break; + } + } + + CurrentIdx = LastIdx; + if (!Success && handleReject() == RejectAndGiveUp) + return false; + break; + } case GIM_CheckMemorySizeEqualTo: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t MMOIdx = MatchTable[CurrentIdx++]; @@ -438,15 +476,15 @@ bool InstructionSelector::executeMatchTable( unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && - MMO->getSize() * 8 != Size) { + MMO->getSizeInBits() != Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && - MMO->getSize() * 8 >= Size) { + MMO->getSizeInBits() >= Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && - MMO->getSize() * 8 <= Size) + MMO->getSizeInBits() <= Size) if (handleReject() == RejectAndGiveUp) return false; @@ -479,17 +517,19 @@ bool InstructionSelector::executeMatchTable( << InsnID << "]->getOperand(" << OpIdx << "), SizeInBits=" << SizeInBits << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + const LLT Ty = MRI.getType(MO.getReg()); + // iPTR must be looked up in the target. if (SizeInBits == 0) { MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent(); - SizeInBits = MF->getDataLayout().getPointerSizeInBits(0); + const unsigned AddrSpace = Ty.getAddressSpace(); + SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace); } assert(SizeInBits != 0 && "Pointer size must be known"); - MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); if (MO.isReg()) { - const LLT &Ty = MRI.getType(MO.getReg()); if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) if (handleReject() == RejectAndGiveUp) return false; diff --git a/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index 20bec7650179..a22778b8848c 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h -----*- C++ -*-// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 helper functions which try to cleanup artifacts @@ -29,6 +28,18 @@ class LegalizationArtifactCombiner { MachineRegisterInfo &MRI; const LegalizerInfo &LI; + static bool isArtifactCast(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_TRUNC: + case TargetOpcode::G_SEXT: + case TargetOpcode::G_ZEXT: + case TargetOpcode::G_ANYEXT: + return true; + default: + return false; + } + } + public: LegalizationArtifactCombiner(MachineIRBuilder &B, MachineRegisterInfo &MRI, const LegalizerInfo &LI) @@ -40,11 +51,11 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // aext(trunc x) - > aext/copy/trunc x - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); Builder.buildAnyExtOrTrunc(DstReg, TruncSrc); @@ -53,7 +64,7 @@ public: } // aext([asz]ext x) -> [asz]ext x - unsigned ExtSrc; + Register ExtSrc; MachineInstr *ExtMI; if (mi_match(SrcReg, MRI, m_all_of(m_MInstr(ExtMI), m_any_of(m_GAnyExt(m_Reg(ExtSrc)), @@ -63,6 +74,20 @@ public: markInstAndDefDead(MI, *ExtMI, DeadInsts); return true; } + + // Try to fold aext(g_constant) when the larger constant type is legal. + // Can't use MIPattern because we don't have a specific constant in mind. + auto *SrcMI = MRI.getVRegDef(SrcReg); + if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { + const LLT &DstTy = MRI.getType(DstReg); + if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { + auto &CstVal = SrcMI->getOperand(1); + Builder.buildConstant( + DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits())); + markInstAndDefDead(MI, *SrcMI, DeadInsts); + return true; + } + } return tryFoldImplicitDef(MI, DeadInsts); } @@ -73,25 +98,39 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // zext(trunc x) - > and (aext/copy/trunc x), mask - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); LLT SrcTy = MRI.getType(SrcReg); - APInt Mask = APInt::getAllOnesValue(SrcTy.getSizeInBits()); + APInt Mask = APInt::getAllOnesValue(SrcTy.getScalarSizeInBits()); auto MIBMask = Builder.buildConstant(DstTy, Mask.getZExtValue()); Builder.buildAnd(DstReg, Builder.buildAnyExtOrTrunc(DstTy, TruncSrc), MIBMask); markInstAndDefDead(MI, *MRI.getVRegDef(SrcReg), DeadInsts); return true; } + + // Try to fold zext(g_constant) when the larger constant type is legal. + // Can't use MIPattern because we don't have a specific constant in mind. + auto *SrcMI = MRI.getVRegDef(SrcReg); + if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) { + const LLT &DstTy = MRI.getType(DstReg); + if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { + auto &CstVal = SrcMI->getOperand(1); + Builder.buildConstant( + DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits())); + markInstAndDefDead(MI, *SrcMI, DeadInsts); + return true; + } + } return tryFoldImplicitDef(MI, DeadInsts); } @@ -102,20 +141,22 @@ public: return false; Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); - unsigned SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg()); // sext(trunc x) - > ashr (shl (aext/copy/trunc x), c), c - unsigned TruncSrc; + Register TruncSrc; if (mi_match(SrcReg, MRI, m_GTrunc(m_Reg(TruncSrc)))) { LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) || - isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + // Guess on the RHS shift amount type, which should be re-legalized if + // applicable. + if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy, DstTy}}) || + isInstUnsupported({TargetOpcode::G_ASHR, {DstTy, DstTy}}) || + isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); LLT SrcTy = MRI.getType(SrcReg); - unsigned ShAmt = DstTy.getSizeInBits() - SrcTy.getSizeInBits(); + unsigned ShAmt = DstTy.getScalarSizeInBits() - SrcTy.getScalarSizeInBits(); auto MIBShAmt = Builder.buildConstant(DstTy, ShAmt); auto MIBShl = Builder.buildInstr( TargetOpcode::G_SHL, {DstTy}, @@ -138,7 +179,7 @@ public: if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(1).getReg(), MRI)) { Builder.setInstr(MI); - unsigned DstReg = MI.getOperand(0).getReg(); + Register DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); if (Opcode == TargetOpcode::G_ANYEXT) { @@ -150,7 +191,7 @@ public: } else { // G_[SZ]EXT (G_IMPLICIT_DEF) -> G_CONSTANT 0 because the top // bits will be 0 for G_ZEXT and 0/1 for the G_SEXT. - if (isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) + if (isConstantUnsupported(DstTy)) return false; LLVM_DEBUG(dbgs() << ".. Combine G_[SZ]EXT(G_IMPLICIT_DEF): " << MI;); Builder.buildConstant(DstReg, 0); @@ -162,6 +203,16 @@ public: return false; } + static unsigned getMergeOpcode(LLT OpTy, LLT DestTy) { + if (OpTy.isVector() && DestTy.isVector()) + return TargetOpcode::G_CONCAT_VECTORS; + + if (OpTy.isVector() && !DestTy.isVector()) + return TargetOpcode::G_BUILD_VECTOR; + + return TargetOpcode::G_MERGE_VALUES; + } + bool tryCombineMerges(MachineInstr &MI, SmallVectorImpl<MachineInstr *> &DeadInsts) { @@ -169,27 +220,33 @@ public: return false; unsigned NumDefs = MI.getNumOperands() - 1; + MachineInstr *SrcDef = + getDefIgnoringCopies(MI.getOperand(NumDefs).getReg(), MRI); + if (!SrcDef) + return false; - unsigned MergingOpcode; LLT OpTy = MRI.getType(MI.getOperand(NumDefs).getReg()); LLT DestTy = MRI.getType(MI.getOperand(0).getReg()); - if (OpTy.isVector() && DestTy.isVector()) - MergingOpcode = TargetOpcode::G_CONCAT_VECTORS; - else if (OpTy.isVector() && !DestTy.isVector()) - MergingOpcode = TargetOpcode::G_BUILD_VECTOR; - else - MergingOpcode = TargetOpcode::G_MERGE_VALUES; - - MachineInstr *MergeI = - getOpcodeDef(MergingOpcode, MI.getOperand(NumDefs).getReg(), MRI); + MachineInstr *MergeI = SrcDef; + unsigned ConvertOp = 0; + + // Handle intermediate conversions + unsigned SrcOp = SrcDef->getOpcode(); + if (isArtifactCast(SrcOp)) { + ConvertOp = SrcOp; + MergeI = getDefIgnoringCopies(SrcDef->getOperand(1).getReg(), MRI); + } - if (!MergeI) + // FIXME: Handle scalarizing concat_vectors (scalar result type with vector + // source) + unsigned MergingOpcode = getMergeOpcode(OpTy, DestTy); + if (!MergeI || MergeI->getOpcode() != MergingOpcode) return false; const unsigned NumMergeRegs = MergeI->getNumOperands() - 1; if (NumMergeRegs < NumDefs) { - if (NumDefs % NumMergeRegs != 0) + if (ConvertOp != 0 || NumDefs % NumMergeRegs != 0) return false; Builder.setInstr(MI); @@ -202,7 +259,7 @@ public: const unsigned NewNumDefs = NumDefs / NumMergeRegs; for (unsigned Idx = 0; Idx < NumMergeRegs; ++Idx) { - SmallVector<unsigned, 2> DstRegs; + SmallVector<Register, 2> DstRegs; for (unsigned j = 0, DefIdx = Idx * NewNumDefs; j < NewNumDefs; ++j, ++DefIdx) DstRegs.push_back(MI.getOperand(DefIdx).getReg()); @@ -211,7 +268,7 @@ public: } } else if (NumMergeRegs > NumDefs) { - if (NumMergeRegs % NumDefs != 0) + if (ConvertOp != 0 || NumMergeRegs % NumDefs != 0) return false; Builder.setInstr(MI); @@ -224,7 +281,7 @@ public: const unsigned NumRegs = NumMergeRegs / NumDefs; for (unsigned DefIdx = 0; DefIdx < NumDefs; ++DefIdx) { - SmallVector<unsigned, 2> Regs; + SmallVector<Register, 2> Regs; for (unsigned j = 0, Idx = NumRegs * DefIdx + 1; j < NumRegs; ++j, ++Idx) Regs.push_back(MergeI->getOperand(Idx).getReg()); @@ -233,10 +290,22 @@ public: } } else { + LLT MergeSrcTy = MRI.getType(MergeI->getOperand(1).getReg()); + if (ConvertOp) { + Builder.setInstr(MI); + + for (unsigned Idx = 0; Idx < NumDefs; ++Idx) { + Register MergeSrc = MergeI->getOperand(Idx + 1).getReg(); + Builder.buildInstr(ConvertOp, {MI.getOperand(Idx).getReg()}, + {MergeSrc}); + } + + markInstAndDefDead(MI, *MergeI, DeadInsts); + return true; + } // FIXME: is a COPY appropriate if the types mismatch? We know both // registers are allocatable by now. - if (MRI.getType(MI.getOperand(0).getReg()) != - MRI.getType(MergeI->getOperand(1).getReg())) + if (DestTy != MergeSrcTy) return false; for (unsigned Idx = 0; Idx < NumDefs; ++Idx) @@ -248,12 +317,77 @@ public: return true; } + static bool isMergeLikeOpcode(unsigned Opc) { + switch (Opc) { + case TargetOpcode::G_MERGE_VALUES: + case TargetOpcode::G_BUILD_VECTOR: + case TargetOpcode::G_CONCAT_VECTORS: + return true; + default: + return false; + } + } + + bool tryCombineExtract(MachineInstr &MI, + SmallVectorImpl<MachineInstr *> &DeadInsts) { + assert(MI.getOpcode() == TargetOpcode::G_EXTRACT); + + // Try to use the source registers from a G_MERGE_VALUES + // + // %2 = G_MERGE_VALUES %0, %1 + // %3 = G_EXTRACT %2, N + // => + // + // for N < %2.getSizeInBits() / 2 + // %3 = G_EXTRACT %0, N + // + // for N >= %2.getSizeInBits() / 2 + // %3 = G_EXTRACT %1, (N - %0.getSizeInBits() + + unsigned Src = lookThroughCopyInstrs(MI.getOperand(1).getReg()); + MachineInstr *MergeI = MRI.getVRegDef(Src); + if (!MergeI || !isMergeLikeOpcode(MergeI->getOpcode())) + return false; + + LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); + LLT SrcTy = MRI.getType(Src); + + // TODO: Do we need to check if the resulting extract is supported? + unsigned ExtractDstSize = DstTy.getSizeInBits(); + unsigned Offset = MI.getOperand(2).getImm(); + unsigned NumMergeSrcs = MergeI->getNumOperands() - 1; + unsigned MergeSrcSize = SrcTy.getSizeInBits() / NumMergeSrcs; + unsigned MergeSrcIdx = Offset / MergeSrcSize; + + // Compute the offset of the last bit the extract needs. + unsigned EndMergeSrcIdx = (Offset + ExtractDstSize - 1) / MergeSrcSize; + + // Can't handle the case where the extract spans multiple inputs. + if (MergeSrcIdx != EndMergeSrcIdx) + return false; + + // TODO: We could modify MI in place in most cases. + Builder.setInstr(MI); + Builder.buildExtract( + MI.getOperand(0).getReg(), + MergeI->getOperand(MergeSrcIdx + 1).getReg(), + Offset - MergeSrcIdx * MergeSrcSize); + markInstAndDefDead(MI, *MergeI, DeadInsts); + return true; + } + /// Try to combine away MI. /// Returns true if it combined away the MI. /// Adds instructions that are dead as a result of the combine /// into DeadInsts, which can include MI. bool tryCombineInstruction(MachineInstr &MI, - SmallVectorImpl<MachineInstr *> &DeadInsts) { + SmallVectorImpl<MachineInstr *> &DeadInsts, + GISelObserverWrapper &WrapperObserver) { + // This might be a recursive call, and we might have DeadInsts already + // populated. To avoid bad things happening later with multiple vreg defs + // etc, process the dead instructions now if any. + if (!DeadInsts.empty()) + deleteMarkedDeadInsts(DeadInsts, WrapperObserver); switch (MI.getOpcode()) { default: return false; @@ -265,16 +399,35 @@ public: return tryCombineSExt(MI, DeadInsts); case TargetOpcode::G_UNMERGE_VALUES: return tryCombineMerges(MI, DeadInsts); + case TargetOpcode::G_EXTRACT: + return tryCombineExtract(MI, DeadInsts); case TargetOpcode::G_TRUNC: { bool Changed = false; for (auto &Use : MRI.use_instructions(MI.getOperand(0).getReg())) - Changed |= tryCombineInstruction(Use, DeadInsts); + Changed |= tryCombineInstruction(Use, DeadInsts, WrapperObserver); return Changed; } } } private: + + static unsigned getArtifactSrcReg(const MachineInstr &MI) { + switch (MI.getOpcode()) { + case TargetOpcode::COPY: + case TargetOpcode::G_TRUNC: + case TargetOpcode::G_ZEXT: + case TargetOpcode::G_ANYEXT: + case TargetOpcode::G_SEXT: + case TargetOpcode::G_UNMERGE_VALUES: + return MI.getOperand(MI.getNumOperands() - 1).getReg(); + case TargetOpcode::G_EXTRACT: + return MI.getOperand(1).getReg(); + default: + llvm_unreachable("Not a legalization artifact happen"); + } + } + /// Mark MI as dead. If a def of one of MI's operands, DefMI, would also be /// dead due to MI being killed, then mark DefMI as dead too. /// Some of the combines (extends(trunc)), try to walk through redundant @@ -295,13 +448,15 @@ private: // and as a result, %3, %2, %1 are dead. MachineInstr *PrevMI = &MI; while (PrevMI != &DefMI) { - unsigned PrevRegSrc = - PrevMI->getOperand(PrevMI->getNumOperands() - 1).getReg(); + unsigned PrevRegSrc = getArtifactSrcReg(*PrevMI); + MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc); if (MRI.hasOneUse(PrevRegSrc)) { if (TmpDef != &DefMI) { - assert(TmpDef->getOpcode() == TargetOpcode::COPY && - "Expecting copy here"); + assert((TmpDef->getOpcode() == TargetOpcode::COPY || + isArtifactCast(TmpDef->getOpcode())) && + "Expecting copy or artifact cast here"); + DeadInsts.push_back(TmpDef); } } else @@ -312,6 +467,22 @@ private: DeadInsts.push_back(&DefMI); } + /// Erase the dead instructions in the list and call the observer hooks. + /// Normally the Legalizer will deal with erasing instructions that have been + /// marked dead. However, for the trunc(ext(x)) cases we can end up trying to + /// process instructions which have been marked dead, but otherwise break the + /// MIR by introducing multiple vreg defs. For those cases, allow the combines + /// to explicitly delete the instructions before we run into trouble. + void deleteMarkedDeadInsts(SmallVectorImpl<MachineInstr *> &DeadInsts, + GISelObserverWrapper &WrapperObserver) { + for (auto *DeadMI : DeadInsts) { + LLVM_DEBUG(dbgs() << *DeadMI << "Is dead, eagerly deleting\n"); + WrapperObserver.erasingInstr(*DeadMI); + DeadMI->eraseFromParentAndMarkDBGValuesForRemoval(); + } + DeadInsts.clear(); + } + /// Checks if the target legalizer info has specified anything about the /// instruction, or if unsupported. bool isInstUnsupported(const LegalityQuery &Query) const { @@ -320,10 +491,23 @@ private: return Step.Action == Unsupported || Step.Action == NotFound; } + bool isInstLegal(const LegalityQuery &Query) const { + return LI.getAction(Query).Action == LegalizeActions::Legal; + } + + bool isConstantUnsupported(LLT Ty) const { + if (!Ty.isVector()) + return isInstUnsupported({TargetOpcode::G_CONSTANT, {Ty}}); + + LLT EltTy = Ty.getElementType(); + return isInstUnsupported({TargetOpcode::G_CONSTANT, {EltTy}}) || + isInstUnsupported({TargetOpcode::G_BUILD_VECTOR, {Ty, EltTy}}); + } + /// Looks through copy instructions and returns the actual /// source register. - unsigned lookThroughCopyInstrs(unsigned Reg) { - unsigned TmpReg; + unsigned lookThroughCopyInstrs(Register Reg) { + Register TmpReg; while (mi_match(Reg, MRI, m_Copy(m_Reg(TmpReg)))) { if (MRI.getType(TmpReg).isValid()) Reg = TmpReg; diff --git a/include/llvm/CodeGen/GlobalISel/Legalizer.h b/include/llvm/CodeGen/GlobalISel/Legalizer.h index 8284ab6dac65..13cf3f7e694d 100644 --- a/include/llvm/CodeGen/GlobalISel/Legalizer.h +++ b/include/llvm/CodeGen/GlobalISel/Legalizer.h @@ -1,9 +1,8 @@ -//== llvm/CodeGen/GlobalISel/LegalizePass.h ------------- -*- C++ -*-==// +//== llvm/CodeGen/GlobalISel/Legalizer.h ---------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -55,6 +54,11 @@ public: MachineFunctionProperties::Property::Legalized); } + MachineFunctionProperties getClearedProperties() const override { + return MachineFunctionProperties() + .set(MachineFunctionProperties::Property::NoPHIs); + } + bool combineExtracts(MachineInstr &MI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII); diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 9b4ecf9284e3..a0f21e8b19d7 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/LegalizerHelper.h ---------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -87,7 +86,7 @@ public: /// Legalize a vector instruction by increasing the number of vector elements /// involved and ignoring the added elements later. LegalizeResult moreElementsVector(MachineInstr &MI, unsigned TypeIdx, - LLT WideTy); + LLT MoreTy); /// Expose MIRBuilder so clients can set their own RecordInsertInstruction /// functions @@ -105,19 +104,126 @@ private: unsigned ExtOpcode); /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Use by truncating the operand's type to \p NarrowTy using G_TRUNC, and + /// replacing the vreg of the operand in place. + void narrowScalarSrc(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx); + + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a /// Def by extending the operand's type to \p WideTy and truncating it back /// with the \p TruncOpcode, and replacing the vreg of the operand in place. void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0, unsigned TruncOpcode = TargetOpcode::G_TRUNC); + // Legalize a single operand \p OpIdx of the machine instruction \p MI as a + // Def by truncating the operand's type to \p NarrowTy, replacing in place and + // extending back with \p ExtOpcode. + void narrowScalarDst(MachineInstr &MI, LLT NarrowTy, unsigned OpIdx, + unsigned ExtOpcode); + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Def by performing it with additional vector elements and extracting the + /// result elements, and replacing the vreg of the operand in place. + void moreElementsVectorDst(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); + + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Use by producing a vector with undefined high elements, extracting the + /// original vector type, and replacing the vreg of the operand in place. + void moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy, unsigned OpIdx); + + LegalizeResult + widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult + widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + /// Helper function to split a wide generic register into bitwise blocks with /// the given Type (which implies the number of blocks needed). The generic /// registers created are appended to Ops, starting at bit 0 of Reg. - void extractParts(unsigned Reg, LLT Ty, int NumParts, - SmallVectorImpl<unsigned> &VRegs); + void extractParts(Register Reg, LLT Ty, int NumParts, + SmallVectorImpl<Register> &VRegs); + + /// Version which handles irregular splits. + bool extractParts(Register Reg, LLT RegTy, LLT MainTy, + LLT &LeftoverTy, + SmallVectorImpl<Register> &VRegs, + SmallVectorImpl<Register> &LeftoverVRegs); + + /// Helper function to build a wide generic register \p DstReg of type \p + /// RegTy from smaller parts. This will produce a G_MERGE_VALUES, + /// G_BUILD_VECTOR, G_CONCAT_VECTORS, or sequence of G_INSERT as appropriate + /// for the types. + /// + /// \p PartRegs must be registers of type \p PartTy. + /// + /// If \p ResultTy does not evenly break into \p PartTy sized pieces, the + /// remainder must be specified with \p LeftoverRegs of type \p LeftoverTy. + void insertParts(Register DstReg, LLT ResultTy, + LLT PartTy, ArrayRef<Register> PartRegs, + LLT LeftoverTy = LLT(), ArrayRef<Register> LeftoverRegs = {}); + + /// Perform generic multiplication of values held in multiple registers. + /// Generated instructions use only types NarrowTy and i1. + /// Destination can be same or two times size of the source. + void multiplyRegisters(SmallVectorImpl<Register> &DstRegs, + ArrayRef<Register> Src1Regs, + ArrayRef<Register> Src2Regs, LLT NarrowTy); + +public: + LegalizeResult fewerElementsVectorImplicitDef(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + /// Legalize a simple vector instruction where all operands are the same type + /// by splitting into multiple components. + LegalizeResult fewerElementsVectorBasic(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); + + /// Legalize a instruction with a vector type where each operand may have a + /// different element type. All type indexes must have the same number of + /// elements. + LegalizeResult fewerElementsVectorMultiEltType(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult fewerElementsVectorCasts(MachineInstr &MI, unsigned TypeIdx, + LLT NarrowTy); + + LegalizeResult + fewerElementsVectorCmp(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult + fewerElementsVectorSelect(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult fewerElementsVectorPhi(MachineInstr &MI, + unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx, + LLT MoreTy); + + LegalizeResult + reduceLoadStoreWidth(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy); + + LegalizeResult narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt, + LLT HalfTy, LLT ShiftAmtTy); + + LegalizeResult narrowScalarShift(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarMul(MachineInstr &MI, LLT Ty); + LegalizeResult narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + + LegalizeResult narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx, LLT Ty); LegalizeResult lowerBitCount(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerU64ToF32BitOps(MachineInstr &MI); + LegalizeResult lowerUITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerSITOFP(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerMinMax(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerFCopySign(MachineInstr &MI, unsigned TypeIdx, LLT Ty); + LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI); + +private: MachineRegisterInfo &MRI; const LegalizerInfo &LI; /// To keep track of changes made by the LegalizerHelper. diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 13776dd3e87d..513c98f2d23f 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/LegalizerInfo.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -93,6 +92,7 @@ enum LegalizeAction : std::uint8_t { UseLegacyRules, }; } // end namespace LegalizeActions +raw_ostream &operator<<(raw_ostream &OS, LegalizeActions::LegalizeAction Action); using LegalizeActions::LegalizeAction; @@ -123,6 +123,7 @@ struct LegalityQuery { struct MemDesc { uint64_t SizeInBits; + uint64_t AlignInBits; AtomicOrdering Ordering; }; @@ -165,13 +166,23 @@ using LegalizeMutation = std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>; namespace LegalityPredicates { -struct TypePairAndMemSize { +struct TypePairAndMemDesc { LLT Type0; LLT Type1; uint64_t MemSize; + uint64_t Align; + + bool operator==(const TypePairAndMemDesc &Other) const { + return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align == Other.Align && + MemSize == Other.MemSize; + } - bool operator==(const TypePairAndMemSize &Other) const { + /// \returns true if this memory access is legal with for the acecss described + /// by \p Other (The alignment is sufficient for the size and result type). + bool isCompatible(const TypePairAndMemDesc &Other) const { return Type0 == Other.Type0 && Type1 == Other.Type1 && + Align >= Other.Align && MemSize == Other.MemSize; } }; @@ -200,20 +211,45 @@ typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, std::initializer_list<std::pair<LLT, LLT>> TypesInit); /// True iff the given types for the given pair of type indexes is one of the /// specified type pairs. -LegalityPredicate typePairAndMemSizeInSet( +LegalityPredicate typePairAndMemDescInSet( unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, - std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit); + std::initializer_list<TypePairAndMemDesc> TypesAndMemDescInit); /// True iff the specified type index is a scalar. LegalityPredicate isScalar(unsigned TypeIdx); +/// True iff the specified type index is a vector. +LegalityPredicate isVector(unsigned TypeIdx); +/// True iff the specified type index is a pointer (with any address space). +LegalityPredicate isPointer(unsigned TypeIdx); +/// True iff the specified type index is a pointer with the specified address +/// space. +LegalityPredicate isPointer(unsigned TypeIdx, unsigned AddrSpace); + /// True iff the specified type index is a scalar that's narrower than the given /// size. LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size); + /// True iff the specified type index is a scalar that's wider than the given /// size. LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size); + +/// True iff the specified type index is a scalar or vector with an element type +/// that's narrower than the given size. +LegalityPredicate scalarOrEltNarrowerThan(unsigned TypeIdx, unsigned Size); + +/// True iff the specified type index is a scalar or a vector with an element +/// type that's wider than the given size. +LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size); + /// True iff the specified type index is a scalar whose size is not a power of /// 2. LegalityPredicate sizeNotPow2(unsigned TypeIdx); + +/// True iff the specified type index is a scalar or vector whose element size +/// is not a power of 2. +LegalityPredicate scalarOrEltSizeNotPow2(unsigned TypeIdx); + +/// True iff the specified type indices are both the same bit size. +LegalityPredicate sameSize(unsigned TypeIdx0, unsigned TypeIdx1); /// True iff the specified MMO index has a size that is not a power of 2 LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); /// True iff the specified type index is a vector whose element count is not a @@ -228,13 +264,25 @@ LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, namespace LegalizeMutations { /// Select this specific type for the given type index. LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); + /// Keep the same type as the given type index. LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); -/// Widen the type for the given type index to the next power of 2. -LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0); + +/// Keep the same scalar or element type as the given type index. +LegalizeMutation changeElementTo(unsigned TypeIdx, unsigned FromTypeIdx); + +/// Keep the same scalar or element type as the given type. +LegalizeMutation changeElementTo(unsigned TypeIdx, LLT Ty); + +/// Widen the scalar type or vector element type for the given type index to the +/// next power of 2. +LegalizeMutation widenScalarOrEltToNextPow2(unsigned TypeIdx, unsigned Min = 0); + /// Add more elements to the type for the given type index to the next power of /// 2. LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); +/// Break up the vector type for the given type index into the element type. +LegalizeMutation scalarize(unsigned TypeIdx); } // end namespace LegalizeMutations /// A single rule in a legalizer info ruleset. @@ -419,13 +467,13 @@ public: return actionFor(LegalizeAction::Legal, Types); } /// The instruction is legal when type indexes 0 and 1 along with the memory - /// size is any type and size tuple in the given list. - LegalizeRuleSet &legalForTypesWithMemSize( - std::initializer_list<LegalityPredicates::TypePairAndMemSize> - TypesAndMemSize) { + /// size and minimum alignment is any type and size tuple in the given list. + LegalizeRuleSet &legalForTypesWithMemDesc( + std::initializer_list<LegalityPredicates::TypePairAndMemDesc> + TypesAndMemDesc) { return actionIf(LegalizeAction::Legal, - LegalityPredicates::typePairAndMemSizeInSet( - typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize)); + LegalityPredicates::typePairAndMemDescInSet( + typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemDesc)); } /// The instruction is legal when type indexes 0 and 1 are both in the given /// list. That is, the type pair is in the cartesian product of the list. @@ -438,6 +486,20 @@ public: std::initializer_list<LLT> Types1) { return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); } + /// The instruction is legal when type indexes 0, 1, and 2 are both their + /// respective lists. + LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1, + std::initializer_list<LLT> Types2) { + return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1, + Types2); + } + + LegalizeRuleSet &alwaysLegal() { + using namespace LegalizeMutations; + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Legal, always); + } /// The instruction is lowered. LegalizeRuleSet &lower() { @@ -588,6 +650,13 @@ public: LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) { return actionFor(LegalizeAction::Custom, Types); } + + /// The instruction is custom when type indexes 0 and 1 is any type pair in the + /// given list. + LegalizeRuleSet &customFor(std::initializer_list<std::pair<LLT, LLT>> Types) { + return actionFor(LegalizeAction::Custom, Types); + } + LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) { return actionForCartesianProduct(LegalizeAction::Custom, Types); } @@ -597,13 +666,29 @@ public: return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); } + /// Unconditionally custom lower. + LegalizeRuleSet &custom() { + return customIf(always); + } + /// Widen the scalar to the next power of two that is at least MinSize. /// No effect if the type is not a scalar or is a power of two. LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize = 0) { using namespace LegalityPredicates; - return actionIf(LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), - LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize)); + return actionIf( + LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); + } + + /// Widen the scalar or vector element type to the next power of two that is + /// at least MinSize. No effect if the scalar size is a power of two. + LegalizeRuleSet &widenScalarOrEltToNextPow2(unsigned TypeIdx, + unsigned MinSize = 0) { + using namespace LegalityPredicates; + return actionIf( + LegalizeAction::WidenScalar, scalarOrEltSizeNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::widenScalarOrEltToNextPow2(TypeIdx, MinSize)); } LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { @@ -612,6 +697,32 @@ public: Mutation); } + LegalizeRuleSet &scalarize(unsigned TypeIdx) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::FewerElements, isVector(typeIdx(TypeIdx)), + LegalizeMutations::scalarize(TypeIdx)); + } + + /// Ensure the scalar or element is at least as wide as Ty. + LegalizeRuleSet &minScalarOrElt(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::WidenScalar, + scalarOrEltNarrowerThan(TypeIdx, Ty.getScalarSizeInBits()), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + + /// Ensure the scalar or element is at least as wide as Ty. + LegalizeRuleSet &minScalarOrEltIf(LegalityPredicate Predicate, + unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::WidenScalar, + all(Predicate, scalarOrEltNarrowerThan( + TypeIdx, Ty.getScalarSizeInBits())), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + /// Ensure the scalar is at least as wide as Ty. LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) { using namespace LegalityPredicates; @@ -622,6 +733,15 @@ public: } /// Ensure the scalar is at most as wide as Ty. + LegalizeRuleSet &maxScalarOrElt(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::NarrowScalar, + scalarOrEltWiderThan(TypeIdx, Ty.getScalarSizeInBits()), + changeElementTo(typeIdx(TypeIdx), Ty)); + } + + /// Ensure the scalar is at most as wide as Ty. LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) { using namespace LegalityPredicates; using namespace LegalizeMutations; @@ -637,12 +757,12 @@ public: const LLT &Ty) { using namespace LegalityPredicates; using namespace LegalizeMutations; - return actionIf(LegalizeAction::NarrowScalar, - [=](const LegalityQuery &Query) { - return widerThan(TypeIdx, Ty.getSizeInBits()) && - Predicate(Query); - }, - changeTo(typeIdx(TypeIdx), Ty)); + return actionIf( + LegalizeAction::NarrowScalar, + [=](const LegalityQuery &Query) { + return widerThan(TypeIdx, Ty.getSizeInBits()) && Predicate(Query); + }, + changeElementTo(typeIdx(TypeIdx), Ty)); } /// Limit the range of scalar sizes to MinTy and MaxTy. @@ -652,6 +772,12 @@ public: return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); } + /// Limit the range of scalar sizes to MinTy and MaxTy. + LegalizeRuleSet &clampScalarOrElt(unsigned TypeIdx, const LLT &MinTy, + const LLT &MaxTy) { + return minScalarOrElt(TypeIdx, MinTy).maxScalarOrElt(TypeIdx, MaxTy); + } + /// Widen the scalar to match the size of another. LegalizeRuleSet &minScalarSameAs(unsigned TypeIdx, unsigned LargeTypeIdx) { typeIdx(TypeIdx); @@ -661,8 +787,25 @@ public: Query.Types[TypeIdx].getSizeInBits(); }, [=](const LegalityQuery &Query) { + LLT T = Query.Types[LargeTypeIdx]; return std::make_pair(TypeIdx, - Query.Types[LargeTypeIdx].getElementType()); + T.isVector() ? T.getElementType() : T); + }); + } + + /// Conditionally widen the scalar or elt to match the size of another. + LegalizeRuleSet &minScalarEltSameAsIf(LegalityPredicate Predicate, + unsigned TypeIdx, unsigned LargeTypeIdx) { + typeIdx(TypeIdx); + return widenScalarIf( + [=](const LegalityQuery &Query) { + return Query.Types[LargeTypeIdx].getScalarSizeInBits() > + Query.Types[TypeIdx].getScalarSizeInBits() && + Predicate(Query); + }, + [=](const LegalityQuery &Query) { + LLT T = Query.Types[LargeTypeIdx]; + return std::make_pair(TypeIdx, T); }); } @@ -691,7 +834,7 @@ public: [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; return std::make_pair( - TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits())); + TypeIdx, LLT::vector(MinElements, VecTy.getElementType())); }); } /// Limit the number of elements in EltTy vectors to at most MaxElements. @@ -708,10 +851,8 @@ public: }, [=](const LegalityQuery &Query) { LLT VecTy = Query.Types[TypeIdx]; - if (MaxElements == 1) - return std::make_pair(TypeIdx, VecTy.getElementType()); - return std::make_pair( - TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits())); + LLT NewTy = LLT::scalarOrVector(MaxElements, VecTy.getElementType()); + return std::make_pair(TypeIdx, NewTy); }); } /// Limit the number of elements for the given vectors to at least MinTy's @@ -962,12 +1103,22 @@ public: LegalizeActionStep getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + bool isLegal(const LegalityQuery &Query) const { + return getAction(Query).Action == LegalizeAction::Legal; + } bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + bool isLegalOrCustom(const MachineInstr &MI, + const MachineRegisterInfo &MRI) const; virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder, GISelChangeObserver &Observer) const; + /// Return true if MI is either legal or has been legalized and false + /// if not legal. + virtual bool legalizeIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &MIRBuilder) const; + private: /// Determine what action should be taken to legalize the given generic /// instruction opcode, type-index and type. Requires computeTables to have diff --git a/include/llvm/CodeGen/GlobalISel/Localizer.h b/include/llvm/CodeGen/GlobalISel/Localizer.h index 1e2d4763e5e1..06de5800b8b7 100644 --- a/include/llvm/CodeGen/GlobalISel/Localizer.h +++ b/include/llvm/CodeGen/GlobalISel/Localizer.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/GlobalISel/Localizer.h - Localizer -------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,12 +21,14 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H #define LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H +#include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { // Forward declarations. class MachineRegisterInfo; +class TargetTransformInfo; /// This pass implements the localization mechanism described at the /// top of this file. One specificity of the implementation is that @@ -44,9 +45,11 @@ private: /// MRI contains all the register class/bank information that this /// pass uses and updates. MachineRegisterInfo *MRI; + /// TTI used for getting remat costs for instructions. + TargetTransformInfo *TTI; /// Check whether or not \p MI needs to be moved close to its uses. - static bool shouldLocalize(const MachineInstr &MI); + bool shouldLocalize(const MachineInstr &MI); /// Check if \p MOUse is used in the same basic block as \p Def. /// If the use is in the same block, we say it is local. @@ -58,6 +61,15 @@ private: /// Initialize the field members using \p MF. void init(MachineFunction &MF); + typedef SmallSetVector<MachineInstr *, 32> LocalizedSetVecT; + + /// Do inter-block localization from the entry block. + bool localizeInterBlock(MachineFunction &MF, + LocalizedSetVecT &LocalizedInstrs); + + /// Do intra-block localization of already localized instructions. + bool localizeIntraBlock(LocalizedSetVecT &LocalizedInstrs); + public: Localizer(); diff --git a/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h index f77f9a8df7ee..13eddd9539fa 100644 --- a/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -1,9 +1,8 @@ -//== ----- llvm/CodeGen/GlobalISel/MIPatternMatch.h --------------------- == // +//==------ llvm/CodeGen/GlobalISel/MIPatternMatch.h -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,8 +30,7 @@ template <typename SubPatternT> struct OneUse_match { SubPatternT SubPat; OneUse_match(const SubPatternT &SP) : SubPat(SP) {} - template <typename OpTy> - bool match(const MachineRegisterInfo &MRI, unsigned Reg) { + bool match(MachineRegisterInfo &MRI, unsigned Reg) { return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg); } }; @@ -162,7 +160,7 @@ template <typename Class> struct bind_ty { } }; -inline bind_ty<unsigned> m_Reg(unsigned &R) { return R; } +inline bind_ty<Register> m_Reg(Register &R) { return R; } inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; } inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; } diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 37de8f030410..10d712176b1b 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.h - MIBuilder --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -60,13 +59,15 @@ struct MachineIRBuilderState { class DstOp { union { LLT LLTTy; - unsigned Reg; + Register Reg; const TargetRegisterClass *RC; }; public: enum class DstType { Ty_LLT, Ty_Reg, Ty_RC }; DstOp(unsigned R) : Reg(R), Ty(DstType::Ty_Reg) {} + DstOp(Register R) : Reg(R), Ty(DstType::Ty_Reg) {} + DstOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(DstType::Ty_Reg) {} DstOp(const LLT &T) : LLTTy(T), Ty(DstType::Ty_LLT) {} DstOp(const TargetRegisterClass *TRC) : RC(TRC), Ty(DstType::Ty_RC) {} @@ -96,7 +97,7 @@ public: llvm_unreachable("Unrecognised DstOp::DstType enum"); } - unsigned getReg() const { + Register getReg() const { assert(Ty == DstType::Ty_Reg && "Not a register"); return Reg; } @@ -119,13 +120,14 @@ private: class SrcOp { union { MachineInstrBuilder SrcMIB; - unsigned Reg; + Register Reg; CmpInst::Predicate Pred; }; public: enum class SrcType { Ty_Reg, Ty_MIB, Ty_Predicate }; - SrcOp(unsigned R) : Reg(R), Ty(SrcType::Ty_Reg) {} + SrcOp(Register R) : Reg(R), Ty(SrcType::Ty_Reg) {} + SrcOp(const MachineOperand &Op) : Reg(Op.getReg()), Ty(SrcType::Ty_Reg) {} SrcOp(const MachineInstrBuilder &MIB) : SrcMIB(MIB), Ty(SrcType::Ty_MIB) {} SrcOp(const CmpInst::Predicate P) : Pred(P), Ty(SrcType::Ty_Predicate) {} @@ -155,7 +157,7 @@ public: llvm_unreachable("Unrecognised SrcOp::SrcType enum"); } - unsigned getReg() const { + Register getReg() const { switch (Ty) { case SrcType::Ty_Predicate: llvm_unreachable("Not a register operand"); @@ -202,6 +204,7 @@ protected: void validateTruncExt(const LLT &Dst, const LLT &Src, bool IsExtend); void validateBinaryOp(const LLT &Res, const LLT &Op0, const LLT &Op1); + void validateShiftOp(const LLT &Res, const LLT &Op0, const LLT &Op1); void validateSelectOp(const LLT &ResTy, const LLT &TstTy, const LLT &Op0Ty, const LLT &Op1Ty); @@ -230,6 +233,15 @@ public: return *State.MF; } + const MachineFunction &getMF() const { + assert(State.MF && "MachineFunction is not set"); + return *State.MF; + } + + const DataLayout &getDataLayout() const { + return getMF().getFunction().getParent()->getDataLayout(); + } + /// Getter for DebugLoc const DebugLoc &getDL() { return State.DL; } @@ -310,13 +322,13 @@ public: /// Build and insert a DBG_VALUE instruction expressing the fact that the /// associated \p Variable lives in \p Reg (suitably modified by \p Expr). - MachineInstrBuilder buildDirectDbgValue(unsigned Reg, const MDNode *Variable, + MachineInstrBuilder buildDirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr); /// Build and insert a DBG_VALUE instruction expressing the fact that the /// associated \p Variable lives in memory at \p Reg (suitably modified by \p /// Expr). - MachineInstrBuilder buildIndirectDbgValue(unsigned Reg, + MachineInstrBuilder buildIndirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr); @@ -345,7 +357,7 @@ public: /// \pre \p Res must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildFrameIndex(unsigned Res, int Idx); + MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx); /// Build and insert \p Res = G_GLOBAL_VALUE \p GV /// @@ -357,8 +369,7 @@ public: /// in the same address space as \p GV. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV); - + MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV); /// Build and insert \p Res = G_GEP \p Op0, \p Op1 /// @@ -371,8 +382,8 @@ public: /// \pre \p Op1 must be a generic virtual register with scalar type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0, - unsigned Op1); + MachineInstrBuilder buildGEP(const DstOp &Res, const SrcOp &Op0, + const SrcOp &Op1); /// Materialize and insert \p Res = G_GEP \p Op0, (G_CONSTANT \p Value) /// @@ -390,7 +401,7 @@ public: /// type as \p Op0 or \p Op0 itself. /// /// \return a MachineInstrBuilder for the newly created instruction. - Optional<MachineInstrBuilder> materializeGEP(unsigned &Res, unsigned Op0, + Optional<MachineInstrBuilder> materializeGEP(Register &Res, Register Op0, const LLT &ValueTy, uint64_t Value); @@ -407,9 +418,24 @@ public: /// be cleared in \p Op0. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0, + MachineInstrBuilder buildPtrMask(const DstOp &Res, const SrcOp &Op0, uint32_t NumBits); + /// Build and insert \p Res, \p CarryOut = G_UADDO \p Op0, \p Op1 + /// + /// G_UADDO sets \p Res to \p Op0 + \p Op1 (truncated to the bit width) and + /// sets \p CarryOut to 1 if the result overflowed in unsigned arithmetic. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers with the + /// same scalar type. + ////\pre \p CarryOut must be generic virtual register with scalar type + ///(typically s1) + /// + /// \return The newly created instruction. + MachineInstrBuilder buildUAddo(const DstOp &Res, const DstOp &CarryOut, + const SrcOp &Op0, const SrcOp &Op1); + /// Build and insert \p Res, \p CarryOut = G_UADDE \p Op0, /// \p Op1, \p CarryIn /// @@ -458,6 +484,25 @@ public: /// \return The newly created instruction. MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op); + /// Build and insert a G_PTRTOINT instruction. + MachineInstrBuilder buildPtrToInt(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_PTRTOINT, {Dst}, {Src}); + } + + /// Build and insert \p Dst = G_BITCAST \p Src + MachineInstrBuilder buildBitcast(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_BITCAST, {Dst}, {Src}); + } + + /// \return The opcode of the extension the target wants to use for boolean + /// values. + unsigned getBoolExtOp(bool IsVec, bool IsFP) const; + + // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_SEXT \p Op, or \p Res + // = G_ZEXT \p Op depending on how the target wants to extend boolean values. + MachineInstrBuilder buildBoolExt(const DstOp &Res, const SrcOp &Op, + bool IsFP); + /// Build and insert \p Res = G_ZEXT \p Op /// /// G_ZEXT produces a register of the specified width, with bits 0 to @@ -538,7 +583,7 @@ public: /// depend on bit 0 (for now). /// /// \return The newly created instruction. - MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &Dest); + MachineInstrBuilder buildBrCond(Register Tst, MachineBasicBlock &Dest); /// Build and insert G_BRINDIRECT \p Tgt /// @@ -548,7 +593,21 @@ public: /// \pre \p Tgt must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBrIndirect(unsigned Tgt); + MachineInstrBuilder buildBrIndirect(Register Tgt); + + /// Build and insert G_BRJT \p TablePtr, \p JTI, \p IndexReg + /// + /// G_BRJT is a jump table branch using a table base pointer \p TablePtr, + /// jump table index \p JTI and index \p IndexReg + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p TablePtr must be a generic virtual register with pointer type. + /// \pre \p JTI must be be a jump table index. + /// \pre \p IndexReg must be a generic virtual register with pointer type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildBrJT(Register TablePtr, unsigned JTI, + Register IndexReg); /// Build and insert \p Res = G_CONSTANT \p Val /// @@ -572,6 +631,7 @@ public: /// /// \return The newly created instruction. MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val); + MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val); /// Build and insert \p Res = G_FCONSTANT \p Val /// @@ -586,6 +646,7 @@ public: const ConstantFP &Val); MachineInstrBuilder buildFConstant(const DstOp &Res, double Val); + MachineInstrBuilder buildFConstant(const DstOp &Res, const APFloat &Val); /// Build and insert \p Res = COPY Op /// @@ -605,7 +666,7 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr, + MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `Res = <opcode> Addr, MMO`. @@ -617,8 +678,8 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildLoadInstr(unsigned Opcode, unsigned Res, - unsigned Addr, MachineMemOperand &MMO); + MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, + const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `G_STORE Val, Addr, MMO`. /// @@ -629,7 +690,7 @@ public: /// \pre \p Addr must be a generic virtual register with pointer type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildStore(unsigned Val, unsigned Addr, + MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO); /// Build and insert `Res0, ... = G_EXTRACT Src, Idx0`. @@ -638,7 +699,7 @@ public: /// \pre \p Res and \p Src must be generic virtual registers. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index); + MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index); /// Build and insert \p Res = IMPLICIT_DEF. MachineInstrBuilder buildUndef(const DstOp &Res); @@ -656,7 +717,7 @@ public: /// \pre The bits defined by each Op (derived from index and scalar size) must /// not overlap. /// \pre \p Indices must be in ascending order of bit position. - void buildSequence(unsigned Res, ArrayRef<unsigned> Ops, + void buildSequence(Register Res, ArrayRef<Register> Ops, ArrayRef<uint64_t> Indices); /// Build and insert \p Res = G_MERGE_VALUES \p Op0, ... @@ -670,7 +731,7 @@ public: /// \pre The type of all \p Ops registers must be identical. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef<unsigned> Ops); + MachineInstrBuilder buildMerge(const DstOp &Res, ArrayRef<Register> Ops); /// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op /// @@ -683,7 +744,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildUnmerge(ArrayRef<LLT> Res, const SrcOp &Op); - MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, const SrcOp &Op); + MachineInstrBuilder buildUnmerge(ArrayRef<Register> Res, const SrcOp &Op); + + /// Build and insert an unmerge of \p Res sized pieces to cover \p Op + MachineInstrBuilder buildUnmerge(LLT Res, const SrcOp &Op); /// Build and insert \p Res = G_BUILD_VECTOR \p Op0, ... /// @@ -695,7 +759,12 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildBuildVector(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); + + /// Build and insert \p Res = G_BUILD_VECTOR with \p Src replicated to fill + /// the number of elements + MachineInstrBuilder buildSplatVector(const DstOp &Res, + const SrcOp &Src); /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ... /// @@ -711,7 +780,7 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); /// Build and insert \p Res = G_CONCAT_VECTORS \p Op0, ... /// @@ -725,10 +794,10 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildConcatVectors(const DstOp &Res, - ArrayRef<unsigned> Ops); + ArrayRef<Register> Ops); - MachineInstrBuilder buildInsert(unsigned Res, unsigned Src, - unsigned Op, unsigned Index); + MachineInstrBuilder buildInsert(Register Res, Register Src, + Register Op, unsigned Index); /// Build and insert either a G_INTRINSIC (if \p HasSideEffects is false) or /// G_INTRINSIC_W_SIDE_EFFECTS instruction. Its first operand will be the @@ -740,7 +809,9 @@ public: /// \pre setBasicBlock or setMI must have been called. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, unsigned Res, + MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef<Register> Res, + bool HasSideEffects); + MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef<DstOp> Res, bool HasSideEffects); /// Build and insert \p Res = G_FPTRUNC \p Op @@ -855,8 +926,8 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder - buildAtomicCmpXchgWithSuccess(unsigned OldValRes, unsigned SuccessRes, - unsigned Addr, unsigned CmpVal, unsigned NewVal, + buildAtomicCmpXchgWithSuccess(Register OldValRes, Register SuccessRes, + Register Addr, Register CmpVal, Register NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, @@ -873,8 +944,8 @@ public: /// registers of the same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr, - unsigned CmpVal, unsigned NewVal, + MachineInstrBuilder buildAtomicCmpXchg(Register OldValRes, Register Addr, + Register CmpVal, Register NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO`. @@ -890,8 +961,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMW(unsigned Opcode, unsigned OldValRes, - unsigned Addr, unsigned Val, + MachineInstrBuilder buildAtomicRMW(unsigned Opcode, Register OldValRes, + Register Addr, Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_XCHG Addr, Val, MMO`. @@ -906,8 +977,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXchg(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWXchg(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_ADD Addr, Val, MMO`. /// @@ -921,8 +992,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAdd(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWAdd(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_SUB Addr, Val, MMO`. /// @@ -936,8 +1007,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWSub(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWSub(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_AND Addr, Val, MMO`. /// @@ -951,8 +1022,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWAnd(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWAnd(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_NAND Addr, Val, MMO`. /// @@ -967,8 +1038,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWNand(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWNand(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_OR Addr, Val, MMO`. /// @@ -982,8 +1053,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWOr(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWOr(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_XOR Addr, Val, MMO`. /// @@ -997,8 +1068,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWXor(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWXor(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_MAX Addr, Val, MMO`. /// @@ -1013,8 +1084,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMax(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWMax(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_MIN Addr, Val, MMO`. /// @@ -1029,8 +1100,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWMin(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWMin(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMAX Addr, Val, MMO`. /// @@ -1045,8 +1116,8 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmax(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWUmax(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMIN Addr, Val, MMO`. /// @@ -1061,8 +1132,11 @@ public: /// same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr, - unsigned Val, MachineMemOperand &MMO); + MachineInstrBuilder buildAtomicRMWUmin(Register OldValRes, Register Addr, + Register Val, MachineMemOperand &MMO); + + /// Build and insert `G_FENCE Ordering, Scope`. + MachineInstrBuilder buildFence(unsigned Ordering, unsigned Scope); /// Build and insert \p Res = G_BLOCK_ADDR \p BA /// @@ -1072,7 +1146,7 @@ public: /// \pre \p Res must be a generic virtual register of a pointer type. /// /// \return The newly created instruction. - MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA); + MachineInstrBuilder buildBlockAddress(Register Res, const BlockAddress *BA); /// Build and insert \p Res = G_ADD \p Op0, \p Op1 /// @@ -1124,6 +1198,36 @@ public: return buildInstr(TargetOpcode::G_MUL, {Dst}, {Src0, Src1}, Flags); } + MachineInstrBuilder buildUMulH(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_UMULH, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildSMulH(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_SMULH, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_SHL, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_LSHR, {Dst}, {Src0, Src1}, Flags); + } + + MachineInstrBuilder buildAShr(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_ASHR, {Dst}, {Src0, Src1}, Flags); + } + /// Build and insert \p Res = G_AND \p Op0, \p Op1 /// /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p @@ -1155,6 +1259,137 @@ public: return buildInstr(TargetOpcode::G_OR, {Dst}, {Src0, Src1}); } + /// Build and insert \p Res = G_XOR \p Op0, \p Op1 + MachineInstrBuilder buildXor(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, Src1}); + } + + /// Build and insert a bitwise not, + /// \p NegOne = G_CONSTANT -1 + /// \p Res = G_OR \p Op0, NegOne + MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0) { + auto NegOne = buildConstant(Dst.getLLTTy(*getMRI()), -1); + return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, NegOne}); + } + + /// Build and insert \p Res = G_CTPOP \p Op0, \p Src0 + MachineInstrBuilder buildCTPOP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTPOP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTLZ \p Op0, \p Src0 + MachineInstrBuilder buildCTLZ(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTLZ, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTLZ_ZERO_UNDEF \p Op0, \p Src0 + MachineInstrBuilder buildCTLZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTTZ \p Op0, \p Src0 + MachineInstrBuilder buildCTTZ(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTTZ, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_CTTZ_ZERO_UNDEF \p Op0, \p Src0 + MachineInstrBuilder buildCTTZ_ZERO_UNDEF(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FADD \p Op0, \p Op1 + MachineInstrBuilder buildFAdd(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FADD, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_FSUB \p Op0, \p Op1 + MachineInstrBuilder buildFSub(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FSUB, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_FMA \p Op0, \p Op1, \p Op2 + MachineInstrBuilder buildFMA(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1, const SrcOp &Src2) { + return buildInstr(TargetOpcode::G_FMA, {Dst}, {Src0, Src1, Src2}); + } + + /// Build and insert \p Res = G_FNEG \p Op0 + MachineInstrBuilder buildFNeg(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FABS \p Op0 + MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FABS, {Dst}, {Src0}); + } + + /// Build and insert \p Dst = G_FCANONICALIZE \p Src0 + MachineInstrBuilder buildFCanonicalize(const DstOp &Dst, const SrcOp &Src0, + Optional<unsigned> Flags = None) { + return buildInstr(TargetOpcode::G_FCANONICALIZE, {Dst}, {Src0}, Flags); + } + + /// Build and insert \p Res = G_FCOPYSIGN \p Op0, \p Op1 + MachineInstrBuilder buildFCopysign(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_FCOPYSIGN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UITOFP \p Src0 + MachineInstrBuilder buildUITOFP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_UITOFP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_SITOFP \p Src0 + MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_SITOFP, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FPTOUI \p Src0 + MachineInstrBuilder buildFPTOUI(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FPTOUI, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_FPTOSI \p Src0 + MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0) { + return buildInstr(TargetOpcode::G_FPTOSI, {Dst}, {Src0}); + } + + /// Build and insert \p Res = G_SMIN \p Op0, \p Op1 + MachineInstrBuilder buildSMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_SMAX \p Op0, \p Op1 + MachineInstrBuilder buildSMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_SMAX, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMIN \p Op0, \p Op1 + MachineInstrBuilder buildUMin(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMIN, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_UMAX \p Op0, \p Op1 + MachineInstrBuilder buildUMax(const DstOp &Dst, const SrcOp &Src0, + const SrcOp &Src1) { + return buildInstr(TargetOpcode::G_UMAX, {Dst}, {Src0, Src1}); + } + + /// Build and insert \p Res = G_JUMP_TABLE \p JTI + /// + /// G_JUMP_TABLE sets \p Res to the address of the jump table specified by + /// the jump table index \p JTI. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildJumpTable(const LLT PtrTy, unsigned JTI); + virtual MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps, Optional<unsigned> Flags = None); diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index c53ae416e60b..d9d076ba312c 100644 --- a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -524,7 +523,7 @@ private: /// \p OnlyAssign == true means that \p Reg just needs to be assigned a /// register bank. I.e., no repairing is necessary to have the /// assignment match. - bool assignmentMatch(unsigned Reg, + bool assignmentMatch(Register Reg, const RegisterBankInfo::ValueMapping &ValMapping, bool &OnlyAssign) const; @@ -563,7 +562,7 @@ private: bool repairReg(MachineOperand &MO, const RegisterBankInfo::ValueMapping &ValMapping, RegBankSelect::RepairingPlacement &RepairPt, - const iterator_range<SmallVectorImpl<unsigned>::const_iterator> + const iterator_range<SmallVectorImpl<Register>::const_iterator> &NewVRegs); /// Return the cost of the instruction needed to map \p MO to \p ValMapping. @@ -634,6 +633,11 @@ public: MachineFunctionProperties::Property::RegBankSelected); } + MachineFunctionProperties getClearedProperties() const override { + return MachineFunctionProperties() + .set(MachineFunctionProperties::Property::NoPHIs); + } + /// Walk through \p MF and assign a register bank to every virtual register /// that are still mapped to nothing. /// The target needs to provide a RegisterBankInfo and in particular diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h index d5612e17393c..f528d1a46012 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/GlobalISel/RegisterBank.h - Register Bank ----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index c33b32b2db40..e84b1c3ea8b1 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/RegisterBankInfo.h ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/CodeGen/Register.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> #include <initializer_list> @@ -161,6 +161,10 @@ public: const PartialMapping *begin() const { return BreakDown; } const PartialMapping *end() const { return BreakDown + NumBreakDowns; } + /// \return true if all partial mappings are the same size and register + /// bank. + bool partsAllUniform() const; + /// Check if this ValueMapping is valid. bool isValid() const { return BreakDown && NumBreakDowns; } @@ -190,7 +194,7 @@ public: unsigned Cost = 0; /// Mapping of all the operands. - const ValueMapping *OperandsMapping; + const ValueMapping *OperandsMapping = nullptr; /// Number of operands. unsigned NumOperands = 0; @@ -207,15 +211,11 @@ public: /// The rationale is that it is more efficient for the optimizers /// to be able to assume that the mapping of the ith operand is /// at the index i. - /// - /// \pre ID != InvalidMappingID InstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) : ID(ID), Cost(Cost), OperandsMapping(OperandsMapping), NumOperands(NumOperands) { - assert(getID() != InvalidMappingID && - "Use the default constructor for invalid mapping"); } /// Default constructor. @@ -282,7 +282,7 @@ public: SmallVector<int, 8> OpToNewVRegIdx; /// Hold the registers that will be used to map MI with InstrMapping. - SmallVector<unsigned, 8> NewVRegs; + SmallVector<Register, 8> NewVRegs; /// Current MachineRegisterInfo, used to create new virtual registers. MachineRegisterInfo &MRI; @@ -303,15 +303,15 @@ public: /// \return The iterator range for the space created. // /// \pre getMI().getOperand(OpIdx).isReg() - iterator_range<SmallVectorImpl<unsigned>::iterator> + iterator_range<SmallVectorImpl<Register>::iterator> getVRegsMem(unsigned OpIdx); /// Get the end iterator for a range starting at \p StartIdx and /// spannig \p NumVal in NewVRegs. /// \pre StartIdx + NumVal <= NewVRegs.size() - SmallVectorImpl<unsigned>::const_iterator + SmallVectorImpl<Register>::const_iterator getNewVRegsEnd(unsigned StartIdx, unsigned NumVal) const; - SmallVectorImpl<unsigned>::iterator getNewVRegsEnd(unsigned StartIdx, + SmallVectorImpl<Register>::iterator getNewVRegsEnd(unsigned StartIdx, unsigned NumVal); public: @@ -357,7 +357,7 @@ public: /// /// \post the \p PartialMapIdx-th register of the value mapping of the \p /// OpIdx-th operand has been set. - void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, unsigned NewVReg); + void setVRegs(unsigned OpIdx, unsigned PartialMapIdx, Register NewVReg); /// Get all the virtual registers required to map the \p OpIdx-th operand of /// the instruction. @@ -371,7 +371,7 @@ public: /// /// \pre getMI().getOperand(OpIdx).isReg() /// \pre ForDebug || All partial mappings have been set a register - iterator_range<SmallVectorImpl<unsigned>::const_iterator> + iterator_range<SmallVectorImpl<Register>::const_iterator> getVRegs(unsigned OpIdx, bool ForDebug = false) const; /// Print this operands mapper on dbgs() stream. @@ -435,7 +435,7 @@ protected: /// Get the MinimalPhysRegClass for Reg. /// \pre Reg is a physical register. const TargetRegisterClass & - getMinimalPhysRegClass(unsigned Reg, const TargetRegisterInfo &TRI) const; + getMinimalPhysRegClass(Register Reg, const TargetRegisterInfo &TRI) const; /// Try to get the mapping of \p MI. /// See getInstrMapping for more details on what a mapping represents. @@ -580,7 +580,7 @@ public: /// or a register bank, then this returns nullptr. /// /// \pre Reg != 0 (NoRegister) - const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI, + const RegisterBank *getRegBank(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const; /// Get the total number of register banks. @@ -618,6 +618,21 @@ public: return &A != &B; } + /// \returns true if emitting a copy from \p Src to \p Dst is impossible. + bool cannotCopy(const RegisterBank &Dst, const RegisterBank &Src, + unsigned Size) const { + return copyCost(Dst, Src, Size) == std::numeric_limits<unsigned>::max(); + } + + /// Get the cost of using \p ValMapping to decompose a register. This is + /// similar to ::copyCost, except for cases where multiple copy-like + /// operations need to be inserted. If the register is used as a source + /// operand and already has a bank assigned, \p CurBank is non-null. + virtual unsigned getBreakDownCost(const ValueMapping &ValMapping, + const RegisterBank *CurBank = nullptr) const { + return std::numeric_limits<unsigned>::max(); + } + /// Constrain the (possibly generic) virtual register \p Reg to \p RC. /// /// \pre \p Reg is a virtual register that either has a bank or a class. @@ -626,7 +641,7 @@ public: /// \note Use MachineRegisterInfo::constrainRegAttrs instead for any non-isel /// purpose, including non-select passes of GlobalISel static const TargetRegisterClass * - constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, + constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI); /// Identifier used when the related instruction mapping instance @@ -711,7 +726,7 @@ public: /// virtual register. /// /// \pre \p Reg != 0 (NoRegister). - unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, + unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const; /// Check that information hold by this instance make sense for the diff --git a/include/llvm/CodeGen/GlobalISel/Types.h b/include/llvm/CodeGen/GlobalISel/Types.h index 7b22e343a7f8..4fd7043ba02d 100644 --- a/include/llvm/CodeGen/GlobalISel/Types.h +++ b/include/llvm/CodeGen/GlobalISel/Types.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/GlobalISel/Types.h - Types used by GISel ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/CodeGen/GlobalISel/Utils.h b/include/llvm/CodeGen/GlobalISel/Utils.h index 82b791d35b2b..4cdaa48fb689 100644 --- a/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/include/llvm/CodeGen/GlobalISel/Utils.h @@ -1,9 +1,8 @@ //==-- llvm/CodeGen/GlobalISel/Utils.h ---------------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,6 +15,7 @@ #define LLVM_CODEGEN_GLOBALISEL_UTILS_H #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/Register.h" namespace llvm { @@ -37,21 +37,37 @@ class ConstantFP; class APFloat; /// Try to constrain Reg to the specified register class. If this fails, -/// create a new virtual register in the correct class and insert a COPY before -/// \p InsertPt. The debug location of \p InsertPt is used for the new copy. +/// create a new virtual register in the correct class. /// /// \return The virtual register constrained to the right register class. unsigned constrainRegToClass(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, - const RegisterBankInfo &RBI, - MachineInstr &InsertPt, unsigned Reg, + const RegisterBankInfo &RBI, unsigned Reg, const TargetRegisterClass &RegClass); +/// Constrain the Register operand OpIdx, so that it is now constrained to the +/// TargetRegisterClass passed as an argument (RegClass). +/// If this fails, create a new virtual register in the correct class and +/// insert a COPY before \p InsertPt if it is a use or after if it is a +/// definition. The debug location of \p InsertPt is used for the new copy. +/// +/// \return The virtual register constrained to the right register class. +unsigned constrainOperandRegClass(const MachineFunction &MF, + const TargetRegisterInfo &TRI, + MachineRegisterInfo &MRI, + const TargetInstrInfo &TII, + const RegisterBankInfo &RBI, + MachineInstr &InsertPt, + const TargetRegisterClass &RegClass, + const MachineOperand &RegMO, unsigned OpIdx); + /// Try to constrain Reg so that it is usable by argument OpIdx of the /// provided MCInstrDesc \p II. If this fails, create a new virtual -/// register in the correct class and insert a COPY before \p InsertPt. -/// This is equivalent to constrainRegToClass() with RegClass obtained from the -/// MCInstrDesc. The debug location of \p InsertPt is used for the new copy. +/// register in the correct class and insert a COPY before \p InsertPt +/// if it is a use or after if it is a definition. +/// This is equivalent to constrainOperandRegClass(..., RegClass, ...) +/// with RegClass obtained from the MCInstrDesc. The debug location of \p +/// InsertPt is used for the new copy. /// /// \return The virtual register constrained to the right register class. unsigned constrainOperandRegClass(const MachineFunction &MF, @@ -90,17 +106,40 @@ void reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, const char *PassName, StringRef Msg, const MachineInstr &MI); +/// If \p VReg is defined by a G_CONSTANT fits in int64_t +/// returns it. Optional<int64_t> getConstantVRegVal(unsigned VReg, const MachineRegisterInfo &MRI); +/// Simple struct used to hold a constant integer value and a virtual +/// register. +struct ValueAndVReg { + int64_t Value; + unsigned VReg; +}; +/// If \p VReg is defined by a statically evaluable chain of +/// instructions rooted on a G_CONSTANT (\p LookThroughInstrs == true) +/// and that constant fits in int64_t, returns its value as well as +/// the virtual register defined by this G_CONSTANT. +/// When \p LookThroughInstrs == false, this function behaves like +/// getConstantVRegVal. +Optional<ValueAndVReg> +getConstantVRegValWithLookThrough(unsigned VReg, const MachineRegisterInfo &MRI, + bool LookThroughInstrs = true); const ConstantFP* getConstantFPVRegVal(unsigned VReg, const MachineRegisterInfo &MRI); /// See if Reg is defined by an single def instruction that is /// Opcode. Also try to do trivial folding if it's a COPY with /// same types. Returns null otherwise. -MachineInstr *getOpcodeDef(unsigned Opcode, unsigned Reg, +MachineInstr *getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI); +/// Find the def instruction for \p Reg, folding away any trivial copies. Note +/// it may still return a COPY, if it changes the type. May return nullptr if \p +/// Reg is not a generic virtual register. +MachineInstr *getDefIgnoringCopies(Register Reg, + const MachineRegisterInfo &MRI); + /// Returns an APFloat from Val converted to the appropriate size. APFloat getAPFloatFromSize(double Val, unsigned Size); @@ -111,5 +150,16 @@ void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1, const unsigned Op2, const MachineRegisterInfo &MRI); + +/// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true, +/// this returns if \p Val can be assumed to never be a signaling NaN. +bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI, + bool SNaN = false); + +/// Returns true if \p Val can be assumed to never be a signaling NaN. +inline bool isKnownNeverSNaN(Register Val, const MachineRegisterInfo &MRI) { + return isKnownNeverNaN(Val, MRI, true); +} + } // End namespace llvm. #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 9c918ae1104f..acf27dcc5fab 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/ISDOpcodes.h - CodeGen opcodes -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -272,12 +271,17 @@ namespace ISD { /// resulting value is this minimum value. SSUBSAT, USUBSAT, - /// RESULT = SMULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on + /// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point multiplication on /// 2 integers with the same width and scale. SCALE represents the scale of /// both operands as fixed point numbers. This SCALE parameter must be a /// constant integer. A scale of zero is effectively performing /// multiplication on 2 integers. - SMULFIX, + SMULFIX, UMULFIX, + + /// Same as the corresponding unsaturated fixed point instructions, but the + /// result is clamped between the min and max values representable by the + /// bits of the first 2 operands. + SMULFIXSAT, /// Simple binary floating point operators. FADD, FSUB, FMUL, FDIV, FREM, @@ -298,6 +302,26 @@ namespace ISD { STRICT_FRINT, STRICT_FNEARBYINT, STRICT_FMAXNUM, STRICT_FMINNUM, STRICT_FCEIL, STRICT_FFLOOR, STRICT_FROUND, STRICT_FTRUNC, + /// X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating + /// point type down to the precision of the destination VT. TRUNC is a + /// flag, which is always an integer that is zero or one. If TRUNC is 0, + /// this is a normal rounding, if it is 1, this FP_ROUND is known to not + /// change the value of Y. + /// + /// The TRUNC = 1 case is used in cases where we know that the value will + /// not be modified by the node, because Y is not using any of the extra + /// precision of source type. This allows certain transformations like + /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,1)) -> X which are not safe for + /// STRICT_FP_EXTEND(STRICT_FP_ROUND(X,0)) because the extra bits aren't + /// removed. + /// It is used to limit optimizations while the DAG is being optimized. + STRICT_FP_ROUND, + + /// X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP + /// type. + /// It is used to limit optimizations while the DAG is being optimized. + STRICT_FP_EXTEND, + /// FMA - Perform a * b + c with no intermediate rounding step. FMA, @@ -580,10 +604,14 @@ namespace ISD { /// is often a storage-only type but has native conversions. FP16_TO_FP, FP_TO_FP16, - /// Perform various unary floating-point operations inspired by libm. + /// Perform various unary floating-point operations inspired by libm. For + /// FPOWI, the result is undefined if if the integer operand doesn't fit + /// into 32 bits. FNEG, FABS, FSQRT, FCBRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, + LROUND, LLROUND, LRINT, LLRINT, + /// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two /// values. // @@ -666,6 +694,9 @@ namespace ISD { /// SDOperands. INLINEASM, + /// INLINEASM_BR - Terminator version of inline asm. Used by asm-goto. + INLINEASM_BR, + /// EH_LABEL - Represents a label in mid basic block used to track /// locations needed for debug and exception handling tables. These nodes /// take a chain as input and return a chain. @@ -819,6 +850,8 @@ namespace ISD { ATOMIC_LOAD_MAX, ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + ATOMIC_LOAD_FADD, + ATOMIC_LOAD_FSUB, // Masked load and store - consecutive vector load and store operations // with additional mask operand that prevents memory accesses to the @@ -866,11 +899,14 @@ namespace ISD { VECREDUCE_STRICT_FADD, VECREDUCE_STRICT_FMUL, /// These reductions are non-strict, and have a single vector operand. VECREDUCE_FADD, VECREDUCE_FMUL, + /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. + VECREDUCE_FMAX, VECREDUCE_FMIN, + /// Integer reductions may have a result type larger than the vector element + /// type. However, the reduction is performed using the vector element type + /// and the value in the top bits is unspecified. VECREDUCE_ADD, VECREDUCE_MUL, VECREDUCE_AND, VECREDUCE_OR, VECREDUCE_XOR, VECREDUCE_SMAX, VECREDUCE_SMIN, VECREDUCE_UMAX, VECREDUCE_UMIN, - /// FMIN/FMAX nodes can have flags, for NaN/NoNaN variants. - VECREDUCE_FMAX, VECREDUCE_FMIN, /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index 597d684909c1..daf2d9a47801 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -1,9 +1,8 @@ //===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,10 +30,6 @@ class IntrinsicLowering { public: explicit IntrinsicLowering(const DataLayout &DL) : DL(DL), Warned(false) {} - /// Add all of the prototypes that might be needed by an intrinsic lowering - /// implementation to be inserted into the module specified. - void AddPrototypes(Module &M); - /// Replace a call to the specified intrinsic function. /// If an intrinsic function must be implemented by the code generator /// (such as va_start), this function should print a message and abort. diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index 9b8d83ce77ca..95f4c6473542 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -1,9 +1,8 @@ //===---- LatencyPriorityQueue.h - A latency-oriented priority queue ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h index 221f16a03f16..ca99c6c89b19 100644 --- a/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h @@ -1,9 +1,8 @@ ///===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*--===// /// -/// The LLVM Compiler Infrastructure -/// -/// This file is distributed under the University of Illinois Open Source -/// License. See LICENSE.TXT for details. +/// 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 diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 3ba503487823..253d4734995b 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -1,9 +1,8 @@ //===- LexicalScopes.cpp - Collecting lexical scope info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index 38fcb37b1e69..75a5c359630e 100644 --- a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -1,9 +1,8 @@ //===- llvm/Codegen/LinkAllAsmWriterComponents.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 18c13ca8f598..56c93b24147e 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -1,9 +1,8 @@ //===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index cdf9ad2588cf..8bb88165d3e1 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LiveInterval.h - Interval representation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -606,6 +605,44 @@ namespace llvm { /// activated in the constructor of the live range. void flushSegmentSet(); + /// Stores indexes from the input index sequence R at which this LiveRange + /// is live to the output O iterator. + /// R is a range of _ascending sorted_ _random_ access iterators + /// to the input indexes. Indexes stored at O are ascending sorted so it + /// can be used directly in the subsequent search (for example for + /// subranges). Returns true if found at least one index. + template <typename Range, typename OutputIt> + bool findIndexesLiveAt(Range &&R, OutputIt O) const { + assert(std::is_sorted(R.begin(), R.end())); + auto Idx = R.begin(), EndIdx = R.end(); + auto Seg = segments.begin(), EndSeg = segments.end(); + bool Found = false; + while (Idx != EndIdx && Seg != EndSeg) { + // if the Seg is lower find first segment that is above Idx using binary + // search + if (Seg->end <= *Idx) { + Seg = std::upper_bound(++Seg, EndSeg, *Idx, + [=](typename std::remove_reference<decltype(*Idx)>::type V, + const typename std::remove_reference<decltype(*Seg)>::type &S) { + return V < S.end; + }); + if (Seg == EndSeg) + break; + } + auto NotLessStart = std::lower_bound(Idx, EndIdx, Seg->start); + if (NotLessStart == EndIdx) + break; + auto NotLessEnd = std::lower_bound(NotLessStart, EndIdx, Seg->end); + if (NotLessEnd != NotLessStart) { + Found = true; + O = std::copy(NotLessStart, NotLessEnd, O); + } + Idx = NotLessEnd; + ++Seg; + } + return Found; + } + void print(raw_ostream &OS) const; void dump() const; @@ -790,8 +827,15 @@ namespace llvm { /// L000F, refining for mask L0018. Will split the L00F0 lane into /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod /// function will be applied to the L0010 and L0008 subranges. + /// + /// \p Indexes and \p TRI are required to clean up the VNIs that + /// don't defne the related lane masks after they get shrunk. E.g., + /// when L000F gets split into L0007 and L0008 maybe only a subset + /// of the VNIs that defined L000F defines L0007. void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, - std::function<void(LiveInterval::SubRange&)> Apply); + std::function<void(LiveInterval::SubRange &)> Apply, + const SlotIndexes &Indexes, + const TargetRegisterInfo &TRI); bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 9e2799bd4414..05506d2c3bc6 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -1,9 +1,8 @@ //===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveIntervals.h b/include/llvm/CodeGen/LiveIntervals.h index 16ab1dc475c4..588b0f9cf39c 100644 --- a/include/llvm/CodeGen/LiveIntervals.h +++ b/include/llvm/CodeGen/LiveIntervals.h @@ -1,9 +1,8 @@ //===- LiveIntervals.h - Live Interval Analysis -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -418,6 +417,15 @@ class VirtRegMap; RegUnitRanges[Unit] = nullptr; } + /// Remove associated live ranges for the register units associated with \p + /// Reg. Subsequent uses should rely on on-demand recomputation. \note This + /// method can result in inconsistent liveness tracking if multiple phyical + /// registers share a regunit, and should be used cautiously. + void removeAllRegUnitsForPhysReg(unsigned Reg) { + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + removeRegUnit(*Units); + } + /// Remove value numbers and related live segments starting at position /// \p Pos that are part of any liverange of physical register \p Reg or one /// of its subregisters. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 7312902e21b7..50da0b3d5c48 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LivePhysRegs.h - Live Physical Register Set -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 53830297c525..6519937ec071 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -1,9 +1,8 @@ //===- LiveRangeEdit.h - Basic tools for split and spill --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index f62a55c73085..ab4d44f9a611 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -1,9 +1,8 @@ //===- LiveRegMatrix.h - Track register interference ----------*- C++ -*---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h index 5e9dd8b3cdf6..7dbb2feab8bf 100644 --- a/include/llvm/CodeGen/LiveRegUnits.h +++ b/include/llvm/CodeGen/LiveRegUnits.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/LiveRegUnits.h - Register Unit Set ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveStacks.h b/include/llvm/CodeGen/LiveStacks.h index 44ed785f7b53..7c4c64d515df 100644 --- a/include/llvm/CodeGen/LiveStacks.h +++ b/include/llvm/CodeGen/LiveStacks.h @@ -1,9 +1,8 @@ //===- LiveStacks.h - Live Stack Slot Analysis ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index ed8da8662106..71de306e2942 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LoopTraversal.h b/include/llvm/CodeGen/LoopTraversal.h index 750da0143c0d..e5810ef1ef26 100644 --- a/include/llvm/CodeGen/LoopTraversal.h +++ b/include/llvm/CodeGen/LoopTraversal.h @@ -1,9 +1,8 @@ //==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/LowLevelType.h b/include/llvm/CodeGen/LowLevelType.h index a3c5c9329f53..687233e4e168 100644 --- a/include/llvm/CodeGen/LowLevelType.h +++ b/include/llvm/CodeGen/LowLevelType.h @@ -1,9 +1,8 @@ //== llvm/CodeGen/LowLevelType.h ------------------------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRParser/MIParser.h b/include/llvm/CodeGen/MIRParser/MIParser.h new file mode 100644 index 000000000000..4e32a04551c1 --- /dev/null +++ b/include/llvm/CodeGen/MIRParser/MIParser.h @@ -0,0 +1,233 @@ +//===- MIParser.h - Machine Instructions Parser -----------------*- 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 function that parses the machine instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H +#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineFunction; +class MDNode; +class RegisterBank; +struct SlotMapping; +class SMDiagnostic; +class SourceMgr; +class StringRef; +class TargetRegisterClass; +class TargetSubtargetInfo; + +struct VRegInfo { + enum uint8_t { + UNKNOWN, NORMAL, GENERIC, REGBANK + } Kind = UNKNOWN; + bool Explicit = false; ///< VReg was explicitly specified in the .mir file. + union { + const TargetRegisterClass *RC; + const RegisterBank *RegBank; + } D; + unsigned VReg; + unsigned PreferredReg = 0; +}; + +using Name2RegClassMap = StringMap<const TargetRegisterClass *>; +using Name2RegBankMap = StringMap<const RegisterBank *>; + +struct PerTargetMIParsingState { +private: + const TargetSubtargetInfo &Subtarget; + + /// Maps from instruction names to op codes. + StringMap<unsigned> Names2InstrOpCodes; + + /// Maps from register names to registers. + StringMap<unsigned> Names2Regs; + + /// Maps from register mask names to register masks. + StringMap<const uint32_t *> Names2RegMasks; + + /// Maps from subregister names to subregister indices. + StringMap<unsigned> Names2SubRegIndices; + + /// Maps from target index names to target indices. + StringMap<int> Names2TargetIndices; + + /// Maps from direct target flag names to the direct target flag values. + StringMap<unsigned> Names2DirectTargetFlags; + + /// Maps from direct target flag names to the bitmask target flag values. + StringMap<unsigned> Names2BitmaskTargetFlags; + + /// Maps from MMO target flag names to MMO target flag values. + StringMap<MachineMemOperand::Flags> Names2MMOTargetFlags; + + /// Maps from register class names to register classes. + Name2RegClassMap Names2RegClasses; + + /// Maps from register bank names to register banks. + Name2RegBankMap Names2RegBanks; + + void initNames2InstrOpCodes(); + void initNames2Regs(); + void initNames2RegMasks(); + void initNames2SubRegIndices(); + void initNames2TargetIndices(); + void initNames2DirectTargetFlags(); + void initNames2BitmaskTargetFlags(); + void initNames2MMOTargetFlags(); + + void initNames2RegClasses(); + void initNames2RegBanks(); + +public: + /// Try to convert an instruction name to an opcode. Return true if the + /// instruction name is invalid. + bool parseInstrName(StringRef InstrName, unsigned &OpCode); + + /// Try to convert a register name to a register number. Return true if the + /// register name is invalid. + bool getRegisterByName(StringRef RegName, unsigned &Reg); + + /// Check if the given identifier is a name of a register mask. + /// + /// Return null if the identifier isn't a register mask. + const uint32_t *getRegMask(StringRef Identifier); + + /// Check if the given identifier is a name of a subregister index. + /// + /// Return 0 if the name isn't a subregister index class. + unsigned getSubRegIndex(StringRef Name); + + /// Try to convert a name of target index to the corresponding target index. + /// + /// Return true if the name isn't a name of a target index. + bool getTargetIndex(StringRef Name, int &Index); + + /// Try to convert a name of a direct target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a direct flag. + bool getDirectTargetFlag(StringRef Name, unsigned &Flag); + + /// Try to convert a name of a bitmask target flag to the corresponding + /// target flag. + /// + /// Return true if the name isn't a name of a bitmask target flag. + bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag); + + /// Try to convert a name of a MachineMemOperand target flag to the + /// corresponding target flag. + /// + /// Return true if the name isn't a name of a target MMO flag. + bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag); + + /// Check if the given identifier is a name of a register class. + /// + /// Return null if the name isn't a register class. + const TargetRegisterClass *getRegClass(StringRef Name); + + /// Check if the given identifier is a name of a register bank. + /// + /// Return null if the name isn't a register bank. + const RegisterBank *getRegBank(StringRef Name); + + PerTargetMIParsingState(const TargetSubtargetInfo &STI) + : Subtarget(STI) { + initNames2RegClasses(); + initNames2RegBanks(); + } + + ~PerTargetMIParsingState() = default; + + void setTarget(const TargetSubtargetInfo &NewSubtarget); +}; + +struct PerFunctionMIParsingState { + BumpPtrAllocator Allocator; + MachineFunction &MF; + SourceMgr *SM; + const SlotMapping &IRSlots; + PerTargetMIParsingState &Target; + + DenseMap<unsigned, MachineBasicBlock *> MBBSlots; + DenseMap<unsigned, VRegInfo *> VRegInfos; + StringMap<VRegInfo *> VRegInfosNamed; + DenseMap<unsigned, int> FixedStackObjectSlots; + DenseMap<unsigned, int> StackObjectSlots; + DenseMap<unsigned, unsigned> ConstantPoolSlots; + DenseMap<unsigned, unsigned> JumpTableSlots; + + PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, + const SlotMapping &IRSlots, + PerTargetMIParsingState &Target); + + VRegInfo &getVRegInfo(unsigned Num); + VRegInfo &getVRegInfoNamed(StringRef RegName); +}; + +/// Parse the machine basic block definitions, and skip the machine +/// instructions. +/// +/// This function runs the first parsing pass on the machine function's body. +/// It parses only the machine basic block definitions and creates the machine +/// basic blocks in the given machine function. +/// +/// The machine instructions aren't parsed during the first pass because all +/// the machine basic blocks aren't defined yet - this makes it impossible to +/// resolve the machine basic block references. +/// +/// Return true if an error occurred. +bool parseMachineBasicBlockDefinitions(PerFunctionMIParsingState &PFS, + StringRef Src, SMDiagnostic &Error); + +/// Parse the machine instructions. +/// +/// This function runs the second parsing pass on the machine function's body. +/// It skips the machine basic block definitions and parses only the machine +/// instructions and basic block attributes like liveins and successors. +/// +/// The second parsing pass assumes that the first parsing pass already ran +/// on the given source string. +/// +/// Return true if an error occurred. +bool parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src, + SMDiagnostic &Error); + +bool parseMBBReference(PerFunctionMIParsingState &PFS, + MachineBasicBlock *&MBB, StringRef Src, + SMDiagnostic &Error); + +bool parseRegisterReference(PerFunctionMIParsingState &PFS, + unsigned &Reg, StringRef Src, + SMDiagnostic &Error); + +bool parseNamedRegisterReference(PerFunctionMIParsingState &PFS, unsigned &Reg, + StringRef Src, SMDiagnostic &Error); + +bool parseVirtualRegisterReference(PerFunctionMIParsingState &PFS, + VRegInfo *&Info, StringRef Src, + SMDiagnostic &Error); + +bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI, + StringRef Src, SMDiagnostic &Error); + +bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, + SMDiagnostic &Error); + +} // end namespace llvm + +#endif // LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h index e199a1f69ad7..6a04e48e533c 100644 --- a/include/llvm/CodeGen/MIRParser/MIRParser.h +++ b/include/llvm/CodeGen/MIRParser/MIRParser.h @@ -1,9 +1,8 @@ //===- MIRParser.h - MIR serialization format parser ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRPrinter.h b/include/llvm/CodeGen/MIRPrinter.h index 078c4b2f6072..a4b03a7fb765 100644 --- a/include/llvm/CodeGen/MIRPrinter.h +++ b/include/llvm/CodeGen/MIRPrinter.h @@ -1,9 +1,8 @@ -//===- MIRPrinter.h - MIR serialization format printer --------------------===// +//===- MIRPrinter.h - MIR serialization format printer ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h index 98ac81915dc0..94e76a75e8da 100644 --- a/include/llvm/CodeGen/MIRYamlMapping.h +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -1,9 +1,8 @@ -//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===// +//===- MIRYamlMapping.h - Describe mapping between MIR and YAML--*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" @@ -37,6 +37,7 @@ struct StringValue { StringValue() = default; StringValue(std::string Value) : Value(std::move(Value)) {} + StringValue(const char Val[]) : Value(Val) {} bool operator==(const StringValue &Other) const { return Value == Other.Value; @@ -212,7 +213,7 @@ struct MachineStackObject { int64_t Offset = 0; uint64_t Size = 0; unsigned Alignment = 0; - uint8_t StackID = 0; + TargetStackID::Value StackID; StringValue CalleeSavedRegister; bool CalleeSavedRestored = true; Optional<int64_t> LocalOffset; @@ -252,7 +253,7 @@ template <> struct MappingTraits<MachineStackObject> { if (Object.Type != MachineStackObject::VariableSized) YamlIO.mapRequired("size", Object.Size); YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); - YamlIO.mapOptional("stack-id", Object.StackID); + YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, StringValue()); // Don't print it out when it's empty. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, @@ -278,7 +279,7 @@ struct FixedMachineStackObject { int64_t Offset = 0; uint64_t Size = 0; unsigned Alignment = 0; - uint8_t StackID = 0; + TargetStackID::Value StackID; bool IsImmutable = false; bool IsAliased = false; StringValue CalleeSavedRegister; @@ -308,6 +309,15 @@ struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { } }; +template <> +struct ScalarEnumerationTraits<TargetStackID::Value> { + static void enumeration(yaml::IO &IO, TargetStackID::Value &ID) { + IO.enumCase(ID, "default", TargetStackID::Default); + IO.enumCase(ID, "sgpr-spill", TargetStackID::SGPRSpill); + IO.enumCase(ID, "noalloc", TargetStackID::NoAlloc); + } +}; + template <> struct MappingTraits<FixedMachineStackObject> { static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { YamlIO.mapRequired("id", Object.ID); @@ -317,7 +327,7 @@ template <> struct MappingTraits<FixedMachineStackObject> { YamlIO.mapOptional("offset", Object.Offset, (int64_t)0); YamlIO.mapOptional("size", Object.Size, (uint64_t)0); YamlIO.mapOptional("alignment", Object.Alignment, (unsigned)0); - YamlIO.mapOptional("stack-id", Object.StackID); + YamlIO.mapOptional("stack-id", Object.StackID, TargetStackID::Default); if (Object.Type != FixedMachineStackObject::SpillSlot) { YamlIO.mapOptional("isImmutable", Object.IsImmutable, false); YamlIO.mapOptional("isAliased", Object.IsAliased, false); @@ -337,6 +347,66 @@ template <> struct MappingTraits<FixedMachineStackObject> { static const bool flow = true; }; + +/// Serializable representation of CallSiteInfo. +struct CallSiteInfo { + // Representation of call argument and register which is used to + // transfer it. + struct ArgRegPair { + StringValue Reg; + uint16_t ArgNo; + + bool operator==(const ArgRegPair &Other) const { + return Reg == Other.Reg && ArgNo == Other.ArgNo; + } + }; + + /// Identifies call instruction location in machine function. + struct MachineInstrLoc { + unsigned BlockNum; + unsigned Offset; + + bool operator==(const MachineInstrLoc &Other) const { + return BlockNum == Other.BlockNum && Offset == Other.Offset; + } + }; + + MachineInstrLoc CallLocation; + std::vector<ArgRegPair> ArgForwardingRegs; + + bool operator==(const CallSiteInfo &Other) const { + return CallLocation.BlockNum == Other.CallLocation.BlockNum && + CallLocation.Offset == Other.CallLocation.Offset; + } +}; + +template <> struct MappingTraits<CallSiteInfo::ArgRegPair> { + static void mapping(IO &YamlIO, CallSiteInfo::ArgRegPair &ArgReg) { + YamlIO.mapRequired("arg", ArgReg.ArgNo); + YamlIO.mapRequired("reg", ArgReg.Reg); + } + + static const bool flow = true; +}; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo::ArgRegPair) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits<CallSiteInfo> { + static void mapping(IO &YamlIO, CallSiteInfo &CSInfo) { + YamlIO.mapRequired("bb", CSInfo.CallLocation.BlockNum); + YamlIO.mapRequired("offset", CSInfo.CallLocation.Offset); + YamlIO.mapOptional("fwdArgRegs", CSInfo.ArgForwardingRegs, + std::vector<CallSiteInfo::ArgRegPair>()); + } + + static const bool flow = true; +}; + struct MachineConstantPoolValue { UnsignedValue ID; StringValue Value; @@ -391,6 +461,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::CallSiteInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) @@ -483,6 +554,20 @@ template <> struct MappingTraits<MachineFrameInfo> { } }; +/// Targets should override this in a way that mirrors the implementation of +/// llvm::MachineFunctionInfo. +struct MachineFunctionInfo { + virtual ~MachineFunctionInfo() {} + virtual void mappingImpl(IO &YamlIO) {} +}; + +template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> { + static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) { + if (MFI) + MFI->mappingImpl(YamlIO); + } +}; + struct MachineFunction { StringRef Name; unsigned Alignment = 0; @@ -504,6 +589,8 @@ struct MachineFunction { std::vector<FixedMachineStackObject> FixedStackObjects; std::vector<MachineStackObject> StackObjects; std::vector<MachineConstantPoolValue> Constants; /// Constant pool. + std::unique_ptr<MachineFunctionInfo> MachineFuncInfo; + std::vector<CallSiteInfo> CallSitesInfo; MachineJumpTable JumpTableInfo; BlockStringValue Body; }; @@ -530,8 +617,11 @@ template <> struct MappingTraits<MachineFunction> { std::vector<FixedMachineStackObject>()); YamlIO.mapOptional("stack", MF.StackObjects, std::vector<MachineStackObject>()); + YamlIO.mapOptional("callSites", MF.CallSitesInfo, + std::vector<CallSiteInfo>()); YamlIO.mapOptional("constants", MF.Constants, std::vector<MachineConstantPoolValue>()); + YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo); if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable()); YamlIO.mapOptional("body", MF.Body, BlockStringValue()); diff --git a/include/llvm/CodeGen/MachORelocation.h b/include/llvm/CodeGen/MachORelocation.h index cbb49695af75..0185c7cbe018 100644 --- a/include/llvm/CodeGen/MachORelocation.h +++ b/include/llvm/CodeGen/MachORelocation.h @@ -1,9 +1,8 @@ //=== MachORelocation.h - Mach-O Relocation Info ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index ec2f270fcb3f..333d0a78618c 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineBasicBlock.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -115,6 +114,10 @@ private: /// branch. bool AddressTaken = false; + /// Indicate that this basic block needs its symbol be emitted regardless of + /// whether the flow just falls-through to it. + bool LabelMustBeEmitted = false; + /// Indicate that this basic block is the entry block of an EH scope, i.e., /// the block that used to have a catchpad or cleanuppad instruction in the /// LLVM IR. @@ -159,6 +162,13 @@ public: /// branch. void setHasAddressTaken() { AddressTaken = true; } + /// Test whether this block must have its label emitted. + bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; } + + /// Set this block to reflect that, regardless how we flow to it, we need + /// its label be emitted. + void setLabelMustBeEmitted() { LabelMustBeEmitted = true; } + /// Return the MachineFunction containing this basic block. const MachineFunction *getParent() const { return xParent; } MachineFunction *getParent() { return xParent; } @@ -900,11 +910,11 @@ class MachineInstrSpan { MachineBasicBlock::iterator I, B, E; public: - MachineInstrSpan(MachineBasicBlock::iterator I) - : MBB(*I->getParent()), - I(I), - B(I == MBB.begin() ? MBB.end() : std::prev(I)), - E(std::next(I)) {} + MachineInstrSpan(MachineBasicBlock::iterator I, MachineBasicBlock *BB) + : MBB(*BB), I(I), B(I == MBB.begin() ? MBB.end() : std::prev(I)), + E(std::next(I)) { + assert(I == BB->end() || I->getParent() == BB); + } MachineBasicBlock::iterator begin() { return B == MBB.end() ? MBB.begin() : std::next(B); diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 5b4b99ca0a5d..a438ecfcc25e 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -1,9 +1,8 @@ //===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 81b0524cf0a4..2b9b2030eb97 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,9 +1,8 @@ //=- MachineBranchProbabilityInfo.h - Branch Probability Analysis -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h index 586535f771c2..4f4034baf801 100644 --- a/include/llvm/CodeGen/MachineCombinerPattern.h +++ b/include/llvm/CodeGen/MachineCombinerPattern.h @@ -1,10 +1,9 @@ //===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by // combiner ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index b0b5420a884b..4d07b620a4b4 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -1,9 +1,8 @@ //===- CodeGen/MachineConstantPool.h - Abstract Constant Pool ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index 75d75bc3669a..f7bbd07a63ab 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineDominanceFrontier.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index e3d3d169db97..d2200080b897 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index c2706a21a177..761735120a64 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -1,9 +1,8 @@ //===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -471,7 +470,10 @@ public: assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].Alignment = Align; - ensureMaxAlignment(Align); + + // Only ensure max alignment for the default stack. + if (getStackID(ObjectIdx) == 0) + ensureMaxAlignment(Align); } /// Return the underlying Alloca of the specified @@ -698,6 +700,8 @@ public: assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].StackID = ID; + // If ID > 0, MaxAlignment may now be overly conservative. + // If ID == 0, MaxAlignment will need to be updated separately. } /// Returns true if the specified index corresponds to a dead object. diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 25edf5bcce51..201c126ee52e 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineFunction.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -31,11 +30,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/AtomicOrdering.h" @@ -53,6 +47,7 @@ namespace llvm { class BasicBlock; class BlockAddress; class DataLayout; +class DebugLoc; class DIExpression; class DILocalVariable; class DILocation; @@ -67,6 +62,7 @@ class MachineModuleInfo; class MachineRegisterInfo; class MCContext; class MCInstrDesc; +class MCSymbol; class Pass; class PseudoSourceValueManager; class raw_ostream; @@ -86,7 +82,7 @@ template <> struct ilist_callback_traits<MachineBasicBlock> { template <class Iterator> void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) { - llvm_unreachable("Never transfer between lists"); + assert(this == &OldList && "never transfer MBBs between functions"); } }; @@ -325,6 +321,10 @@ class MachineFunction { /// CodeView label annotations. std::vector<std::pair<MCSymbol *, MDNode *>> CodeViewAnnotations; + /// CodeView heapallocsites. + std::vector<std::tuple<MCSymbol*, MCSymbol*, DIType*>> + CodeViewHeapAllocSites; + bool CallsEHReturn = false; bool CallsUnwindInit = false; bool HasEHScopes = false; @@ -378,9 +378,28 @@ public: virtual void MF_HandleRemoval(MachineInstr &MI) = 0; }; + /// Structure used to represent pair of argument number after call lowering + /// and register used to transfer that argument. + /// For now we support only cases when argument is transferred through one + /// register. + struct ArgRegPair { + unsigned Reg; + uint16_t ArgNo; + ArgRegPair(unsigned R, unsigned Arg) : Reg(R), ArgNo(Arg) { + assert(Arg < (1 << 16) && "Arg out of range"); + } + }; + /// Vector of call argument and its forwarding register. + using CallSiteInfo = SmallVector<ArgRegPair, 1>; + using CallSiteInfoImpl = SmallVectorImpl<ArgRegPair>; + private: Delegate *TheDelegate = nullptr; + using CallSiteInfoMap = DenseMap<const MachineInstr *, CallSiteInfo>; + /// Map a call instruction to call site arguments forwarding info. + CallSiteInfoMap CallSitesInfo; + // Callbacks for insertion and removal. void handleInsertion(MachineInstr &MI); void handleRemoval(MachineInstr &MI); @@ -443,7 +462,6 @@ public: /// getSubtarget - Return the subtarget for which this machine code is being /// compiled. const TargetSubtargetInfo &getSubtarget() const { return *STI; } - void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } /// getSubtarget - This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being @@ -741,6 +759,12 @@ public: MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, const AAMDNodes &AAInfo); + /// Allocate a new MachineMemOperand by copying an existing one, + /// replacing the flags. MachineMemOperands are owned + /// by the MachineFunction and need not be explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + MachineMemOperand::Flags Flags); + using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity; /// Allocate an array of MachineOperands. This is only intended for use by @@ -791,10 +815,7 @@ public: return FrameInstructions; } - LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst) { - FrameInstructions.push_back(Inst); - return FrameInstructions.size() - 1; - } + LLVM_NODISCARD unsigned addFrameInst(const MCCFIInstruction &Inst); /// \name Exception Handling /// \{ @@ -913,6 +934,14 @@ public: return CodeViewAnnotations; } + /// Record heapallocsites + void addCodeViewHeapAllocSite(MachineInstr *I, MDNode *MD); + + ArrayRef<std::tuple<MCSymbol*, MCSymbol*, DIType*>> + getCodeViewHeapAllocSites() const { + return CodeViewHeapAllocSites; + } + /// Return a reference to the C++ typeinfo for the current function. const std::vector<const GlobalValue *> &getTypeInfos() const { return TypeInfos; @@ -936,6 +965,23 @@ public: const VariableDbgInfoMapTy &getVariableDbgInfo() const { return VariableDbgInfos; } + + void addCallArgsForwardingRegs(const MachineInstr *CallI, + CallSiteInfoImpl &&CallInfo) { + assert(CallI->isCall()); + CallSitesInfo[CallI] = std::move(CallInfo); + } + + const CallSiteInfoMap &getCallSitesInfo() const { + return CallSitesInfo; + } + + /// Update call sites info by deleting entry for \p Old call instruction. + /// If \p New is present then transfer \p Old call info to it. This function + /// should be called before removing call instruction or before replacing + /// call instruction with new one. + void updateCallSiteInfo(const MachineInstr *Old, + const MachineInstr *New = nullptr); }; //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h index 6d978daa2018..caaf22c2139e 100644 --- a/include/llvm/CodeGen/MachineFunctionPass.h +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -1,9 +1,8 @@ //===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index ea1a2a536fc7..c82c5b137507 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineInstr.h - MachineInstr class ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,6 +24,7 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/InlineAsm.h" #include "llvm/MC/MCInstrDesc.h" @@ -103,8 +103,10 @@ public: // no unsigned wrap. NoSWrap = 1 << 12, // Instruction supports binary operator // no signed wrap. - IsExact = 1 << 13 // Instruction supports division is + IsExact = 1 << 13, // Instruction supports division is // known to be exact. + FPExcept = 1 << 14, // Instruction may raise floating-point + // exceptions. }; private: @@ -831,6 +833,17 @@ public: return mayLoad(Type) || mayStore(Type); } + /// Return true if this instruction could possibly raise a floating-point + /// exception. This is the case if the instruction is a floating-point + /// instruction that can in principle raise an exception, as indicated + /// by the MCID::MayRaiseFPException property, *and* at the same time, + /// the instruction is used in a context where we expect floating-point + /// exceptions might be enabled, as indicated by the FPExcept MI flag. + bool mayRaiseFPException() const { + return hasProperty(MCID::MayRaiseFPException) && + getFlag(MachineInstr::MIFlag::FPExcept); + } + //===--------------------------------------------------------------------===// // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// @@ -1006,16 +1019,33 @@ public: && getOperand(1).isImm(); } + /// A DBG_VALUE is an entry value iff its debug expression contains the + /// DW_OP_entry_value DWARF operation. + bool isDebugEntryValue() const { + return isDebugValue() && getDebugExpression()->isEntryValue(); + } + + /// Return true if the instruction is a debug value which describes a part of + /// a variable as unavailable. + bool isUndefDebugValue() const { + return isDebugValue() && getOperand(0).isReg() && !getOperand(0).getReg(); + } + bool isPHI() const { return getOpcode() == TargetOpcode::PHI || getOpcode() == TargetOpcode::G_PHI; } bool isKill() const { return getOpcode() == TargetOpcode::KILL; } bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } - bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isInlineAsm() const { + return getOpcode() == TargetOpcode::INLINEASM || + getOpcode() == TargetOpcode::INLINEASM_BR; + } + /// FIXME: Seems like a layering violation that the AsmDialect, which is X86 + /// specific, be attached to a generic MachineInstr. bool isMSInlineAsm() const { - return getOpcode() == TargetOpcode::INLINEASM && getInlineAsmDialect(); + return isInlineAsm() && getInlineAsmDialect() == InlineAsm::AD_Intel; } bool isStackAligningInlineAsm() const; @@ -1197,12 +1227,22 @@ public: /// Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. - MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, - const TargetRegisterInfo *TRI = nullptr) { - int Idx = findRegisterDefOperandIdx(Reg, isDead, false, TRI); + MachineOperand * + findRegisterDefOperand(unsigned Reg, bool isDead = false, + bool Overlap = false, + const TargetRegisterInfo *TRI = nullptr) { + int Idx = findRegisterDefOperandIdx(Reg, isDead, Overlap, TRI); return (Idx == -1) ? nullptr : &getOperand(Idx); } + const MachineOperand * + findRegisterDefOperand(unsigned Reg, bool isDead = false, + bool Overlap = false, + const TargetRegisterInfo *TRI = nullptr) const { + return const_cast<MachineInstr *>(this)->findRegisterDefOperand( + Reg, isDead, Overlap, TRI); + } + /// Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. @@ -1364,7 +1404,7 @@ public: /// @param AA Optional alias analysis, used to compare memory operands. /// @param Other MachineInstr to check aliasing against. /// @param UseTBAA Whether to pass TBAA information to alias analysis. - bool mayAlias(AliasAnalysis *AA, MachineInstr &Other, bool UseTBAA); + bool mayAlias(AliasAnalysis *AA, const MachineInstr &Other, bool UseTBAA) const; /// Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory @@ -1400,6 +1440,19 @@ public: /// Return true if all the defs of this instruction are dead. bool allDefsAreDead() const; + /// Return a valid size if the instruction is a spill instruction. + Optional<unsigned> getSpillSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a folded spill instruction. + Optional<unsigned> getFoldedSpillSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a restore instruction. + Optional<unsigned> getRestoreSize(const TargetInstrInfo *TII) const; + + /// Return a valid size if the instruction is a folded restore instruction. + Optional<unsigned> + getFoldedRestoreSize(const TargetInstrInfo *TII) const; + /// Copy implicit register operands from specified /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI); @@ -1521,11 +1574,17 @@ public: /// FIXME: This is not fully implemented yet. void setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol); + /// Clone another MachineInstr's pre- and post- instruction symbols and + /// replace ours with it. + void cloneInstrSymbols(MachineFunction &MF, const MachineInstr &MI); + /// Return the MIFlags which represent both MachineInstrs. This /// should be used when merging two MachineInstrs into one. This routine does /// not modify the MIFlags of this MachineInstr. uint16_t mergeFlagsWith(const MachineInstr& Other) const; + static uint16_t copyFlagsFromInstruction(const Instruction &I); + /// Copy all flags to MachineInst MIFlags void copyIRFlags(const Instruction &I); diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index b5e523f655e7..6d7fb72b6bd1 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -1,9 +1,8 @@ //===- CodeGen/MachineInstrBuilder.h - Simplify creation of MIs --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -80,6 +79,11 @@ public: /// explicitly. MachineInstr *getInstr() const { return MI; } + /// Get the register for the operand index. + /// The operand at the index should be a register (asserted by + /// MachineOperand). + Register getReg(unsigned Idx) const { return MI->getOperand(Idx).getReg(); } + /// Add a new virtual register operand. const MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, unsigned SubReg = 0) const { @@ -283,6 +287,9 @@ public: case MachineOperand::MO_GlobalAddress: return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off, TargetFlags); + case MachineOperand::MO_BlockAddress: + return addBlockAddress(Disp.getBlockAddress(), Disp.getOffset() + off, + TargetFlags); } } diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index b5341fd1ae49..1810d23072d0 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -1,9 +1,8 @@ -//===-- CodeGen/MachineInstBundle.h - MI bundle utilities -------*- C++ -*-===// +//===- llvm/CodeGen/MachineInstrBundle.h - MI bundle utilities --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -62,7 +61,8 @@ inline MachineBasicBlock::instr_iterator getBundleEnd( MachineBasicBlock::instr_iterator I) { while (I->isBundledWithSucc()) ++I; - return ++I; + ++I; + return I; } /// Returns an iterator pointing beyond the bundle containing \p I. @@ -70,7 +70,8 @@ inline MachineBasicBlock::const_instr_iterator getBundleEnd( MachineBasicBlock::const_instr_iterator I) { while (I->isBundledWithSucc()) ++I; - return ++I; + ++I; + return I; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineInstrBundleIterator.h b/include/llvm/CodeGen/MachineInstrBundleIterator.h index 5fe4964ff116..0f59563e7e1b 100644 --- a/include/llvm/CodeGen/MachineInstrBundleIterator.h +++ b/include/llvm/CodeGen/MachineInstrBundleIterator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h index 25a3e6b556a3..11781145b378 100644 --- a/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -1,9 +1,8 @@ //===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 917fb90380f5..da6df59c739c 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineLoopInfo.h - Natural Loop Calculator -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 078ef7ca510c..65f706302bc2 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,8 +18,6 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*> #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/DataTypes.h" @@ -223,6 +220,9 @@ public: /// Return the size in bytes of the memory reference. uint64_t getSize() const { return Size; } + /// Return the size in bits of the memory reference. + uint64_t getSizeInBits() const { return Size * 8; } + /// Return the minimum known alignment in bytes of the actual memory /// reference. uint64_t getAlignment() const; @@ -267,13 +267,13 @@ public: bool isAtomic() const { return getOrdering() != AtomicOrdering::NotAtomic; } /// Returns true if this memory operation doesn't have any ordering - /// constraints other than normal aliasing. Volatile and atomic memory - /// operations can't be reordered. - /// - /// Currently, we don't model the difference between volatile and atomic - /// operations. They should retain their ordering relative to all memory - /// operations. - bool isUnordered() const { return !isVolatile(); } + /// constraints other than normal aliasing. Volatile and (ordered) atomic + /// memory operations can't be reordered. + bool isUnordered() const { + return (getOrdering() == AtomicOrdering::NotAtomic || + getOrdering() == AtomicOrdering::Unordered) && + !isVolatile(); + } /// Update this MachineMemOperand to reflect the alignment of MMO, if it has a /// greater alignment. This must only be used when the new alignment applies diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 4371420bc7a2..4ff5c7fd013a 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -114,10 +113,9 @@ class MachineModuleInfo : public ImmutablePass { /// True if debugging information is available in this module. bool DbgInfoAvailable; - /// True if this module calls VarArg function with floating-point arguments. - /// This is used to emit an undefined reference to _fltused on Windows - /// targets. - bool UsesVAFloatArgument; + /// True if this module is being built for windows/msvc, and uses floating + /// point. This is used to emit an undefined reference to _fltused. + bool UsesMSVCFloatingPoint; /// True if the module calls the __morestack function indirectly, as is /// required under the large code model on x86. This is used to emit @@ -152,6 +150,8 @@ public: bool doInitialization(Module &) override; bool doFinalization(Module &) override; + const LLVMTargetMachine &getTarget() const { return TM; } + const MCContext &getContext() const { return Context; } MCContext &getContext() { return Context; } @@ -187,13 +187,9 @@ public: bool hasDebugInfo() const { return DbgInfoAvailable; } void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } - bool usesVAFloatArgument() const { - return UsesVAFloatArgument; - } + bool usesMSVCFloatingPoint() const { return UsesMSVCFloatingPoint; } - void setUsesVAFloatArgument(bool b) { - UsesVAFloatArgument = b; - } + void setUsesMSVCFloatingPoint(bool b) { UsesMSVCFloatingPoint = b; } bool usesMorestackAddr() const { return UsesMorestackAddr; @@ -258,14 +254,6 @@ public: /// \} }; // End class MachineModuleInfo -//===- MMI building helpers -----------------------------------------------===// - -/// Determine if any floating-point values are being passed to this variadic -/// function, and set the MachineModuleInfo's usesVAFloatArgument flag if so. -/// This flag is used to emit an undefined reference to _fltused on Windows, -/// which will link in MSVCRT's floating-point support. -void computeUsesVAFloatArgument(const CallInst &I, MachineModuleInfo &MMI); - } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEMODULEINFO_H diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index 17df1fa792b7..746e92239613 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineModuleInfoImpls.h --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 53e8889d118a..2152c7582e5a 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/MachineOperand.h - MachineOperand class ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_CODEGEN_MACHINEOPERAND_H #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/Register.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/LowLevelTypeImpl.h" @@ -346,9 +346,9 @@ public: //===--------------------------------------------------------------------===// /// getReg - Returns the register number. - unsigned getReg() const { + Register getReg() const { assert(isReg() && "This is not a register operand!"); - return SmallContents.RegNo; + return Register(SmallContents.RegNo); } unsigned getSubReg() const { @@ -684,6 +684,11 @@ public: Contents.RegMask = RegMaskPtr; } + void setPredicate(unsigned Predicate) { + assert(isPredicate() && "Wrong MachineOperand mutator"); + Contents.Pred = Predicate; + } + //===--------------------------------------------------------------------===// // Other methods. //===--------------------------------------------------------------------===// @@ -714,6 +719,10 @@ public: /// ChangeToES - Replace this operand with a new external symbol operand. void ChangeToES(const char *SymName, unsigned char TargetFlags = 0); + /// ChangeToGA - Replace this operand with a new global address operand. + void ChangeToGA(const GlobalValue *GV, int64_t Offset, + unsigned char TargetFlags = 0); + /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. void ChangeToMCSymbol(MCSymbol *Sym); diff --git a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h index a7ce870400c2..a461a299917c 100644 --- a/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ b/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -1,9 +1,8 @@ ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===// /// -/// The LLVM Compiler Infrastructure -/// -/// This file is distributed under the University of Illinois Open Source -/// License. See LICENSE.TXT for details. +/// 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 @@ -159,9 +158,10 @@ public: /// (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 (MF.getFunction().getContext().getDiagnosticsOutputFile() || - MF.getFunction().getContext() - .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); + return ( + MF.getFunction().getContext().getRemarkStreamer() || + MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled( + PassName)); } /// Take a lambda that returns a remark which will be emitted. Second @@ -172,8 +172,11 @@ public: // remarks enabled. We can't currently check whether remarks are requested // for the calling pass since that requires actually building the remark. - if (MF.getFunction().getContext().getDiagnosticsOutputFile() || - MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { + if (MF.getFunction().getContext().getRemarkStreamer() || + MF.getFunction() + .getContext() + .getDiagHandlerPtr() + ->isAnyRemarkEnabled()) { auto R = RemarkBuilder(); emit((DiagnosticInfoOptimizationBase &)R); } diff --git a/include/llvm/CodeGen/MachineOutliner.h b/include/llvm/CodeGen/MachineOutliner.h index bfd1e994053a..3868fa415579 100644 --- a/include/llvm/CodeGen/MachineOutliner.h +++ b/include/llvm/CodeGen/MachineOutliner.h @@ -1,9 +1,8 @@ //===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -172,13 +171,13 @@ public: /// Represents the size of a sequence in bytes. (Some instructions vary /// widely in size, so just counting the instructions isn't very useful.) - unsigned SequenceSize; + unsigned SequenceSize = 0; /// Target-defined overhead of constructing a frame for this function. - unsigned FrameOverhead; + unsigned FrameOverhead = 0; /// Target-defined identifier for constructing a frame for this function. - unsigned FrameConstructionID; + unsigned FrameConstructionID = 0; /// Return the number of candidates for this \p OutlinedFunction. unsigned getOccurrenceCount() const { return Candidates.size(); } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index a031c92d914f..f5b3723db0aa 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachinePassRegistry.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachinePipeliner.h b/include/llvm/CodeGen/MachinePipeliner.h index 38cb33e90e63..03ca53072685 100644 --- a/include/llvm/CodeGen/MachinePipeliner.h +++ b/include/llvm/CodeGen/MachinePipeliner.h @@ -1,9 +1,8 @@ //===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -63,6 +62,8 @@ public: const InstrItineraryData *InstrItins; const TargetInstrInfo *TII = nullptr; RegisterClassInfo RegClassInfo; + bool disabledByPragma = false; + unsigned II_setByPragma = 0; #ifndef NDEBUG static int NumTries; @@ -100,6 +101,7 @@ private: bool canPipelineLoop(MachineLoop &L); bool scheduleLoop(MachineLoop &L); bool swingModuloScheduler(MachineLoop &L); + void setPragmaPipelineOptions(MachineLoop &L); }; /// This class builds the dependence graph for the instructions in a loop, @@ -108,11 +110,14 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs { MachinePipeliner &Pass; /// The minimum initiation interval between iterations for this schedule. unsigned MII = 0; + /// The maximum initiation interval between iterations for this schedule. + unsigned MAX_II = 0; /// Set to true if a valid pipelined schedule is found for the loop. bool Scheduled = false; MachineLoop &Loop; LiveIntervals &LIS; const RegisterClassInfo &RegClassInfo; + unsigned II_setByPragma = 0; /// A toplogical ordering of the SUnits, which is needed for changing /// dependences and iterating over the SUnits. @@ -190,9 +195,9 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs { public: SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis, - const RegisterClassInfo &rci) + const RegisterClassInfo &rci, unsigned II) : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis), - RegClassInfo(rci), Topo(SUnits, &ExitSU) { + RegClassInfo(rci), II_setByPragma(II), Topo(SUnits, &ExitSU) { P.MF->getSubtarget().getSMSMutations(Mutations); if (SwpEnableCopyToPhi) Mutations.push_back(llvm::make_unique<CopyToPhiMutation>()); @@ -253,9 +258,6 @@ public: return 0; } - /// Set the Minimum Initiation Interval for this schedule attempt. - void setMII(unsigned mii) { MII = mii; } - void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule); void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs); @@ -316,9 +318,9 @@ private: MBBVectorTy &EpilogBBs); void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, SMSchedule &Schedule); - void addBranches(MBBVectorTy &PrologBBs, MachineBasicBlock *KernelBB, - MBBVectorTy &EpilogBBs, SMSchedule &Schedule, - ValueMapTy *VRMap); + void addBranches(MachineBasicBlock &PreheaderBB, MBBVectorTy &PrologBBs, + MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs, + SMSchedule &Schedule, ValueMapTy *VRMap); bool computeDelta(MachineInstr &MI, unsigned &Delta); void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI, unsigned Num); @@ -346,6 +348,10 @@ private: unsigned &OffsetPos, unsigned &NewBase, int64_t &NewOffset); void postprocessDAG(); + /// Set the Minimum Initiation Interval for this schedule attempt. + void setMII(unsigned ResMII, unsigned RecMII); + /// Set the Maximum Initiation Interval for this schedule attempt. + void setMAX_II(); }; /// A NodeSet contains a set of SUnit DAG nodes with additional information @@ -457,6 +463,56 @@ public: #endif }; +// 16 was selected based on the number of ProcResource kinds for all +// existing Subtargets, so that SmallVector don't need to resize too often. +static const int DefaultProcResSize = 16; + +class ResourceManager { +private: + const MCSubtargetInfo *STI; + const MCSchedModel &SM; + const bool UseDFA; + std::unique_ptr<DFAPacketizer> DFAResources; + /// Each processor resource is associated with a so-called processor resource + /// mask. This vector allows to correlate processor resource IDs with + /// processor resource masks. There is exactly one element per each processor + /// resource declared by the scheduling model. + llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceMasks; + + llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceCount; + +public: + ResourceManager(const TargetSubtargetInfo *ST) + : STI(ST), SM(ST->getSchedModel()), UseDFA(ST->useDFAforSMS()), + ProcResourceMasks(SM.getNumProcResourceKinds(), 0), + ProcResourceCount(SM.getNumProcResourceKinds(), 0) { + if (UseDFA) + DFAResources.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST)); + initProcResourceVectors(SM, ProcResourceMasks); + } + + void initProcResourceVectors(const MCSchedModel &SM, + SmallVectorImpl<uint64_t> &Masks); + /// Check if the resources occupied by a MCInstrDesc are available in + /// the current state. + bool canReserveResources(const MCInstrDesc *MID) const; + + /// Reserve the resources occupied by a MCInstrDesc and change the current + /// state to reflect that change. + void reserveResources(const MCInstrDesc *MID); + + /// Check if the resources occupied by a machine instruction are available + /// in the current state. + bool canReserveResources(const MachineInstr &MI) const; + + /// Reserve the resources occupied by a machine instruction and change the + /// current state to reflect that change. + void reserveResources(const MachineInstr &MI); + + /// Reset the state + void clearResources(); +}; + /// This class represents the scheduled code. The main data structure is a /// map from scheduled cycle to instructions. During scheduling, the /// data structure explicitly represents all stages/iterations. When @@ -495,12 +551,11 @@ private: /// Virtual register information. MachineRegisterInfo &MRI; - std::unique_ptr<DFAPacketizer> Resources; + ResourceManager ProcItinResources; public: SMSchedule(MachineFunction *mf) - : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), - Resources(ST.getInstrInfo()->CreateTargetScheduleState(ST)) {} + : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), ProcItinResources(&ST) {} void reset() { ScheduledInstrs.clear(); diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index c6a41598ce32..b67e6b52ac8f 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -1,9 +1,8 @@ -//=- llvm/CodeGen/MachineDominators.h ----------------------------*- C++ -*-==// +//===- llvm/CodeGen/MachinePostDominators.h ----------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index 8394b58d0a16..6d9fb9b9100a 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineRegionInfo.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index fef010a23ef9..b5deed1f5010 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/MachineRegisterInfo.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -562,9 +561,14 @@ public: } /// hasOneNonDBGUse - Return true if there is exactly one non-Debug - /// instruction using the specified register. + /// use of the specified register. bool hasOneNonDBGUse(unsigned RegNo) const; + /// hasOneNonDBGUse - Return true if there is exactly one non-Debug + /// instruction using the specified register. Said instruction may have + /// multiple uses. + bool hasOneNonDBGUser(unsigned RegNo) const; + /// replaceRegWith - Replace all instances of FromReg with ToReg in the /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), /// except that it also changes any definitions of the register as well. @@ -713,12 +717,12 @@ public: /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. - unsigned createVirtualRegister(const TargetRegisterClass *RegClass, + Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name = ""); /// Create and return a new virtual register in the function with the same /// attributes as the given register. - unsigned cloneVirtualRegister(unsigned VReg, StringRef Name = ""); + Register cloneVirtualRegister(Register VReg, StringRef Name = ""); /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic /// (target independent) virtual register. @@ -733,7 +737,7 @@ public: /// Create and return a new generic virtual register with low-level /// type \p Ty. - unsigned createGenericVirtualRegister(LLT Ty, StringRef Name = ""); + Register createGenericVirtualRegister(LLT Ty, StringRef Name = ""); /// Remove all types associated to virtual registers (after instruction /// selection and constraining of all generic virtual registers). diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 5e91246b402c..0319ec774671 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -1,9 +1,8 @@ //===- MachineSSAUpdater.h - Unstructured SSA Update Tool -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 4bc31ae7c61a..75a334f61ad0 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -1,9 +1,8 @@ //===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -265,10 +264,6 @@ protected: LiveIntervals *LIS; std::unique_ptr<MachineSchedStrategy> SchedImpl; - /// Topo - A topological ordering for SUnits which permits fast IsReachable - /// and similar queries. - ScheduleDAGTopologicalSort Topo; - /// Ordered list of DAG postprocessing steps. std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations; @@ -292,7 +287,7 @@ public: ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, bool RemoveKillFlags) : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA), - LIS(C->LIS), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU) {} + LIS(C->LIS), SchedImpl(std::move(S)) {} // Provide a vtable anchor ~ScheduleDAGMI() override; @@ -320,17 +315,6 @@ public: Mutations.push_back(std::move(Mutation)); } - /// True if an edge can be added from PredSU to SuccSU without creating - /// a cycle. - bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); - - /// Add a DAG edge to the given SU with the given predecessor - /// dependence data. - /// - /// \returns true if the edge may be added without creating a cycle OR if an - /// equivalent edge already existed (false indicates failure). - bool addEdge(SUnit *SuccSU, const SDep &PredDep); - MachineBasicBlock::iterator top() const { return CurrentTop; } MachineBasicBlock::iterator bottom() const { return CurrentBottom; } @@ -682,6 +666,10 @@ private: // scheduled instruction. SmallVector<unsigned, 16> ReservedCycles; + // For each PIdx, stores first index into ReservedCycles that corresponds to + // it. + SmallVector<unsigned, 16> ReservedCyclesIndex; + #ifndef NDEBUG // Remember the greatest possible stall as an upper bound on the number of // times we should retry the pending queue because of a hazard. @@ -756,7 +744,11 @@ public: /// cycle. unsigned getLatencyStallCycles(SUnit *SU); - unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles); + unsigned getNextResourceCycleByInstance(unsigned InstanceIndex, + unsigned Cycles); + + std::pair<unsigned, unsigned> getNextResourceCycle(unsigned PIdx, + unsigned Cycles); bool checkHazard(SUnit *SU); @@ -1015,6 +1007,7 @@ protected: /// Callbacks from ScheduleDAGMI: /// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... class PostGenericScheduler : public GenericSchedulerBase { +protected: ScheduleDAGMI *DAG; SchedBoundary Top; SmallVector<SUnit*, 8> BotRoots; diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 9d8db393ca92..025989504177 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -1,9 +1,8 @@ //===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/MacroFusion.h b/include/llvm/CodeGen/MacroFusion.h index a77226ddaf33..3a140fe63fde 100644 --- a/include/llvm/CodeGen/MacroFusion.h +++ b/include/llvm/CodeGen/MacroFusion.h @@ -1,9 +1,8 @@ //===- MacroFusion.h - Macro Fusion -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h index bde451ae1fcc..0d6d8a31317b 100644 --- a/include/llvm/CodeGen/PBQP/CostAllocator.h +++ b/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -1,9 +1,8 @@ //===- CostAllocator.h - PBQP Cost Allocator --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index a6d88b057dcb..c2cd6dadae5f 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -1,9 +1,8 @@ //===- Graph.h - PBQP Graph -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index d1432a3053c4..8b014ccbb07b 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -1,9 +1,8 @@ //===- Math.h - PBQP Vector and Matrix classes ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index 21b99027970d..51822d082bad 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -1,9 +1,8 @@ //===- ReductionRules.h - Reduction Rules -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 4d4379fbc2c2..d5b1474f0f4c 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -1,9 +1,8 @@ //===- Solution.h - PBQP Solution -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PBQPRAConstraint.h b/include/llvm/CodeGen/PBQPRAConstraint.h index 995467dc56d8..876ab97a669f 100644 --- a/include/llvm/CodeGen/PBQPRAConstraint.h +++ b/include/llvm/CodeGen/PBQPRAConstraint.h @@ -1,9 +1,8 @@ -//===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// +//===- llvm/CodeGen/PBQPRAConstraint.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ParallelCG.h b/include/llvm/CodeGen/ParallelCG.h index dbf09ea31e20..a44715d4fc4f 100644 --- a/include/llvm/CodeGen/ParallelCG.h +++ b/include/llvm/CodeGen/ParallelCG.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/ParallelCG.h - Parallel code generation ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index acf1ebb5bc83..d92ee93268e7 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -1,9 +1,8 @@ //===-- Passes.h - Target independent code generation passes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -346,8 +345,9 @@ namespace llvm { /// pointer or stack pointer index addressing. extern char &LocalStackSlotAllocationID; - /// ExpandISelPseudos - This pass expands pseudo-instructions. - extern char &ExpandISelPseudosID; + /// This pass expands pseudo-instructions, reserves registers and adjusts + /// machine frame information. + extern char &FinalizeISelID; /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; @@ -447,6 +447,9 @@ namespace llvm { /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp FunctionPass *createCFIInstrInserter(); + /// Create Hardware Loop pass. \see HardwareLoops.cpp + FunctionPass *createHardwareLoopsPass(); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/PreISelIntrinsicLowering.h b/include/llvm/CodeGen/PreISelIntrinsicLowering.h index b7f83e515b7e..73d7d779e55b 100644 --- a/include/llvm/CodeGen/PreISelIntrinsicLowering.h +++ b/include/llvm/CodeGen/PreISelIntrinsicLowering.h @@ -1,9 +1,8 @@ //===- PreISelIntrinsicLowering.h - Pre-ISel intrinsic lowering pass ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index f66191bc9fb4..4b3cc9145a13 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/PseudoSourceValue.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,7 +15,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Value.h" #include "llvm/IR/ValueMap.h" #include <map> @@ -124,7 +122,7 @@ public: bool mayAlias(const MachineFrameInfo *) const override; }; -/// A specialized pseudo soruce value for holding GlobalValue values. +/// A specialized pseudo source value for holding GlobalValue values. class GlobalValuePseudoSourceValue : public CallEntryPseudoSourceValue { const GlobalValue *GV; diff --git a/include/llvm/CodeGen/ReachingDefAnalysis.h b/include/llvm/CodeGen/ReachingDefAnalysis.h index b21b745c8fd1..a599fb62f5e2 100644 --- a/include/llvm/CodeGen/ReachingDefAnalysis.h +++ b/include/llvm/CodeGen/ReachingDefAnalysis.h @@ -1,15 +1,14 @@ //==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 Reaching Defs Analysis pass. /// -/// This pass tracks for each instruction what is the “closest” reaching def of +/// This pass tracks for each instruction what is the "closest" reaching def of /// a given register. It is used by BreakFalseDeps (for clearance calculation) /// and ExecutionDomainFix (for arbitrating conflicting domains). /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index ba9763077d09..f7f92248f4ce 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -1,9 +1,8 @@ //===- RegAllocPBQP.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RegAllocRegistry.h b/include/llvm/CodeGen/RegAllocRegistry.h index b518fbb9c9da..9a63674689b3 100644 --- a/include/llvm/CodeGen/RegAllocRegistry.h +++ b/include/llvm/CodeGen/RegAllocRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/RegAllocRegistry.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,29 +22,30 @@ class FunctionPass; //===----------------------------------------------------------------------===// /// -/// RegisterRegAlloc class - Track the registration of register allocators. +/// RegisterRegAllocBase class - Track the registration of register allocators. /// //===----------------------------------------------------------------------===// -class RegisterRegAlloc : public MachinePassRegistryNode<FunctionPass *(*)()> { +template <class SubClass> +class RegisterRegAllocBase : public MachinePassRegistryNode<FunctionPass *(*)()> { public: using FunctionPassCtor = FunctionPass *(*)(); static MachinePassRegistry<FunctionPassCtor> Registry; - RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + RegisterRegAllocBase(const char *N, const char *D, FunctionPassCtor C) : MachinePassRegistryNode(N, D, C) { Registry.Add(this); } - ~RegisterRegAlloc() { Registry.Remove(this); } + ~RegisterRegAllocBase() { Registry.Remove(this); } // Accessors. - RegisterRegAlloc *getNext() const { - return (RegisterRegAlloc *)MachinePassRegistryNode::getNext(); + SubClass *getNext() const { + return static_cast<SubClass *>(MachinePassRegistryNode::getNext()); } - static RegisterRegAlloc *getList() { - return (RegisterRegAlloc *)Registry.getList(); + static SubClass *getList() { + return static_cast<SubClass *>(Registry.getList()); } static FunctionPassCtor getDefault() { return Registry.getDefault(); } @@ -57,6 +57,17 @@ public: } }; +class RegisterRegAlloc : public RegisterRegAllocBase<RegisterRegAlloc> { +public: + RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + : RegisterRegAllocBase(N, D, C) {} +}; + +/// RegisterRegAlloc's global Registry tracks allocator registration. +template <class T> +MachinePassRegistry<RegisterRegAlloc::FunctionPassCtor> +RegisterRegAllocBase<T>::Registry; + } // end namespace llvm #endif // LLVM_CODEGEN_REGALLOCREGISTRY_H diff --git a/include/llvm/CodeGen/Register.h b/include/llvm/CodeGen/Register.h new file mode 100644 index 000000000000..907c1a99e56f --- /dev/null +++ b/include/llvm/CodeGen/Register.h @@ -0,0 +1,60 @@ +//===-- llvm/CodeGen/Register.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_CODEGEN_REGISTER_H +#define LLVM_CODEGEN_REGISTER_H + +#include <cassert> + +namespace llvm { + +/// Wrapper class representing virtual and physical registers. Should be passed +/// by value. +class Register { + unsigned Reg; + +public: + Register(unsigned Val = 0): Reg(Val) {} + + /// Return true if the specified register number is in the virtual register + /// namespace. + bool isVirtual() const { + return int(Reg) < 0; + } + + /// Return true if the specified register number is in the physical register + /// namespace. + bool isPhysical() const { + return int(Reg) > 0; + } + + /// Convert a virtual register number to a 0-based index. The first virtual + /// register in a function will get the index 0. + unsigned virtRegIndex() const { + assert(isVirtual() && "Not a virtual register"); + return Reg & ~(1u << 31); + } + + /// Convert a 0-based index to a virtual register number. + /// This is the inverse operation of VirtReg2IndexFunctor below. + static Register index2VirtReg(unsigned Index) { + return Register(Index | (1u << 31)); + } + + operator unsigned() const { + return Reg; + } + + bool isValid() const { + return Reg != 0; + } +}; + +} + +#endif diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 97113c575815..14af5c4d090d 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -1,9 +1,8 @@ //===- RegisterClassInfo.h - Dynamic Register Class Info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 79054b9e33b7..5bbaa03fd751 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -1,9 +1,8 @@ //===- RegisterPressure.h - Dynamic Register Pressure -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -132,10 +131,6 @@ public: } }; -template <> struct isPodLike<PressureChange> { - static const bool value = true; -}; - /// List of PressureChanges in order of increasing, unique PSetID. /// /// Use a small fixed number, because we can fit more PressureChanges in an diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index b6bd028a8cac..9c48df82f07d 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -1,9 +1,8 @@ //===- RegisterScavenging.h - Machine register scavenging -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -158,10 +157,15 @@ public: /// Returns the scavenged register. /// This is deprecated as it depends on the quality of the kill flags being /// present; Use scavengeRegisterBackwards() instead! + /// + /// If \p AllowSpill is false, fail if a spill is required to make the + /// register available, and return NoRegister. unsigned scavengeRegister(const TargetRegisterClass *RC, - MachineBasicBlock::iterator I, int SPAdj); - unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { - return scavengeRegister(RegClass, MBBI, SPAdj); + MachineBasicBlock::iterator I, int SPAdj, + bool AllowSpill = true); + unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj, + bool AllowSpill = true) { + return scavengeRegister(RegClass, MBBI, SPAdj, AllowSpill); } /// Make a register of the specific register class available from the current @@ -170,9 +174,13 @@ public: /// SPAdj is the stack adjustment due to call frame, it's passed along to /// eliminateFrameIndex(). /// Returns the scavenged register. + /// + /// If \p AllowSpill is false, fail if a spill is required to make the + /// register available, and return NoRegister. unsigned scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, - bool RestoreAfter, int SPAdj); + bool RestoreAfter, int SPAdj, + bool AllowSpill = true); /// Tell the scavenger a register is used. void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll()); diff --git a/include/llvm/CodeGen/RegisterUsageInfo.h b/include/llvm/CodeGen/RegisterUsageInfo.h index efecc61d9c30..33554550b9dc 100644 --- a/include/llvm/CodeGen/RegisterUsageInfo.h +++ b/include/llvm/CodeGen/RegisterUsageInfo.h @@ -1,9 +1,8 @@ //==- RegisterUsageInfo.h - Register Usage Informartion Storage --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index 8d582ee298b6..81587a3170ce 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -1,9 +1,8 @@ //===----- ResourcePriorityQueue.h - A DFA-oriented priority queue -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 28567a1ce437..f71f39e5bf03 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -1,9 +1,8 @@ //===-- CodeGen/RuntimeLibcalls.h - Runtime Library Calls -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SDNodeProperties.td b/include/llvm/CodeGen/SDNodeProperties.td index 83bbab2fdc8d..d25e0bda26a9 100644 --- a/include/llvm/CodeGen/SDNodeProperties.td +++ b/include/llvm/CodeGen/SDNodeProperties.td @@ -1,9 +1,8 @@ //===- SDNodeProperties.td - Common code for DAG isels ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 0870d67db390..e004f3bf2cc1 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/ScheduleDAG.h - Common Base Class -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -239,9 +238,6 @@ class TargetRegisterInfo; void dump(const TargetRegisterInfo *TRI = nullptr) const; }; - template <> - struct isPodLike<SDep> { static const bool value = true; }; - /// Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: @@ -418,7 +414,7 @@ class TargetRegisterInfo; /// dirty. void setDepthToAtLeast(unsigned NewDepth); - /// If NewDepth is greater than this node's depth value, set it to be + /// If NewHeight is greater than this node's height value, set it to be /// the new height value. This also recursively marks predecessor nodes /// dirty. void setHeightToAtLeast(unsigned NewHeight); @@ -695,6 +691,12 @@ class TargetRegisterInfo; std::vector<SUnit> &SUnits; SUnit *ExitSU; + // Have any new nodes been added? + bool Dirty = false; + + // Outstanding added edges, that have not been applied to the ordering. + SmallVector<std::pair<SUnit *, SUnit *>, 16> Updates; + /// Maps topological index to the node number. std::vector<int> Index2Node; /// Maps the node number to its topological index. @@ -714,6 +716,11 @@ class TargetRegisterInfo; /// Assigns the topological index to the node n. void Allocate(int n, int index); + /// Fix the ordering, by either recomputing from scratch or by applying + /// any outstanding updates. Uses a heuristic to estimate what will be + /// cheaper. + void FixOrder(); + public: ScheduleDAGTopologicalSort(std::vector<SUnit> &SUnits, SUnit *ExitSU); @@ -738,11 +745,19 @@ class TargetRegisterInfo; /// added from SUnit \p X to SUnit \p Y. void AddPred(SUnit *Y, SUnit *X); + /// Queues an update to the topological ordering to accommodate an edge to + /// be added from SUnit \p X to SUnit \p Y. + void AddPredQueued(SUnit *Y, SUnit *X); + /// Updates the topological ordering to accommodate an an edge to be /// removed from the specified node \p N from the predecessors of the /// current node \p M. void RemovePred(SUnit *M, SUnit *N); + /// Mark the ordering as temporarily broken, after a new node has been + /// added. + void MarkDirty() { Dirty = true; } + typedef std::vector<int>::iterator iterator; typedef std::vector<int>::const_iterator const_iterator; iterator begin() { return Index2Node.begin(); } diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index daad18125db9..3e3b604acbac 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -1,9 +1,8 @@ //===- ScheduleDAGInstrs.h - MachineInstr Scheduling ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -235,6 +234,11 @@ namespace llvm { /// For an unanalyzable memory access, this Value is used in maps. UndefValue *UnknownValue; + + /// Topo - A topological ordering for SUnits which permits fast IsReachable + /// and similar queries. + ScheduleDAGTopologicalSort Topo; + using DbgValueVector = std::vector<std::pair<MachineInstr *, MachineInstr *>>; /// Remember instruction that precedes DBG_VALUE. @@ -339,6 +343,17 @@ namespace llvm { /// Fixes register kill flags that scheduling has made invalid. void fixupKills(MachineBasicBlock &MBB); + /// True if an edge can be added from PredSU to SuccSU without creating + /// a cycle. + bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); + + /// Add a DAG edge to the given SU with the given predecessor + /// dependence data. + /// + /// \returns true if the edge may be added without creating a cycle OR if an + /// equivalent edge already existed (false indicates failure). + bool addEdge(SUnit *SuccSU, const SDep &PredDep); + protected: void initSUnits(); void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx); diff --git a/include/llvm/CodeGen/ScheduleDAGMutation.h b/include/llvm/CodeGen/ScheduleDAGMutation.h index 5c236427e0b8..d1dd72859a38 100644 --- a/include/llvm/CodeGen/ScheduleDAGMutation.h +++ b/include/llvm/CodeGen/ScheduleDAGMutation.h @@ -1,9 +1,8 @@ //===- ScheduleDAGMutation.h - MachineInstr Scheduling ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index 3ecc033ac35a..d60deab95f5d 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -1,9 +1,8 @@ -//===- ScheduleDAGILP.h - ILP metric for ScheduleDAGInstrs ------*- C++ -*-===// +//===- ScheduleDFS.h - ILP metric for ScheduleDAGInstrs ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index ace4a2d836ca..37590f496ca2 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index fbe559f25556..0ccfaafd9e50 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SchedulerRegistry.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 3f75d108f282..ac67f3008fa7 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -1,9 +1,8 @@ //=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 67fe87fc96af..12a970847021 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -268,6 +267,10 @@ class SelectionDAG { /// Tracks dbg_value and dbg_label information through SDISel. SDDbgInfo *DbgInfo; + using CallSiteInfo = MachineFunction::CallSiteInfo; + using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; + DenseMap<const SDNode *, CallSiteInfo> SDCallSiteInfo; + uint16_t NextPersistentId = 0; public: @@ -298,6 +301,9 @@ public: /// The node N that was updated. virtual void NodeUpdated(SDNode *N); + + /// The node N that was inserted. + virtual void NodeInserted(SDNode *N); }; struct DAGNodeDeletedListener : public DAGUpdateListener { @@ -404,6 +410,7 @@ public: const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetLibraryInfo &getLibInfo() const { return *LibInfo; } const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } + const LegacyDivergenceAnalysis *getDivergenceAnalysis() const { return DA; } LLVMContext *getContext() const {return Context; } OptimizationRemarkEmitter &getORE() const { return *ORE; } @@ -573,6 +580,9 @@ public: bool isTarget = false, bool isOpaque = false); SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget = false); + SDValue getShiftAmountConstant(uint64_t Val, EVT VT, const SDLoc &DL, + bool LegalTypes = true); + SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque = false) { return getConstant(Val, DL, VT, true, isOpaque); @@ -789,6 +799,16 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the integer type VT, by + /// either truncating it or performing either zero or sign extension as + /// appropriate extension for the pointer's semantics. + SDValue getPtrExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + + /// Return the expression required to extend the Op as a pointer value + /// assuming it was the smaller SrcTy value. This may be either a zero extend + /// or a sign extend. + SDValue getPtrExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the integer type VT, /// by using an extension appropriate for the target's /// BooleanContent for type OpVT or truncating it. @@ -971,6 +991,10 @@ public: /// Try to simplify a shift into 1 of its operands or a constant. SDValue simplifyShift(SDValue X, SDValue Y); + /// Try to simplify a floating-point binary operation into 1 of its operands + /// or a constant. + SDValue simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y); + /// VAArg produces a result and token chain, and takes a pointer /// and a source value as input. SDValue getVAArg(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, @@ -982,21 +1006,11 @@ public: /// a success flag (initially i1), and a chain. SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDVTList VTs, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, - unsigned Alignment, AtomicOrdering SuccessOrdering, - AtomicOrdering FailureOrdering, - SyncScope::ID SSID); - SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT, - SDVTList VTs, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO); /// Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Val, const Value *PtrVal, - unsigned Alignment, AtomicOrdering Ordering, - SyncScope::ID SSID); - SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO); /// Gets a node for an atomic op, produces result and chain and @@ -1021,12 +1035,19 @@ public: unsigned Align = 0, MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore, - unsigned Size = 0); + unsigned Size = 0, + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef<SDValue> Ops, EVT MemVT, MachineMemOperand *MMO); + /// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends + /// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between + /// offsets `Offset` and `Offset + Size`. + SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain, + int FrameIndex, int64_t Size, int64_t Offset = -1); + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl); @@ -1154,6 +1175,11 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); + /// Creates a new TokenFactor containing \p Vals. If \p Vals contains 64k + /// values or more, move values into new TokenFactors in 64k-1 blocks, until + /// the final TokenFactor has less than 64k operands. + SDValue getTokenFactor(const SDLoc &DL, SmallVectorImpl<SDValue> &Vals); + /// *Mutate* the specified machine node's memory references to the provided /// list. void setNodeMemRefs(MachineSDNode *N, @@ -1358,21 +1384,20 @@ public: /// with this SelectionDAG. bool hasDebugValues() const { return !DbgInfo->empty(); } - SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); } - SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); } + SDDbgInfo::DbgIterator DbgBegin() const { return DbgInfo->DbgBegin(); } + SDDbgInfo::DbgIterator DbgEnd() const { return DbgInfo->DbgEnd(); } - SDDbgInfo::DbgIterator ByvalParmDbgBegin() { + SDDbgInfo::DbgIterator ByvalParmDbgBegin() const { return DbgInfo->ByvalParmDbgBegin(); } - - SDDbgInfo::DbgIterator ByvalParmDbgEnd() { + SDDbgInfo::DbgIterator ByvalParmDbgEnd() const { return DbgInfo->ByvalParmDbgEnd(); } - SDDbgInfo::DbgLabelIterator DbgLabelBegin() { + SDDbgInfo::DbgLabelIterator DbgLabelBegin() const { return DbgInfo->DbgLabelBegin(); } - SDDbgInfo::DbgLabelIterator DbgLabelEnd() { + SDDbgInfo::DbgLabelIterator DbgLabelEnd() const { return DbgInfo->DbgLabelEnd(); } @@ -1395,27 +1420,42 @@ public: const SDNode *N2); SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, - SDNode *Cst1, SDNode *Cst2); + SDNode *N1, SDNode *N2); SDValue FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, - const ConstantSDNode *Cst1, - const ConstantSDNode *Cst2); + const ConstantSDNode *C1, + const ConstantSDNode *C2); SDValue FoldConstantVectorArithmetic(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef<SDValue> Ops, const SDNodeFlags Flags = SDNodeFlags()); + /// Fold floating-point operations with 2 operands when both operands are + /// constants and/or undefined. + SDValue foldConstantFPMath(unsigned Opcode, const SDLoc &DL, EVT VT, + SDValue N1, SDValue N2); + /// Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, const SDLoc &dl); - /// See if the specified operand can be simplified with the knowledge that only - /// the bits specified by Mask are used. If so, return the simpler operand, - /// otherwise return a null SDValue. + /// See if the specified operand can be simplified with the knowledge that + /// only the bits specified by DemandedBits are used. If so, return the + /// simpler operand, otherwise return a null SDValue. + /// + /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can + /// simplify nodes with multiple uses more aggressively.) + SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits); + + /// See if the specified operand can be simplified with the knowledge that + /// only the bits specified by DemandedBits are used in the elements specified + /// by DemandedElts. If so, return the simpler operand, otherwise return a + /// null SDValue. /// /// (This exists alongside SimplifyDemandedBits because GetDemandedBits can /// simplify nodes with multiple uses more aggressively.) - SDValue GetDemandedBits(SDValue V, const APInt &Mask); + SDValue GetDemandedBits(SDValue V, const APInt &DemandedBits, + const APInt &DemandedElts); /// Return true if the sign bit of Op is known to be zero. /// We use this predicate to simplify operations downstream. @@ -1424,8 +1464,19 @@ public: /// Return true if 'Op & Mask' is known to be zero. We /// use this predicate to simplify operations downstream. Op and Mask are /// known to be the same type. - bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) - const; + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, + unsigned Depth = 0) const; + + /// Return true if 'Op & Mask' is known to be zero in DemandedElts. We + /// use this predicate to simplify operations downstream. Op and Mask are + /// known to be the same type. + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, + const APInt &DemandedElts, unsigned Depth = 0) const; + + /// Return true if '(Op & Mask) == Mask'. + /// Op and Mask are known to be the same type. + bool MaskedValueIsAllOnes(SDValue Op, const APInt &Mask, + unsigned Depth = 0) const; /// Determine which bits of Op are known to be either zero or one and return /// them in Known. For vectors, the known bits are those that are shared by @@ -1525,6 +1576,13 @@ public: /// Test whether \p V has a splatted value. bool isSplatValue(SDValue V, bool AllowUndefs = false); + /// If V is a splatted value, return the source vector and its splat index. + SDValue getSplatSourceVector(SDValue V, int &SplatIndex); + + /// If V is a splat vector, return its scalar source operand by extracting + /// that element from the source vector. + SDValue getSplatValue(SDValue V); + /// Match a binop + shuffle pyramid that represents a horizontal reduction /// over the elements of a vector starting from the EXTRACT_VECTOR_ELT node /p /// Extract. The reduction must use one of the opcodes listed in /p @@ -1542,6 +1600,11 @@ public: /// vector op and fill the end of the resulting vector with UNDEFS. SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); + /// Like UnrollVectorOp(), but for the [US](ADD|SUB|MUL)O family of opcodes. + /// This is a separate function because those opcodes have two results. + std::pair<SDValue, SDValue> UnrollVectorOverflowOp(SDNode *N, + unsigned ResNE = 0); + /// Return true if loads are next to each other and can be /// merged. Check that both are nonvolatile and if LD is loading /// 'Bytes' bytes from a location that is 'Dist' units away from the @@ -1576,6 +1639,9 @@ public: return SplitVector(N->getOperand(OpNo), SDLoc(N)); } + /// Widen the vector up to the next power of two using INSERT_SUBVECTOR. + SDValue WidenVector(const SDValue &N, const SDLoc &DL); + /// Append the extracted elements from Start to Count out of the vector Op /// in Args. If Count is 0, all of the elements will be extracted. void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args, @@ -1597,6 +1663,17 @@ public: isConstantFPBuildVectorOrConstantFP(N); } + void addCallSiteInfo(const SDNode *CallNode, CallSiteInfoImpl &&CallInfo) { + SDCallSiteInfo[CallNode] = std::move(CallInfo); + } + + CallSiteInfo getSDCallSiteInfo(const SDNode *CallNode) { + auto I = SDCallSiteInfo.find(CallNode); + if (I != SDCallSiteInfo.end()) + return std::move(I->second); + return CallSiteInfo(); + } + private: void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); diff --git a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h index 2b2c48d57bc0..4ee58333495b 100644 --- a/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ b/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -1,9 +1,8 @@ //===- SelectionDAGAddressAnalysis.h - DAG Address Analysis -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -34,11 +33,13 @@ class BaseIndexOffset { private: SDValue Base; SDValue Index; - int64_t Offset = 0; + Optional<int64_t> Offset; bool IsIndexSignExt = false; public: BaseIndexOffset() = default; + BaseIndexOffset(SDValue Base, SDValue Index, bool IsIndexSignExt) + : Base(Base), Index(Index), Offset(), IsIndexSignExt(IsIndexSignExt) {} BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset, bool IsIndexSignExt) : Base(Base), Index(Index), Offset(Offset), @@ -48,6 +49,13 @@ public: SDValue getBase() const { return Base; } SDValue getIndex() { return Index; } SDValue getIndex() const { return Index; } + bool hasValidOffset() const { return Offset.hasValue(); } + + // Returns true if `Other` and `*this` are both some offset from the same base + // pointer. In that case, `Off` is set to the offset between `*this` and + // `Other` (negative if `Other` is before `*this`). + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off) const; bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG) const { @@ -55,11 +63,31 @@ public: return equalBaseIndex(Other, DAG, Off); } - bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) const; + // Returns true if `Other` (with size `OtherSize`) can be proven to be fully + // contained in `*this` (with size `Size`). + bool contains(const SelectionDAG &DAG, int64_t BitSize, + const BaseIndexOffset &Other, int64_t OtherBitSize, + int64_t &BitOffset) const; + + bool contains(const SelectionDAG &DAG, int64_t BitSize, + const BaseIndexOffset &Other, int64_t OtherBitSize) const { + int64_t BitOffset; + return contains(DAG, BitSize, Other, OtherBitSize, BitOffset); + } + + // Returns true `Op0` and `Op1` can be proven to alias/not alias, in + // which case `IsAlias` is set to true/false. + static bool computeAliasing(const SDNode *Op0, + const Optional<int64_t> NumBytes0, + const SDNode *Op1, + const Optional<int64_t> NumBytes1, + const SelectionDAG &DAG, bool &IsAlias); + + /// Parses tree in N for base, index, offset addresses. + static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG); - /// Parses tree in Ptr for base, index, offset addresses. - static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG); + void print(raw_ostream& OS) const; + void dump() const; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 6758c55c696a..147c325342fc 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,6 +34,7 @@ namespace llvm { class TargetLibraryInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; + class SwiftErrorValueTracking; class GCFunctionInfo; class ScheduleDAGSDNodes; class LoadInst; @@ -46,6 +46,7 @@ public: TargetMachine &TM; const TargetLibraryInfo *LibInfo; FunctionLoweringInfo *FuncInfo; + SwiftErrorValueTracking *SwiftError; MachineFunction *MF; MachineRegisterInfo *RegInfo; SelectionDAG *CurDAG; @@ -144,10 +145,12 @@ public: OPC_CheckInteger, OPC_CheckChild0Integer, OPC_CheckChild1Integer, OPC_CheckChild2Integer, OPC_CheckChild3Integer, OPC_CheckChild4Integer, - OPC_CheckCondCode, + OPC_CheckCondCode, OPC_CheckChild2CondCode, OPC_CheckValueType, OPC_CheckComplexPat, OPC_CheckAndImm, OPC_CheckOrImm, + OPC_CheckImmAllOnesV, + OPC_CheckImmAllZerosV, OPC_CheckFoldableChainNode, OPC_EmitInteger, @@ -303,7 +306,7 @@ public: private: // Calls to these functions are generated by tblgen. - void Select_INLINEASM(SDNode *N); + void Select_INLINEASM(SDNode *N, bool Branch); void Select_READ_REGISTER(SDNode *Op); void Select_WRITE_REGISTER(SDNode *Op); void Select_UNDEF(SDNode *N); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 10f284179084..5aab9643e09d 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -184,6 +183,7 @@ public: inline unsigned getNumOperands() const; inline const SDValue &getOperand(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const; + inline const APInt &getConstantOperandAPInt(unsigned i) const; inline bool isTargetMemoryOpcode() const; inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; @@ -232,7 +232,6 @@ template<> struct DenseMapInfo<SDValue> { return LHS == RHS; } }; -template <> struct isPodLike<SDValue> { static const bool value = true; }; /// Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. @@ -369,6 +368,13 @@ private: bool ApproximateFuncs : 1; bool AllowReassociation : 1; + // We assume instructions do not raise floating-point exceptions by default, + // and only those marked explicitly may do so. We could choose to represent + // this via a positive "FPExcept" flags like on the MI level, but having a + // negative "NoFPExcept" flag here (that defaults to true) makes the flag + // intersection logic more straightforward. + bool NoFPExcept : 1; + public: /// Default constructor turns off all optimization flags. SDNodeFlags() @@ -376,7 +382,7 @@ public: Exact(false), NoNaNs(false), NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false), AllowContract(false), ApproximateFuncs(false), - AllowReassociation(false) {} + AllowReassociation(false), NoFPExcept(true) {} /// Propagate the fast-math-flags from an IR FPMathOperator. void copyFMF(const FPMathOperator &FPMO) { @@ -439,6 +445,10 @@ public: setDefined(); AllowReassociation = b; } + void setFPExcept(bool b) { + setDefined(); + NoFPExcept = !b; + } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } @@ -452,9 +462,10 @@ public: bool hasAllowContract() const { return AllowContract; } bool hasApproximateFuncs() const { return ApproximateFuncs; } bool hasAllowReassociation() const { return AllowReassociation; } + bool hasFPExcept() const { return !NoFPExcept; } bool isFast() const { - return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && + return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && NoFPExcept && AllowContract && ApproximateFuncs && AllowReassociation; } @@ -474,6 +485,7 @@ public: AllowContract &= Flags.AllowContract; ApproximateFuncs &= Flags.ApproximateFuncs; AllowReassociation &= Flags.AllowReassociation; + NoFPExcept &= Flags.NoFPExcept; } }; @@ -489,6 +501,17 @@ protected: // SubclassData. These are designed to fit within a uint16_t so they pack // with NodeType. +#if defined(_AIX) && (!defined(__GNUC__) || defined(__ibmxl__)) +// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words +// and give the `pack` pragma push semantics. +#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)") +#define END_TWO_BYTE_PACK() _Pragma("pack(pop)") +#else +#define BEGIN_TWO_BYTE_PACK() +#define END_TWO_BYTE_PACK() +#endif + +BEGIN_TWO_BYTE_PACK() class SDNodeBitfields { friend class SDNode; friend class MemIntrinsicSDNode; @@ -561,6 +584,9 @@ protected: LoadSDNodeBitfields LoadSDNodeBits; StoreSDNodeBitfields StoreSDNodeBits; }; +END_TWO_BYTE_PACK() +#undef BEGIN_TWO_BYTE_PACK +#undef END_TWO_BYTE_PACK // RawSDNodeBits must cover the entirety of the union. This means that all of // the union's members must have size <= RawSDNodeBits. We write the RHS as @@ -678,6 +704,8 @@ public: case ISD::STRICT_FFLOOR: case ISD::STRICT_FROUND: case ISD::STRICT_FTRUNC: + case ISD::STRICT_FP_ROUND: + case ISD::STRICT_FP_EXTEND: return true; } } @@ -898,9 +926,17 @@ public: /// Return the number of values used by this operation. unsigned getNumOperands() const { return NumOperands; } + /// Return the maximum number of operands that a SDNode can hold. + static constexpr size_t getMaxNumOperands() { + return std::numeric_limits<decltype(SDNode::NumOperands)>::max(); + } + /// Helper method returns the integer value of a ConstantSDNode operand. inline uint64_t getConstantOperandVal(unsigned Num) const; + /// Helper method returns the APInt of a ConstantSDNode operand. + inline const APInt &getConstantOperandAPInt(unsigned Num) const; + const SDValue &getOperand(unsigned Num) const { assert(Num < NumOperands && "Invalid child # of SDNode!"); return OperandList[Num]; @@ -1128,6 +1164,10 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { return Node->getConstantOperandVal(i); } +inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const { + return Node->getConstantOperandAPInt(i); +} + inline bool SDValue::isTargetOpcode() const { return Node->isTargetOpcode(); } @@ -1356,6 +1396,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD_FADD || + N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || N->getOpcode() == ISD::MLOAD || @@ -1372,7 +1414,10 @@ class AtomicSDNode : public MemSDNode { public: AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL, EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {} + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) || + MMO->isAtomic()) && "then why are we using an AtomicSDNode?"); + } const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } @@ -1408,6 +1453,8 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->getOpcode() == ISD::ATOMIC_LOAD_FADD || + N->getOpcode() == ISD::ATOMIC_LOAD_FSUB || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE; } @@ -1467,14 +1514,16 @@ public: bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() const { + int getSplatIndex() const { assert(isSplat() && "Cannot get splat index for non-splat!"); EVT VT = getValueType(0); - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) if (Mask[i] >= 0) return Mask[i]; - } - llvm_unreachable("Splat with all undef indices?"); + + // We can choose any index value here and be correct because all elements + // are undefined. Return 0 for better potential for callers to simplify. + return 0; } static bool isSplatMask(const int *Mask, EVT VT); @@ -1536,6 +1585,10 @@ uint64_t SDNode::getConstantOperandVal(unsigned Num) const { return cast<ConstantSDNode>(getOperand(Num))->getZExtValue(); } +const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const { + return cast<ConstantSDNode>(getOperand(Num))->getAPIntValue(); +} + class ConstantFPSDNode : public SDNode { friend class SelectionDAG; @@ -1603,20 +1656,36 @@ SDValue peekThroughBitcasts(SDValue V); /// If \p V is not a bitcasted one-use value, it is returned as-is. SDValue peekThroughOneUseBitcasts(SDValue V); +/// Return the non-extracted vector source operand of \p V if it exists. +/// If \p V is not an extracted subvector, it is returned as-is. +SDValue peekThroughExtractSubvectors(SDValue V); + /// Returns true if \p V is a bitwise not operation. Assumes that an all ones /// constant is canonicalized to be operand 1. -bool isBitwiseNot(SDValue V); +bool isBitwiseNot(SDValue V, bool AllowUndefs = false); /// Returns the SDNode if it is a constant splat BuildVector or constant int. -ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false); +ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false, + bool AllowTruncation = false); + +/// Returns the SDNode if it is a demanded constant splat BuildVector or +/// constant int. +ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts, + bool AllowUndefs = false, + bool AllowTruncation = false); /// Returns the SDNode if it is a constant splat BuildVector or constant float. ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false); +/// Returns the SDNode if it is a demanded constant splat BuildVector or +/// constant float. +ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts, + bool AllowUndefs = false); + /// Return true if the value is a constant 0 integer or a splatted vector of -/// a constant 0 integer (with no undefs). +/// a constant 0 integer (with no undefs by default). /// Build vector implicit truncation is not an issue for null values. -bool isNullOrNullSplat(SDValue V); +bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false); /// Return true if the value is a constant 1 integer or a splatted vector of a /// constant 1 integer (with no undefs). @@ -1673,6 +1742,38 @@ public: } }; +/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate +/// the offet and size that are started/ended in the underlying FrameIndex. +class LifetimeSDNode : public SDNode { + friend class SelectionDAG; + int64_t Size; + int64_t Offset; // -1 if offset is unknown. + + LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, + SDVTList VTs, int64_t Size, int64_t Offset) + : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {} +public: + int64_t getFrameIndex() const { + return cast<FrameIndexSDNode>(getOperand(1))->getIndex(); + } + + bool hasOffset() const { return Offset >= 0; } + int64_t getOffset() const { + assert(hasOffset() && "offset is unknown"); + return Offset; + } + int64_t getSize() const { + assert(hasOffset() && "offset is unknown"); + return Size; + } + + // Methods to support isa and dyn_cast + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LIFETIME_START || + N->getOpcode() == ISD::LIFETIME_END; + } +}; + class JumpTableSDNode : public SDNode { friend class SelectionDAG; @@ -1818,12 +1919,31 @@ public: unsigned MinSplatBits = 0, bool isBigEndian = false) const; + /// Returns the demanded splatted value or a null value if this is not a + /// splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + SDValue getSplatValue(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted value or a null value if this is not a splat. /// /// If passed a non-null UndefElements bitvector, it will resize it to match /// the vector width and set the bits where elements are undef. SDValue getSplatValue(BitVector *UndefElements = nullptr) const; + /// Returns the demanded splatted constant or null if this is not a constant + /// splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantSDNode * + getConstantSplatNode(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted constant or null if this is not a constant /// splat. /// @@ -1832,6 +1952,16 @@ public: ConstantSDNode * getConstantSplatNode(BitVector *UndefElements = nullptr) const; + /// Returns the demanded splatted constant FP or null if this is not a + /// constant FP splat. + /// + /// The DemandedElts mask indicates the elements that must be in the splat. + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantFPSDNode * + getConstantFPSplatNode(const APInt &DemandedElts, + BitVector *UndefElements = nullptr) const; + /// Returns the splatted constant FP or null if this is not a constant /// FP splat. /// @@ -1956,8 +2086,10 @@ class LabelSDNode : public SDNode { MCSymbol *Label; - LabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L) - : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {} + LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L) + : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) { + assert(LabelSDNode::classof(this) && "not a label opcode"); + } public: MCSymbol *getLabel() const { return Label; } @@ -2049,6 +2181,8 @@ public: : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { LSBaseSDNodeBits.AddressingMode = AM; assert(getAddressingMode() == AM && "Value truncated"); + assert((!MMO->isAtomic() || MMO->isVolatile()) && + "use an AtomicSDNode instead for non-volatile atomics"); } const SDValue &getOffset() const { @@ -2473,18 +2607,6 @@ namespace ISD { cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; } - /// Return true if the node is a math/logic binary operator. This corresponds - /// to the IR function of the same name. - inline bool isBinaryOp(const SDNode *N) { - auto Op = N->getOpcode(); - return (Op == ISD::ADD || Op == ISD::SUB || Op == ISD::MUL || - Op == ISD::AND || Op == ISD::OR || Op == ISD::XOR || - Op == ISD::SHL || Op == ISD::SRL || Op == ISD::SRA || - Op == ISD::SDIV || Op == ISD::UDIV || Op == ISD::SREM || - Op == ISD::UREM || Op == ISD::FADD || Op == ISD::FSUB || - Op == ISD::FMUL || Op == ISD::FDIV || Op == ISD::FREM); - } - /// Attempt to match a unary predicate against a scalar/splat constant or /// every element of a constant BUILD_VECTOR. /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. @@ -2495,10 +2617,11 @@ namespace ISD { /// Attempt to match a binary predicate against a pair of scalar/splat /// constants or every element of a pair of constant BUILD_VECTORs. /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match. + /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match. bool matchBinaryPredicate( SDValue LHS, SDValue RHS, std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match, - bool AllowUndefs = false); + bool AllowUndefs = false, bool AllowTypeMismatch = false); } // end namespace ISD } // end namespace llvm diff --git a/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/include/llvm/CodeGen/SelectionDAGTargetInfo.h index 45c1df48a5e6..6f6a9a5ae269 100644 --- a/include/llvm/CodeGen/SelectionDAGTargetInfo.h +++ b/include/llvm/CodeGen/SelectionDAGTargetInfo.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/SelectionDAGTargetInfo.h - SelectionDAG Info --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -148,6 +147,14 @@ public: return std::make_pair(SDValue(), SDValue()); } + virtual SDValue EmitTargetCodeForSetTag(SelectionDAG &DAG, const SDLoc &dl, + SDValue Chain, SDValue Addr, + SDValue Size, + MachinePointerInfo DstPtrInfo, + bool ZeroData) const { + return SDValue(); + } + // Return true when the decision to generate FMA's (or FMS, FMLA etc) rather // than FMUL and ADD is delegated to the machine combiner. virtual bool generateFMAsInMachineCombiner(CodeGenOpt::Level OptLevel) const { diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 8c8a7be459fd..2b32a4d30dff 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/SlotIndexes.h - Slot indexes representation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -302,8 +301,6 @@ class raw_ostream; } }; - template <> struct isPodLike<SlotIndex> { static const bool value = true; }; - inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { li.print(os); return os; @@ -311,20 +308,6 @@ class raw_ostream; using IdxMBBPair = std::pair<SlotIndex, MachineBasicBlock *>; - inline bool operator<(SlotIndex V, const IdxMBBPair &IM) { - return V < IM.first; - } - - inline bool operator<(const IdxMBBPair &IM, SlotIndex V) { - return IM.first < V; - } - - struct Idx2MBBCompare { - bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const { - return LHS.first < RHS.first; - } - }; - /// SlotIndexes pass. /// /// This pass assigns indexes to each instruction. @@ -336,10 +319,6 @@ class raw_ostream; using IndexList = ilist<IndexListEntry>; IndexList indexList; -#ifdef EXPENSIVE_CHECKS - IndexList graveyardList; -#endif // EXPENSIVE_CHECKS - MachineFunction *mf; using Mi2IndexMap = DenseMap<const MachineInstr *, SlotIndex>; @@ -368,7 +347,7 @@ class raw_ostream; public: static char ID; - SlotIndexes() : MachineFunctionPass(ID) { + SlotIndexes() : MachineFunctionPass(ID), mf(nullptr) { initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); } @@ -385,9 +364,6 @@ class raw_ostream; /// Dump the indexes. void dump() const; - /// Renumber the index list, providing space for new instructions. - void renumberIndexes(); - /// Repair indexes after adding and removing instructions. void repairIndexesInRange(MachineBasicBlock *MBB, MachineBasicBlock::iterator Begin, @@ -516,7 +492,9 @@ class raw_ostream; /// Move iterator to the next IdxMBBPair where the SlotIndex is greater or /// equal to \p To. MBBIndexIterator advanceMBBIndex(MBBIndexIterator I, SlotIndex To) const { - return std::lower_bound(I, idx2MBBMap.end(), To); + return std::partition_point( + I, idx2MBBMap.end(), + [=](const IdxMBBPair &IM) { return IM.first < To; }); } /// Get an iterator pointing to the IdxMBBPair with the biggest SlotIndex @@ -552,29 +530,6 @@ class raw_ostream; return J->second; } - /// Returns the MBB covering the given range, or null if the range covers - /// more than one basic block. - MachineBasicBlock* getMBBCoveringRange(SlotIndex start, SlotIndex end) const { - - assert(start < end && "Backwards ranges not allowed."); - MBBIndexIterator itr = findMBBIndex(start); - if (itr == MBBIndexEnd()) { - itr = std::prev(itr); - return itr->second; - } - - // Check that we don't cross the boundary into this block. - if (itr->first < end) - return nullptr; - - itr = std::prev(itr); - - if (itr->first <= start) - return itr->second; - - return nullptr; - } - /// Insert the given machine instruction into the mapping. Returns the /// assigned index. /// If Late is set and there are null indexes between mi's neighboring @@ -680,33 +635,7 @@ class raw_ostream; idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); renumberIndexes(newItr); - llvm::sort(idx2MBBMap, Idx2MBBCompare()); - } - - /// Free the resources that were required to maintain a SlotIndex. - /// - /// Once an index is no longer needed (for instance because the instruction - /// at that index has been moved), the resources required to maintain the - /// index can be relinquished to reduce memory use and improve renumbering - /// performance. Any remaining SlotIndex objects that point to the same - /// index are left 'dangling' (much the same as a dangling pointer to a - /// freed object) and should not be accessed, except to destruct them. - /// - /// Like dangling pointers, access to dangling SlotIndexes can cause - /// painful-to-track-down bugs, especially if the memory for the index - /// previously pointed to has been re-used. To detect dangling SlotIndex - /// bugs, build with EXPENSIVE_CHECKS=1. This will cause "erased" indexes to - /// be retained in a graveyard instead of being freed. Operations on indexes - /// in the graveyard will trigger an assertion. - void eraseIndex(SlotIndex index) { - IndexListEntry *entry = index.listEntry(); -#ifdef EXPENSIVE_CHECKS - indexList.remove(entry); - graveyardList.push_back(entry); - entry->setPoison(); -#else - indexList.erase(entry); -#endif + llvm::sort(idx2MBBMap, less_first()); } }; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 8be9ae378557..d7d88de6f682 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,9 +1,8 @@ //===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h index a506ac636a17..2bdf4425e24a 100644 --- a/include/llvm/CodeGen/StackProtector.h +++ b/include/llvm/CodeGen/StackProtector.h @@ -1,9 +1,8 @@ //===- StackProtector.h - Stack Protector Insertion -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -62,12 +61,6 @@ private: /// protection when -fstack-protection is used. unsigned SSPBufferSize = 0; - /// VisitedPHIs - The set of PHI nodes visited when determining - /// if a variable's reference has been taken. This set - /// is maintained to ensure we don't visit the same PHI node multiple - /// times. - SmallPtrSet<const PHINode *, 16> VisitedPHIs; - // A prologue is generated. bool HasPrologue = false; diff --git a/include/llvm/CodeGen/SwiftErrorValueTracking.h b/include/llvm/CodeGen/SwiftErrorValueTracking.h new file mode 100644 index 000000000000..fb7a12853c09 --- /dev/null +++ b/include/llvm/CodeGen/SwiftErrorValueTracking.h @@ -0,0 +1,110 @@ +//===- SwiftErrorValueTracking.h - Track swifterror VReg vals --*- 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 implements a limited mem2reg-like analysis to promote uses of function +// arguments and allocas marked with swiftalloc from memory into virtual +// registers tracked by this class. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFTERRORVALUETRACKING_H +#define SWIFTERRORVALUETRACKING_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Register.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DebugLoc.h" +#include <functional> +#include <type_traits> +#include <utility> + + +namespace llvm { + class Function; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class TargetInstrInfo; + class TargetLowering; + +class SwiftErrorValueTracking { + // Some useful objects to reduce the number of function arguments needed. + MachineFunction *MF; + const Function *Fn; + const TargetLowering *TLI; + const TargetInstrInfo *TII; + + /// A map from swifterror value in a basic block to the virtual register it is + /// currently represented by. + DenseMap<std::pair<const MachineBasicBlock *, const Value *>, Register> + VRegDefMap; + + /// A list of upward exposed vreg uses that need to be satisfied by either a + /// copy def or a phi node at the beginning of the basic block representing + /// the predecessor(s) swifterror value. + DenseMap<std::pair<const MachineBasicBlock *, const Value *>, Register> + VRegUpwardsUse; + + /// A map from instructions that define/use a swifterror value to the virtual + /// register that represents that def/use. + llvm::DenseMap<PointerIntPair<const Instruction *, 1, bool>, Register> + VRegDefUses; + + /// The swifterror argument of the current function. + const Value *SwiftErrorArg; + + using SwiftErrorValues = SmallVector<const Value*, 1>; + /// A function can only have a single swifterror argument. And if it does + /// have a swifterror argument, it must be the first entry in + /// SwiftErrorVals. + SwiftErrorValues SwiftErrorVals; + +public: + /// Initialize data structures for specified new function. + void setFunction(MachineFunction &MF); + + /// Get the (unique) function argument that was marked swifterror, or nullptr + /// if this function has no swifterror args. + const Value *getFunctionArg() const { + return SwiftErrorArg; + } + + /// Get or create the swifterror value virtual register in + /// VRegDefMap for this basic block. + Register getOrCreateVReg(const MachineBasicBlock *, const Value *); + + /// Set the swifterror virtual register in the VRegDefMap for this + /// basic block. + void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register); + + /// Get or create the swifterror value virtual register for a def of a + /// swifterror by an instruction. + Register getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Get or create the swifterror value virtual register for a use of a + /// swifterror by an instruction. + Register getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Create initial definitions of swifterror values in the entry block of the + /// current function. + bool createEntriesInEntryBlock(DebugLoc DbgLoc); + + /// Propagate assigned swifterror vregs through a function, synthesizing PHI + /// nodes when needed to maintain consistency. + void propagateVRegs(); + + void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End); +}; + +} + +#endif diff --git a/include/llvm/CodeGen/SwitchLoweringUtils.h b/include/llvm/CodeGen/SwitchLoweringUtils.h new file mode 100644 index 000000000000..62134dc792f7 --- /dev/null +++ b/include/llvm/CodeGen/SwitchLoweringUtils.h @@ -0,0 +1,297 @@ +//===- SwitchLoweringUtils.h - Switch Lowering ------------------*- 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_CODEGEN_SWITCHLOWERINGUTILS_H +#define LLVM_CODEGEN_SWITCHLOWERINGUTILS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/IR/Constants.h" +#include "llvm/Support/BranchProbability.h" + +namespace llvm { + +class FunctionLoweringInfo; +class MachineBasicBlock; + +namespace SwitchCG { + +enum CaseClusterKind { + /// A cluster of adjacent case labels with the same destination, or just one + /// case. + CC_Range, + /// A cluster of cases suitable for jump table lowering. + CC_JumpTable, + /// A cluster of cases suitable for bit test lowering. + CC_BitTests +}; + +/// A cluster of case labels. +struct CaseCluster { + CaseClusterKind Kind; + const ConstantInt *Low, *High; + union { + MachineBasicBlock *MBB; + unsigned JTCasesIndex; + unsigned BTCasesIndex; + }; + BranchProbability Prob; + + static CaseCluster range(const ConstantInt *Low, const ConstantInt *High, + MachineBasicBlock *MBB, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_Range; + C.Low = Low; + C.High = High; + C.MBB = MBB; + C.Prob = Prob; + return C; + } + + static CaseCluster jumpTable(const ConstantInt *Low, const ConstantInt *High, + unsigned JTCasesIndex, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_JumpTable; + C.Low = Low; + C.High = High; + C.JTCasesIndex = JTCasesIndex; + C.Prob = Prob; + return C; + } + + static CaseCluster bitTests(const ConstantInt *Low, const ConstantInt *High, + unsigned BTCasesIndex, BranchProbability Prob) { + CaseCluster C; + C.Kind = CC_BitTests; + C.Low = Low; + C.High = High; + C.BTCasesIndex = BTCasesIndex; + C.Prob = Prob; + return C; + } +}; + +using CaseClusterVector = std::vector<CaseCluster>; +using CaseClusterIt = CaseClusterVector::iterator; + +/// Sort Clusters and merge adjacent cases. +void sortAndRangeify(CaseClusterVector &Clusters); + +struct CaseBits { + uint64_t Mask = 0; + MachineBasicBlock *BB = nullptr; + unsigned Bits = 0; + BranchProbability ExtraProb; + + CaseBits() = default; + CaseBits(uint64_t mask, MachineBasicBlock *bb, unsigned bits, + BranchProbability Prob) + : Mask(mask), BB(bb), Bits(bits), ExtraProb(Prob) {} +}; + +using CaseBitsVector = std::vector<CaseBits>; + +/// This structure is used to communicate between SelectionDAGBuilder and +/// SDISel for the code generation of additional basic blocks needed by +/// multi-case switch statements. +struct CaseBlock { + // For the GISel interface. + struct PredInfoPair { + CmpInst::Predicate Pred; + // Set when no comparison should be emitted. + bool NoCmp; + }; + union { + // The condition code to use for the case block's setcc node. + // Besides the integer condition codes, this can also be SETTRUE, in which + // case no comparison gets emitted. + ISD::CondCode CC; + struct PredInfoPair PredInfo; + }; + + // The LHS/MHS/RHS of the comparison to emit. + // Emit by default LHS op RHS. MHS is used for range comparisons: + // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). + const Value *CmpLHS, *CmpMHS, *CmpRHS; + + // The block to branch to if the setcc is true/false. + MachineBasicBlock *TrueBB, *FalseBB; + + // The block into which to emit the code for the setcc and branches. + MachineBasicBlock *ThisBB; + + /// The debug location of the instruction this CaseBlock was + /// produced from. + SDLoc DL; + DebugLoc DbgLoc; + + // Branch weights. + BranchProbability TrueProb, FalseProb; + + // Constructor for SelectionDAG. + CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs, + const Value *cmpmiddle, MachineBasicBlock *truebb, + MachineBasicBlock *falsebb, MachineBasicBlock *me, SDLoc dl, + BranchProbability trueprob = BranchProbability::getUnknown(), + BranchProbability falseprob = BranchProbability::getUnknown()) + : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), + TrueBB(truebb), FalseBB(falsebb), ThisBB(me), DL(dl), + TrueProb(trueprob), FalseProb(falseprob) {} + + // Constructor for GISel. + CaseBlock(CmpInst::Predicate pred, bool nocmp, const Value *cmplhs, + const Value *cmprhs, const Value *cmpmiddle, + MachineBasicBlock *truebb, MachineBasicBlock *falsebb, + MachineBasicBlock *me, DebugLoc dl, + BranchProbability trueprob = BranchProbability::getUnknown(), + BranchProbability falseprob = BranchProbability::getUnknown()) + : PredInfo({pred, nocmp}), CmpLHS(cmplhs), CmpMHS(cmpmiddle), + CmpRHS(cmprhs), TrueBB(truebb), FalseBB(falsebb), ThisBB(me), + DbgLoc(dl), TrueProb(trueprob), FalseProb(falseprob) {} +}; + +struct JumpTable { + /// The virtual register containing the index of the jump table entry + /// to jump to. + unsigned Reg; + /// The JumpTableIndex for this jump table in the function. + unsigned JTI; + /// The MBB into which to emit the code for the indirect jump. + MachineBasicBlock *MBB; + /// The MBB of the default bb, which is a successor of the range + /// check MBB. This is when updating PHI nodes in successors. + MachineBasicBlock *Default; + + JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, MachineBasicBlock *D) + : Reg(R), JTI(J), MBB(M), Default(D) {} +}; +struct JumpTableHeader { + APInt First; + APInt Last; + const Value *SValue; + MachineBasicBlock *HeaderBB; + bool Emitted; + bool OmitRangeCheck; + + JumpTableHeader(APInt F, APInt L, const Value *SV, MachineBasicBlock *H, + bool E = false) + : First(std::move(F)), Last(std::move(L)), SValue(SV), HeaderBB(H), + Emitted(E), OmitRangeCheck(false) {} +}; +using JumpTableBlock = std::pair<JumpTableHeader, JumpTable>; + +struct BitTestCase { + uint64_t Mask; + MachineBasicBlock *ThisBB; + MachineBasicBlock *TargetBB; + BranchProbability ExtraProb; + + BitTestCase(uint64_t M, MachineBasicBlock *T, MachineBasicBlock *Tr, + BranchProbability Prob) + : Mask(M), ThisBB(T), TargetBB(Tr), ExtraProb(Prob) {} +}; + +using BitTestInfo = SmallVector<BitTestCase, 3>; + +struct BitTestBlock { + APInt First; + APInt Range; + const Value *SValue; + unsigned Reg; + MVT RegVT; + bool Emitted; + bool ContiguousRange; + MachineBasicBlock *Parent; + MachineBasicBlock *Default; + BitTestInfo Cases; + BranchProbability Prob; + BranchProbability DefaultProb; + + BitTestBlock(APInt F, APInt R, const Value *SV, unsigned Rg, MVT RgVT, bool E, + bool CR, MachineBasicBlock *P, MachineBasicBlock *D, + BitTestInfo C, BranchProbability Pr) + : First(std::move(F)), Range(std::move(R)), SValue(SV), Reg(Rg), + RegVT(RgVT), Emitted(E), ContiguousRange(CR), Parent(P), Default(D), + Cases(std::move(C)), Prob(Pr) {} +}; + +/// Return the range of value within a range. +uint64_t getJumpTableRange(const CaseClusterVector &Clusters, unsigned First, + unsigned Last); + +/// Return the number of cases within a range. +uint64_t getJumpTableNumCases(const SmallVectorImpl<unsigned> &TotalCases, + unsigned First, unsigned Last); + +struct SwitchWorkListItem { + MachineBasicBlock *MBB; + CaseClusterIt FirstCluster; + CaseClusterIt LastCluster; + const ConstantInt *GE; + const ConstantInt *LT; + BranchProbability DefaultProb; +}; +using SwitchWorkList = SmallVector<SwitchWorkListItem, 4>; + +class SwitchLowering { +public: + SwitchLowering(FunctionLoweringInfo &funcinfo) : FuncInfo(funcinfo) {} + + void init(const TargetLowering &tli, const TargetMachine &tm, + const DataLayout &dl) { + TLI = &tli; + TM = &tm; + DL = &dl; + } + + /// Vector of CaseBlock structures used to communicate SwitchInst code + /// generation information. + std::vector<CaseBlock> SwitchCases; + + /// Vector of JumpTable structures used to communicate SwitchInst code + /// generation information. + std::vector<JumpTableBlock> JTCases; + + /// Vector of BitTestBlock structures used to communicate SwitchInst code + /// generation information. + std::vector<BitTestBlock> BitTestCases; + + void findJumpTables(CaseClusterVector &Clusters, const SwitchInst *SI, + MachineBasicBlock *DefaultMBB); + + bool buildJumpTable(const CaseClusterVector &Clusters, unsigned First, + unsigned Last, const SwitchInst *SI, + MachineBasicBlock *DefaultMBB, CaseCluster &JTCluster); + + + void findBitTestClusters(CaseClusterVector &Clusters, const SwitchInst *SI); + + /// Build a bit test cluster from Clusters[First..Last]. Returns false if it + /// decides it's not a good idea. + bool buildBitTests(CaseClusterVector &Clusters, unsigned First, unsigned Last, + const SwitchInst *SI, CaseCluster &BTCluster); + + virtual void addSuccessorWithProb( + MachineBasicBlock *Src, MachineBasicBlock *Dst, + BranchProbability Prob = BranchProbability::getUnknown()) = 0; + + virtual ~SwitchLowering() = default; + +private: + const TargetLowering *TLI; + const TargetMachine *TM; + const DataLayout *DL; + FunctionLoweringInfo &FuncInfo; +}; + +} // namespace SwitchCG +} // namespace llvm + +#endif // LLVM_CODEGEN_SWITCHLOWERINGUTILS_H + diff --git a/include/llvm/CodeGen/TailDuplicator.h b/include/llvm/CodeGen/TailDuplicator.h index be6562c85f2e..358798d5ed60 100644 --- a/include/llvm/CodeGen/TailDuplicator.h +++ b/include/llvm/CodeGen/TailDuplicator.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TailDuplicator.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetCallingConv.h b/include/llvm/CodeGen/TargetCallingConv.h index 7d138f585171..aebeeecbe506 100644 --- a/include/llvm/CodeGen/TargetCallingConv.h +++ b/include/llvm/CodeGen/TargetCallingConv.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,9 +45,12 @@ namespace ISD { unsigned IsInConsecutiveRegsLast : 1; unsigned IsInConsecutiveRegs : 1; unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate + unsigned IsPointer : 1; unsigned ByValSize; ///< Byval struct size + unsigned PointerAddrSpace; ///< Address space of pointer argument + public: ArgFlagsTy() : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), @@ -56,8 +58,9 @@ namespace ISD { IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), ByValSize(0) { - static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big"); + IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0), + PointerAddrSpace(0) { + static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); } bool isZExt() const { return IsZExt; } @@ -114,6 +117,9 @@ namespace ISD { bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } + bool isPointer() const { return IsPointer; } + void setPointer() { IsPointer = 1; } + unsigned getByValAlign() const { return (1U << ByValAlign) / 2; } void setByValAlign(unsigned A) { ByValAlign = Log2_32(A) + 1; @@ -128,7 +134,10 @@ namespace ISD { unsigned getByValSize() const { return ByValSize; } void setByValSize(unsigned S) { ByValSize = S; } - }; + + unsigned getPointerAddrSpace() const { return PointerAddrSpace; } + void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } +}; /// InputArg - This struct carries flags and type information about a /// single incoming (formal) argument or incoming (from the perspective diff --git a/include/llvm/CodeGen/TargetFrameLowering.h b/include/llvm/CodeGen/TargetFrameLowering.h index b4d1da941433..878c9ffd2b51 100644 --- a/include/llvm/CodeGen/TargetFrameLowering.h +++ b/include/llvm/CodeGen/TargetFrameLowering.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetFrameLowering.h ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #define LLVM_CODEGEN_TARGETFRAMELOWERING_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/StringSwitch.h" #include <utility> #include <vector> @@ -24,6 +24,14 @@ namespace llvm { class MachineFunction; class RegScavenger; +namespace TargetStackID { + enum Value { + Default = 0, + SGPRSpill = 1, + NoAlloc = 255 + }; +} + /// Information about stack frame layout on the target. It holds the direction /// of stack growth, the known stack alignment on entry to each function, and /// the offset to the locals area. @@ -262,6 +270,17 @@ public: return getFrameIndexReference(MF, FI, FrameReg); } + /// getNonLocalFrameIndexReference - This method returns the offset used to + /// reference a frame index location. The offset can be from either FP/BP/SP + /// based on which base register is returned by llvm.localaddress. + virtual int getNonLocalFrameIndexReference(const MachineFunction &MF, + int FI) const { + // By default, dispatch to getFrameIndexReference. Interested targets can + // override this. + unsigned FrameReg; + return getFrameIndexReference(MF, FI, FrameReg); + } + /// This method determines which of the registers reported by /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. /// The default implementation checks populates the \p SavedRegs bitset with @@ -335,6 +354,16 @@ public: return true; } + virtual bool isSupportedStackID(TargetStackID::Value ID) const { + switch (ID) { + default: + return false; + case TargetStackID::Default: + case TargetStackID::NoAlloc: + return true; + } + } + /// Check if given function is safe for not having callee saved registers. /// This is used when interprocedural register allocation is enabled. static bool isSafeForNoCSROpt(const Function &F) { diff --git a/include/llvm/CodeGen/TargetInstrInfo.h b/include/llvm/CodeGen/TargetInstrInfo.h index 961b90e9bc12..25b04f8c019a 100644 --- a/include/llvm/CodeGen/TargetInstrInfo.h +++ b/include/llvm/CodeGen/TargetInstrInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetInstrInfo.h - Instruction Info --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -27,6 +26,7 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOutliner.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/VirtRegMap.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/ErrorHandling.h" @@ -81,6 +81,7 @@ public: /// Given a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. + virtual const TargetRegisterClass *getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const; @@ -429,6 +430,13 @@ public: RegSubRegPair(unsigned Reg = 0, unsigned SubReg = 0) : Reg(Reg), SubReg(SubReg) {} + + bool operator==(const RegSubRegPair& P) const { + return Reg == P.Reg && SubReg == P.SubReg; + } + bool operator!=(const RegSubRegPair& P) const { + return !(*this == P); + } }; /// A pair composed of a pair of a register and a sub-register index, @@ -663,8 +671,9 @@ public: /// is finished. Return the value/register of the new loop count. We need /// this function when peeling off one or more iterations of a loop. This /// function assumes the nth iteration is peeled first. - virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, MachineInstr *IndVar, - MachineInstr &Cmp, + virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, + MachineBasicBlock &PreHeader, + MachineInstr *IndVar, MachineInstr &Cmp, SmallVectorImpl<MachineOperand> &Cond, SmallVectorImpl<MachineInstr *> &PrevInsts, unsigned Iter, unsigned MaxIter) const { @@ -926,9 +935,12 @@ public: /// operand folded, otherwise NULL is returned. /// The new instruction is inserted before MI, and the client is responsible /// for removing the old instruction. + /// If VRM is passed, the assigned physregs can be inspected by target to + /// decide on using an opcode (note that those assignments can still change). MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops, int FI, - LiveIntervals *LIS = nullptr) const; + LiveIntervals *LIS = nullptr, + VirtRegMap *VRM = nullptr) const; /// Same as the previous version except it allows folding of any load and /// store from / to any address, not just from a specific stack slot. @@ -1018,7 +1030,8 @@ protected: foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, - LiveIntervals *LIS = nullptr) const { + LiveIntervals *LIS = nullptr, + VirtRegMap *VRM = nullptr) const { return nullptr; } @@ -1138,8 +1151,9 @@ public: /// Get the base operand and byte offset of an instruction that reads/writes /// memory. - virtual bool getMemOperandWithOffset(MachineInstr &MI, - MachineOperand *&BaseOp, int64_t &Offset, + virtual bool getMemOperandWithOffset(const MachineInstr &MI, + const MachineOperand *&BaseOp, + int64_t &Offset, const TargetRegisterInfo *TRI) const { return false; } @@ -1164,8 +1178,8 @@ public: /// or /// DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); /// to TargetPassConfig::createMachineScheduler() to have an effect. - virtual bool shouldClusterMemOps(MachineOperand &BaseOp1, - MachineOperand &BaseOp2, + virtual bool shouldClusterMemOps(const MachineOperand &BaseOp1, + const MachineOperand &BaseOp2, unsigned NumLoads) const { llvm_unreachable("target did not implement shouldClusterMemOps()"); } @@ -1253,8 +1267,9 @@ public: /// Measure the specified inline asm to determine an approximation of its /// length. - virtual unsigned getInlineAsmLength(const char *Str, - const MCAsmInfo &MAI) const; + virtual unsigned getInlineAsmLength( + const char *Str, const MCAsmInfo &MAI, + const TargetSubtargetInfo *STI = nullptr) const; /// Allocate and return a hazard recognizer to use for this target when /// scheduling the machine instructions before register allocation. @@ -1542,7 +1557,8 @@ public: /// See also MachineInstr::mayAlias, which is implemented on top of this /// function. virtual bool - areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb, + areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, + const MachineInstr &MIb, AliasAnalysis *AA = nullptr) const { assert((MIa.mayLoad() || MIa.mayStore()) && "MIa must load from or modify a memory location"); diff --git a/include/llvm/CodeGen/TargetLowering.h b/include/llvm/CodeGen/TargetLowering.h index 23dbaac03ebe..d5cca60bb1b2 100644 --- a/include/llvm/CodeGen/TargetLowering.h +++ b/include/llvm/CodeGen/TargetLowering.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetLowering.h - Target Lowering Info -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -189,13 +188,18 @@ public: bool IsSwiftSelf : 1; bool IsSwiftError : 1; uint16_t Alignment = 0; + Type *ByValType = nullptr; ArgListEntry() : IsSExt(false), IsZExt(false), IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), IsInAlloca(false), IsReturned(false), IsSwiftSelf(false), IsSwiftError(false) {} - void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx); + void setAttributes(const CallBase *Call, unsigned ArgIdx); + + void setAttributes(ImmutableCallSite *CS, unsigned ArgIdx) { + return setAttributes(cast<CallBase>(CS->getInstruction()), ArgIdx); + } }; using ArgListTy = std::vector<ArgListEntry>; @@ -235,7 +239,14 @@ public: /// Return the pointer type for the given address space, defaults to /// the pointer type from the data layout. /// FIXME: The default needs to be removed once all the code is updated. - MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { + virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { + return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); + } + + /// Return the in-memory pointer type for the given address space, defaults to + /// the pointer type from the data layout. FIXME: The default needs to be + /// removed once all the code is updated. + MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const { return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } @@ -291,6 +302,9 @@ public: // The default action for one element vectors is to scalarize if (VT.getVectorNumElements() == 1) return TypeScalarizeVector; + // The default action for an odd-width vector is to widen. + if (!VT.isPow2VectorType()) + return TypeWidenVector; // The default action for other vectors is to promote return TypePromoteInteger; } @@ -387,8 +401,9 @@ public: /// efficiently, casting the load to a smaller vector of larger types and /// loading is more efficient, however, this can be undone by optimizations in /// dag combiner. - virtual bool isLoadBitCastBeneficial(EVT LoadVT, - EVT BitcastVT) const { + virtual bool isLoadBitCastBeneficial(EVT LoadVT, EVT BitcastVT, + const SelectionDAG &DAG, + const MachineMemOperand &MMO) const { // Don't do if we could do an indexed load on the original type, but not on // the new one. if (!LoadVT.isSimple() || !BitcastVT.isSimple()) @@ -402,14 +417,18 @@ public: getTypeToPromoteTo(ISD::LOAD, LoadMVT) == BitcastVT.getSimpleVT()) return false; - return true; + bool Fast = false; + return allowsMemoryAccess(*DAG.getContext(), DAG.getDataLayout(), BitcastVT, + MMO, &Fast) && Fast; } /// Return true if the following transform is beneficial: /// (store (y (conv x)), y*)) -> (store x, (x*)) - virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT) const { + virtual bool isStoreBitCastBeneficial(EVT StoreVT, EVT BitcastVT, + const SelectionDAG &DAG, + const MachineMemOperand &MMO) const { // Default to the same logic as loads. - return isLoadBitCastBeneficial(StoreVT, BitcastVT); + return isLoadBitCastBeneficial(StoreVT, BitcastVT, DAG, MMO); } /// Return true if it is expected to be cheaper to do a store of a non-zero @@ -421,10 +440,12 @@ public: return false; } - /// Allow store merging after legalization in addition to before legalization. - /// This may catch stores that do not exist earlier (eg, stores created from - /// intrinsics). - virtual bool mergeStoresAfterLegalization() const { return true; } + /// Allow store merging for the specified type after legalization in addition + /// to before legalization. This may transform stores that do not exist + /// earlier (for example, stores created from intrinsics). + virtual bool mergeStoresAfterLegalization(EVT MemVT) const { + return true; + } /// Returns if it's reasonable to merge stores to MemVT size. virtual bool canMergeStoresTo(unsigned AS, EVT MemVT, @@ -521,13 +542,22 @@ public: /// There are two ways to clear extreme bits (either low or high): /// Mask: x & (-1 << y) (the instcombine canonical form) /// Shifts: x >> y << y - /// Return true if the variant with 2 shifts is preferred. + /// Return true if the variant with 2 variable shifts is preferred. /// Return false if there is no preference. - virtual bool preferShiftsToClearExtremeBits(SDValue X) const { + virtual bool shouldFoldMaskToVariableShiftPair(SDValue X) const { // By default, let's assume that no one prefers shifts. return false; } + /// Return true if it is profitable to fold a pair of shifts into a mask. + /// This is usually true on most targets. But some targets, like Thumb1, + /// have immediate shift instructions, but no immediate "and" instruction; + /// this makes the fold unprofitable. + virtual bool shouldFoldConstantShiftPairToMask(const SDNode *N, + CombineLevel Level) const { + return true; + } + /// Should we tranform the IR-optimal check for whether given truncation /// down into KeptBits would be truncating or not: /// (add %x, (1 << (KeptBits-1))) srccond (1 << KeptBits) @@ -541,6 +571,16 @@ public: return false; } + /// These two forms are equivalent: + /// sub %y, (xor %x, -1) + /// add (add %x, 1), %y + /// The variant with two add's is IR-canonical. + /// Some targets may prefer one to the other. + virtual bool preferIncOfAddToSubOfNot(EVT VT) const { + // By default, let's assume that everyone prefers the form with two add's. + return true; + } + /// Return true if the target wants to use the optimization that /// turns ext(promotableInst1(...(promotableInstN(load)))) into /// promotedInst1(...(promotedInstN(ext(load)))). @@ -560,11 +600,6 @@ public: return false; } - /// Return true if target supports floating point exceptions. - bool hasFloatingPointExceptions() const { - return HasFloatingPointExceptions; - } - /// Return true if target always beneficiates from combining into FMA for a /// given value type. This must typically return false on targets where FMA /// takes more cycles to execute than FADD. @@ -619,12 +654,21 @@ public: /// Return the register class that should be used for the specified value /// type. - virtual const TargetRegisterClass *getRegClassFor(MVT VT) const { + virtual const TargetRegisterClass *getRegClassFor(MVT VT, bool isDivergent = false) const { + (void)isDivergent; const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy]; assert(RC && "This value type is not natively supported!"); return RC; } + /// Allows target to decide about the register class of the + /// specific value that is live outside the defining block. + /// Returns true if the value needs uniform register class. + virtual bool requiresUniformRegister(MachineFunction &MF, + const Value *) const { + return false; + } + /// Return the 'representative' register class for the specified value /// type. /// @@ -643,6 +687,13 @@ public: return RepRegClassCostForVT[VT.SimpleTy]; } + /// Return true if SHIFT instructions should be expanded to SHIFT_PARTS + /// instructions, and false if a library call is preferred (e.g for code-size + /// reasons). + virtual bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const { + return true; + } + /// Return true if the target has native support for the specified value type. /// This means that it has a register that directly holds it without /// promotions or expansions. @@ -768,7 +819,8 @@ public: /// Returns true if the target can instruction select the specified FP /// immediate natively. If false, the legalizer will materialize the FP /// immediate as a load from a constant pool. - virtual bool isFPImmLegal(const APFloat &/*Imm*/, EVT /*VT*/) const { + virtual bool isFPImmLegal(const APFloat & /*Imm*/, EVT /*VT*/, + bool ForCodeSize = false) const { return false; } @@ -830,6 +882,8 @@ public: default: llvm_unreachable("Unexpected fixed point operation."); case ISD::SMULFIX: + case ISD::SMULFIXSAT: + case ISD::UMULFIX: Supported = isSupportedFixedPointOperation(Op, VT, Scale); break; } @@ -865,6 +919,8 @@ public: case ISD::STRICT_FFLOOR: EqOpc = ISD::FFLOOR; break; case ISD::STRICT_FROUND: EqOpc = ISD::FROUND; break; case ISD::STRICT_FTRUNC: EqOpc = ISD::FTRUNC; break; + case ISD::STRICT_FP_ROUND: EqOpc = ISD::FP_ROUND; break; + case ISD::STRICT_FP_EXTEND: EqOpc = ISD::FP_EXTEND; break; } auto Action = getOperationAction(EqOpc, VT); @@ -931,21 +987,20 @@ public: /// Return true if lowering to a jump table is suitable for a set of case /// clusters which may contain \p NumCases cases, \p Range range of values. - /// FIXME: This function check the maximum table size and density, but the - /// minimum size is not checked. It would be nice if the minimum size is - /// also combined within this function. Currently, the minimum size check is - /// performed in findJumpTable() in SelectionDAGBuiler and - /// getEstimatedNumberOfCaseClusters() in BasicTTIImpl. virtual bool isSuitableForJumpTable(const SwitchInst *SI, uint64_t NumCases, uint64_t Range) const { - const bool OptForSize = SI->getParent()->getParent()->optForSize(); + // FIXME: This function check the maximum table size and density, but the + // minimum size is not checked. It would be nice if the minimum size is + // also combined within this function. Currently, the minimum size check is + // performed in findJumpTable() in SelectionDAGBuiler and + // getEstimatedNumberOfCaseClusters() in BasicTTIImpl. + const bool OptForSize = SI->getParent()->getParent()->hasOptSize(); const unsigned MinDensity = getMinimumJumpTableDensity(OptForSize); - const unsigned MaxJumpTableSize = - OptForSize || getMaximumJumpTableSize() == 0 - ? UINT_MAX - : getMaximumJumpTableSize(); - // Check whether a range of clusters is dense enough for a jump table. - if (Range <= MaxJumpTableSize && + const unsigned MaxJumpTableSize = getMaximumJumpTableSize(); + + // Check whether the number of cases is small enough and + // the range is dense enough for a jump table. + if ((OptForSize || Range <= MaxJumpTableSize) && (NumCases * 100 >= Range * MinDensity)) { return true; } @@ -1140,24 +1195,42 @@ public: EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown = false) const { // Lower scalar pointers to native pointer types. - if (PointerType *PTy = dyn_cast<PointerType>(Ty)) + if (auto *PTy = dyn_cast<PointerType>(Ty)) return getPointerTy(DL, PTy->getAddressSpace()); - if (Ty->isVectorTy()) { - VectorType *VTy = cast<VectorType>(Ty); - Type *Elm = VTy->getElementType(); + if (auto *VTy = dyn_cast<VectorType>(Ty)) { + Type *EltTy = VTy->getElementType(); // Lower vectors of pointers to native pointer types. + if (auto *PTy = dyn_cast<PointerType>(EltTy)) { + EVT PointerTy(getPointerTy(DL, PTy->getAddressSpace())); + EltTy = PointerTy.getTypeForEVT(Ty->getContext()); + } + return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(EltTy, false), + VTy->getNumElements()); + } + + return EVT::getEVT(Ty, AllowUnknown); + } + + EVT getMemValueType(const DataLayout &DL, Type *Ty, + bool AllowUnknown = false) const { + // Lower scalar pointers to native pointer types. + if (PointerType *PTy = dyn_cast<PointerType>(Ty)) + return getPointerMemTy(DL, PTy->getAddressSpace()); + else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) { + Type *Elm = VTy->getElementType(); if (PointerType *PT = dyn_cast<PointerType>(Elm)) { - EVT PointerTy(getPointerTy(DL, PT->getAddressSpace())); + EVT PointerTy(getPointerMemTy(DL, PT->getAddressSpace())); Elm = PointerTy.getTypeForEVT(Ty->getContext()); } - return EVT::getVectorVT(Ty->getContext(), EVT::getEVT(Elm, false), VTy->getNumElements()); } - return EVT::getEVT(Ty, AllowUnknown); + + return getValueType(DL, Ty, AllowUnknown); } + /// Return the MVT corresponding to this LLVM type. See getValueType. MVT getSimpleValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown = false) const { @@ -1327,18 +1400,6 @@ public: return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp; } - /// For memcmp expansion when the memcmp result is only compared equal or - /// not-equal to 0, allow up to this number of load pairs per block. As an - /// example, this may allow 'memcmp(a, b, 3) == 0' in a single block: - /// a0 = load2bytes &a[0] - /// b0 = load2bytes &b[0] - /// a2 = load1byte &a[2] - /// b2 = load1byte &b[2] - /// r = cmp eq (a0 ^ b0 | a2 ^ b2), 0 - virtual unsigned getMemcmpEqZeroLoadsPerBlock() const { - return 1; - } - /// Get maximum # of store operations permitted for llvm.memmove /// /// This function returns the maximum number of store operations permitted @@ -1358,10 +1419,10 @@ public: /// copy/move/set is converted to a sequence of store operations. Its use /// helps to ensure that such replacements don't generate code that causes an /// alignment error (trap) on the target machine. - virtual bool allowsMisalignedMemoryAccesses(EVT, - unsigned AddrSpace = 0, - unsigned Align = 1, - bool * /*Fast*/ = nullptr) const { + virtual bool allowsMisalignedMemoryAccesses( + EVT, unsigned AddrSpace = 0, unsigned Align = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool * /*Fast*/ = nullptr) const { return false; } @@ -1369,8 +1430,18 @@ public: /// given address space and alignment. If the access is allowed, the optional /// final parameter returns if the access is also fast (as defined by the /// target). + bool + allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, + unsigned AddrSpace = 0, unsigned Alignment = 1, + MachineMemOperand::Flags Flags = MachineMemOperand::MONone, + bool *Fast = nullptr) const; + + /// Return true if the target supports a memory access of this type for the + /// given MachineMemOperand. If the access is allowed, the optional + /// final parameter returns if the access is also fast (as defined by the + /// target). bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, - unsigned AddrSpace = 0, unsigned Alignment = 1, + const MachineMemOperand &MMO, bool *Fast = nullptr) const; /// Returns the target specific optimal type for load and store operations as @@ -1384,12 +1455,11 @@ public: /// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it /// does not need to be loaded. It returns EVT::Other if the type should be /// determined using generic target-independent logic. - virtual EVT getOptimalMemOpType(uint64_t /*Size*/, - unsigned /*DstAlign*/, unsigned /*SrcAlign*/, - bool /*IsMemset*/, - bool /*ZeroMemset*/, - bool /*MemcpyStrSrc*/, - MachineFunction &/*MF*/) const { + virtual EVT + getOptimalMemOpType(uint64_t /*Size*/, unsigned /*DstAlign*/, + unsigned /*SrcAlign*/, bool /*IsMemset*/, + bool /*ZeroMemset*/, bool /*MemcpyStrSrc*/, + const AttributeList & /*FuncAttributes*/) const { return MVT::Other; } @@ -1515,7 +1585,7 @@ public: /// performs validation and error handling, returns the function. Otherwise, /// returns nullptr. Must be previously inserted by insertSSPDeclarations. /// Should be used only when getIRStackGuard returns nullptr. - virtual Value *getSSPStackGuardCheck(const Module &M) const; + virtual Function *getSSPStackGuardCheck(const Module &M) const; protected: Value *getDefaultSafeStackPointerLocation(IRBuilder<> &IRB, @@ -1537,8 +1607,9 @@ public: } /// Returns true if a cast from SrcAS to DestAS is "cheap", such that e.g. we - /// are happy to sink it into basic blocks. - virtual bool isCheapAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { + /// are happy to sink it into basic blocks. A cast may be free, but not + /// necessarily a no-op. e.g. a free truncate from a 64-bit to 32-bit pointer. + virtual bool isFreeAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const { return isNoopAddrSpaceCast(SrcAS, DestAS); } @@ -1716,8 +1787,9 @@ public: /// Returns how the IR-level AtomicExpand pass should expand the given /// AtomicRMW, if at all. Default is to never expand. - virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const { - return AtomicExpansionKind::None; + virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { + return RMW->isFloatingPointOperation() ? + AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None; } /// On some platforms, an AtomicRMW that never actually modifies the value @@ -1762,6 +1834,8 @@ public: Action != TypeSplitVector; } + virtual bool isProfitableToCombineMinNumMaxNum(EVT VT) const { return true; } + /// Return true if a select of constants (select Cond, C1, C2) should be /// transformed into simple math ops with the condition value. For example: /// select Cond, C1, C1-1 --> add (zext Cond), C1-1 @@ -1865,12 +1939,6 @@ protected: /// control. void setJumpIsExpensive(bool isExpensive = true); - /// Tells the code generator that this target supports floating point - /// exceptions and cares about preserving floating point exception behavior. - void setHasFloatingPointExceptions(bool FPExceptions = true) { - HasFloatingPointExceptions = FPExceptions; - } - /// Tells the code generator which bitwidths to bypass. void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; @@ -2159,6 +2227,8 @@ public: case ISD::UADDSAT: case ISD::FMINNUM: case ISD::FMAXNUM: + case ISD::FMINNUM_IEEE: + case ISD::FMAXNUM_IEEE: case ISD::FMINIMUM: case ISD::FMAXIMUM: return true; @@ -2166,6 +2236,30 @@ public: } } + /// Return true if the node is a math/logic binary operator. + virtual bool isBinOp(unsigned Opcode) const { + // A commutative binop must be a binop. + if (isCommutativeBinOp(Opcode)) + return true; + // These are non-commutative binops. + switch (Opcode) { + case ISD::SUB: + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FSUB: + case ISD::FDIV: + case ISD::FREM: + return true; + default: + return false; + } + } + /// Return true if it's free to truncate a value of type FromTy to type /// ToTy. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. @@ -2270,6 +2364,16 @@ public: return false; } + /// Return true if sinking I's operands to the same basic block as I is + /// profitable, e.g. because the operands can be folded into a target + /// instruction during instruction selection. After calling the function + /// \p Ops contains the Uses to sink ordered by dominance (dominating users + /// come first). + virtual bool shouldSinkOperands(Instruction *I, + SmallVectorImpl<Use *> &Ops) const { + return false; + } + /// Return true if the target supplies and combines to a paired load /// two loaded values of type LoadedType next to each other in memory. /// RequiredAlignment gives the minimal alignment constraints that must be met @@ -2415,6 +2519,31 @@ public: return false; } + /// Return true if extraction of a scalar element from the given vector type + /// at the given index is cheap. For example, if scalar operations occur on + /// the same register file as vector operations, then an extract element may + /// be a sub-register rename rather than an actual instruction. + virtual bool isExtractVecEltCheap(EVT VT, unsigned Index) const { + return false; + } + + /// Try to convert math with an overflow comparison into the corresponding DAG + /// node operation. Targets may want to override this independently of whether + /// the operation is legal/custom for the given type because it may obscure + /// matching of other patterns. + virtual bool shouldFormOverflowOp(unsigned Opcode, EVT VT) const { + // TODO: The default logic is inherited from code in CodeGenPrepare. + // The opcode should not make a difference by default? + if (Opcode != ISD::UADDO) + return false; + + // Allow the transform as long as we have an integer type that is not + // obviously illegal and unsupported. + if (VT.isVector()) + return false; + return VT.isSimple() || !isOperationExpand(Opcode, VT); + } + // Return true if it is profitable to use a scalar input to a BUILD_VECTOR // even if the vector itself has multiple uses. virtual bool aggressivelyPreferBuildVectorSources(EVT VecVT) const { @@ -2495,10 +2624,6 @@ private: /// predication. bool JumpIsExpensive; - /// Whether the target supports or cares about preserving floating point - /// exception behavior. - bool HasFloatingPointExceptions; - /// This target prefers to use _setjmp to implement llvm.setjmp. /// /// Defaults to false. @@ -2834,11 +2959,10 @@ public: /// Returns a pair of (return value, chain). /// It is an error to pass RTLIB::UNKNOWN_LIBCALL as \p LC. - std::pair<SDValue, SDValue> makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, - EVT RetVT, ArrayRef<SDValue> Ops, - bool isSigned, const SDLoc &dl, - bool doesNotReturn = false, - bool isReturnValueUsed = true) const; + std::pair<SDValue, SDValue> makeLibCall( + SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef<SDValue> Ops, + bool isSigned, const SDLoc &dl, bool doesNotReturn = false, + bool isReturnValueUsed = true, bool isPostTypeLegalization = false) const; /// Check whether parameters to a call that are passed in callee saved /// registers are the same as from the calling function. This needs to be @@ -2876,6 +3000,20 @@ public: } }; + /// Determines the optimal series of memory ops to replace the memset / memcpy. + /// Return true if the number of memory ops is below the threshold (Limit). + /// It returns the types of the sequence of memory ops to perform + /// memset / memcpy by reference. + bool findOptimalMemOpLowering(std::vector<EVT> &MemOps, + unsigned Limit, uint64_t Size, + unsigned DstAlign, unsigned SrcAlign, + bool IsMemset, + bool ZeroMemset, + bool MemcpyStrSrc, + bool AllowOverlap, + unsigned DstAS, unsigned SrcAS, + const AttributeList &FuncAttributes) const; + /// Check to see if the specified operand of the specified instruction is a /// constant integer. If so, check to see if there are any bits set in the /// constant that are not demanded. If so, shrink the constant and return @@ -3001,6 +3139,10 @@ public: TargetLoweringOpt &TLO, unsigned Depth = 0) const; + /// This method returns the constant pool value that will be loaded by LD. + /// NOTE: You must check for implicit extensions of the constant by LD. + virtual const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const; + /// If \p SNaN is false, \returns true if \p Op is known to never be any /// NaN. If \p sNaN is true, returns if \p Op is known to never be a signaling /// NaN. @@ -3088,15 +3230,6 @@ public: return true; } - /// Return true if it is profitable to fold a pair of shifts into a mask. - /// This is usually true on most targets. But some targets, like Thumb1, - /// have immediate shift instructions, but no immediate "and" instruction; - /// this makes the fold unprofitable. - virtual bool shouldFoldShiftPairToMask(const SDNode *N, - CombineLevel Level) const { - return true; - } - // Return true if it is profitable to combine a BUILD_VECTOR with a stride-pattern // to a shuffle and a truncate. // Example of such a combine: @@ -3430,6 +3563,15 @@ public: return false; } + /// For most targets, an LLVM type must be broken down into multiple + /// smaller types. Usually the halves are ordered according to the endianness + /// but for some platform that would break. So this method will default to + /// matching the endianness but can be overridden. + virtual bool + shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) const { + return DL.isLittleEndian(); + } + /// Returns a 0 terminated array of registers that can be safely used as /// scratch registers. virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const { @@ -3638,6 +3780,12 @@ public: std::vector<SDValue> &Ops, SelectionDAG &DAG) const; + // Lower custom output constraints. If invalid, return SDValue(). + virtual SDValue LowerAsmOutputForConstraint(SDValue &Chain, SDValue &Flag, + SDLoc DL, + const AsmOperandInfo &OpInfo, + SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Div utility functions // @@ -3840,8 +3988,26 @@ public: /// Method for building the DAG expansion of ISD::SMULFIX. This method accepts /// integers as its arguments. - SDValue getExpandedFixedPointMultiplication(SDNode *Node, - SelectionDAG &DAG) const; + SDValue expandFixedPointMul(SDNode *Node, SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::U(ADD|SUB)O. Expansion + /// always suceeds and populates the Result and Overflow arguments. + void expandUADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::S(ADD|SUB)O. Expansion + /// always suceeds and populates the Result and Overflow arguments. + void expandSADDSUBO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Method for building the DAG expansion of ISD::[US]MULO. Returns whether + /// expansion was successful and populates the Result and Overflow arguments. + bool expandMULO(SDNode *Node, SDValue &Result, SDValue &Overflow, + SelectionDAG &DAG) const; + + /// Expand a VECREDUCE_* into an explicit calculation. If Count is specified, + /// only the first Count elements of the vector are used. + SDValue expandVecReduce(SDNode *Node, SelectionDAG &DAG) const; //===--------------------------------------------------------------------===// // Instruction Emitting Hooks @@ -3894,14 +4060,23 @@ public: SDValue lowerCmpEqZeroToCtlzSrl(SDValue Op, SelectionDAG &DAG) const; private: - SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1, - ISD::CondCode Cond, DAGCombinerInfo &DCI, - const SDLoc &DL) const; + SDValue foldSetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + const SDLoc &DL, DAGCombinerInfo &DCI) const; + SDValue foldSetCCWithBinOp(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + const SDLoc &DL, DAGCombinerInfo &DCI) const; SDValue optimizeSetCCOfSignedTruncationCheck(EVT SCCVT, SDValue N0, SDValue N1, ISD::CondCode Cond, DAGCombinerInfo &DCI, const SDLoc &DL) const; + + SDValue prepareUREMEqFold(EVT SETCCVT, SDValue REMNode, + SDValue CompTargetNode, ISD::CondCode Cond, + DAGCombinerInfo &DCI, const SDLoc &DL, + SmallVectorImpl<SDNode *> &Created) const; + SDValue buildUREMEqFold(EVT SETCCVT, SDValue REMNode, SDValue CompTargetNode, + ISD::CondCode Cond, DAGCombinerInfo &DCI, + const SDLoc &DL) const; }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 052d1f8bc686..a1fb81cb009d 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -1,9 +1,8 @@ //==- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object Info --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetOpcodes.h b/include/llvm/CodeGen/TargetOpcodes.h index d0d959c4ae11..080a244f6f69 100644 --- a/include/llvm/CodeGen/TargetOpcodes.h +++ b/include/llvm/CodeGen/TargetOpcodes.h @@ -1,9 +1,8 @@ //===-- llvm/CodeGen/TargetOpcodes.h - Target Indep Opcodes -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h index 3288711a335d..0bd82aafac37 100644 --- a/include/llvm/CodeGen/TargetPassConfig.h +++ b/include/llvm/CodeGen/TargetPassConfig.h @@ -1,9 +1,8 @@ //===- TargetPassConfig.h - Code Generation pass options --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,6 +24,7 @@ class LLVMTargetMachine; struct MachineSchedContext; class PassConfigImpl; class ScheduleDAGInstrs; +class CSEConfigBase; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -75,9 +75,6 @@ public: } }; -template <> struct isPodLike<IdentifyingPassPtr> { - static const bool value = true; -}; /// Target-Independent Code Generator Pass Configuration Options. /// @@ -319,6 +316,13 @@ public: /// when GlobalISel failed and isGlobalISelAbortEnabled is false. virtual bool reportDiagnosticWhenGlobalISelFallback() const; + /// Check whether continuous CSE should be enabled in GISel passes. + /// By default, it's enabled for non O0 levels. + virtual bool isGISelCSEEnabled() const; + + /// Returns the CSEConfig object to use for the current optimization level. + virtual std::unique_ptr<CSEConfigBase> getCSEConfig() const; + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -360,11 +364,11 @@ protected: /// addFastRegAlloc - Add the minimum set of target-independent passes that /// are required for fast register allocation. - virtual void addFastRegAlloc(FunctionPass *RegAllocPass); + virtual void addFastRegAlloc(); /// addOptimizedRegAlloc - Add passes related to register allocation. /// LLVMTargetMachine provides standard regalloc passes for most targets. - virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass); + virtual void addOptimizedRegAlloc(); /// addPreRewrite - Add passes to the optimized register allocation pipeline /// after register allocation is complete, but before virtual registers are @@ -374,10 +378,18 @@ protected: /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. /// When these passes run, VirtRegMap contains legal physreg assignments for /// all virtual registers. + /// + /// Note if the target overloads addRegAssignAndRewriteOptimized, this may not + /// be honored. This is also not generally used for the the fast variant, + /// where the allocation and rewriting are done in one pass. virtual bool addPreRewrite() { return false; } + /// Add passes to be run immediately after virtual registers are rewritten + /// to physical registers. + virtual void addPostRewrite() { } + /// This method may be implemented by targets that want to run passes after /// register allocation pass pipeline but before prolog-epilog insertion. virtual void addPostRegAlloc() { } @@ -431,7 +443,12 @@ protected: /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. - FunctionPass *createRegAllocPass(bool Optimized); + virtual FunctionPass *createRegAllocPass(bool Optimized); + + /// Add core register alloator passes which do the actual register assignment + /// and rewriting. \returns true if any passes were added. + virtual bool addRegAssignmentFast(); + virtual bool addRegAssignmentOptimized(); }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetRegisterInfo.h b/include/llvm/CodeGen/TargetRegisterInfo.h index 0fbff3137653..ddbd677b3eaa 100644 --- a/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/include/llvm/CodeGen/TargetRegisterInfo.h @@ -1,9 +1,8 @@ //==- CodeGen/TargetRegisterInfo.h - Target Register Information -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -521,6 +520,11 @@ public: /// function. Used by MachineRegisterInfo::isConstantPhysReg(). virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; } + /// Returns true if the register class is considered divergent. + virtual bool isDivergentRegClass(const TargetRegisterClass *RC) const { + return false; + } + /// Physical registers that may be modified within a function but are /// guaranteed to be restored before any uses. This is useful for targets that /// have call sequences where a GOT register may be updated by the caller @@ -986,7 +990,7 @@ public: /// getFrameRegister - This method should return the register used as a base /// for values allocated in the current stack frame. - virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; + virtual Register getFrameRegister(const MachineFunction &MF) const = 0; /// Mark a register and all its aliases as reserved in the given set. void markSuperRegs(BitVector &RegisterSet, unsigned Reg) const; diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 6173925e23a1..cce85c8d7b0d 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/TargetSubtargetInfo.h b/include/llvm/CodeGen/TargetSubtargetInfo.h index 968e4c4b8102..037fc3ed3243 100644 --- a/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/TargetSubtargetInfo.h - Target Information --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,6 +42,7 @@ class RegisterBankInfo; class SDep; class SelectionDAGTargetInfo; struct SubtargetFeatureKV; +struct SubtargetSubTypeKV; struct SubtargetInfoKV; class SUnit; class TargetFrameLowering; @@ -63,8 +63,7 @@ class TargetSubtargetInfo : public MCSubtargetInfo { protected: // Can only create subclasses... TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF, - ArrayRef<SubtargetFeatureKV> PD, - const SubtargetInfoKV *ProcSched, + ArrayRef<SubtargetSubTypeKV> PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, @@ -190,13 +189,13 @@ public: /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; - /// Support printing of [latency:throughput] comment in output .S file. - virtual bool supportPrintSchedInfo() const { return false; } - /// True if the machine scheduler should disable the TLI preference /// for preRA scheduling with the source level scheduler. virtual bool enableMachineSchedDefaultSched() const { return true; } + /// True if the subtarget should run MachinePipeliner + virtual bool enableMachinePipeliner() const { return true; }; + /// True if the subtarget should enable joining global copies. /// /// By default this is enabled if the machine scheduler is enabled, but @@ -250,6 +249,10 @@ public: std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { } + /// Default to DFA for resource management, return false when target will use + /// ProcResource in InstrSchedModel instead. + virtual bool useDFAforSMS() const { return true; } + // For use with PostRAScheduling: get the minimum optimization level needed // to enable post-RA scheduling. virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { @@ -286,12 +289,16 @@ public: /// possible. virtual bool enableSubRegLiveness() const { return false; } - /// Returns string representation of scheduler comment - std::string getSchedInfoStr(const MachineInstr &MI) const; - std::string getSchedInfoStr(MCInst const &MCI) const override; - /// This is called after a .mir file was loaded. virtual void mirFileLoaded(MachineFunction &MF) const; + + /// True if the register allocator should use the allocation orders exactly as + /// written in the tablegen descriptions, false if it should allocate + /// the specified physical register later if is it callee-saved. + virtual bool ignoreCSRForAllocationOrder(const MachineFunction &MF, + unsigned PhysReg) const { + return false; + } }; } // end namespace llvm diff --git a/include/llvm/CodeGen/UnreachableBlockElim.h b/include/llvm/CodeGen/UnreachableBlockElim.h index 3e7afd4cd433..d52d7c3c5b49 100644 --- a/include/llvm/CodeGen/UnreachableBlockElim.h +++ b/include/llvm/CodeGen/UnreachableBlockElim.h @@ -1,9 +1,8 @@ //===-- UnreachableBlockElim.h - Remove unreachable blocks for codegen --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index d2ef4a94f8e2..c540c94f79d9 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -1,9 +1,8 @@ //===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 0abb4ece1d14..5818ac183fcc 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -1,9 +1,8 @@ //===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -63,89 +62,105 @@ def v32i16 : ValueType<512, 38>; // 32 x i16 vector value def v64i16 : ValueType<1024,39>; // 64 x i16 vector value def v128i16: ValueType<2048,40>; //128 x i16 vector value -def v1i32 : ValueType<32 , 41>; // 1 x i32 vector value -def v2i32 : ValueType<64 , 42>; // 2 x i32 vector value -def v4i32 : ValueType<128, 43>; // 4 x i32 vector value -def v8i32 : ValueType<256, 44>; // 8 x i32 vector value -def v16i32 : ValueType<512, 45>; // 16 x i32 vector value -def v32i32 : ValueType<1024,46>; // 32 x i32 vector value -def v64i32 : ValueType<2048,47>; // 64 x i32 vector value - -def v1i64 : ValueType<64 , 48>; // 1 x i64 vector value -def v2i64 : ValueType<128, 49>; // 2 x i64 vector value -def v4i64 : ValueType<256, 50>; // 4 x i64 vector value -def v8i64 : ValueType<512, 51>; // 8 x i64 vector value -def v16i64 : ValueType<1024,52>; // 16 x i64 vector value -def v32i64 : ValueType<2048,53>; // 32 x i64 vector value - -def v1i128 : ValueType<128, 54>; // 1 x i128 vector value - -def nxv1i1 : ValueType<1, 55>; // n x 1 x i1 vector value -def nxv2i1 : ValueType<2, 56>; // n x 2 x i1 vector value -def nxv4i1 : ValueType<4, 57>; // n x 4 x i1 vector value -def nxv8i1 : ValueType<8, 58>; // n x 8 x i1 vector value -def nxv16i1 : ValueType<16, 59>; // n x 16 x i1 vector value -def nxv32i1 : ValueType<32, 60>; // n x 32 x i1 vector value - -def nxv1i8 : ValueType<8, 61>; // n x 1 x i8 vector value -def nxv2i8 : ValueType<16, 62>; // n x 2 x i8 vector value -def nxv4i8 : ValueType<32, 63>; // n x 4 x i8 vector value -def nxv8i8 : ValueType<64, 64>; // n x 8 x i8 vector value -def nxv16i8 : ValueType<128, 65>; // n x 16 x i8 vector value -def nxv32i8 : ValueType<256, 66>; // n x 32 x i8 vector value - -def nxv1i16 : ValueType<16, 67>; // n x 1 x i16 vector value -def nxv2i16 : ValueType<32, 68>; // n x 2 x i16 vector value -def nxv4i16 : ValueType<64, 69>; // n x 4 x i16 vector value -def nxv8i16 : ValueType<128, 70>; // n x 8 x i16 vector value -def nxv16i16: ValueType<256, 71>; // n x 16 x i16 vector value -def nxv32i16: ValueType<512, 72>; // n x 32 x i16 vector value - -def nxv1i32 : ValueType<32, 73>; // n x 1 x i32 vector value -def nxv2i32 : ValueType<64, 74>; // n x 2 x i32 vector value -def nxv4i32 : ValueType<128, 75>; // n x 4 x i32 vector value -def nxv8i32 : ValueType<256, 76>; // n x 8 x i32 vector value -def nxv16i32: ValueType<512, 77>; // n x 16 x i32 vector value -def nxv32i32: ValueType<1024,78>; // n x 32 x i32 vector value - -def nxv1i64 : ValueType<64, 79>; // n x 1 x i64 vector value -def nxv2i64 : ValueType<128, 80>; // n x 2 x i64 vector value -def nxv4i64 : ValueType<256, 81>; // n x 4 x i64 vector value -def nxv8i64 : ValueType<512, 82>; // n x 8 x i64 vector value -def nxv16i64: ValueType<1024,83>; // n x 16 x i64 vector value -def nxv32i64: ValueType<2048,84>; // n x 32 x i64 vector value - -def v2f16 : ValueType<32 , 85>; // 2 x f16 vector value -def v4f16 : ValueType<64 , 86>; // 4 x f16 vector value -def v8f16 : ValueType<128, 87>; // 8 x f16 vector value -def v1f32 : ValueType<32 , 88>; // 1 x f32 vector value -def v2f32 : ValueType<64 , 89>; // 2 x f32 vector value -def v4f32 : ValueType<128, 90>; // 4 x f32 vector value -def v8f32 : ValueType<256, 91>; // 8 x f32 vector value -def v16f32 : ValueType<512, 92>; // 16 x f32 vector value -def v1f64 : ValueType<64, 93>; // 1 x f64 vector value -def v2f64 : ValueType<128, 94>; // 2 x f64 vector value -def v4f64 : ValueType<256, 95>; // 4 x f64 vector value -def v8f64 : ValueType<512, 96>; // 8 x f64 vector value - -def nxv2f16 : ValueType<32 , 97>; // n x 2 x f16 vector value -def nxv4f16 : ValueType<64 , 98>; // n x 4 x f16 vector value -def nxv8f16 : ValueType<128, 99>; // n x 8 x f16 vector value -def nxv1f32 : ValueType<32 , 100>; // n x 1 x f32 vector value -def nxv2f32 : ValueType<64 , 101>; // n x 2 x f32 vector value -def nxv4f32 : ValueType<128, 102>; // n x 4 x f32 vector value -def nxv8f32 : ValueType<256, 103>; // n x 8 x f32 vector value -def nxv16f32 : ValueType<512, 104>; // n x 16 x f32 vector value -def nxv1f64 : ValueType<64, 105>; // n x 1 x f64 vector value -def nxv2f64 : ValueType<128, 106>; // n x 2 x f64 vector value -def nxv4f64 : ValueType<256, 107>; // n x 4 x f64 vector value -def nxv8f64 : ValueType<512, 108>; // n x 8 x f64 vector value - -def x86mmx : ValueType<64 , 109>; // X86 MMX value -def FlagVT : ValueType<0 , 110>; // Pre-RA sched glue -def isVoid : ValueType<0 , 111>; // Produces no value -def untyped: ValueType<8 , 112>; // Produces an untyped value -def ExceptRef: ValueType<0, 113>; // WebAssembly's except_ref type +def v1i32 : ValueType<32 , 41>; // 1 x i32 vector value +def v2i32 : ValueType<64 , 42>; // 2 x i32 vector value +def v3i32 : ValueType<96 , 43>; // 3 x i32 vector value +def v4i32 : ValueType<128, 44>; // 4 x i32 vector value +def v5i32 : ValueType<160, 45>; // 5 x i32 vector value +def v8i32 : ValueType<256, 46>; // 8 x i32 vector value +def v16i32 : ValueType<512, 47>; // 16 x i32 vector value +def v32i32 : ValueType<1024,48>; // 32 x i32 vector value +def v64i32 : ValueType<2048,49>; // 64 x i32 vector value +def v128i32 : ValueType<4096,50>; // 128 x i32 vector value +def v256i32 : ValueType<8182,51>; // 256 x i32 vector value +def v512i32 : ValueType<16384,52>; // 512 x i32 vector value +def v1024i32 : ValueType<32768,53>; // 1024 x i32 vector value +def v2048i32 : ValueType<65536,54>; // 2048 x i32 vector value + +def v1i64 : ValueType<64 , 55>; // 1 x i64 vector value +def v2i64 : ValueType<128, 56>; // 2 x i64 vector value +def v4i64 : ValueType<256, 57>; // 4 x i64 vector value +def v8i64 : ValueType<512, 58>; // 8 x i64 vector value +def v16i64 : ValueType<1024,59>; // 16 x i64 vector value +def v32i64 : ValueType<2048,60>; // 32 x i64 vector value + +def v1i128 : ValueType<128, 61>; // 1 x i128 vector value + +def nxv1i1 : ValueType<1, 62>; // n x 1 x i1 vector value +def nxv2i1 : ValueType<2, 63>; // n x 2 x i1 vector value +def nxv4i1 : ValueType<4, 64>; // n x 4 x i1 vector value +def nxv8i1 : ValueType<8, 65>; // n x 8 x i1 vector value +def nxv16i1 : ValueType<16, 66>; // n x 16 x i1 vector value +def nxv32i1 : ValueType<32, 67>; // n x 32 x i1 vector value + +def nxv1i8 : ValueType<8, 68>; // n x 1 x i8 vector value +def nxv2i8 : ValueType<16, 69>; // n x 2 x i8 vector value +def nxv4i8 : ValueType<32, 70>; // n x 4 x i8 vector value +def nxv8i8 : ValueType<64, 71>; // n x 8 x i8 vector value +def nxv16i8 : ValueType<128, 72>; // n x 16 x i8 vector value +def nxv32i8 : ValueType<256, 73>; // n x 32 x i8 vector value + +def nxv1i16 : ValueType<16, 74>; // n x 1 x i16 vector value +def nxv2i16 : ValueType<32, 75>; // n x 2 x i16 vector value +def nxv4i16 : ValueType<64, 76>; // n x 4 x i16 vector value +def nxv8i16 : ValueType<128, 77>; // n x 8 x i16 vector value +def nxv16i16: ValueType<256, 78>; // n x 16 x i16 vector value +def nxv32i16: ValueType<512, 79>; // n x 32 x i16 vector value + +def nxv1i32 : ValueType<32, 80>; // n x 1 x i32 vector value +def nxv2i32 : ValueType<64, 81>; // n x 2 x i32 vector value +def nxv4i32 : ValueType<128, 82>; // n x 4 x i32 vector value +def nxv8i32 : ValueType<256, 83>; // n x 8 x i32 vector value +def nxv16i32: ValueType<512, 84>; // n x 16 x i32 vector value +def nxv32i32: ValueType<1024,85>; // n x 32 x i32 vector value + +def nxv1i64 : ValueType<64, 86>; // n x 1 x i64 vector value +def nxv2i64 : ValueType<128, 87>; // n x 2 x i64 vector value +def nxv4i64 : ValueType<256, 88>; // n x 4 x i64 vector value +def nxv8i64 : ValueType<512, 89>; // n x 8 x i64 vector value +def nxv16i64: ValueType<1024,90>; // n x 16 x i64 vector value +def nxv32i64: ValueType<2048,91>; // n x 32 x i64 vector value + +def v2f16 : ValueType<32 , 92>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 93>; // 4 x f16 vector value +def v8f16 : ValueType<128, 94>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 95>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 96>; // 2 x f32 vector value +def v3f32 : ValueType<96 , 97>; // 3 x f32 vector value +def v4f32 : ValueType<128, 98>; // 4 x f32 vector value +def v5f32 : ValueType<160, 99>; // 5 x f32 vector value +def v8f32 : ValueType<256, 100>; // 8 x f32 vector value +def v16f32 : ValueType<512, 101>; // 16 x f32 vector value +def v32f32 : ValueType<1024, 102>; // 32 x f32 vector value +def v64f32 : ValueType<2048, 103>; // 64 x f32 vector value +def v128f32 : ValueType<4096, 104>; // 128 x f32 vector value +def v256f32 : ValueType<8182, 105>; // 256 x f32 vector value +def v512f32 : ValueType<16384, 106>; // 512 x f32 vector value +def v1024f32 : ValueType<32768, 107>; // 1024 x f32 vector value +def v2048f32 : ValueType<65536, 108>; // 2048 x f32 vector value +def v1f64 : ValueType<64, 109>; // 1 x f64 vector value +def v2f64 : ValueType<128, 110>; // 2 x f64 vector value +def v4f64 : ValueType<256, 111>; // 4 x f64 vector value +def v8f64 : ValueType<512, 112>; // 8 x f64 vector value + +def nxv2f16 : ValueType<32 , 113>; // n x 2 x f16 vector value +def nxv4f16 : ValueType<64 , 114>; // n x 4 x f16 vector value +def nxv8f16 : ValueType<128, 115>; // n x 8 x f16 vector value +def nxv1f32 : ValueType<32 , 116>; // n x 1 x f32 vector value +def nxv2f32 : ValueType<64 , 117>; // n x 2 x f32 vector value +def nxv4f32 : ValueType<128, 118>; // n x 4 x f32 vector value +def nxv8f32 : ValueType<256, 119>; // n x 8 x f32 vector value +def nxv16f32 : ValueType<512, 120>; // n x 16 x f32 vector value +def nxv1f64 : ValueType<64, 121>; // n x 1 x f64 vector value +def nxv2f64 : ValueType<128, 122>; // n x 2 x f64 vector value +def nxv4f64 : ValueType<256, 123>; // n x 4 x f64 vector value +def nxv8f64 : ValueType<512, 124>; // n x 8 x f64 vector value + +def x86mmx : ValueType<64 , 125>; // X86 MMX value +def FlagVT : ValueType<0 , 126>; // Pre-RA sched glue +def isVoid : ValueType<0 , 127>; // Produces no value +def untyped: ValueType<8 , 128>; // Produces an untyped value +def exnref: ValueType<0, 129>; // WebAssembly's exnref type def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata @@ -167,3 +182,14 @@ def iPTR : ValueType<0 , 254>; // Pseudo valuetype to represent "any type of any size". def Any : ValueType<0 , 255>; + +/// This class is for targets that want to use pointer types in patterns +/// with the GlobalISelEmitter. Targets must define their own pointer +/// derived from this class. The scalar argument should be an +/// integer type with the same bit size as the ponter. +/// e.g. def p0 : PtrValueType <i64, 0>; + +class PtrValueType <ValueType scalar, int addrspace> : + ValueType<scalar.Size, scalar.Value> { + int AddrSpace = addrspace; +} diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index 6a8e50a7e5f5..70eb048f05eb 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/VirtRegMap.h - Virtual Register Map ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -68,8 +67,10 @@ class TargetInstrInfo; public: static char ID; - VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), - Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} + VirtRegMap() + : MachineFunctionPass(ID), MRI(nullptr), TII(nullptr), TRI(nullptr), + MF(nullptr), Virt2PhysMap(NO_PHYS_REG), + Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) {} VirtRegMap(const VirtRegMap &) = delete; VirtRegMap &operator=(const VirtRegMap &) = delete; @@ -98,8 +99,8 @@ class TargetInstrInfo; /// returns the physical register mapped to the specified /// virtual register - unsigned getPhys(unsigned virtReg) const { - assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + Register getPhys(Register virtReg) const { + assert(virtReg.isVirtual()); return Virt2PhysMap[virtReg]; } diff --git a/include/llvm/CodeGen/WasmEHFuncInfo.h b/include/llvm/CodeGen/WasmEHFuncInfo.h index 219fff988f6e..887a1467b3e4 100644 --- a/include/llvm/CodeGen/WasmEHFuncInfo.h +++ b/include/llvm/CodeGen/WasmEHFuncInfo.h @@ -1,9 +1,8 @@ //===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -29,10 +28,6 @@ struct WasmEHFuncInfo { // When there is an entry <A, B>, if an exception is not caught by A, it // should next unwind to the EH pad B. DenseMap<BBOrMBB, BBOrMBB> EHPadUnwindMap; - // For entry <A, B>, A is a BB with an instruction that may throw - // (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH - // pad that A unwinds to. - DenseMap<BBOrMBB, BBOrMBB> ThrowUnwindMap; // Helper functions const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const { @@ -41,18 +36,9 @@ struct WasmEHFuncInfo { void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { EHPadUnwindMap[BB] = Dest; } - const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const { - return ThrowUnwindMap.lookup(BB).get<const BasicBlock *>(); - } - void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { - ThrowUnwindMap[BB] = Dest; - } bool hasEHPadUnwindDest(const BasicBlock *BB) const { return EHPadUnwindMap.count(BB); } - bool hasThrowUnwindDest(const BasicBlock *BB) const { - return ThrowUnwindMap.count(BB); - } MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const { return EHPadUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); @@ -60,18 +46,9 @@ struct WasmEHFuncInfo { void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { EHPadUnwindMap[MBB] = Dest; } - MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const { - return ThrowUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); - } - void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { - ThrowUnwindMap[MBB] = Dest; - } bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const { return EHPadUnwindMap.count(MBB); } - bool hasThrowUnwindDest(MachineBasicBlock *MBB) const { - return ThrowUnwindMap.count(MBB); - } }; // Analyze the IR in the given function to build WasmEHFuncInfo. diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 8043024626a0..f098316de793 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -1,9 +1,8 @@ //===- llvm/CodeGen/WinEHFuncInfo.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h index bd1743511ed4..0ac8b651939d 100644 --- a/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h +++ b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h @@ -1,9 +1,8 @@ //===- AppendingTypeTableBuilder.h -------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h index 11ca9ff108de..784c47e3bf5d 100644 --- a/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -1,9 +1,8 @@ -//===- RecordIterator.h -----------------------------------------*- C++ -*-===// +//===- CVRecord.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -25,17 +24,31 @@ namespace llvm { namespace codeview { +/// CVRecord is a fat pointer (base + size pair) to a symbol or type record. +/// Carrying the size separately instead of trusting the size stored in the +/// record prefix provides some extra safety and flexibility. template <typename Kind> class CVRecord { public: - CVRecord() : Type(static_cast<Kind>(0)) {} + CVRecord() = default; + + CVRecord(ArrayRef<uint8_t> Data) : RecordData(Data) {} - CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {} + CVRecord(const RecordPrefix *P, size_t Size) + : RecordData(reinterpret_cast<const uint8_t *>(P), Size) {} - bool valid() const { return Type != static_cast<Kind>(0); } + bool valid() const { return kind() != Kind(0); } uint32_t length() const { return RecordData.size(); } - Kind kind() const { return Type; } + + Kind kind() const { + if (RecordData.size() < sizeof(RecordPrefix)) + return Kind(0); + return static_cast<Kind>(static_cast<uint16_t>( + reinterpret_cast<const RecordPrefix *>(RecordData.data())->RecordKind)); + } + ArrayRef<uint8_t> data() const { return RecordData; } + StringRef str_data() const { return StringRef(reinterpret_cast<const char *>(RecordData.data()), RecordData.size()); @@ -45,7 +58,6 @@ public: return RecordData.drop_front(sizeof(RecordPrefix)); } - Kind Type; ArrayRef<uint8_t> RecordData; }; @@ -72,8 +84,7 @@ Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) { ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen); StreamBuffer = StreamBuffer.drop_front(RealLen); - Record R(static_cast<decltype(Record::Type)>((uint16_t)Prefix->RecordKind), - Data); + Record R(Data); if (auto EC = F(R)) return EC; } @@ -92,13 +103,12 @@ inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream, return std::move(EC); if (Prefix->RecordLen < 2) return make_error<CodeViewError>(cv_error_code::corrupt_record); - Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind)); Reader.setOffset(Offset); ArrayRef<uint8_t> RawData; if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t))) return std::move(EC); - return codeview::CVRecord<Kind>(K, RawData); + return codeview::CVRecord<Kind>(RawData); } } // end namespace codeview diff --git a/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h index 7c8cd121751a..1615ff41df12 100644 --- a/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -1,9 +1,8 @@ //===- CVSymbolVisitor.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index b765ba1abb4d..7d20bb0a7bde 100644 --- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -1,9 +1,8 @@ //===- CVTypeVisitor.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -12,6 +11,7 @@ #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/Support/Error.h" namespace llvm { @@ -31,6 +31,9 @@ enum VisitorDataSource { Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeRecord(CVType &Record, TypeIndex Index, + TypeVisitorCallbackPipeline &Callbacks, + VisitorDataSource Source = VDS_BytesPresent); Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source = VDS_BytesPresent); diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h index 8e0d9f608e93..c3acb05ea8b1 100644 --- a/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/include/llvm/DebugInfo/CodeView/CodeView.h @@ -1,9 +1,8 @@ //===- CodeView.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -160,9 +159,10 @@ enum SourceLanguage : uint8_t { MSIL = 0x0f, HLSL = 0x10, - /// The DMD compiler emits 'D' for the CV source language. Microsoft doesn't - /// have an enumerator for it yet. + /// The DMD & Swift compilers emit 'D' and 'S', respectively, for the CV + /// source language. Microsoft does not have enumerators for them yet. D = 'D', + Swift = 'S', }; /// These values correspond to the CV_call_e enumeration, and are documented @@ -304,6 +304,9 @@ enum class ModifierOptions : uint16_t { }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) +// If the subsection kind has this bit set, then the linker should ignore it. +enum : uint32_t { SubsectionIgnoreFlag = 0x80000000 }; + enum class DebugSubsectionKind : uint32_t { None = 0, Symbols = 0xf1, @@ -509,9 +512,23 @@ enum class FrameCookieKind : uint8_t { // Corresponds to CV_HREG_e enum. enum class RegisterId : uint16_t { +#define CV_REGISTERS_ALL #define CV_REGISTER(name, value) name = value, #include "CodeViewRegisters.def" #undef CV_REGISTER +#undef CV_REGISTERS_ALL +}; + +// Register Ids are shared between architectures in CodeView. CPUType is needed +// to map register Id to name. +struct CPURegister { + CPURegister() = delete; + CPURegister(CPUType Cpu, codeview::RegisterId Reg) { + this->Cpu = Cpu; + this->Reg = Reg; + } + CPUType Cpu; + RegisterId Reg; }; /// Two-bit value indicating which register is the designated frame pointer diff --git a/include/llvm/DebugInfo/CodeView/CodeViewError.h b/include/llvm/DebugInfo/CodeView/CodeViewError.h index d4615d02220d..9990c8d05d1c 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ b/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -1,9 +1,8 @@ //===- CodeViewError.h - Error extensions for CodeView ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index 94f104ff772c..00fb0cf4cc90 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -1,9 +1,8 @@ //===- CodeViewRecordIO.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -25,28 +24,65 @@ #include <type_traits> namespace llvm { + namespace codeview { +class CodeViewRecordStreamer { +public: + virtual void EmitBytes(StringRef Data) = 0; + virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0; + virtual void EmitBinaryData(StringRef Data) = 0; + virtual void AddComment(const Twine &T) = 0; + virtual ~CodeViewRecordStreamer() = default; +}; + class CodeViewRecordIO { uint32_t getCurrentOffset() const { - return (isWriting()) ? Writer->getOffset() : Reader->getOffset(); + if (isWriting()) + return Writer->getOffset(); + else if (isReading()) + return Reader->getOffset(); + else + return 0; } public: + // deserializes records to structures explicit CodeViewRecordIO(BinaryStreamReader &Reader) : Reader(&Reader) {} + + // serializes records to buffer explicit CodeViewRecordIO(BinaryStreamWriter &Writer) : Writer(&Writer) {} + // writes records to assembly file using MC library interface + explicit CodeViewRecordIO(CodeViewRecordStreamer &Streamer) + : Streamer(&Streamer) {} + Error beginRecord(Optional<uint32_t> MaxLength); Error endRecord(); - Error mapInteger(TypeIndex &TypeInd); + Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = ""); - bool isReading() const { return Reader != nullptr; } - bool isWriting() const { return !isReading(); } + bool isStreaming() const { + return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr); + } + bool isReading() const { + return (Reader != nullptr) && (Streamer == nullptr) && (Writer == nullptr); + } + bool isWriting() const { + return (Writer != nullptr) && (Streamer == nullptr) && (Reader == nullptr); + } uint32_t maxFieldLength() const; template <typename T> Error mapObject(T &Value) { + if (isStreaming()) { + StringRef BytesSR = + StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value)); + Streamer->EmitBytes(BytesSR); + incrStreamedLen(sizeof(T)); + return Error::success(); + } + if (isWriting()) return Writer->writeObject(Value); @@ -57,41 +93,63 @@ public: return Error::success(); } - template <typename T> Error mapInteger(T &Value) { + template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") { + if (isStreaming()) { + emitComment(Comment); + Streamer->EmitIntValue((int)Value, sizeof(T)); + incrStreamedLen(sizeof(T)); + return Error::success(); + } + if (isWriting()) return Writer->writeInteger(Value); return Reader->readInteger(Value); } - template <typename T> Error mapEnum(T &Value) { - if (sizeof(Value) > maxFieldLength()) + template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") { + if (!isStreaming() && sizeof(Value) > maxFieldLength()) return make_error<CodeViewError>(cv_error_code::insufficient_buffer); using U = typename std::underlying_type<T>::type; U X; - if (isWriting()) + + if (isWriting() || isStreaming()) X = static_cast<U>(Value); - if (auto EC = mapInteger(X)) + if (auto EC = mapInteger(X, Comment)) return EC; + if (isReading()) Value = static_cast<T>(X); + return Error::success(); } - Error mapEncodedInteger(int64_t &Value); - Error mapEncodedInteger(uint64_t &Value); - Error mapEncodedInteger(APSInt &Value); - Error mapStringZ(StringRef &Value); - Error mapGuid(GUID &Guid); + Error mapEncodedInteger(int64_t &Value, const Twine &Comment = ""); + Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = ""); + Error mapEncodedInteger(APSInt &Value, const Twine &Comment = ""); + Error mapStringZ(StringRef &Value, const Twine &Comment = ""); + Error mapGuid(GUID &Guid, const Twine &Comment = ""); - Error mapStringZVectorZ(std::vector<StringRef> &Value); + Error mapStringZVectorZ(std::vector<StringRef> &Value, + const Twine &Comment = ""); template <typename SizeType, typename T, typename ElementMapper> - Error mapVectorN(T &Items, const ElementMapper &Mapper) { + Error mapVectorN(T &Items, const ElementMapper &Mapper, + const Twine &Comment = "") { SizeType Size; - if (isWriting()) { + if (isStreaming()) { + Size = static_cast<SizeType>(Items.size()); + emitComment(Comment); + Streamer->EmitIntValue(Size, sizeof(Size)); + incrStreamedLen(sizeof(Size)); // add 1 for the delimiter + + for (auto &X : Items) { + if (auto EC = Mapper(*this, X)) + return EC; + } + } else if (isWriting()) { Size = static_cast<SizeType>(Items.size()); if (auto EC = Writer->writeInteger(Size)) return EC; @@ -115,8 +173,10 @@ public: } template <typename T, typename ElementMapper> - Error mapVectorTail(T &Items, const ElementMapper &Mapper) { - if (isWriting()) { + Error mapVectorTail(T &Items, const ElementMapper &Mapper, + const Twine &Comment = "") { + emitComment(Comment); + if (isStreaming() || isWriting()) { for (auto &Item : Items) { if (auto EC = Mapper(*this, Item)) return EC; @@ -133,16 +193,44 @@ public: return Error::success(); } - Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes); - Error mapByteVectorTail(std::vector<uint8_t> &Bytes); + Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes, const Twine &Comment = ""); + Error mapByteVectorTail(std::vector<uint8_t> &Bytes, + const Twine &Comment = ""); Error padToAlignment(uint32_t Align); Error skipPadding(); + uint64_t getStreamedLen() { + if (isStreaming()) + return StreamedLen; + return 0; + } + private: + void emitEncodedSignedInteger(const int64_t &Value, + const Twine &Comment = ""); + void emitEncodedUnsignedInteger(const uint64_t &Value, + const Twine &Comment = ""); Error writeEncodedSignedInteger(const int64_t &Value); Error writeEncodedUnsignedInteger(const uint64_t &Value); + void incrStreamedLen(const uint64_t &Len) { + if (isStreaming()) + StreamedLen += Len; + } + + void resetStreamedLen() { + if (isStreaming()) + StreamedLen = 4; // The record prefix is 4 bytes long + } + + void emitComment(const Twine &Comment) { + if (isStreaming()) { + Twine TComment(Comment); + Streamer->AddComment(TComment); + } + } + struct RecordLimit { uint32_t BeginOffset; Optional<uint32_t> MaxLength; @@ -163,6 +251,8 @@ private: BinaryStreamReader *Reader = nullptr; BinaryStreamWriter *Writer = nullptr; + CodeViewRecordStreamer *Streamer = nullptr; + uint64_t StreamedLen = 0; }; } // end namespace codeview diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def index fdfcf4d53a23..9767e49c44f5 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def +++ b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -1,9 +1,8 @@ //===-- CodeViewRegisters.def - CodeView registers --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,8 +14,15 @@ #define CV_REGISTER(name, value) #endif +#if !defined(CV_REGISTERS_ALL) && !defined(CV_REGISTERS_X86) && \ + !defined(CV_REGISTERS_ARM64) +#error Need include at least one register set. +#endif + // This currently only contains the "register subset shared by all processor -// types" (ERR etc.) and the x86 registers. +// types" (ERR etc.) and the x86/arm64 registers. + +#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_X86) // Some system headers define macros that conflict with our enums. Every // compiler supported by LLVM has the push_macro and pop_macro pragmas, so use @@ -357,3 +363,197 @@ CV_REGISTER(AMD64_K7, 765) #pragma pop_macro("CR2") #pragma pop_macro("CR3") #pragma pop_macro("CR4") + +#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_X86) + +#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64) + +// ARM64 registers + +CV_REGISTER(ARM64_NOREG, 0) + +// General purpose 32-bit integer registers + +CV_REGISTER(ARM64_W0, 10) +CV_REGISTER(ARM64_W1, 11) +CV_REGISTER(ARM64_W2, 12) +CV_REGISTER(ARM64_W3, 13) +CV_REGISTER(ARM64_W4, 14) +CV_REGISTER(ARM64_W5, 15) +CV_REGISTER(ARM64_W6, 16) +CV_REGISTER(ARM64_W7, 17) +CV_REGISTER(ARM64_W8, 18) +CV_REGISTER(ARM64_W9, 19) +CV_REGISTER(ARM64_W10, 20) +CV_REGISTER(ARM64_W11, 21) +CV_REGISTER(ARM64_W12, 22) +CV_REGISTER(ARM64_W13, 23) +CV_REGISTER(ARM64_W14, 24) +CV_REGISTER(ARM64_W15, 25) +CV_REGISTER(ARM64_W16, 26) +CV_REGISTER(ARM64_W17, 27) +CV_REGISTER(ARM64_W18, 28) +CV_REGISTER(ARM64_W19, 29) +CV_REGISTER(ARM64_W20, 30) +CV_REGISTER(ARM64_W21, 31) +CV_REGISTER(ARM64_W22, 32) +CV_REGISTER(ARM64_W23, 33) +CV_REGISTER(ARM64_W24, 34) +CV_REGISTER(ARM64_W25, 35) +CV_REGISTER(ARM64_W26, 36) +CV_REGISTER(ARM64_W27, 37) +CV_REGISTER(ARM64_W28, 38) +CV_REGISTER(ARM64_W29, 39) +CV_REGISTER(ARM64_W30, 40) +CV_REGISTER(ARM64_WZR, 41) + +// General purpose 64-bit integer registers + +CV_REGISTER(ARM64_X0, 50) +CV_REGISTER(ARM64_X1, 51) +CV_REGISTER(ARM64_X2, 52) +CV_REGISTER(ARM64_X3, 53) +CV_REGISTER(ARM64_X4, 54) +CV_REGISTER(ARM64_X5, 55) +CV_REGISTER(ARM64_X6, 56) +CV_REGISTER(ARM64_X7, 57) +CV_REGISTER(ARM64_X8, 58) +CV_REGISTER(ARM64_X9, 59) +CV_REGISTER(ARM64_X10, 60) +CV_REGISTER(ARM64_X11, 61) +CV_REGISTER(ARM64_X12, 62) +CV_REGISTER(ARM64_X13, 63) +CV_REGISTER(ARM64_X14, 64) +CV_REGISTER(ARM64_X15, 65) +CV_REGISTER(ARM64_X16, 66) +CV_REGISTER(ARM64_X17, 67) +CV_REGISTER(ARM64_X18, 68) +CV_REGISTER(ARM64_X19, 69) +CV_REGISTER(ARM64_X20, 70) +CV_REGISTER(ARM64_X21, 71) +CV_REGISTER(ARM64_X22, 72) +CV_REGISTER(ARM64_X23, 73) +CV_REGISTER(ARM64_X24, 74) +CV_REGISTER(ARM64_X25, 75) +CV_REGISTER(ARM64_X26, 76) +CV_REGISTER(ARM64_X27, 77) +CV_REGISTER(ARM64_X28, 78) +CV_REGISTER(ARM64_FP, 79) +CV_REGISTER(ARM64_LR, 80) +CV_REGISTER(ARM64_SP, 81) +CV_REGISTER(ARM64_ZR, 82) + +// status register + +CV_REGISTER(ARM64_NZCV, 90) + +// 32-bit floating point registers + +CV_REGISTER(ARM64_S0, 100) +CV_REGISTER(ARM64_S1, 101) +CV_REGISTER(ARM64_S2, 102) +CV_REGISTER(ARM64_S3, 103) +CV_REGISTER(ARM64_S4, 104) +CV_REGISTER(ARM64_S5, 105) +CV_REGISTER(ARM64_S6, 106) +CV_REGISTER(ARM64_S7, 107) +CV_REGISTER(ARM64_S8, 108) +CV_REGISTER(ARM64_S9, 109) +CV_REGISTER(ARM64_S10, 110) +CV_REGISTER(ARM64_S11, 111) +CV_REGISTER(ARM64_S12, 112) +CV_REGISTER(ARM64_S13, 113) +CV_REGISTER(ARM64_S14, 114) +CV_REGISTER(ARM64_S15, 115) +CV_REGISTER(ARM64_S16, 116) +CV_REGISTER(ARM64_S17, 117) +CV_REGISTER(ARM64_S18, 118) +CV_REGISTER(ARM64_S19, 119) +CV_REGISTER(ARM64_S20, 120) +CV_REGISTER(ARM64_S21, 121) +CV_REGISTER(ARM64_S22, 122) +CV_REGISTER(ARM64_S23, 123) +CV_REGISTER(ARM64_S24, 124) +CV_REGISTER(ARM64_S25, 125) +CV_REGISTER(ARM64_S26, 126) +CV_REGISTER(ARM64_S27, 127) +CV_REGISTER(ARM64_S28, 128) +CV_REGISTER(ARM64_S29, 129) +CV_REGISTER(ARM64_S30, 130) +CV_REGISTER(ARM64_S31, 131) + +// 64-bit floating point registers + +CV_REGISTER(ARM64_D0, 140) +CV_REGISTER(ARM64_D1, 141) +CV_REGISTER(ARM64_D2, 142) +CV_REGISTER(ARM64_D3, 143) +CV_REGISTER(ARM64_D4, 144) +CV_REGISTER(ARM64_D5, 145) +CV_REGISTER(ARM64_D6, 146) +CV_REGISTER(ARM64_D7, 147) +CV_REGISTER(ARM64_D8, 148) +CV_REGISTER(ARM64_D9, 149) +CV_REGISTER(ARM64_D10, 150) +CV_REGISTER(ARM64_D11, 151) +CV_REGISTER(ARM64_D12, 152) +CV_REGISTER(ARM64_D13, 153) +CV_REGISTER(ARM64_D14, 154) +CV_REGISTER(ARM64_D15, 155) +CV_REGISTER(ARM64_D16, 156) +CV_REGISTER(ARM64_D17, 157) +CV_REGISTER(ARM64_D18, 158) +CV_REGISTER(ARM64_D19, 159) +CV_REGISTER(ARM64_D20, 160) +CV_REGISTER(ARM64_D21, 161) +CV_REGISTER(ARM64_D22, 162) +CV_REGISTER(ARM64_D23, 163) +CV_REGISTER(ARM64_D24, 164) +CV_REGISTER(ARM64_D25, 165) +CV_REGISTER(ARM64_D26, 166) +CV_REGISTER(ARM64_D27, 167) +CV_REGISTER(ARM64_D28, 168) +CV_REGISTER(ARM64_D29, 169) +CV_REGISTER(ARM64_D30, 170) +CV_REGISTER(ARM64_D31, 171) + +// 128-bit SIMD registers + +CV_REGISTER(ARM64_Q0, 180) +CV_REGISTER(ARM64_Q1, 181) +CV_REGISTER(ARM64_Q2, 182) +CV_REGISTER(ARM64_Q3, 183) +CV_REGISTER(ARM64_Q4, 184) +CV_REGISTER(ARM64_Q5, 185) +CV_REGISTER(ARM64_Q6, 186) +CV_REGISTER(ARM64_Q7, 187) +CV_REGISTER(ARM64_Q8, 188) +CV_REGISTER(ARM64_Q9, 189) +CV_REGISTER(ARM64_Q10, 190) +CV_REGISTER(ARM64_Q11, 191) +CV_REGISTER(ARM64_Q12, 192) +CV_REGISTER(ARM64_Q13, 193) +CV_REGISTER(ARM64_Q14, 194) +CV_REGISTER(ARM64_Q15, 195) +CV_REGISTER(ARM64_Q16, 196) +CV_REGISTER(ARM64_Q17, 197) +CV_REGISTER(ARM64_Q18, 198) +CV_REGISTER(ARM64_Q19, 199) +CV_REGISTER(ARM64_Q20, 200) +CV_REGISTER(ARM64_Q21, 201) +CV_REGISTER(ARM64_Q22, 202) +CV_REGISTER(ARM64_Q23, 203) +CV_REGISTER(ARM64_Q24, 204) +CV_REGISTER(ARM64_Q25, 205) +CV_REGISTER(ARM64_Q26, 206) +CV_REGISTER(ARM64_Q27, 207) +CV_REGISTER(ARM64_Q28, 208) +CV_REGISTER(ARM64_Q29, 209) +CV_REGISTER(ARM64_Q30, 210) +CV_REGISTER(ARM64_Q31, 211) + +// Floating point status register + +CV_REGISTER(ARM64_FPSR, 220) + +#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64) diff --git a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def index b5f1cc0198dc..4f8ccfdd16af 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def +++ b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def @@ -1,9 +1,8 @@ //===-- CodeViewSymbols.def - All CodeView leaf types -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -103,7 +102,6 @@ CV_SYMBOL(S_LPROCIA64_ST , 0x1015) CV_SYMBOL(S_GPROCIA64_ST , 0x1016) CV_SYMBOL(S_LOCALSLOT_ST , 0x1017) CV_SYMBOL(S_PARAMSLOT_ST , 0x1018) -CV_SYMBOL(S_ANNOTATION , 0x1019) CV_SYMBOL(S_GMANPROC_ST , 0x101a) CV_SYMBOL(S_LMANPROC_ST , 0x101b) CV_SYMBOL(S_RESERVED1 , 0x101c) @@ -255,6 +253,7 @@ SYMBOL_RECORD(S_LTHREAD32 , 0x1112, ThreadLocalDataSym) SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym) SYMBOL_RECORD(S_UNAMESPACE , 0x1124, UsingNamespaceSym) +SYMBOL_RECORD(S_ANNOTATION , 0x1019, AnnotationSym) #undef CV_SYMBOL #undef SYMBOL_RECORD diff --git a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def index e9a479dba496..a31111eb80a4 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def +++ b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def @@ -1,9 +1,8 @@ //===-- CodeViewTypes.def - All CodeView leaf types -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h index 7f851a2595dc..53ab2dd04aa7 100644 --- a/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h +++ b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h @@ -1,9 +1,8 @@ //===- ContinuationRecordBuilder.h ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -62,4 +61,4 @@ public: } // namespace codeview } // namespace llvm -#endif
\ No newline at end of file +#endif diff --git a/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h b/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h index 78b284563afd..01f83676afdf 100644 --- a/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h @@ -1,9 +1,8 @@ //===- DebugChecksumsSubsection.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h b/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h index 2f9e9814d998..64a78a7cef21 100644 --- a/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugCrossExSubsection.h @@ -1,9 +1,8 @@ //===- DebugCrossExSubsection.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h b/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h index 8be7ef265c82..e7683cb2a9c4 100644 --- a/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h @@ -1,9 +1,8 @@ -//===- DebugCrossExSubsection.h ---------------------------------*- C++ -*-===// +//===- DebugCrossImpSubsection.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h index 847d93f0e985..d5cd640231f9 100644 --- a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -1,9 +1,8 @@ //===- DebugFrameDataSubsection.h ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h index b88c0eae1de2..9fd88a64873a 100644 --- a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -1,9 +1,8 @@ //===- DebugInlineeLinesSubsection.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -71,6 +70,11 @@ public: } Error initialize(BinaryStreamReader Reader); + Error initialize(BinaryStreamRef Section) { + return initialize(BinaryStreamReader(Section)); + } + + bool valid() const { return Lines.valid(); } bool hasExtraFiles() const; Iterator begin() const { return Lines.begin(); } @@ -78,7 +82,7 @@ public: private: InlineeLinesSignature Signature; - VarStreamArray<InlineeSourceLine> Lines; + LinesArray Lines; }; class DebugInlineeLinesSubsection final : public DebugSubsection { diff --git a/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h b/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h index 53044b6c3dc8..1f8e56c5311f 100644 --- a/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugLinesSubsection.h @@ -1,9 +1,8 @@ //===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h index bebc960223cc..6e5b8adddd4a 100644 --- a/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -1,9 +1,8 @@ //===- DebugStringTableSubsection.h - CodeView String Table -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsection.h b/include/llvm/DebugInfo/CodeView/DebugSubsection.h index e427e0006a55..66272870efda 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsection.h @@ -1,9 +1,8 @@ //===- DebugSubsection.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index fc0cf0d1d90e..bcb379f00d68 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -1,9 +1,8 @@ //===- DebugSubsectionRecord.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 75f749dfa933..720b1b49581f 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -1,9 +1,8 @@ //===- DebugSubsectionVisitor.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h b/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h index a4c04b55eb4c..91b740ce6b9a 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h @@ -1,9 +1,8 @@ //===- DebugSymbolRVASubsection.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h index dfda7deb6cb4..784fc59484b9 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -1,9 +1,8 @@ //===- DebugSymbolsSubsection.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h b/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h index ea9a96ca8d68..fa7df325499f 100644 --- a/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugUnknownSubsection.h @@ -1,9 +1,8 @@ //===- DebugUnknownSubsection.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/EnumTables.h b/include/llvm/DebugInfo/CodeView/EnumTables.h index ee0f0f7c6023..ed126ed9e2ff 100644 --- a/include/llvm/DebugInfo/CodeView/EnumTables.h +++ b/include/llvm/DebugInfo/CodeView/EnumTables.h @@ -1,9 +1,8 @@ //===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -21,7 +20,7 @@ namespace codeview { ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames(); ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames(); -ArrayRef<EnumEntry<uint16_t>> getRegisterNames(); +ArrayRef<EnumEntry<uint16_t>> getRegisterNames(CPUType Cpu); ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames(); ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames(); ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames(); diff --git a/include/llvm/DebugInfo/CodeView/Formatters.h b/include/llvm/DebugInfo/CodeView/Formatters.h index 278ad02a39cd..7d04a6a89bef 100644 --- a/include/llvm/DebugInfo/CodeView/Formatters.h +++ b/include/llvm/DebugInfo/CodeView/Formatters.h @@ -1,9 +1,8 @@ //===- Formatters.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/FunctionId.h b/include/llvm/DebugInfo/CodeView/FunctionId.h index 1af3da810b5a..bc102278819c 100644 --- a/include/llvm/DebugInfo/CodeView/FunctionId.h +++ b/include/llvm/DebugInfo/CodeView/FunctionId.h @@ -1,9 +1,8 @@ //===- FunctionId.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/GUID.h b/include/llvm/DebugInfo/CodeView/GUID.h index a055ce9e2e45..5f807e6f7eeb 100644 --- a/include/llvm/DebugInfo/CodeView/GUID.h +++ b/include/llvm/DebugInfo/CodeView/GUID.h @@ -1,9 +1,8 @@ //===- GUID.h ---------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h index c4704168ed34..a43ce20edde6 100644 --- a/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h +++ b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h @@ -1,9 +1,8 @@ //===- GlobalTypeTableBuilder.h ----------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -74,14 +73,30 @@ public: CreateFunc Create) { auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex()); - if (LLVM_UNLIKELY(Result.second)) { + if (LLVM_UNLIKELY(Result.second /*inserted*/ || + Result.first->second.isSimple())) { uint8_t *Stable = RecordStorage.Allocate<uint8_t>(RecordSize); MutableArrayRef<uint8_t> Data(Stable, RecordSize); - SeenRecords.push_back(Create(Data)); + ArrayRef<uint8_t> StableRecord = Create(Data); + if (StableRecord.empty()) { + // Records with forward references into the Type stream will be deferred + // for insertion at a later time, on the second pass. + Result.first->getSecond() = TypeIndex(SimpleTypeKind::NotTranslated); + return TypeIndex(SimpleTypeKind::NotTranslated); + } + if (Result.first->second.isSimple()) { + assert(Result.first->second.getIndex() == + (uint32_t)SimpleTypeKind::NotTranslated); + // On the second pass, update with index to remapped record. The + // (initially misbehaved) record will now come *after* other records + // resolved in the first pass, with proper *back* references in the + // stream. + Result.first->second = nextTypeIndex(); + } + SeenRecords.push_back(StableRecord); SeenHashes.push_back(Hash); } - // Update the caller's copy of Record to point a stable copy. return Result.first->second; } diff --git a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h index 383f7dd9fb6a..4e03627e9580 100644 --- a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h +++ b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -1,9 +1,8 @@ //===- LazyRandomTypeCollection.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/Line.h b/include/llvm/DebugInfo/CodeView/Line.h index ac229c337513..eb2aa154df1b 100644 --- a/include/llvm/DebugInfo/CodeView/Line.h +++ b/include/llvm/DebugInfo/CodeView/Line.h @@ -1,9 +1,8 @@ //===- Line.h ---------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h index 9030918ebbb3..1b2f6d29a9b6 100644 --- a/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h +++ b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h @@ -1,9 +1,8 @@ //===- MergingTypeTableBuilder.h ---------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/RecordName.h b/include/llvm/DebugInfo/CodeView/RecordName.h index b022108df3d6..cc09db8933bd 100644 --- a/include/llvm/DebugInfo/CodeView/RecordName.h +++ b/include/llvm/DebugInfo/CodeView/RecordName.h @@ -1,9 +1,8 @@ //===- RecordName.h ------------------------------------------- *- C++ --*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/RecordSerialization.h b/include/llvm/DebugInfo/CodeView/RecordSerialization.h index 36237e1a4d9e..36c0f2fbd8fa 100644 --- a/include/llvm/DebugInfo/CodeView/RecordSerialization.h +++ b/include/llvm/DebugInfo/CodeView/RecordSerialization.h @@ -1,9 +1,8 @@ //===- RecordSerialization.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -32,6 +31,9 @@ using llvm::support::ulittle32_t; enum : unsigned { MaxRecordLength = 0xFF00 }; struct RecordPrefix { + RecordPrefix() = default; + explicit RecordPrefix(uint16_t Kind) : RecordLen(2), RecordKind(Kind) {} + ulittle16_t RecordLen; // Record length, starting from &RecordKind. ulittle16_t RecordKind; // Record kind enum (SymRecordKind or TypeRecordKind) }; diff --git a/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h index a85d9270186b..3ca09b445a30 100644 --- a/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h +++ b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h @@ -1,9 +1,8 @@ //===- SimpleTypeSerializer.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h index 22a333e631a0..22a283e785e1 100644 --- a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h +++ b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h @@ -1,9 +1,8 @@ //===- StringsAndChecksums.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h index 6b5dd2d20d17..62761cb87c81 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -1,9 +1,8 @@ //===- SymbolDeserializer.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h index 823636c398de..12f45dcb21ff 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h +++ b/include/llvm/DebugInfo/CodeView/SymbolDumpDelegate.h @@ -1,9 +1,8 @@ //===-- SymbolDumpDelegate.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/include/llvm/DebugInfo/CodeView/SymbolDumper.h index 215da2e2b522..d832a48b1265 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -1,9 +1,8 @@ //===-- SymbolDumper.h - CodeView symbol info dumper ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index b58825c4a788..5e9a7432b9b6 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -1,9 +1,8 @@ //===- SymbolRecord.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -14,6 +13,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" @@ -156,15 +156,19 @@ public: uint32_t RecordOffset; }; -struct BinaryAnnotationIterator { - struct AnnotationData { - BinaryAnnotationsOpCode OpCode; - StringRef Name; - uint32_t U1; - uint32_t U2; - int32_t S1; - }; +struct DecodedAnnotation { + StringRef Name; + ArrayRef<uint8_t> Bytes; + BinaryAnnotationsOpCode OpCode; + uint32_t U1 = 0; + uint32_t U2 = 0; + int32_t S1 = 0; +}; +struct BinaryAnnotationIterator + : public iterator_facade_base<BinaryAnnotationIterator, + std::forward_iterator_tag, + DecodedAnnotation> { BinaryAnnotationIterator() = default; BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {} BinaryAnnotationIterator(const BinaryAnnotationIterator &Other) @@ -174,10 +178,6 @@ struct BinaryAnnotationIterator { return Data == Other.Data; } - bool operator!=(const BinaryAnnotationIterator &Other) const { - return !(*this == Other); - } - BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) { Data = Other.Data; return *this; @@ -194,13 +194,7 @@ struct BinaryAnnotationIterator { return *this; } - BinaryAnnotationIterator operator++(int) { - BinaryAnnotationIterator Orig(*this); - ++(*this); - return Orig; - } - - const AnnotationData &operator*() { + const DecodedAnnotation &operator*() { ParseCurrentAnnotation(); return Current.getValue(); } @@ -242,17 +236,17 @@ private: (ThirdByte << 8) | FourthByte; return -1; - }; + } static int32_t DecodeSignedOperand(uint32_t Operand) { if (Operand & 1) return -(Operand >> 1); return Operand >> 1; - }; + } static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) { return DecodeSignedOperand(GetCompressedAnnotation(Annotations)); - }; + } bool ParseCurrentAnnotation() { if (Current.hasValue()) @@ -260,7 +254,7 @@ private: Next = Data; uint32_t Op = GetCompressedAnnotation(Next); - AnnotationData Result; + DecodedAnnotation Result; Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op); switch (Result.OpCode) { case BinaryAnnotationsOpCode::Invalid: @@ -325,11 +319,12 @@ private: break; } } + Result.Bytes = Data.take_front(Data.size() - Next.size()); Current = Result; return true; } - Optional<AnnotationData> Current; + Optional<DecodedAnnotation> Current; ArrayRef<uint8_t> Data; ArrayRef<uint8_t> Next; }; @@ -974,7 +969,7 @@ class UsingNamespaceSym : public SymbolRecord { public: explicit UsingNamespaceSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} explicit UsingNamespaceSym(uint32_t RecordOffset) - : SymbolRecord(SymbolRecordKind::RegRelativeSym), + : SymbolRecord(SymbolRecordKind::UsingNamespaceSym), RecordOffset(RecordOffset) {} StringRef Name; @@ -983,6 +978,19 @@ public: }; // S_ANNOTATION +class AnnotationSym : public SymbolRecord { +public: + explicit AnnotationSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} + explicit AnnotationSym(uint32_t RecordOffset) + : SymbolRecord(SymbolRecordKind::AnnotationSym), + RecordOffset(RecordOffset) {} + + uint32_t CodeOffset = 0; + uint16_t Segment = 0; + std::vector<StringRef> Strings; + + uint32_t RecordOffset; +}; using CVSymbol = CVRecord<SymbolKind>; using CVSymbolArray = VarStreamArray<CVSymbol>; diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h b/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h index 3713fe118eaa..57dbc56c0769 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h @@ -1,9 +1,8 @@ //===- SymbolRecordHelpers.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h index 391e8f127665..34368b6185d6 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecordMapping.h @@ -1,9 +1,8 @@ //===- SymbolRecordMapping.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h index f4d8ab0c3c2e..b805b6595e80 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h +++ b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h @@ -1,9 +1,8 @@ //===- SymbolSerializer.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -52,8 +51,8 @@ public: template <typename SymType> static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, CodeViewContainer Container) { - CVSymbol Result; - Result.Type = static_cast<SymbolKind>(Sym.Kind); + RecordPrefix Prefix{uint16_t(Sym.Kind)}; + CVSymbol Result(&Prefix, sizeof(Prefix)); SymbolSerializer Serializer(Storage, Container); consumeError(Serializer.visitSymbolBegin(Result)); consumeError(Serializer.visitKnownRecord(Result, Sym)); diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h index e29511a67b7f..145d63a6fe61 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h +++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h @@ -1,9 +1,8 @@ //===- SymbolVisitorCallbackPipeline.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h index 0816f7c62656..1a4d5b9d31df 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h +++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h @@ -1,9 +1,8 @@ //===- SymbolVisitorCallbacks.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h index a2a3c6f18fba..368d8b288315 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h +++ b/include/llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h @@ -1,9 +1,8 @@ //===-- SymbolVisitorDelegate.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeCollection.h b/include/llvm/DebugInfo/CodeView/TypeCollection.h index e9fc9b0de8ef..58b1dd058c1a 100644 --- a/include/llvm/DebugInfo/CodeView/TypeCollection.h +++ b/include/llvm/DebugInfo/CodeView/TypeCollection.h @@ -1,9 +1,8 @@ //===- TypeCollection.h - A collection of CodeView type records -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h index 9887d901773a..081de32dd02c 100644 --- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -1,9 +1,8 @@ //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -59,7 +58,7 @@ public: TypeRecordKind K = static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind)); T Record(K); - CVType CVT(static_cast<TypeLeafKind>(K), Data); + CVType CVT(Data); if (auto EC = deserializeAs<T>(CVT, Record)) return std::move(EC); return Record; @@ -112,14 +111,14 @@ class FieldListDeserializer : public TypeVisitorCallbacks { public: explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) { - CVType FieldList; - FieldList.Type = TypeLeafKind::LF_FIELDLIST; + RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST)); + CVType FieldList(&Pre, sizeof(Pre)); consumeError(Mapping.Mapping.visitTypeBegin(FieldList)); } ~FieldListDeserializer() override { - CVType FieldList; - FieldList.Type = TypeLeafKind::LF_FIELDLIST; + RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST)); + CVType FieldList(&Pre, sizeof(Pre)); consumeError(Mapping.Mapping.visitTypeEnd(FieldList)); } diff --git a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h index afb8b3636361..41a219ae5a7b 100644 --- a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h +++ b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -1,9 +1,8 @@ //===-- TypeDumpVisitor.h - CodeView type info dumper -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeHashing.h b/include/llvm/DebugInfo/CodeView/TypeHashing.h index 1f732d29a538..b0a16cccbff3 100644 --- a/include/llvm/DebugInfo/CodeView/TypeHashing.h +++ b/include/llvm/DebugInfo/CodeView/TypeHashing.h @@ -1,9 +1,8 @@ //===- TypeHashing.h ---------------------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -85,6 +84,8 @@ struct GloballyHashedType { } std::array<uint8_t, 8> Hash; + bool empty() const { return *(const uint64_t*)Hash.data() == 0; } + /// Given a sequence of bytes representing a record, compute a global hash for /// this record. Due to the nature of global hashes incorporating the hashes /// of referenced records, this function requires a list of types and ids @@ -108,8 +109,33 @@ struct GloballyHashedType { template <typename Range> static std::vector<GloballyHashedType> hashTypes(Range &&Records) { std::vector<GloballyHashedType> Hashes; - for (const auto &R : Records) - Hashes.push_back(hashType(R, Hashes, Hashes)); + bool UnresolvedRecords = false; + for (const auto &R : Records) { + GloballyHashedType H = hashType(R, Hashes, Hashes); + if (H.empty()) + UnresolvedRecords = true; + Hashes.push_back(H); + } + + // In some rare cases, there might be records with forward references in the + // stream. Several passes might be needed to fully hash each record in the + // Type stream. However this occurs on very small OBJs generated by MASM, + // with a dozen records at most. Therefore this codepath isn't + // time-critical, as it isn't taken in 99% of cases. + while (UnresolvedRecords) { + UnresolvedRecords = false; + auto HashIt = Hashes.begin(); + for (const auto &R : Records) { + if (HashIt->empty()) { + GloballyHashedType H = hashType(R, Hashes, Hashes); + if (H.empty()) + UnresolvedRecords = true; + else + *HashIt = H; + } + ++HashIt; + } + } return Hashes; } diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h index 58463a6b13df..b9e2562bfc2b 100644 --- a/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -1,9 +1,8 @@ //===- TypeIndex.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h index c424a09ece89..469768787274 100644 --- a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h +++ b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h @@ -1,9 +1,8 @@ //===- TypeIndexDiscovery.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h index 7b4a30ee622d..b147dd6c3d05 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -1,9 +1,8 @@ //===- TypeRecord.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h index 389472ed1aea..e84704d99ddc 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h +++ b/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h @@ -1,9 +1,8 @@ //===- TypeRecordHelpers.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h index cbe8d6066bb9..4c309c10ff0c 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h +++ b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h @@ -1,9 +1,8 @@ //===- TypeRecordMapping.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -24,9 +23,11 @@ class TypeRecordMapping : public TypeVisitorCallbacks { public: explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {} explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {} + explicit TypeRecordMapping(CodeViewRecordStreamer &Streamer) : IO(Streamer) {} using TypeVisitorCallbacks::visitTypeBegin; Error visitTypeBegin(CVType &Record) override; + Error visitTypeBegin(CVType &Record, TypeIndex Index) override; Error visitTypeEnd(CVType &Record) override; Error visitMemberBegin(CVMemberRecord &Record) override; diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index 0b9f54ec60bf..d0506cce8176 100644 --- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -1,9 +1,8 @@ //===- TypeStreamMerger.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h b/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h index dfba83d62fce..4f2e5deb10b4 100644 --- a/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h +++ b/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h @@ -1,9 +1,8 @@ //===- TypeSymbolEmitter.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h index 80326a0ffd39..5cbe3400e029 100644 --- a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h +++ b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h @@ -1,9 +1,8 @@ //===- TypeTableCollection.h ---------------------------------- *- C++ --*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h index 126fb8abb0da..169715be2d52 100644 --- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h +++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h @@ -1,9 +1,8 @@ //===- TypeVisitorCallbackPipeline.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -83,6 +82,11 @@ public: Pipeline.push_back(&Callbacks); } + void addCallbackToPipelineFront(TypeVisitorCallbacks &Callbacks) { + auto CallBackItr = Pipeline.begin(); + Pipeline.insert(CallBackItr, &Callbacks); + } + #define TYPE_RECORD(EnumName, EnumVal, Name) \ Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ return visitKnownRecordImpl(CVR, Record); \ diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h index d7a473306bc2..33f8b1f24b1b 100644 --- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h +++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h @@ -1,9 +1,8 @@ //===- TypeVisitorCallbacks.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 85e96402a246..d2a5318179eb 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -1,9 +1,8 @@ //===- DIContext.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -98,11 +97,10 @@ public: void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); } - + void resize(unsigned i) { Frames.resize(i); } - }; /// Container for description of a global variable. @@ -114,6 +112,16 @@ struct DIGlobal { DIGlobal() : Name("<invalid>") {} }; +struct DILocal { + std::string FunctionName; + std::string Name; + std::string DeclFile; + uint64_t DeclLine = 0; + Optional<int64_t> FrameOffset; + Optional<uint64_t> Size; + Optional<uint64_t> TagOffset; +}; + /// A DINameKind is passed to name search methods to specify a /// preference regarding the type of name resolution the caller wants. enum class DINameKind { None, ShortName, LinkageName }; @@ -158,7 +166,8 @@ enum DIDumpType : unsigned { /// dumped. struct DIDumpOptions { unsigned DumpType = DIDT_All; - unsigned RecurseDepth = -1U; + unsigned ChildRecurseDepth = -1U; + unsigned ParentRecurseDepth = -1U; uint16_t Version = 0; // DWARF version to assume when extracting. uint8_t AddrSize = 4; // Address byte size to assume when extracting. bool ShowAddresses = true; @@ -172,15 +181,18 @@ struct DIDumpOptions { /// Return default option set for printing a single DIE without children. static DIDumpOptions getForSingleDIE() { DIDumpOptions Opts; - Opts.RecurseDepth = 0; + Opts.ChildRecurseDepth = 0; + Opts.ParentRecurseDepth = 0; return Opts; } /// Return the options with RecurseDepth set to 0 unless explicitly required. DIDumpOptions noImplicitRecursion() const { DIDumpOptions Opts = *this; - if (RecurseDepth == -1U && !ShowChildren) - Opts.RecurseDepth = 0; + if (ChildRecurseDepth == -1U && !ShowChildren) + Opts.ChildRecurseDepth = 0; + if (ParentRecurseDepth == -1U && !ShowParents) + Opts.ParentRecurseDepth = 0; return Opts; } }; @@ -204,12 +216,18 @@ public: return true; } - virtual DILineInfo getLineInfoForAddress(uint64_t Address, + virtual DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + virtual DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + + virtual std::vector<DILocal> + getLocalsForAddress(object::SectionedAddress Address) = 0; private: const DIContextKind Kind; diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 84b23398b8cc..ccf2891c2e21 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -1,9 +1,8 @@ //===- DWARFAbbreviationDeclaration.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 1d448728338f..303375703d2e 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -1,9 +1,8 @@ //===- DWARFAcceleratorTable.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -72,7 +71,7 @@ public: : AccelSection(AccelSection), StringSection(StringSection) {} virtual ~DWARFAcceleratorTable(); - virtual llvm::Error extract() = 0; + virtual Error extract() = 0; virtual void dump(raw_ostream &OS) const = 0; DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete; @@ -175,7 +174,7 @@ public: DataExtractor StringSection) : DWARFAcceleratorTable(AccelSection, StringSection) {} - llvm::Error extract() override; + Error extract() override; uint32_t getNumBuckets(); uint32_t getNumHashes(); uint32_t getSizeHdr(); @@ -223,7 +222,7 @@ public: /// referenced by the name table and interpreted with the help of the /// abbreviation table. class DWARFDebugNames : public DWARFAcceleratorTable { - /// The fixed-size part of a Dwarf 5 Name Index header + /// The fixed-size part of a DWARF v5 Name Index header struct HeaderPOD { uint32_t UnitLength; uint16_t Version; @@ -242,7 +241,7 @@ public: class NameIterator; class ValueIterator; - /// Dwarf 5 Name Index header. + /// DWARF v5 Name Index header. struct Header : public HeaderPOD { SmallString<8> AugmentationString; @@ -349,7 +348,7 @@ private: }; public: - /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name + /// A single entry in the Name Table (DWARF v5 sect. 6.1.1.4.6) of the Name /// Index. class NameTableEntry { DataExtractor StrData; @@ -381,7 +380,7 @@ public: uint32_t getEntryOffset() const { return EntryOffset; } }; - /// Represents a single accelerator table within the Dwarf 5 .debug_names + /// Represents a single accelerator table within the DWARF v5 .debug_names /// section. class NameIndex { DenseSet<Abbrev, AbbrevMapInfo> Abbrevs; @@ -460,7 +459,7 @@ public: NameIterator begin() const { return NameIterator(this, 1); } NameIterator end() const { return NameIterator(this, getNameCount() + 1); } - llvm::Error extract(); + Error extract(); uint32_t getUnitOffset() const { return Base; } uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } void dump(ScopedPrinter &W) const; @@ -580,7 +579,7 @@ public: DataExtractor StringSection) : DWARFAcceleratorTable(AccelSection, StringSection) {} - llvm::Error extract() override; + Error extract() override; void dump(raw_ostream &OS) const override; /// Look up all entries in the accelerator table matching \c Key. diff --git a/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h index 5a7df5c353e8..2d5f9f3c7658 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h @@ -1,9 +1,8 @@ //===- DWARFAddressRange.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -43,12 +42,6 @@ struct DWARFAddressRange { return LowPC < RHS.HighPC && RHS.LowPC < HighPC; } - /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC). - bool contains(const DWARFAddressRange &RHS) const { - assert(valid() && RHS.valid()); - return LowPC <= RHS.LowPC && RHS.HighPC <= HighPC; - } - void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts = {}) const; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h index f0672bb0ca75..c8ad19ad6bf6 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAttribute.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h @@ -1,9 +1,8 @@ //===- DWARFAttribute.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -28,13 +27,10 @@ struct DWARFAttribute { /// The debug info/types section byte size of the data for this attribute. uint32_t ByteSize = 0; /// The attribute enumeration of this attribute. - dwarf::Attribute Attr; + dwarf::Attribute Attr = dwarf::Attribute(0); /// The form and value for this attribute. DWARFFormValue Value; - DWARFAttribute(uint32_t O, dwarf::Attribute A = dwarf::Attribute(0), - dwarf::Form F = dwarf::Form(0)) : Attr(A), Value(F) {} - bool isValid() const { return Offset != 0 && Attr != dwarf::Attribute(0); } @@ -43,12 +39,9 @@ struct DWARFAttribute { return isValid(); } - void clear() { - Offset = 0; - ByteSize = 0; - Attr = dwarf::Attribute(0); - Value = DWARFFormValue(); - } + /// Identifies DWARF attributes that may contain a reference to a + /// DWARF expression. + static bool mayHaveLocationDescription(dwarf::Attribute Attr); }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index 33797419a7b8..16b9bfb5de56 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -1,9 +1,8 @@ //===- DWARFCompileUnit.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index dbb6be04544b..23cf21c3523f 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -1,9 +1,8 @@ //===- DWARFContext.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===/ @@ -318,15 +317,23 @@ public: /// Get the compilation unit, the function DIE and lexical block DIE for the /// given address where applicable. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" DIEsForAddress getDIEsForAddress(uint64_t Address); - DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfo getLineInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoTable getLineInfoForAddressRange( + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DIInliningInfo getInliningInfoForAddress( + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + std::vector<DILocal> + getLocalsForAddress(object::SectionedAddress Address) override; + bool isLittleEndian() const { return DObj->isLittleEndian(); } static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3 || version == 4 || version == 5; @@ -367,7 +374,11 @@ public: private: /// Return the compile unit which contains instruction with provided /// address. + /// TODO: change input parameter from "uint64_t Address" + /// into "SectionedAddress Address" DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); + void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die, + std::vector<DILocal> &Result); }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h index 1ed087520b30..7c2a159b71fa 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -1,9 +1,8 @@ //===- DWARFDataExtractor.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h index d277ec382ba5..28fd8484b4a9 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -1,9 +1,8 @@ //===- DWARFDebugAbbrev.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h index ffbd1b06d1e2..a98bf282fe7c 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h @@ -1,9 +1,8 @@ //===- DWARFDebugAddr.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index ab46fac39f7c..5b6c578bc3bf 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -1,9 +1,8 @@ //===- DWARFDebugArangeSet.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h index ea71a50f3270..03223fbc80a9 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -1,9 +1,8 @@ //===- DWARFDebugAranges.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -50,10 +49,6 @@ private: return -1ULL; } - bool containsAddress(uint64_t Address) const { - return LowPC <= Address && Address < HighPC(); - } - bool operator<(const Range &other) const { return LowPC < other.LowPC; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index 7dc07d774aba..d960f4bc9b1c 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -1,9 +1,8 @@ //===- DWARFDebugFrame.h - Parsing of .debug_frame --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index 88c8f57bc33c..f50063b24370 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -1,9 +1,8 @@ //===- DWARFDebugInfoEntry.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index d50af5a057f1..e7425c192373 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -1,9 +1,8 @@ //===- DWARFDebugLine.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -122,6 +121,17 @@ public: return LineBase + (int8_t)LineRange - 1; } + /// Get DWARF-version aware access to the file name entry at the provided + /// index. + const llvm::DWARFDebugLine::FileNameEntry & + getFileNameEntry(uint64_t Index) const; + + bool hasFileAtIndex(uint64_t FileIndex) const; + + bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + void clear(); void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, @@ -140,12 +150,16 @@ public: static void dumpTableHeader(raw_ostream &OS); static bool orderByAddress(const Row &LHS, const Row &RHS) { - return LHS.Address < RHS.Address; + return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) < + std::tie(RHS.Address.SectionIndex, RHS.Address.Address); } /// The program-counter value corresponding to a machine instruction - /// generated by the compiler. - uint64_t Address; + /// generated by the compiler and section index pointing to the section + /// containg this PC. If relocation information is present then section + /// index is the index of the section which contains above address. + /// Otherwise this is object::SectionedAddress::Undef value. + object::SectionedAddress Address; /// An unsigned integer indicating a source line number. Lines are numbered /// beginning at 1. The compiler may emit the value 0 in cases where an /// instruction cannot be attributed to any source line. @@ -193,21 +207,29 @@ public: /// and is described by line table rows [FirstRowIndex, LastRowIndex). uint64_t LowPC; uint64_t HighPC; + /// If relocation information is present then this is the index of the + /// section which contains above addresses. Otherwise this is + /// object::SectionedAddress::Undef value. + uint64_t SectionIndex; unsigned FirstRowIndex; unsigned LastRowIndex; bool Empty; void reset(); - static bool orderByLowPC(const Sequence &LHS, const Sequence &RHS) { - return LHS.LowPC < RHS.LowPC; + static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS) { + return std::tie(LHS.SectionIndex, LHS.HighPC) < + std::tie(RHS.SectionIndex, RHS.HighPC); } bool isValid() const { return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); } - bool containsPC(uint64_t PC) const { return (LowPC <= PC && PC < HighPC); } + bool containsPC(object::SectionedAddress PC) const { + return SectionIndex == PC.SectionIndex && + (LowPC <= PC.Address && PC.Address < HighPC); + } }; struct LineTable { @@ -224,22 +246,30 @@ public: /// Returns the index of the row with file/line info for a given address, /// or UnknownRowIndex if there is no such row. - uint32_t lookupAddress(uint64_t Address) const; + uint32_t lookupAddress(object::SectionedAddress Address) const; - bool lookupAddressRange(uint64_t Address, uint64_t Size, + bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector<uint32_t> &Result) const; - bool hasFileAtIndex(uint64_t FileIndex) const; + bool hasFileAtIndex(uint64_t FileIndex) const { + return Prologue.hasFileAtIndex(FileIndex); + } /// Extracts filename by its index in filename table in prologue. + /// In Dwarf 4, the files are 1-indexed and the current compilation file + /// name is not represented in the list. In DWARF v5, the files are + /// 0-indexed and the primary source file has the index 0. /// Returns true on success. - bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, - std::string &Result) const; + std::string &Result) const { + return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result); + } /// Fills the Result argument with the file and line information /// corresponding to Address. Returns true on success. - bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + bool getFileLineInfoForAddress(object::SectionedAddress Address, + const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const; @@ -264,10 +294,15 @@ public: private: uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, - uint64_t Address) const; + object::SectionedAddress Address) const; Optional<StringRef> getSourceByIndex(uint64_t FileIndex, DILineInfoSpecifier::FileLineInfoKind Kind) const; + + uint32_t lookupAddressImpl(object::SectionedAddress Address) const; + + bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size, + std::vector<uint32_t> &Result) const; }; const LineTable *getLineTable(uint32_t Offset) const; @@ -334,13 +369,10 @@ private: ParsingState(struct LineTable *LT); void resetRowAndSequence(); - void appendRowToMatrix(uint32_t Offset); + void appendRowToMatrix(); /// Line table we're currently parsing. struct LineTable *LineTable; - /// The row number that starts at zero for the prologue, and increases for - /// each row added to the matrix. - unsigned RowNumber = 0; struct Row Row; struct Sequence Sequence; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index da2098e15402..cced6048e811 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -1,9 +1,8 @@ //===- DWARFDebugLoc.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -42,7 +41,7 @@ public: SmallVector<Entry, 2> Entries; /// Dump this list on OS. void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, uint64_t BaseAddress, + const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress, unsigned Indent) const; }; @@ -87,7 +86,7 @@ public: SmallVector<Entry, 2> Entries; void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *RegInfo, - unsigned Indent) const; + DWARFUnit *U, unsigned Indent) const; }; private: diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h index bfe2fc3ac02d..a6c125990ca7 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -1,9 +1,8 @@ //===- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h index 9e1656eb1615..99e91ca90319 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -1,9 +1,8 @@ //===- DWARFDebugPubTable.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index bc26edf00647..a66f60292343 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -1,9 +1,8 @@ //===- DWARFDebugRangeList.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -77,7 +76,7 @@ public: /// list. Has to be passed base address of the compile unit referencing this /// range list. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr) const; + getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr) const; }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index 5cc8d789e598..167ddde3ec3d 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -1,9 +1,8 @@ //===- DWARFDebugRnglists.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -38,7 +37,7 @@ struct RangeListEntry : public DWARFListEntryBase { Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress) const; bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } }; @@ -48,7 +47,7 @@ class DWARFDebugRnglist : public DWARFListType<RangeListEntry> { public: /// Build a DWARFAddressRangesVector from a rangelist. DWARFAddressRangesVector - getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, + getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index 56d46cd739a2..21e68f983bb3 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -1,9 +1,8 @@ //===- DWARFDie.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/include/llvm/DebugInfo/DWARF/DWARFExpression.h index 3fad68a9b48b..f066dd58d606 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -1,9 +1,8 @@ //===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -42,7 +41,8 @@ public: SizeAddr = 5, SizeRefAddr = 6, SizeBlock = 7, ///< Preceding operand contains block size - SignBit = 0x8, + BaseTypeRef = 8, + SignBit = 0x80, SignedSize1 = SignBit | Size1, SignedSize2 = SignBit | Size2, SignedSize4 = SignBit | Size4, @@ -55,7 +55,8 @@ public: DwarfNA, ///< Serves as a marker for unused entries Dwarf2 = 2, Dwarf3, - Dwarf4 + Dwarf4, + Dwarf5 }; /// Description of the encoding of one expression Op. @@ -78,17 +79,20 @@ public: bool Error; uint32_t EndOffset; uint64_t Operands[2]; + uint32_t OperandEndOffsets[2]; public: Description &getDescription() { return Desc; } uint8_t getCode() { return Opcode; } uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } + uint32_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; } uint32_t getEndOffset() { return EndOffset; } bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize, uint32_t Offset); bool isError() { return Error; } - bool print(raw_ostream &OS, const DWARFExpression *U, - const MCRegisterInfo *RegInfo, bool isEH); + bool print(raw_ostream &OS, const DWARFExpression *Expr, + const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH); + bool verify(DWARFUnit *U); }; /// An iterator to go through the expression operations. @@ -125,15 +129,17 @@ public: DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize) : Data(Data), Version(Version), AddressSize(AddressSize) { - assert(AddressSize == 8 || AddressSize == 4); + assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2); } iterator begin() const { return iterator(this, 0); } iterator end() const { return iterator(this, Data.getData().size()); } - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool IsEH = false) const; + bool verify(DWARFUnit *U); + private: DataExtractor Data; uint16_t Version; diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 727e853c09fb..731e71ed9eae 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -1,9 +1,8 @@ //===- DWARFFormValue.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -42,6 +41,9 @@ public: private: struct ValueType { ValueType() { uval = 0; } + ValueType(int64_t V) : sval(V) {} + ValueType(uint64_t V) : uval(V) {} + ValueType(const char *V) : cstr(V) {} union { uint64_t uval; @@ -56,26 +58,28 @@ private: ValueType Value; /// Contains all data for the form. const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time. const DWARFContext *C = nullptr; /// Context for extract time. + + DWARFFormValue(dwarf::Form F, ValueType V) : Form(F), Value(V) {} + public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {} + static DWARFFormValue createFromSValue(dwarf::Form F, int64_t V); + static DWARFFormValue createFromUValue(dwarf::Form F, uint64_t V); + static DWARFFormValue createFromPValue(dwarf::Form F, const char *V); + static DWARFFormValue createFromBlockValue(dwarf::Form F, + ArrayRef<uint8_t> D); + static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit, + uint32_t *OffsetPtr); + dwarf::Form getForm() const { return Form; } uint64_t getRawUValue() const { return Value.uval; } - void setForm(dwarf::Form F) { Form = F; } - void setUValue(uint64_t V) { Value.uval = V; } - void setSValue(int64_t V) { Value.sval = V; } - void setPValue(const char *V) { Value.cstr = V; } - - void setBlockValue(const ArrayRef<uint8_t> &Data) { - Value.data = Data.data(); - setUValue(Data.size()); - } bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const; void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, - SectionedAddress SA) const; + object::SectionedAddress SA) const; static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, DIDumpOptions DumpOpts, uint64_t SectionIndex); @@ -100,11 +104,16 @@ public: /// getAsFoo functions below return the extracted value as Foo if only /// DWARFFormValue has form class is suitable for representing Foo. Optional<uint64_t> getAsReference() const; + struct UnitOffset { + DWARFUnit *Unit; + uint64_t Offset; + }; + Optional<UnitOffset> getAsRelativeReference() const; Optional<uint64_t> getAsUnsignedConstant() const; Optional<int64_t> getAsSignedConstant() const; Optional<const char *> getAsCString() const; Optional<uint64_t> getAsAddress() const; - Optional<SectionedAddress> getAsSectionedAddress() const; + Optional<object::SectionedAddress> getAsSectionedAddress() const; Optional<uint64_t> getAsSectionOffset() const; Optional<ArrayRef<uint8_t>> getAsBlock() const; Optional<uint64_t> getAsCStringOffset() const; @@ -155,6 +164,19 @@ inline Optional<const char *> toString(const Optional<DWARFFormValue> &V) { return None; } +/// Take an optional DWARFFormValue and try to extract a string value from it. +/// +/// \param V and optional DWARFFormValue to attempt to extract the value from. +/// \returns an optional value that contains a value if the form value +/// was valid and was a string. +inline StringRef toStringRef(const Optional<DWARFFormValue> &V, + StringRef Default = {}) { + if (V) + if (auto S = V->getAsCString()) + return *S; + return Default; +} + /// Take an optional DWARFFormValue and extract a string value from it. /// /// \param V and optional DWARFFormValue to attempt to extract the value from. @@ -242,7 +264,7 @@ inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue> &V) { return None; } -inline Optional<SectionedAddress> +inline Optional<object::SectionedAddress> toSectionedAddress(const Optional<DWARFFormValue> &V) { if (V) return V->getAsSectionedAddress(); diff --git a/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h b/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h index 073e02903c39..38cd42ddb883 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h +++ b/include/llvm/DebugInfo/DWARF/DWARFGdbIndex.h @@ -1,9 +1,8 @@ //===- DWARFGdbIndex.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/include/llvm/DebugInfo/DWARF/DWARFListTable.h index 9b987314f209..a1ea69b040f0 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -1,9 +1,8 @@ //===- DWARFListTable.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -158,7 +157,7 @@ public: uint8_t getAddrSize() const { return Header.getAddrSize(); } void dump(raw_ostream &OS, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts = {}) const; @@ -235,7 +234,7 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, template <typename DWARFListType> void DWARFListTableBase<DWARFListType>::dump( raw_ostream &OS, - llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress, DIDumpOptions DumpOpts) const { Header.dump(OS, DumpOpts); diff --git a/include/llvm/DebugInfo/DWARF/DWARFObject.h b/include/llvm/DebugInfo/DWARF/DWARFObject.h index d611b5d075c8..1bba74a25d0e 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -1,9 +1,8 @@ //===- DWARFObject.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===-----------------------------------------------------------------------===/ diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h index f51838424614..3add711943d0 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h +++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h @@ -1,9 +1,8 @@ //===- DWARFRelocMap.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define LLVM_DEBUGINFO_DWARF_DWARFRELOCMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Object/RelocationResolver.h" #include <cstdint> namespace llvm { @@ -19,7 +19,11 @@ namespace llvm { /// Section index is -1LL if relocation points to absolute symbol. struct RelocAddrEntry { uint64_t SectionIndex; - uint64_t Value; + object::RelocationRef Reloc; + uint64_t SymbolValue; + Optional<object::RelocationRef> Reloc2; + uint64_t SymbolValue2; + object::RelocationResolver Resolver; }; /// In place of applying the relocations to the data we've read from disk we use diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h index 7f8235965297..054524d368ed 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFSection.h +++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -1,9 +1,8 @@ //===- DWARFSection.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -23,11 +22,6 @@ struct SectionName { bool IsNameUnique; }; -struct SectionedAddress { - uint64_t Address; - uint64_t SectionIndex; -}; - } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFSECTION_H diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index 8ca5ba13fc23..90d89375fd35 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -1,9 +1,8 @@ //===- DWARFTypeUnit.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 79c3ce1106d5..f9f90db31890 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -1,9 +1,8 @@ //===- DWARFUnit.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -49,7 +48,7 @@ class DWARFUnitHeader { uint32_t Offset = 0; // Version, address size, and DWARF format. dwarf::FormParams FormParams; - uint32_t Length = 0; + uint64_t Length = 0; uint64_t AbbrOffset = 0; // For DWO units only. @@ -83,7 +82,7 @@ public: uint8_t getDwarfOffsetByteSize() const { return FormParams.getDwarfOffsetByteSize(); } - uint32_t getLength() const { return Length; } + uint64_t getLength() const { return Length; } uint64_t getAbbrOffset() const { return AbbrOffset; } Optional<uint64_t> getDWOId() const { return DWOId; } void setDWOId(uint64_t Id) { @@ -98,8 +97,11 @@ public: return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type; } uint8_t getSize() const { return Size; } - // FIXME: Support DWARF64. - uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getNextUnitOffset() const { + return Offset + Length + + (FormParams.Format == llvm::dwarf::DwarfFormat::DWARF64 ? 4 : 0) + + FormParams.getDwarfOffsetByteSize(); + } }; const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, @@ -173,6 +175,7 @@ struct StrOffsetsContributionDescriptor { StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size, uint8_t Version, dwarf::DwarfFormat Format) : Base(Base), Size(Size), FormParams({Version, 0, Format}) {} + StrOffsetsContributionDescriptor() = default; uint8_t getVersion() const { return FormParams.Version; } dwarf::DwarfFormat getFormat() const { return FormParams.Format; } @@ -182,7 +185,7 @@ struct StrOffsetsContributionDescriptor { /// Determine whether a contribution to the string offsets table is /// consistent with the relevant section size and that its length is /// a multiple of the size of one of its entries. - Optional<StrOffsetsContributionDescriptor> + Expected<StrOffsetsContributionDescriptor> validateContributionSize(DWARFDataExtractor &DA); }; @@ -218,7 +221,7 @@ class DWARFUnit { Optional<DWARFDebugRnglistTable> RngListTable; mutable const DWARFAbbreviationDeclarationSet *Abbrevs; - llvm::Optional<SectionedAddress> BaseAddr; + llvm::Optional<object::SectionedAddress> BaseAddr; /// The compile unit debug information entry items. std::vector<DWARFDebugInfoEntry> DieArray; @@ -247,14 +250,14 @@ protected: /// Find the unit's contribution to the string offsets table and determine its /// length and form. The given offset is expected to be derived from the unit /// DIE's DW_AT_str_offsets_base attribute. - Optional<StrOffsetsContributionDescriptor> + Expected<Optional<StrOffsetsContributionDescriptor>> determineStringOffsetsTableContribution(DWARFDataExtractor &DA); /// Find the unit's contribution to the string offsets table and determine its /// length and form. The given offset is expected to be 0 in a dwo file or, /// in a dwp file, the start of the unit's contribution to the string offsets /// table section (as determined by the index table). - Optional<StrOffsetsContributionDescriptor> + Expected<Optional<StrOffsetsContributionDescriptor>> determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA); public: @@ -305,7 +308,8 @@ public: RangeSectionBase = Base; } - Optional<SectionedAddress> getAddrOffsetSectionItem(uint32_t Index) const; + Optional<object::SectionedAddress> + getAddrOffsetSectionItem(uint32_t Index) const; Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const; DWARFDataExtractor getDebugInfoExtractor() const; @@ -376,7 +380,7 @@ public: llvm_unreachable("Invalid UnitType."); } - llvm::Optional<SectionedAddress> getBaseAddress(); + llvm::Optional<object::SectionedAddress> getBaseAddress(); DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); @@ -385,6 +389,13 @@ public: return DWARFDie(this, &DieArray[0]); } + DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true) { + parseDWO(); + if (DWO) + return DWO->getUnitDIE(ExtractUnitDIEOnly); + return getUnitDIE(ExtractUnitDIEOnly); + } + const char *getCompilationDir(); Optional<uint64_t> getDWOId() { extractDIEsIfNeeded(/*CUDieOnly*/ true); @@ -462,13 +473,12 @@ public: DWARFDie getDIEForOffset(uint32_t Offset) { extractDIEsIfNeeded(false); assert(!DieArray.empty()); - auto it = std::lower_bound( - DieArray.begin(), DieArray.end(), Offset, - [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { - return LHS.getOffset() < Offset; + auto It = + llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) { + return DIE.getOffset() < Offset; }); - if (it != DieArray.end() && it->getOffset() == Offset) - return DWARFDie(this, &*it); + if (It != DieArray.end() && It->getOffset() == Offset) + return DWARFDie(this, &*It); return DWARFDie(); } diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h index 16be5f9401c0..fc8c707c512e 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -1,9 +1,8 @@ //===- DWARFUnitIndex.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index e47fbea5646e..f1268f220272 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -1,9 +1,8 @@ //===- DWARFVerifier.h ----------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/GSYM/FileEntry.h b/include/llvm/DebugInfo/GSYM/FileEntry.h new file mode 100644 index 000000000000..228b4efa0656 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/FileEntry.h @@ -0,0 +1,68 @@ +//===- FileEntry.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_FILEENTRY_H +#define LLVM_DEBUGINFO_GSYM_FILEENTRY_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Hashing.h" +#include <functional> +#include <stdint.h> +#include <utility> + +namespace llvm { +namespace gsym { + +/// Files in GSYM are contained in FileEntry structs where we split the +/// directory and basename into two different strings in the string +/// table. This allows paths to shared commont directory and filename +/// strings and saves space. +struct FileEntry { + + /// Offsets in the string table. + /// @{ + uint32_t Dir = 0; + uint32_t Base = 0; + /// @} + + FileEntry() = default; + FileEntry(uint32_t D, uint32_t B) : Dir(D), Base(B) {} + + // Implement operator== so that FileEntry can be used as key in + // unordered containers. + bool operator==(const FileEntry &RHS) const { + return Base == RHS.Base && Dir == RHS.Dir; + }; + bool operator!=(const FileEntry &RHS) const { + return Base != RHS.Base || Dir != RHS.Dir; + }; +}; + +} // namespace gsym + +template <> struct DenseMapInfo<gsym::FileEntry> { + static inline gsym::FileEntry getEmptyKey() { + uint32_t key = DenseMapInfo<uint32_t>::getEmptyKey(); + return gsym::FileEntry(key, key); + } + static inline gsym::FileEntry getTombstoneKey() { + uint32_t key = DenseMapInfo<uint32_t>::getTombstoneKey(); + return gsym::FileEntry(key, key); + } + static unsigned getHashValue(const gsym::FileEntry &Val) { + return llvm::hash_combine(DenseMapInfo<uint32_t>::getHashValue(Val.Dir), + DenseMapInfo<uint32_t>::getHashValue(Val.Base)); + } + static bool isEqual(const gsym::FileEntry &LHS, const gsym::FileEntry &RHS) { + return LHS == RHS; + } +}; + +} // namespace llvm +#endif // #ifndef LLVM_DEBUGINFO_GSYM_FILEENTRY_H diff --git a/include/llvm/DebugInfo/GSYM/FunctionInfo.h b/include/llvm/DebugInfo/GSYM/FunctionInfo.h new file mode 100644 index 000000000000..eedb1e638fd1 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/FunctionInfo.h @@ -0,0 +1,107 @@ +//===- FunctionInfo.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H +#define LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H + +#include "llvm/DebugInfo/GSYM/InlineInfo.h" +#include "llvm/DebugInfo/GSYM/LineEntry.h" +#include "llvm/DebugInfo/GSYM/Range.h" +#include "llvm/DebugInfo/GSYM/StringTable.h" +#include <tuple> +#include <vector> + +namespace llvm { +class raw_ostream; +namespace gsym { + +/// Function information in GSYM files encodes information for one +/// contiguous address range. The name of the function is encoded as +/// a string table offset and allows multiple functions with the same +/// name to share the name string in the string table. Line tables are +/// stored in a sorted vector of gsym::LineEntry objects and are split +/// into line tables for each function. If a function has a discontiguous +/// range, it will be split into two gsym::FunctionInfo objects. If the +/// function has inline functions, the information will be encoded in +/// the "Inline" member, see gsym::InlineInfo for more information. +struct FunctionInfo { + AddressRange Range; + uint32_t Name; ///< String table offset in the string table. + std::vector<gsym::LineEntry> Lines; + InlineInfo Inline; + + FunctionInfo(uint64_t Addr = 0, uint64_t Size = 0, uint32_t N = 0) + : Range(Addr, Addr + Size), Name(N) {} + + bool hasRichInfo() const { + /// Returns whether we have something else than range and name. When + /// converting information from a symbol table and from debug info, we + /// might end up with multiple FunctionInfo objects for the same range + /// and we need to be able to tell which one is the better object to use. + return !Lines.empty() || Inline.isValid(); + } + + bool isValid() const { + /// Address and size can be zero and there can be no line entries for a + /// symbol so the only indication this entry is valid is if the name is + /// not zero. This can happen when extracting information from symbol + /// tables that do not encode symbol sizes. In that case only the + /// address and name will be filled in. + return Name != 0; + } + + uint64_t startAddress() const { return Range.Start; } + uint64_t endAddress() const { return Range.End; } + uint64_t size() const { return Range.size(); } + void setStartAddress(uint64_t Addr) { Range.Start = Addr; } + void setEndAddress(uint64_t Addr) { Range.End = Addr; } + void setSize(uint64_t Size) { Range.End = Range.Start + Size; } + + void clear() { + Range = {0, 0}; + Name = 0; + Lines.clear(); + Inline.clear(); + } +}; + +inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { + return LHS.Range == RHS.Range && LHS.Name == RHS.Name && + LHS.Lines == RHS.Lines && LHS.Inline == RHS.Inline; +} +inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) { + return !(LHS == RHS); +} +/// This sorting will order things consistently by address range first, but then +/// followed by inlining being valid and line tables. We might end up with a +/// FunctionInfo from debug info that will have the same range as one from the +/// symbol table, but we want to quickly be able to sort and use the best version +/// when creating the final GSYM file. +inline bool operator<(const FunctionInfo &LHS, const FunctionInfo &RHS) { + // First sort by address range + if (LHS.Range != RHS.Range) + return LHS.Range < RHS.Range; + + // Then sort by inline + if (LHS.Inline.isValid() != RHS.Inline.isValid()) + return RHS.Inline.isValid(); + + // If the number of lines is the same, then compare line table entries + if (LHS.Lines.size() == RHS.Lines.size()) + return LHS.Lines < RHS.Lines; + // Then sort by number of line table entries (more is better) + return LHS.Lines.size() < RHS.Lines.size(); +} + +raw_ostream &operator<<(raw_ostream &OS, const FunctionInfo &R); + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H diff --git a/include/llvm/DebugInfo/GSYM/InlineInfo.h b/include/llvm/DebugInfo/GSYM/InlineInfo.h new file mode 100644 index 000000000000..222430622932 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/InlineInfo.h @@ -0,0 +1,78 @@ +//===- InlineInfo.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H +#define LLVM_DEBUGINFO_GSYM_INLINEINFO_H + +#include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/GSYM/Range.h" +#include <stdint.h> +#include <vector> + + +namespace llvm { +class raw_ostream; + +namespace gsym { + +/// Inline information stores the name of the inline function along with +/// an array of address ranges. It also stores the call file and call line +/// that called this inline function. This allows us to unwind inline call +/// stacks back to the inline or concrete function that called this +/// function. Inlined functions contained in this function are stored in the +/// "Children" variable. All address ranges must be sorted and all address +/// ranges of all children must be contained in the ranges of this function. +/// Any clients that encode information will need to ensure the ranges are +/// all contined correctly or lookups could fail. Add ranges in these objects +/// must be contained in the top level FunctionInfo address ranges as well. +struct InlineInfo { + + uint32_t Name; ///< String table offset in the string table. + uint32_t CallFile; ///< 1 based file index in the file table. + uint32_t CallLine; ///< Source line number. + AddressRanges Ranges; + std::vector<InlineInfo> Children; + InlineInfo() : Name(0), CallFile(0), CallLine(0) {} + void clear() { + Name = 0; + CallFile = 0; + CallLine = 0; + Ranges.clear(); + Children.clear(); + } + bool isValid() const { return !Ranges.empty(); } + + using InlineArray = std::vector<const InlineInfo *>; + + /// Lookup an address in the InlineInfo object + /// + /// This function is used to symbolicate an inline call stack and can + /// turn one address in the program into one or more inline call stacks + /// and have the stack trace show the original call site from + /// non-inlined code. + /// + /// \param Addr the address to lookup + /// + /// \returns optional vector of InlineInfo objects that describe the + /// inline call stack for a given address, false otherwise. + llvm::Optional<InlineArray> getInlineStack(uint64_t Addr) const; +}; + +inline bool operator==(const InlineInfo &LHS, const InlineInfo &RHS) { + return LHS.Name == RHS.Name && LHS.CallFile == RHS.CallFile && + LHS.CallLine == RHS.CallLine && LHS.Ranges == RHS.Ranges && + LHS.Children == RHS.Children; +} + +raw_ostream &operator<<(raw_ostream &OS, const InlineInfo &FI); + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_INLINEINFO_H diff --git a/include/llvm/DebugInfo/GSYM/LineEntry.h b/include/llvm/DebugInfo/GSYM/LineEntry.h new file mode 100644 index 000000000000..6b9380940bd3 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/LineEntry.h @@ -0,0 +1,48 @@ +//===- LineEntry.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_LINEENTRY_H +#define LLVM_DEBUGINFO_GSYM_LINEENTRY_H + +#include "llvm/DebugInfo/GSYM/Range.h" + +namespace llvm { +namespace gsym { + +/// Line entries are used to encode the line tables in FunctionInfo objects. +/// They are stored as a sorted vector of these objects and store the +/// address, file and line of the line table row for a given address. The +/// size of a line table entry is calculated by looking at the next entry +/// in the FunctionInfo's vector of entries. +struct LineEntry { + uint64_t Addr; ///< Start address of this line entry. + uint32_t File; ///< 1 based index of file in FileTable + uint32_t Line; ///< Source line number. + LineEntry(uint64_t A = 0, uint32_t F = 0, uint32_t L = 0) + : Addr(A), File(F), Line(L) {} + bool isValid() { return File != 0; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const LineEntry &LE) { + return OS << "addr=" << HEX64(LE.Addr) << ", file=" << format("%3u", LE.File) + << ", line=" << format("%3u", LE.Line); +} + +inline bool operator==(const LineEntry &LHS, const LineEntry &RHS) { + return LHS.Addr == RHS.Addr && LHS.File == RHS.File && LHS.Line == RHS.Line; +} +inline bool operator!=(const LineEntry &LHS, const LineEntry &RHS) { + return !(LHS == RHS); +} +inline bool operator<(const LineEntry &LHS, const LineEntry &RHS) { + return LHS.Addr < RHS.Addr; +} +} // namespace gsym +} // namespace llvm +#endif // #ifndef LLVM_DEBUGINFO_GSYM_LINEENTRY_H diff --git a/include/llvm/DebugInfo/GSYM/Range.h b/include/llvm/DebugInfo/GSYM/Range.h new file mode 100644 index 000000000000..772ff244c5b7 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/Range.h @@ -0,0 +1,87 @@ +//===- AddressRange.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_RANGE_H +#define LLVM_DEBUGINFO_GSYM_RANGE_H + +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <stdint.h> +#include <vector> + +#define HEX8(v) llvm::format_hex(v, 4) +#define HEX16(v) llvm::format_hex(v, 6) +#define HEX32(v) llvm::format_hex(v, 10) +#define HEX64(v) llvm::format_hex(v, 18) + +namespace llvm { +class raw_ostream; + +namespace gsym { + +/// A class that represents an address range. The range is specified using +/// a start and an end address. +struct AddressRange { + uint64_t Start; + uint64_t End; + AddressRange() : Start(0), End(0) {} + AddressRange(uint64_t S, uint64_t E) : Start(S), End(E) {} + uint64_t size() const { return End - Start; } + bool contains(uint64_t Addr) const { return Start <= Addr && Addr < End; } + bool intersects(const AddressRange &R) const { + return Start < R.End && R.Start < End; + } + + bool operator==(const AddressRange &R) const { + return Start == R.Start && End == R.End; + } + bool operator!=(const AddressRange &R) const { + return !(*this == R); + } + bool operator<(const AddressRange &R) const { + return std::make_pair(Start, End) < std::make_pair(R.Start, R.End); + } +}; + +raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R); + +/// The AddressRanges class helps normalize address range collections. +/// This class keeps a sorted vector of AddressRange objects and can perform +/// insertions and searches efficiently. The address ranges are always sorted +/// and never contain any invalid or empty address ranges. This allows us to +/// emit address ranges into the GSYM file efficiently. Intersecting address +/// ranges are combined during insertion so that we can emit the most compact +/// representation for address ranges when writing to disk. +class AddressRanges { +protected: + using Collection = std::vector<AddressRange>; + Collection Ranges; +public: + void clear() { Ranges.clear(); } + bool empty() const { return Ranges.empty(); } + bool contains(uint64_t Addr) const; + void insert(AddressRange Range); + size_t size() const { return Ranges.size(); } + bool operator==(const AddressRanges &RHS) const { + return Ranges == RHS.Ranges; + } + const AddressRange &operator[](size_t i) const { + assert(i < Ranges.size()); + return Ranges[i]; + } + Collection::const_iterator begin() const { return Ranges.begin(); } + Collection::const_iterator end() const { return Ranges.end(); } +}; + +raw_ostream &operator<<(raw_ostream &OS, const AddressRanges &AR); + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_RANGE_H diff --git a/include/llvm/DebugInfo/GSYM/StringTable.h b/include/llvm/DebugInfo/GSYM/StringTable.h new file mode 100644 index 000000000000..0001b8b82743 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/StringTable.h @@ -0,0 +1,54 @@ +//===- StringTable.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_STRINGTABLE_H +#define LLVM_DEBUGINFO_GSYM_STRINGTABLE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/GSYM/Range.h" +#include <stdint.h> +#include <string> + + +namespace llvm { +namespace gsym { + +/// String tables in GSYM files are required to start with an empty +/// string at offset zero. Strings must be UTF8 NULL terminated strings. +struct StringTable { + StringRef Data; + StringTable() : Data() {} + StringTable(StringRef D) : Data(D) {} + StringRef operator[](size_t Offset) const { return getString(Offset); } + StringRef getString(uint32_t Offset) const { + if (Offset < Data.size()) { + auto End = Data.find('\0', Offset); + return Data.substr(Offset, End - Offset); + } + return StringRef(); + } + void clear() { Data = StringRef(); } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const StringTable &S) { + OS << "String table:\n"; + uint32_t Offset = 0; + const size_t Size = S.Data.size(); + while (Offset < Size) { + StringRef Str = S.getString(Offset); + OS << HEX32(Offset) << ": \"" << Str << "\"\n"; + Offset += Str.size() + 1; + } + return OS; +} + +} // namespace gsym +} // namespace llvm +#endif // #ifndef LLVM_DEBUGINFO_GSYM_STRINGTABLE_H diff --git a/include/llvm/DebugInfo/MSF/IMSFFile.h b/include/llvm/DebugInfo/MSF/IMSFFile.h index f98e715e6b15..7e80f96b89ae 100644 --- a/include/llvm/DebugInfo/MSF/IMSFFile.h +++ b/include/llvm/DebugInfo/MSF/IMSFFile.h @@ -1,9 +1,8 @@ //===- IMSFFile.h - Abstract base class for an MSF file ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/MSF/MSFBuilder.h b/include/llvm/DebugInfo/MSF/MSFBuilder.h index 3de98c4ecba8..282870f5b3f1 100644 --- a/include/llvm/DebugInfo/MSF/MSFBuilder.h +++ b/include/llvm/DebugInfo/MSF/MSFBuilder.h @@ -1,9 +1,8 @@ //===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/MSF/MSFCommon.h b/include/llvm/DebugInfo/MSF/MSFCommon.h index 2db2b71df4a7..83331b14b8af 100644 --- a/include/llvm/DebugInfo/MSF/MSFCommon.h +++ b/include/llvm/DebugInfo/MSF/MSFCommon.h @@ -1,9 +1,8 @@ //===- MSFCommon.h - Common types and functions for MSF files ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/MSF/MSFError.h b/include/llvm/DebugInfo/MSF/MSFError.h index 5c043a7837b3..fbc4e6928536 100644 --- a/include/llvm/DebugInfo/MSF/MSFError.h +++ b/include/llvm/DebugInfo/MSF/MSFError.h @@ -1,9 +1,8 @@ //===- MSFError.h - Error extensions for MSF Files --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/include/llvm/DebugInfo/MSF/MappedBlockStream.h index f65e52922da7..593d781b990e 100644 --- a/include/llvm/DebugInfo/MSF/MappedBlockStream.h +++ b/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -1,9 +1,8 @@ //==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h index ac7f19637ab1..49ba20af7263 100644 --- a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h +++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -1,9 +1,8 @@ //===- ConcreteSymbolEnumerator.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h index 881d7329ab66..f05b58c55507 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIADataStream.h @@ -1,9 +1,8 @@ //===- DIADataStream.h - DIA implementation of IPDBDataStream ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h index 1f129052d034..8a00ad45291a 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h @@ -1,9 +1,8 @@ //==- DIAEnumDebugStreams.h - DIA Debug Stream Enumerator impl ---*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h index f3b02f07e648..bd417c0746b1 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h @@ -1,9 +1,8 @@ //==- DIAEnumFrameData.h --------------------------------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h index 4669a8d31196..1f75ca27c4f8 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h @@ -1,9 +1,8 @@ //==- DIAEnumInjectedSources.h - DIA Injected Sources Enumerator -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h index f1cb6268a26d..8800baac105d 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h @@ -1,9 +1,8 @@ //==- DIAEnumLineNumbers.h - DIA Line Number Enumerator impl -----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h index ac2ae317d263..be8613bfba9d 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h @@ -1,9 +1,8 @@ //==- DIAEnumSectionContribs.h --------------------------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h index dac3df06a178..61278994ed36 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h @@ -1,9 +1,8 @@ //==- DIAEnumSourceFiles.h - DIA Source File Enumerator impl -----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h index 9689859ae0f8..f55342cea2e5 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h @@ -1,9 +1,8 @@ //==- DIAEnumSymbols.h - DIA Symbol Enumerator impl --------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h index f4f856ebb6fd..057cb06fc8ca 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h @@ -1,9 +1,8 @@ //===- DIAEnumTables.h - DIA Tables Enumerator Impl -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAError.h b/include/llvm/DebugInfo/PDB/DIA/DIAError.h index 2b33a65a0a14..96d960599f7e 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAError.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAError.h @@ -1,9 +1,8 @@ //===- DIAError.h - Error extensions for PDB DIA implementation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h b/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h index 0ce6cfc93030..c04f7cd00836 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAFrameData.h @@ -1,9 +1,8 @@ //===- DIAFrameData.h - DIA Impl. of IPDBFrameData ---------------- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h index 635508da84ea..67963a06d939 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h @@ -1,9 +1,8 @@ //===- DIAInjectedSource.h - DIA impl for IPDBInjectedSource ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -26,7 +25,7 @@ public: std::string getFileName() const override; std::string getObjectFileName() const override; std::string getVirtualFileName() const override; - PDB_SourceCompression getCompression() const override; + uint32_t getCompression() const override; std::string getCode() const override; private: diff --git a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h index a59e3a19c8c2..d8bb27220763 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIALineNumber.h @@ -1,9 +1,8 @@ //===- DIALineNumber.h - DIA implementation of IPDBLineNumber ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index 5d4f855c63ca..7f201d3a4e36 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -1,9 +1,8 @@ //===- DIARawSymbol.h - DIA implementation of IPDBRawSymbol ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h b/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h index 4688f1f91a89..0972831e8b16 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h @@ -1,9 +1,8 @@ //===- DIASectionContrib.h - DIA Impl. of IPDBSectionContrib ------ C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 592e061a8d83..6f62e6061f56 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -1,9 +1,8 @@ //===- DIASession.h - DIA implementation of IPDBSession ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h index 1088ea54981c..96edfc9f9e29 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASourceFile.h @@ -1,9 +1,8 @@ //===- DIASourceFile.h - DIA implementation of IPDBSourceFile ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h index 92ebc04ae5a4..1a7c2f3aeeab 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASupport.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -1,9 +1,8 @@ //===- DIASupport.h - Common header includes for DIA ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // Common defines and header includes for all LLVMDebugInfoPDBDIA. The diff --git a/include/llvm/DebugInfo/PDB/DIA/DIATable.h b/include/llvm/DebugInfo/PDB/DIA/DIATable.h index ce93fa0b86c3..65396a042f06 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIATable.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIATable.h @@ -1,9 +1,8 @@ //===- DIATable.h - DIA implementation of IPDBTable -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h b/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h index aa843e05de70..5e01d8f10a6e 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h @@ -1,9 +1,8 @@ //===- DIAUtils.h - Utility functions for working with DIA ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/GenericError.h b/include/llvm/DebugInfo/PDB/GenericError.h index 997f13f5f30e..ec85d92d2a92 100644 --- a/include/llvm/DebugInfo/PDB/GenericError.h +++ b/include/llvm/DebugInfo/PDB/GenericError.h @@ -1,9 +1,8 @@ -//===- Error.h - system_error extensions for PDB ----------------*- C++ -*-===// +//===- GenericError.h - system_error extensions for PDB ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBDataStream.h b/include/llvm/DebugInfo/PDB/IPDBDataStream.h index 0d7a286a11a6..4d0589a87915 100644 --- a/include/llvm/DebugInfo/PDB/IPDBDataStream.h +++ b/include/llvm/DebugInfo/PDB/IPDBDataStream.h @@ -1,9 +1,8 @@ //===- IPDBDataStream.h - base interface for child enumerator ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h index 7017f2600e9b..bfa67d39bc76 100644 --- a/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h +++ b/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h @@ -1,9 +1,8 @@ //===- IPDBEnumChildren.h - base interface for child enumerator -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBFrameData.h b/include/llvm/DebugInfo/PDB/IPDBFrameData.h index 74679215b880..24138b380db4 100644 --- a/include/llvm/DebugInfo/PDB/IPDBFrameData.h +++ b/include/llvm/DebugInfo/PDB/IPDBFrameData.h @@ -1,9 +1,8 @@ //===- IPDBFrameData.h - base interface for frame data ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h index e75d64af92bb..d5b36f9846b5 100644 --- a/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h +++ b/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h @@ -1,16 +1,14 @@ //===- IPDBInjectedSource.h - base class for PDB injected file --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H #define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H -#include "PDBTypes.h" #include "llvm/Support/raw_ostream.h" #include <memory> #include <string> @@ -33,7 +31,10 @@ public: virtual std::string getFileName() const = 0; virtual std::string getObjectFileName() const = 0; virtual std::string getVirtualFileName() const = 0; - virtual PDB_SourceCompression getCompression() const = 0; + // The returned value depends on the PDB producer, + // but 0 is guaranteed to mean "no compression". + // The enum PDB_SourceCompression lists known return values. + virtual uint32_t getCompression() const = 0; virtual std::string getCode() const = 0; }; } // namespace pdb diff --git a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h index e20080f2fbfc..77e88999497e 100644 --- a/include/llvm/DebugInfo/PDB/IPDBLineNumber.h +++ b/include/llvm/DebugInfo/PDB/IPDBLineNumber.h @@ -1,9 +1,8 @@ //===- IPDBLineNumber.h - base interface for PDB line no. info ---*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index 7c818d7cadeb..b24e712e3b78 100644 --- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -1,9 +1,8 @@ //===- IPDBRawSymbol.h - base interface for PDB symbol types ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h b/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h index 4fda62404672..c5cf4bbe5560 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h +++ b/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h @@ -1,9 +1,8 @@ //==- IPDBSectionContrib.h - Interfaces for PDB SectionContribs --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h index 88fd02c0a345..aa8d9c76d63e 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -1,9 +1,8 @@ //===- IPDBSession.h - base interface for a PDB symbol context --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h index 3676c4030b13..d7e49fb70580 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSourceFile.h +++ b/include/llvm/DebugInfo/PDB/IPDBSourceFile.h @@ -1,9 +1,8 @@ //===- IPDBSourceFile.h - base interface for a PDB source file --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/IPDBTable.h b/include/llvm/DebugInfo/PDB/IPDBTable.h index 4561c4e847b2..55ca230d58c4 100644 --- a/include/llvm/DebugInfo/PDB/IPDBTable.h +++ b/include/llvm/DebugInfo/PDB/IPDBTable.h @@ -1,9 +1,8 @@ //===- IPDBTable.h - Base Interface for a PDB Symbol Context ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h index 9eef4041d0a1..568f0c98c559 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -1,9 +1,8 @@ //===- DbiModuleDescriptor.h - PDB module information -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index ac7f741afefa..4f5d28bbd05a 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -1,9 +1,8 @@ //===- DbiModuleDescriptorBuilder.h - PDB module information ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h index 5f6e7ab92a96..14223273c898 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h @@ -1,9 +1,8 @@ //===- DbiModuleList.h - PDB module information list ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/include/llvm/DebugInfo/PDB/Native/DbiStream.h index a3ca607efbef..7d75c159b7ae 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -1,9 +1,8 @@ //===- DbiStream.h - PDB Dbi Stream (Stream 3) Access -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #include "llvm/DebugInfo/CodeView/DebugSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" @@ -80,7 +80,10 @@ public: FixedStreamArray<object::coff_section> getSectionHeaders() const; - FixedStreamArray<object::FpoData> getFpoRecords(); + bool hasOldFpoRecords() const; + FixedStreamArray<object::FpoData> getOldFpoRecords() const; + bool hasNewFpoRecords() const; + const codeview::DebugFrameDataSubsectionRef &getNewFpoRecords() const; FixedStreamArray<SecMapEntry> getSectionMap() const; void visitSectionContributions(ISectionContribVisitor &Visitor) const; @@ -91,7 +94,11 @@ private: Error initializeSectionContributionData(); Error initializeSectionHeadersData(PDBFile *Pdb); Error initializeSectionMapData(); - Error initializeFpoRecords(PDBFile *Pdb); + Error initializeOldFpoRecords(PDBFile *Pdb); + Error initializeNewFpoRecords(PDBFile *Pdb); + + Expected<std::unique_ptr<msf::MappedBlockStream>> + createIndexedStreamForHeaderType(PDBFile *Pdb, DbgHeaderType Type) const; std::unique_ptr<BinaryStream> Stream; @@ -117,8 +124,11 @@ private: std::unique_ptr<msf::MappedBlockStream> SectionHeaderStream; FixedStreamArray<object::coff_section> SectionHeaders; - std::unique_ptr<msf::MappedBlockStream> FpoStream; - FixedStreamArray<object::FpoData> FpoRecords; + std::unique_ptr<msf::MappedBlockStream> OldFpoStream; + FixedStreamArray<object::FpoData> OldFpoRecords; + + std::unique_ptr<msf::MappedBlockStream> NewFpoStream; + codeview::DebugFrameDataSubsectionRef NewFpoRecords; const DbiStreamHeader *Header; }; diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index b538de576677..d9be238af07b 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -1,9 +1,8 @@ //===- DbiStreamBuilder.h - PDB Dbi Stream Creation -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/EnumTables.h b/include/llvm/DebugInfo/PDB/Native/EnumTables.h index c018445630fe..70161fadf7d2 100644 --- a/include/llvm/DebugInfo/PDB/Native/EnumTables.h +++ b/include/llvm/DebugInfo/PDB/Native/EnumTables.h @@ -1,9 +1,8 @@ //===- EnumTables.h - Enum to string conversion tables ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/Formatters.h b/include/llvm/DebugInfo/PDB/Native/Formatters.h index 7d5eab2e2a09..29c957eeb5e0 100644 --- a/include/llvm/DebugInfo/PDB/Native/Formatters.h +++ b/include/llvm/DebugInfo/PDB/Native/Formatters.h @@ -1,9 +1,8 @@ //===- Formatters.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h index 4c39ca762b5b..a49795600028 100644 --- a/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h @@ -1,9 +1,8 @@ //===- GSIStreamBuilder.h - PDB Publics/Globals Stream Creation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h index 7f84564ee988..404baaa25077 100644 --- a/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h +++ b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h @@ -1,9 +1,8 @@ //===- GlobalsStream.h - PDB Index of Symbols by Name -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/Hash.h b/include/llvm/DebugInfo/PDB/Native/Hash.h index 1f11d43ecdd4..b048d878a12c 100644 --- a/include/llvm/DebugInfo/PDB/Native/Hash.h +++ b/include/llvm/DebugInfo/PDB/Native/Hash.h @@ -1,9 +1,8 @@ //===- Hash.h - PDB hash functions ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/HashTable.h b/include/llvm/DebugInfo/PDB/Native/HashTable.h index 34cc6179688b..aa38417bcf4c 100644 --- a/include/llvm/DebugInfo/PDB/Native/HashTable.h +++ b/include/llvm/DebugInfo/PDB/Native/HashTable.h @@ -1,9 +1,8 @@ //===- HashTable.h - PDB Hash Table -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -32,21 +31,21 @@ namespace pdb { Error readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V); Error writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec); -template <typename ValueT, typename TraitsT> class HashTable; +template <typename ValueT> class HashTable; -template <typename ValueT, typename TraitsT> +template <typename ValueT> class HashTableIterator - : public iterator_facade_base<HashTableIterator<ValueT, TraitsT>, + : public iterator_facade_base<HashTableIterator<ValueT>, std::forward_iterator_tag, - std::pair<uint32_t, ValueT>> { - friend HashTable<ValueT, TraitsT>; + const std::pair<uint32_t, ValueT>> { + friend HashTable<ValueT>; - HashTableIterator(const HashTable<ValueT, TraitsT> &Map, uint32_t Index, + HashTableIterator(const HashTable<ValueT> &Map, uint32_t Index, bool IsEnd) : Map(&Map), Index(Index), IsEnd(IsEnd) {} public: - HashTableIterator(const HashTable<ValueT, TraitsT> &Map) : Map(&Map) { + HashTableIterator(const HashTable<ValueT> &Map) : Map(&Map) { int I = Map.Present.find_first(); if (I == -1) { Index = 0; @@ -73,6 +72,12 @@ public: assert(Map->Present.test(Index)); return Map->Buckets[Index]; } + + // Implement postfix op++ in terms of prefix op++ by using the superclass + // implementation. + using iterator_facade_base<HashTableIterator<ValueT>, + std::forward_iterator_tag, + const std::pair<uint32_t, ValueT>>::operator++; HashTableIterator &operator++() { while (Index < Map->Buckets.size()) { ++Index; @@ -88,24 +93,13 @@ private: bool isEnd() const { return IsEnd; } uint32_t index() const { return Index; } - const HashTable<ValueT, TraitsT> *Map; + const HashTable<ValueT> *Map; uint32_t Index; bool IsEnd; }; -template <typename T> struct PdbHashTraits {}; - -template <> struct PdbHashTraits<uint32_t> { - uint32_t hashLookupKey(uint32_t N) const { return N; } - uint32_t storageKeyToLookupKey(uint32_t N) const { return N; } - uint32_t lookupKeyToStorageKey(uint32_t N) { return N; } -}; - -template <typename ValueT, typename TraitsT = PdbHashTraits<ValueT>> +template <typename ValueT> class HashTable { - using iterator = HashTableIterator<ValueT, TraitsT>; - friend iterator; - struct Header { support::ulittle32_t Size; support::ulittle32_t Capacity; @@ -114,10 +108,11 @@ class HashTable { using BucketList = std::vector<std::pair<uint32_t, ValueT>>; public: - HashTable() { Buckets.resize(8); } + using const_iterator = HashTableIterator<ValueT>; + friend const_iterator; - explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {} - HashTable(uint32_t Capacity, TraitsT Traits) : Traits(Traits) { + HashTable() { Buckets.resize(8); } + explicit HashTable(uint32_t Capacity) { Buckets.resize(Capacity); } @@ -144,7 +139,7 @@ public: return EC; if (Present.intersects(Deleted)) return make_error<RawError>(raw_error_code::corrupt_file, - "Present bit vector interesects deleted!"); + "Present bit vector intersects deleted!"); for (uint32_t P : Present) { if (auto EC = Stream.readInteger(Buckets[P].first)) @@ -217,19 +212,20 @@ public: uint32_t capacity() const { return Buckets.size(); } uint32_t size() const { return Present.count(); } - iterator begin() const { return iterator(*this); } - iterator end() const { return iterator(*this, 0, true); } + const_iterator begin() const { return const_iterator(*this); } + const_iterator end() const { return const_iterator(*this, 0, true); } /// Find the entry whose key has the specified hash value, using the specified /// traits defining hash function and equality. - template <typename Key> iterator find_as(const Key &K) const { + template <typename Key, typename TraitsT> + const_iterator find_as(const Key &K, TraitsT &Traits) const { uint32_t H = Traits.hashLookupKey(K) % capacity(); uint32_t I = H; Optional<uint32_t> FirstUnused; do { if (isPresent(I)) { if (Traits.storageKeyToLookupKey(Buckets[I].first) == K) - return iterator(*this, I, false); + return const_iterator(*this, I, false); } else { if (!FirstUnused) FirstUnused = I; @@ -248,17 +244,19 @@ public: // table were Present. But this would violate the load factor constraints // that we impose, so it should never happen. assert(FirstUnused); - return iterator(*this, *FirstUnused, true); + return const_iterator(*this, *FirstUnused, true); } /// Set the entry using a key type that the specified Traits can convert /// from a real key to an internal key. - template <typename Key> bool set_as(const Key &K, ValueT V) { - return set_as_internal(K, std::move(V), None); + template <typename Key, typename TraitsT> + bool set_as(const Key &K, ValueT V, TraitsT &Traits) { + return set_as_internal(K, std::move(V), Traits, None); } - template <typename Key> ValueT get(const Key &K) const { - auto Iter = find_as(K); + template <typename Key, typename TraitsT> + ValueT get(const Key &K, TraitsT &Traits) const { + auto Iter = find_as(K, Traits); assert(Iter != end()); return (*Iter).second; } @@ -267,7 +265,6 @@ protected: bool isPresent(uint32_t K) const { return Present.test(K); } bool isDeleted(uint32_t K) const { return Deleted.test(K); } - TraitsT Traits; BucketList Buckets; mutable SparseBitVector<> Present; mutable SparseBitVector<> Deleted; @@ -275,9 +272,10 @@ protected: private: /// Set the entry using a key type that the specified Traits can convert /// from a real key to an internal key. - template <typename Key> - bool set_as_internal(const Key &K, ValueT V, Optional<uint32_t> InternalKey) { - auto Entry = find_as(K); + template <typename Key, typename TraitsT> + bool set_as_internal(const Key &K, ValueT V, TraitsT &Traits, + Optional<uint32_t> InternalKey) { + auto Entry = find_as(K, Traits); if (Entry != end()) { assert(isPresent(Entry.index())); assert(Traits.storageKeyToLookupKey(Buckets[Entry.index()].first) == K); @@ -294,15 +292,16 @@ private: Present.set(Entry.index()); Deleted.reset(Entry.index()); - grow(); + grow(Traits); - assert((find_as(K)) != end()); + assert((find_as(K, Traits)) != end()); return true; } static uint32_t maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; } - void grow() { + template <typename TraitsT> + void grow(TraitsT &Traits) { uint32_t S = size(); uint32_t MaxLoad = maxLoad(capacity()); if (S < maxLoad(capacity())) @@ -314,10 +313,11 @@ private: // Growing requires rebuilding the table and re-hashing every item. Make a // copy with a larger capacity, insert everything into the copy, then swap // it in. - HashTable NewMap(NewCapacity, Traits); + HashTable NewMap(NewCapacity); for (auto I : Present) { auto LookupKey = Traits.storageKeyToLookupKey(Buckets[I].first); - NewMap.set_as_internal(LookupKey, Buckets[I].second, Buckets[I].first); + NewMap.set_as_internal(LookupKey, Buckets[I].second, Traits, + Buckets[I].first); } Buckets.swap(NewMap.Buckets); diff --git a/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h b/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h index fb00d6ad4bc7..717dce2f2737 100644 --- a/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h +++ b/include/llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h @@ -1,9 +1,8 @@ //===- ISectionContribVisitor.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h index 8c52b042f289..315b09356ae3 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStream.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -1,9 +1,8 @@ //===- InfoStream.h - PDB Info Stream (Stream 1) Access ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h index 101127a355f5..208a37c45d49 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h @@ -1,9 +1,8 @@ //===- InfoStreamBuilder.h - PDB Info Stream Creation -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h b/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h new file mode 100644 index 000000000000..d0cac3749bca --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h @@ -0,0 +1,44 @@ +//===- InjectedSourceStream.h - PDB Headerblock Stream Access ---*- 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_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H + +#include "llvm/DebugInfo/PDB/Native/HashTable.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace msf { +class MappedBlockStream; +} +namespace pdb { +class PDBFile; +class PDBStringTable; + +class InjectedSourceStream { +public: + InjectedSourceStream(std::unique_ptr<msf::MappedBlockStream> Stream); + Error reload(const PDBStringTable &Strings); + + using const_iterator = HashTable<SrcHeaderBlockEntry>::const_iterator; + const_iterator begin() const { return InjectedSourceTable.begin(); } + const_iterator end() const { return InjectedSourceTable.end(); } + + uint32_t size() const { return InjectedSourceTable.size(); } + +private: + std::unique_ptr<msf::MappedBlockStream> Stream; + + const SrcHeaderBlockHeader* Header; + HashTable<SrcHeaderBlockEntry> InjectedSourceTable; +}; +} +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h index 8d590df288f3..cb1ffc729512 100644 --- a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -1,9 +1,8 @@ //===- ModuleDebugStream.h - PDB Module Info Stream Access ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -69,6 +68,8 @@ public: findChecksumsSubsection() const; private: + Error reloadSerialize(BinaryStreamReader &Reader); + DbiModuleDescriptor Mod; uint32_t Signature; diff --git a/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h index 01b8f1b5da56..1df059ffa9fd 100644 --- a/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h +++ b/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h @@ -1,9 +1,8 @@ //===- NamedStreamMap.h - PDB Named Stream Map ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -60,7 +59,7 @@ private: NamedStreamMapTraits HashTraits; /// Closed hash table from Offset -> StreamNumber, where Offset is the offset /// of the stream name in NamesBuffer. - HashTable<support::ulittle32_t, NamedStreamMapTraits> OffsetIndexMap; + HashTable<support::ulittle32_t> OffsetIndexMap; /// Buffer of string data. std::vector<char> NamesBuffer; diff --git a/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h index 3cd465503044..50d437642d0f 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h @@ -1,9 +1,8 @@ //===- NativeCompilandSymbol.h - native impl for compiland syms -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h index 4442a1ec41fb..073878afd129 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h @@ -1,9 +1,8 @@ //==- NativeEnumGlobals.h - Native Global Enumerator impl --------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h new file mode 100644 index 000000000000..ca1e22bd82a2 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h @@ -0,0 +1,43 @@ +//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==// +// +// 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_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" +#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h" + +namespace llvm { +namespace pdb { + +class InjectedSourceStream; +class PDBStringTable; + +class NativeEnumInjectedSources : public IPDBEnumChildren<IPDBInjectedSource> { +public: + NativeEnumInjectedSources(PDBFile &File, const InjectedSourceStream &IJS, + const PDBStringTable &Strings); + + uint32_t getChildCount() const override; + std::unique_ptr<IPDBInjectedSource> + getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<IPDBInjectedSource> getNext() override; + void reset() override; + +private: + PDBFile &File; + const InjectedSourceStream &Stream; + const PDBStringTable &Strings; + InjectedSourceStream::const_iterator Cur; +}; + +} // namespace pdb +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h index c268641a1008..94f1ee18ed9f 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumModules.h @@ -1,9 +1,8 @@ //==- NativeEnumModules.h - Native Module Enumerator impl --------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h index f8ac1655dc61..25c56567384f 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h @@ -1,9 +1,8 @@ //==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h index f4030da1d026..280358d02305 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h @@ -1,9 +1,8 @@ //===- NativeExeSymbol.h - native impl for PDBSymbolExe ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 6505a7d39573..4133be220713 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -1,9 +1,8 @@ //==- NativeRawSymbol.h - Native implementation of IPDBRawSymbol -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/include/llvm/DebugInfo/PDB/Native/NativeSession.h index 4878e47d3121..ee7d8cdec93b 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -1,9 +1,8 @@ //===- NativeSession.h - Native implementation of IPDBSession ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h index acc5eb8ff2c2..063585097899 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h @@ -1,9 +1,8 @@ //===- NativeSymbolEnumerator.h - info about enumerator values --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h index 10e68e6df450..262864fd709f 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeArray.h @@ -1,9 +1,8 @@ //===- NativeTypeArray.h ------------------------------------------ C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h index 725dfb89222f..8bb09f05d0bc 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h @@ -1,9 +1,8 @@ //===- NativeTypeBuiltin.h ---------------------------------------- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h index a5cbefc18111..2068c88fc74a 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeEnum.h @@ -1,9 +1,8 @@ //===- NativeTypeEnum.h - info about enum type ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h index 1b1b87f6581f..a7ea287dffc8 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h @@ -1,9 +1,8 @@ //===- NativeTypeFunctionSig.h - info about function signature ---*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h index bcb7431fecf1..446f77db0f6c 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h @@ -1,9 +1,8 @@ //===- NativeTypePointer.h - info about pointer type -------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h index 06eb6fcf3764..fe8a6f7f2bda 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h @@ -1,9 +1,8 @@ //===- NativeTypeTypedef.h - info about typedef ------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h index 84821d8731be..8f4dee3e658c 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h @@ -1,9 +1,8 @@ //===- NativeTypeUDT.h - info about class/struct type ------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h index a996f34ef859..4ec0f9bf6b3d 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h @@ -1,9 +1,8 @@ //===- NativeTypeVTShape.h - info about virtual table shape ------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h index 5e39ac3e37b7..56de4030167d 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -1,9 +1,8 @@ //===- PDBFile.h - Low level interface to a PDB file ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -33,6 +32,7 @@ namespace pdb { class DbiStream; class GlobalsStream; class InfoStream; +class InjectedSourceStream; class PDBStringTable; class PDBFileBuilder; class PublicsStream; @@ -84,7 +84,12 @@ public: ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const; - std::unique_ptr<msf::MappedBlockStream> createIndexedStream(uint16_t SN); + std::unique_ptr<msf::MappedBlockStream> + createIndexedStream(uint16_t SN) const; + Expected<std::unique_ptr<msf::MappedBlockStream>> + safelyCreateIndexedStream(uint32_t StreamIndex) const; + Expected<std::unique_ptr<msf::MappedBlockStream>> + safelyCreateNamedStream(StringRef Name); msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const; msf::MSFStreamLayout getFpmStreamLayout() const; @@ -100,6 +105,7 @@ public: Expected<PublicsStream &> getPDBPublicsStream(); Expected<SymbolStream &> getPDBSymbolStream(); Expected<PDBStringTable &> getStringTable(); + Expected<InjectedSourceStream &> getInjectedSourceStream(); BumpPtrAllocator &getAllocator() { return Allocator; } @@ -111,15 +117,11 @@ public: bool hasPDBSymbolStream(); bool hasPDBTpiStream() const; bool hasPDBStringTable(); + bool hasPDBInjectedSourceStream(); uint32_t getPointerSize(); private: - Expected<std::unique_ptr<msf::MappedBlockStream>> - safelyCreateIndexedStream(const msf::MSFLayout &Layout, - BinaryStreamRef MsfData, - uint32_t StreamIndex) const; - std::string FilePath; BumpPtrAllocator &Allocator; @@ -136,6 +138,7 @@ private: std::unique_ptr<SymbolStream> Symbols; std::unique_ptr<msf::MappedBlockStream> DirectoryStream; std::unique_ptr<msf::MappedBlockStream> StringTableStream; + std::unique_ptr<InjectedSourceStream> InjectedSources; std::unique_ptr<PDBStringTable> Strings; }; } diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h index 37458749a8d8..2abaa5f4cdc4 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -1,9 +1,8 @@ //===- PDBFileBuilder.h - PDB File Creation ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -98,7 +97,7 @@ private: PDBStringTableBuilder Strings; StringTableHashTraits InjectedSourceHashTraits; - HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable; + HashTable<SrcHeaderBlockEntry> InjectedSourceTable; SmallVector<InjectedSourceDescriptor, 2> InjectedSources; diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index 29167c966d42..57f0b64a32a6 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -1,9 +1,8 @@ //===- PDBStringTable.h - PDB String Table -----------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h index 0f81c18eafe6..57267ef5c6c5 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -1,9 +1,8 @@ //===- PDBStringTableBuilder.h - PDB String Table Builder -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h index 2d0222a9071a..ee28d108df8b 100644 --- a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h +++ b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h @@ -1,9 +1,8 @@ //===- PublicsStream.h - PDB Public Symbol Stream -------- ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/include/llvm/DebugInfo/PDB/Native/RawConstants.h index fbbd3318d958..0dde5ef66932 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawConstants.h +++ b/include/llvm/DebugInfo/PDB/Native/RawConstants.h @@ -1,9 +1,8 @@ //===- RawConstants.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/RawError.h b/include/llvm/DebugInfo/PDB/Native/RawError.h index 97d11b4f20d1..aadb64c2e3f1 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawError.h +++ b/include/llvm/DebugInfo/PDB/Native/RawError.h @@ -1,9 +1,8 @@ //===- RawError.h - Error extensions for raw PDB implementation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 8f6d6611c032..6119e6e5db26 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -1,9 +1,8 @@ //===- RawTypes.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -177,7 +176,7 @@ struct DbiStreamHeader { }; static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); -/// The header preceeding the File Info Substream of the DBI stream. +/// The header preceding the File Info Substream of the DBI stream. struct FileInfoSubstreamHeader { /// Total # of modules, should match number of records in the ModuleInfo /// substream. @@ -208,7 +207,7 @@ struct ModInfoFlags { static const uint16_t TypeServerIndexShift = 8; }; -/// The header preceeding each entry in the Module Info substream of the DBI +/// The header preceding each entry in the Module Info substream of the DBI /// stream. Corresponds to the type MODI in the reference implementation. struct ModuleInfoHeader { /// Currently opened module. This field is a pointer in the reference @@ -273,7 +272,7 @@ struct PublicsStreamHeader { support::ulittle32_t NumSections; }; -// The header preceeding the global TPI stream. +// The header preceding the global TPI stream. // This corresponds to `HDR` in PDB/dbi/tpi.h. struct TpiStreamHeader { struct EmbeddedBuf { @@ -301,7 +300,7 @@ struct TpiStreamHeader { const uint32_t MinTpiHashBuckets = 0x1000; const uint32_t MaxTpiHashBuckets = 0x40000; -/// The header preceeding the global PDB Stream (Stream 1) +/// The header preceding the global PDB Stream (Stream 1) struct InfoStreamHeader { support::ulittle32_t Version; support::ulittle32_t Signature; @@ -309,7 +308,7 @@ struct InfoStreamHeader { codeview::GUID Guid; }; -/// The header preceeding the /names stream. +/// The header preceding the /names stream. struct PDBStringTableHeader { support::ulittle32_t Signature; // PDBStringTableSignature support::ulittle32_t HashVersion; // 1 or 2 @@ -342,7 +341,6 @@ struct SrcHeaderBlockEntry { short Padding; // Pad to 4 bytes. char Reserved[8]; }; - static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!"); } // namespace pdb diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index 08e1d41e6ee9..0b15ab474f71 100644 --- a/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -1,9 +1,8 @@ //==- SymbolCache.h - Cache of native symbols and ids ------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h index ae9f7d657b70..4fe1bd9734e4 100644 --- a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h +++ b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h @@ -1,9 +1,8 @@ //===- SymbolStream.cpp - PDB Symbol Stream Access --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h index c2996ccf1825..4ac60a80e701 100644 --- a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h +++ b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h @@ -1,9 +1,8 @@ //===- TpiHashing.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/include/llvm/DebugInfo/PDB/Native/TpiStream.h index b76576a7a263..1b7fd2d54cb2 100644 --- a/include/llvm/DebugInfo/PDB/Native/TpiStream.h +++ b/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -1,9 +1,8 @@ //===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 Access ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h index 411720d6f56b..72d98e9c2c4d 100644 --- a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h @@ -1,9 +1,8 @@ //===- TpiStreamBuilder.h - PDB Tpi Stream Creation -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h index 9f9da39ca6cc..6d734dc2f243 100644 --- a/include/llvm/DebugInfo/PDB/PDB.h +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -1,9 +1,8 @@ //===- PDB.h - base header file for creating a PDB reader -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h index 0ce49f5ef922..7b6793f0a639 100644 --- a/include/llvm/DebugInfo/PDB/PDBContext.h +++ b/include/llvm/DebugInfo/PDB/PDBContext.h @@ -1,9 +1,8 @@ //===-- PDBContext.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===/ @@ -44,15 +43,18 @@ namespace pdb { void dump(raw_ostream &OS, DIDumpOptions DIDumpOpts) override; DILineInfo getLineInfoForAddress( - uint64_t Address, + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DILineInfoTable getLineInfoForAddressRange( - uint64_t Address, uint64_t Size, + object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; DIInliningInfo getInliningInfoForAddress( - uint64_t Address, + object::SectionedAddress Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + std::vector<DILocal> + getLocalsForAddress(object::SectionedAddress Address) override; + private: std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; std::unique_ptr<IPDBSession> Session; diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h index aaec71aa8c90..45aba013e7c8 100644 --- a/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -1,9 +1,8 @@ //===- PDBExtras.h - helper functions and classes for PDBs ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -28,7 +27,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value); raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv); raw_ostream &operator<<(raw_ostream &OS, const PDB_BuiltinType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_DataKind &Data); -raw_ostream &operator<<(raw_ostream &OS, const codeview::RegisterId &Reg); +raw_ostream &operator<<(raw_ostream &OS, + const llvm::codeview::CPURegister &CpuReg); raw_ostream &operator<<(raw_ostream &OS, const PDB_LocType &Loc); raw_ostream &operator<<(raw_ostream &OS, const codeview::ThunkOrdinal &Thunk); raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); @@ -37,13 +37,12 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); -raw_ostream &operator<<(raw_ostream &OS, - const PDB_SourceCompression &Compression); raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats); +raw_ostream& dumpPDBSourceCompression(raw_ostream& OS, uint32_t Compression); template <typename T> void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent) { diff --git a/include/llvm/DebugInfo/PDB/PDBSymDumper.h b/include/llvm/DebugInfo/PDB/PDBSymDumper.h index c976935c48e0..f81b15f2353d 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymDumper.h +++ b/include/llvm/DebugInfo/PDB/PDBSymDumper.h @@ -1,9 +1,8 @@ //===- PDBSymDumper.h - base interface for PDB symbol dumper *- C++ -----*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h index 3a74f7c3aace..d9004a8894d9 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -1,9 +1,8 @@ //===- PDBSymbol.h - base class for user-facing symbol types -----*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h index ef00df15cb0a..c76466a97b66 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolAnnotation.h @@ -1,9 +1,8 @@ //===- PDBSymbolAnnotation.h - Accessors for querying PDB annotations ---*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_DEBUGINFO_PDB_PDBSYMBOLANNOTATION_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h index 2cf9c72a8886..cf471450d989 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolBlock.h @@ -1,9 +1,8 @@ //===- PDBSymbolBlock.h - Accessors for querying PDB blocks -------------*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_DEBUGINFO_PDB_PDBSYMBOLBLOCK_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h index 04dbd962ebd4..ca8b39d03f86 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -1,9 +1,8 @@ //===- PDBSymbolCompiland.h - Accessors for querying PDB compilands -----*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_DEBUGINFO_PDB_PDBSYMBOLCOMPILAND_H diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h index 3d651a464d94..b82bb6c0a352 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h @@ -1,9 +1,8 @@ //===- PDBSymbolCompilandDetails.h - PDB compiland details ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h index ffc408314d9a..61607a03593d 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h @@ -1,9 +1,8 @@ //===- PDBSymbolCompilandEnv.h - compiland environment variables *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h index c29e4c31d3f3..75a86411643a 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolCustom.h @@ -1,9 +1,8 @@ //===- PDBSymbolCustom.h - compiler-specific types --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/include/llvm/DebugInfo/PDB/PDBSymbolData.h index 217e1e976e6b..7e9b69d7cf4b 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -1,9 +1,8 @@ //===- PDBSymbolData.h - PDB data (e.g. variable) accessors -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h index 366d0cf4777f..1a9fb240a248 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolExe.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolExe.h @@ -1,9 +1,8 @@ //===- PDBSymbolExe.h - Accessors for querying executables in a PDB ----*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index 129e557c7f25..6be27c8d3bc7 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -1,9 +1,8 @@ //===- PDBSymbolFunc.h - class representing a function instance -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h index 18db8a50fd1b..7152249cbd03 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h @@ -1,9 +1,8 @@ //===- PDBSymbolFuncDebugEnd.h - function end bounds info -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h index 83d82f0cbcc5..3125c271d2e8 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h @@ -1,9 +1,8 @@ //===- PDBSymbolFuncDebugStart.h - function start bounds info ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h index 8b2617fcd757..3625e23f014f 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolLabel.h @@ -1,9 +1,8 @@ //===- PDBSymbolLabel.h - label info ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h index 9def3edb469a..e2b2545d78ec 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h @@ -1,9 +1,8 @@ //===- PDBSymbolPublicSymbol.h - public symbol info -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h index 7bb0555362db..274de8b0b16f 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolThunk.h @@ -1,9 +1,8 @@ //===- PDBSymbolThunk.h - Support for querying PDB thunks ---------------*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h index 488f668bdc10..c0215c9ee4b1 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeArray.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeArray.h - array type information ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h index 550deedd7504..bab292ee0d46 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeBaseClass.h - base class type information ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h index e07e88802b8f..7d94c3c97a2b 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeBuiltin.h - builtin type information --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h index 0d8979c9c5c5..dc647aff48d3 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeCustom.h - custom compiler type information -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h index 58292a63501f..7a9e43785d67 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeDimension.h - array dimension type info -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h index f463047bb5b5..3ac72801b202 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeEnum.h - enum type info ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h index 5b940b0737af..c4d9dd6308a3 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeFriend.h - friend type info -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h index 074cb418fc82..22d3623496f2 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeFunctionArg.h - function arg type info ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index dfdf436197c3..a1491ca2e415 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeFunctionSig.h - function signature type info *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h index d716abd640c6..6bc70bca82e7 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeManaged.h - managed type info ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index 300d6722fc4d..b36f459e880c 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypePointer.h - pointer type info ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h index d6e2a36486d5..2712d0617e0e 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeTypedef.h - typedef type info ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index 937dd6c87221..3e73ad7ac85a 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeUDT.h - UDT type info -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h index 6efce4bbd686..e8161d311ea7 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeVTable.h - VTable type info -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h index 8949052b0c0f..614060867042 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h @@ -1,9 +1,8 @@ //===- PDBSymbolTypeVTableShape.h - VTable shape info -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h index e935ac6ce0dc..cc29d38c2578 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUnknown.h @@ -1,9 +1,8 @@ //===- PDBSymbolUnknown.h - unknown symbol type -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h index 4e8c99fc8d89..fd812cb2f793 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h @@ -1,9 +1,8 @@ //===- PDBSymbolUsingNamespace.h - using namespace info ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h index 917f3ed73910..c26d8d1ed10c 100644 --- a/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -1,9 +1,8 @@ //===- PDBTypes.h - Defines enums for various fields contained in PDB ----====// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -127,6 +126,7 @@ enum class PDB_Machine { Am33 = 0x13, Amd64 = 0x8664, Arm = 0x1C0, + Arm64 = 0xaa64, ArmNT = 0x1C4, Ebc = 0xEBC, x86 = 0x14C, @@ -146,11 +146,69 @@ enum class PDB_Machine { WceMipsV2 = 0x169 }; -enum class PDB_SourceCompression { - None, - RunLengthEncoded, - Huffman, - LZ, +// A struct with an inner unnamed enum with explicit underlying type resuls +// in an enum class that can implicitly convert to the underlying type, which +// is convenient for this enum. +struct PDB_SourceCompression { + enum : uint32_t { + // No compression. Produced e.g. by `link.exe /natvis:foo.natvis`. + None, + // Not known what produces this. + RunLengthEncoded, + // Not known what produces this. + Huffman, + // Not known what produces this. + LZ, + // Produced e.g. by `csc /debug`. The encoded data is its own mini-stream + // with the following layout (in little endian): + // GUID LanguageTypeGuid; + // GUID LanguageVendorGuid; + // GUID DocumentTypeGuid; + // GUID HashFunctionGuid; + // uint32_t HashDataSize; + // uint32_t CompressedDataSize; + // Followed by HashDataSize bytes containing a hash checksum, + // followed by CompressedDataSize bytes containing source contents. + // + // CompressedDataSize can be 0, in this case only the hash data is present. + // (CompressedDataSize is != 0 e.g. if `/embed` is passed to csc.exe.) + // The compressed data format is: + // uint32_t UncompressedDataSize; + // If UncompressedDataSize is 0, the data is stored uncompressed and + // CompressedDataSize stores the uncompressed size. + // If UncompressedDataSize is != 0, then the data is in raw deflate + // encoding as described in rfc1951. + // + // A GUID is 16 bytes, stored in the usual + // uint32_t + // uint16_t + // uint16_t + // uint8_t[24] + // layout. + // + // Well-known GUIDs for LanguageTypeGuid are: + // 63a08714-fc37-11d2-904c-00c04fa302a1 C + // 3a12d0b7-c26c-11d0-b442-00a0244a1dd2 C++ + // 3f5162f8-07c6-11d3-9053-00c04fa302a1 C# + // af046cd1-d0e1-11d2-977c-00a0c9b4d50c Cobol + // ab4f38c9-b6e6-43ba-be3b-58080b2ccce3 F# + // 3a12d0b4-c26c-11d0-b442-00a0244a1dd2 Java + // 3a12d0b6-c26c-11d0-b442-00a0244a1dd2 JScript + // af046cd2-d0e1-11d2-977c-00a0c9b4d50c Pascal + // 3a12d0b8-c26c-11d0-b442-00a0244a1dd2 Visual Basic + // + // Well-known GUIDs for LanguageVendorGuid are: + // 994b45c4-e6e9-11d2-903f-00c04fa302a1 Microsoft + // + // Well-known GUIDs for DocumentTypeGuid are: + // 5a869d0b-6611-11d3-bd2a-0000f80849bd Text + // + // Well-known GUIDs for HashFunctionGuid are: + // 406ea660-64cf-4c82-b6f0-42d48172a799 MD5 (HashDataSize is 16) + // ff1816ec-aa5e-4d10-87f7-6f4963833460 SHA1 (HashDataSize is 20) + // 8829d00f-11b8-4213-878b-770e8597ac16 SHA256 (HashDataSize is 32) + DotNet = 101, + }; }; /// These values correspond to the CV_call_e enumeration, and are documented diff --git a/include/llvm/DebugInfo/PDB/UDTLayout.h b/include/llvm/DebugInfo/PDB/UDTLayout.h index c4234c191e21..c67b093b63c0 100644 --- a/include/llvm/DebugInfo/PDB/UDTLayout.h +++ b/include/llvm/DebugInfo/PDB/UDTLayout.h @@ -1,9 +1,8 @@ //===- UDTLayout.h - UDT layout info ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/include/llvm/DebugInfo/Symbolize/DIPrinter.h index ab82be3706d8..db7a61a8f160 100644 --- a/include/llvm/DebugInfo/Symbolize/DIPrinter.h +++ b/include/llvm/DebugInfo/Symbolize/DIPrinter.h @@ -1,9 +1,8 @@ //===- llvm/DebugInfo/Symbolize/DIPrinter.h ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,15 +20,22 @@ namespace llvm { struct DILineInfo; class DIInliningInfo; struct DIGlobal; +struct DILocal; namespace symbolize { class DIPrinter { +public: + enum class OutputStyle { LLVM, GNU }; + +private: raw_ostream &OS; bool PrintFunctionNames; bool PrintPretty; int PrintSourceContext; bool Verbose; + bool Basenames; + OutputStyle Style; void print(const DILineInfo &Info, bool Inlined); void printContext(const std::string &FileName, int64_t Line); @@ -37,14 +43,16 @@ class DIPrinter { public: DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true, bool PrintPretty = false, int PrintSourceContext = 0, - bool Verbose = false) + bool Verbose = false, bool Basenames = false, + OutputStyle Style = OutputStyle::LLVM) : OS(OS), PrintFunctionNames(PrintFunctionNames), PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext), - Verbose(Verbose) {} + Verbose(Verbose), Basenames(Basenames), Style(Style) {} DIPrinter &operator<<(const DILineInfo &Info); DIPrinter &operator<<(const DIInliningInfo &Info); DIPrinter &operator<<(const DIGlobal &Global); + DIPrinter &operator<<(const DILocal &Local); }; } } diff --git a/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h b/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h index e576a91e887c..506ecc424b4c 100644 --- a/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h +++ b/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h @@ -1,9 +1,8 @@ //===- SymbolizableModule.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,13 +24,16 @@ class SymbolizableModule { public: virtual ~SymbolizableModule() = default; - virtual DILineInfo symbolizeCode(uint64_t ModuleOffset, + virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const = 0; - virtual DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const = 0; - virtual DIGlobal symbolizeData(uint64_t ModuleOffset) const = 0; + virtual DIInliningInfo + symbolizeInlinedCode(object::SectionedAddress ModuleOffset, + FunctionNameKind FNKind, bool UseSymbolTable) const = 0; + virtual DIGlobal + symbolizeData(object::SectionedAddress ModuleOffset) const = 0; + virtual std::vector<DILocal> + symbolizeFrame(object::SectionedAddress ModuleOffset) const = 0; // Return true if this is a 32-bit x86 PE COFF module. virtual bool isWin32Module() const = 0; diff --git a/include/llvm/DebugInfo/Symbolize/Symbolize.h b/include/llvm/DebugInfo/Symbolize/Symbolize.h index 289148f569db..d3da28ca0b7b 100644 --- a/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -1,9 +1,8 @@ //===- Symbolize.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -36,35 +35,35 @@ using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; class LLVMSymbolizer { public: struct Options { - FunctionNameKind PrintFunctions; - bool UseSymbolTable : 1; - bool Demangle : 1; - bool RelativeAddresses : 1; + FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName; + bool UseSymbolTable = true; + bool Demangle = true; + bool RelativeAddresses = false; std::string DefaultArch; std::vector<std::string> DsymHints; - - Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, - bool UseSymbolTable = true, bool Demangle = true, - bool RelativeAddresses = false, std::string DefaultArch = "") - : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable), - Demangle(Demangle), RelativeAddresses(RelativeAddresses), - DefaultArch(std::move(DefaultArch)) {} + std::string FallbackDebugPath; + std::string DWPName; }; - LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} + LLVMSymbolizer() = default; + LLVMSymbolizer(const Options &Opts) : Opts(Opts) {} ~LLVMSymbolizer() { flush(); } + Expected<DILineInfo> symbolizeCode(const ObjectFile &Obj, + object::SectionedAddress ModuleOffset); Expected<DILineInfo> symbolizeCode(const std::string &ModuleName, - uint64_t ModuleOffset, - StringRef DWPName = ""); - Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName, - uint64_t ModuleOffset, - StringRef DWPName = ""); + object::SectionedAddress ModuleOffset); + Expected<DIInliningInfo> + symbolizeInlinedCode(const std::string &ModuleName, + object::SectionedAddress ModuleOffset); Expected<DIGlobal> symbolizeData(const std::string &ModuleName, - uint64_t ModuleOffset); + object::SectionedAddress ModuleOffset); + Expected<std::vector<DILocal>> + symbolizeFrame(const std::string &ModuleName, + object::SectionedAddress ModuleOffset); void flush(); static std::string @@ -74,14 +73,23 @@ public: private: // Bundles together object file with code/data and object file with // corresponding debug info. These objects can be the same. - using ObjectPair = std::pair<ObjectFile *, ObjectFile *>; + using ObjectPair = std::pair<const ObjectFile *, const ObjectFile *>; + + Expected<DILineInfo> + symbolizeCodeCommon(SymbolizableModule *Info, + object::SectionedAddress ModuleOffset); /// Returns a SymbolizableModule or an error if loading debug info failed. /// Only one attempt is made to load a module, and errors during loading are /// only reported once. Subsequent calls to get module info for a module that /// failed to load will return nullptr. Expected<SymbolizableModule *> - getOrCreateModuleInfo(const std::string &ModuleName, StringRef DWPName = ""); + getOrCreateModuleInfo(const std::string &ModuleName); + + Expected<SymbolizableModule *> + createModuleInfo(const ObjectFile *Obj, + std::unique_ptr<DIContext> Context, + StringRef ModuleName); ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, diff --git a/include/llvm/Demangle/Compiler.h b/include/llvm/Demangle/Compiler.h deleted file mode 100644 index 248d6e3a7faa..000000000000 --- a/include/llvm/Demangle/Compiler.h +++ /dev/null @@ -1,93 +0,0 @@ -//===--- Compiler.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// This file contains a variety of feature test macros copied from -// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take -// a dependency on LLVMSupport. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEMANGLE_COMPILER_H -#define LLVM_DEMANGLE_COMPILER_H - -#ifdef _MSC_VER -// snprintf is implemented in VS 2015 -#if _MSC_VER < 1900 -#define snprintf _snprintf_s -#endif -#endif - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 -#endif - -#ifndef __has_attribute -#define __has_attribute(x) 0 -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#ifndef LLVM_GNUC_PREREQ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ - ((maj) << 20) + ((min) << 10) + (patch)) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) -#else -#define LLVM_GNUC_PREREQ(maj, min, patch) 0 -#endif -#endif - -#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) -#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) -#else -#define LLVM_ATTRIBUTE_USED -#endif - -#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) -#define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() -#elif defined(_MSC_VER) -#define LLVM_BUILTIN_UNREACHABLE __assume(false) -#endif - -#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) -#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define LLVM_ATTRIBUTE_NOINLINE -#endif - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED -#else -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE -#endif - -#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) -#define LLVM_FALLTHROUGH [[fallthrough]] -#elif __has_cpp_attribute(gnu::fallthrough) -#define LLVM_FALLTHROUGH [[gnu::fallthrough]] -#elif !__cplusplus -// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious -// error when __has_cpp_attribute is given a scoped attribute in C mode. -#define LLVM_FALLTHROUGH -#elif __has_cpp_attribute(clang::fallthrough) -#define LLVM_FALLTHROUGH [[clang::fallthrough]] -#else -#define LLVM_FALLTHROUGH -#endif - -#endif diff --git a/include/llvm/Demangle/Demangle.h b/include/llvm/Demangle/Demangle.h index 4c9dc9569e18..6fea7ef13f11 100644 --- a/include/llvm/Demangle/Demangle.h +++ b/include/llvm/Demangle/Demangle.h @@ -1,9 +1,8 @@ //===--- Demangle.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -11,6 +10,7 @@ #define LLVM_DEMANGLE_DEMANGLE_H #include <cstddef> +#include <string> namespace llvm { /// This is a llvm local version of __cxa_demangle. Other than the name and @@ -36,6 +36,13 @@ enum MSDemangleFlags { MSDF_None = 0, MSDF_DumpBackrefs = 1 << 0 }; char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, int *status, MSDemangleFlags Flags = MSDF_None); +/// Attempt to demangle a string using different demangling schemes. +/// The function uses heuristics to determine which demangling scheme to use. +/// \param MangledName - reference to string to demangle. +/// \returns - the demangled string, or a copy of the input string if no +/// demangling occurred. +std::string demangle(const std::string &MangledName); + /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain /// properties or partially printing the demangled name. diff --git a/include/llvm/Demangle/DemangleConfig.h b/include/llvm/Demangle/DemangleConfig.h new file mode 100644 index 000000000000..73f89d357c85 --- /dev/null +++ b/include/llvm/Demangle/DemangleConfig.h @@ -0,0 +1,99 @@ +//===--- DemangleConfig.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 contains a variety of feature test macros copied from +// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take +// a dependency on LLVMSupport. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_COMPILER_H +#define LLVM_DEMANGLE_COMPILER_H + +#ifdef _MSC_VER +// snprintf is implemented in VS 2015 +#if _MSC_VER < 1900 +#define snprintf _snprintf_s +#endif +#endif + +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +#ifndef __has_cpp_attribute +#define __has_cpp_attribute(x) 0 +#endif + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +#ifndef DEMANGLE_GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ + ((maj) << 20) + ((min) << 10) + (patch)) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \ + ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) +#else +#define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0 +#endif +#endif + +#if __has_attribute(used) || DEMANGLE_GNUC_PREREQ(3, 1, 0) +#define DEMANGLE_ATTRIBUTE_USED __attribute__((__used__)) +#else +#define DEMANGLE_ATTRIBUTE_USED +#endif + +#if __has_builtin(__builtin_unreachable) || DEMANGLE_GNUC_PREREQ(4, 5, 0) +#define DEMANGLE_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +#define DEMANGLE_UNREACHABLE __assume(false) +#else +#define DEMANGLE_UNREACHABLE +#endif + +#if __has_attribute(noinline) || DEMANGLE_GNUC_PREREQ(3, 4, 0) +#define DEMANGLE_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define DEMANGLE_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define DEMANGLE_ATTRIBUTE_NOINLINE +#endif + +#if !defined(NDEBUG) +#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE DEMANGLE_ATTRIBUTE_USED +#else +#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE +#endif + +#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) +#define DEMANGLE_FALLTHROUGH [[fallthrough]] +#elif __has_cpp_attribute(gnu::fallthrough) +#define DEMANGLE_FALLTHROUGH [[gnu::fallthrough]] +#elif !__cplusplus +// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious +// error when __has_cpp_attribute is given a scoped attribute in C mode. +#define DEMANGLE_FALLTHROUGH +#elif __has_cpp_attribute(clang::fallthrough) +#define DEMANGLE_FALLTHROUGH [[clang::fallthrough]] +#else +#define DEMANGLE_FALLTHROUGH +#endif + +#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle { +#define DEMANGLE_NAMESPACE_END } } + +#endif diff --git a/include/llvm/Demangle/ItaniumDemangle.h b/include/llvm/Demangle/ItaniumDemangle.h index 0b9187f30a5a..aaccb27e17a3 100644 --- a/include/llvm/Demangle/ItaniumDemangle.h +++ b/include/llvm/Demangle/ItaniumDemangle.h @@ -1,23 +1,26 @@ //===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure +// 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 is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// Generic itanium demangler library. This file has two byte-per-byte identical +// copies in the source tree, one in libcxxabi, and the other in llvm. // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_H -#define LLVM_DEMANGLE_ITANIUMDEMANGLE_H +#ifndef DEMANGLE_ITANIUMDEMANGLE_H +#define DEMANGLE_ITANIUMDEMANGLE_H // FIXME: (possibly) incomplete list of features that clang mangles that this // file does not yet support: // - C++ modules TS -#include "llvm/Demangle/Compiler.h" -#include "llvm/Demangle/StringView.h" -#include "llvm/Demangle/Utility.h" - +#include "DemangleConfig.h" +#include "StringView.h" +#include "Utility.h" #include <cassert> #include <cctype> #include <cstdio> @@ -86,6 +89,7 @@ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ + X(UUIDOfExpr) \ X(BoolExpr) \ X(IntegerCastExpr) \ X(IntegerLiteral) \ @@ -95,8 +99,8 @@ X(BracedExpr) \ X(BracedRangeExpr) -namespace llvm { -namespace itanium_demangle { +DEMANGLE_NAMESPACE_BEGIN + // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. class Node { @@ -194,7 +198,7 @@ public: virtual ~Node() = default; #ifndef NDEBUG - LLVM_DUMP_METHOD void dump() const; + DEMANGLE_DUMP_METHOD void dump() const; #endif }; @@ -1278,7 +1282,7 @@ public: case SpecialSubKind::iostream: return StringView("basic_iostream"); } - LLVM_BUILTIN_UNREACHABLE; + DEMANGLE_UNREACHABLE; } void printLeft(OutputStream &S) const override { @@ -1330,7 +1334,7 @@ public: case SpecialSubKind::iostream: return StringView("iostream"); } - LLVM_BUILTIN_UNREACHABLE; + DEMANGLE_UNREACHABLE; } void printLeft(OutputStream &S) const override { @@ -1870,6 +1874,21 @@ public: } }; +// MSVC __uuidof extension, generated by clang in -fms-extensions mode. +class UUIDOfExpr : public Node { + Node *Operand; +public: + UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} + + template<typename Fn> void match(Fn F) const { F(Operand); } + + void printLeft(OutputStream &S) const override { + S << "__uuidof("; + Operand->print(S); + S << ")"; + } +}; + class BoolExpr : public Node { bool Value; @@ -2476,6 +2495,12 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) { return nullptr; return make<ClosureTypeName>(Params, Count); } + if (consumeIf("Ub")) { + (void)parseNumber(); + if (!consumeIf('_')) + return nullptr; + return make<NameType>("'block-literal'"); + } return nullptr; } @@ -2785,11 +2810,13 @@ AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) { // <ctor-dtor-name> ::= C1 # complete object constructor // ::= C2 # base object constructor // ::= C3 # complete object allocating constructor -// extension ::= C5 # ? +// extension ::= C4 # gcc old-style "[unified]" constructor +// extension ::= C5 # the COMDAT used for ctors // ::= D0 # deleting destructor // ::= D1 # complete object destructor // ::= D2 # base object destructor -// extension ::= D5 # ? +// extension ::= D4 # gcc old-style "[unified]" destructor +// extension ::= D5 # the COMDAT used for dtors template <typename Derived, typename Alloc> Node * AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar, @@ -2812,7 +2839,8 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar, if (consumeIf('C')) { bool IsInherited = consumeIf('I'); - if (look() != '1' && look() != '2' && look() != '3' && look() != '5') + if (look() != '1' && look() != '2' && look() != '3' && look() != '4' && + look() != '5') return nullptr; int Variant = look() - '0'; ++First; @@ -2821,15 +2849,15 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar, if (getDerived().parseName(State) == nullptr) return nullptr; } - return make<CtorDtorName>(SoFar, false, Variant); + return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant); } - if (look() == 'D' && - (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) { + if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' || + look(1) == '4' || look(1) == '5')) { int Variant = look(1) - '0'; First += 2; if (State) State->CtorDtorConversion = true; - return make<CtorDtorName>(SoFar, true, Variant); + return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant); } return nullptr; @@ -3467,7 +3495,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { Result = getDerived().parseFunctionType(); break; } - LLVM_FALLTHROUGH; + DEMANGLE_FALLTHROUGH; } case 'U': { Result = getDerived().parseQualifiedType(); @@ -3564,7 +3592,11 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { StringView Res = parseBareSourceName(); if (Res.empty()) return nullptr; - return make<NameType>(Res); + // Typically, <builtin-type>s are not considered substitution candidates, + // but the exception to that exception is vendor extended types (Itanium C++ + // ABI 5.9.1). + Result = make<NameType>(Res); + break; } case 'D': switch (look(1)) { @@ -3592,6 +3624,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { case 's': First += 2; return make<NameType>("char16_t"); + // ::= Du # char8_t (C++2a, not yet in the Itanium spec) + case 'u': + First += 2; + return make<NameType>("char8_t"); // ::= Da # auto (in dependent new-expressions) case 'a': First += 2; @@ -3754,7 +3790,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { // substitution table. return Sub; } - LLVM_FALLTHROUGH; + DEMANGLE_FALLTHROUGH; } // ::= <class-enum-type> default: { @@ -4633,6 +4669,21 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } + + if (consumeIf("u8__uuidoft")) { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make<UUIDOfExpr>(Ty); + } + + if (consumeIf("u8__uuidofz")) { + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make<UUIDOfExpr>(Ex); + } + return nullptr; } @@ -5139,7 +5190,7 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) { // extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+ template <typename Derived, typename Alloc> Node *AbstractManglingParser<Derived, Alloc>::parse() { - if (consumeIf("_Z")) { + if (consumeIf("_Z") || consumeIf("__Z")) { Node *Encoding = getDerived().parseEncoding(); if (Encoding == nullptr) return nullptr; @@ -5152,7 +5203,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() { return Encoding; } - if (consumeIf("___Z")) { + if (consumeIf("___Z") || consumeIf("____Z")) { Node *Encoding = getDerived().parseEncoding(); if (Encoding == nullptr || !consumeIf("_block_invoke")) return nullptr; @@ -5178,7 +5229,6 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> { Alloc>::AbstractManglingParser; }; -} // namespace itanium_demangle -} // namespace llvm +DEMANGLE_NAMESPACE_END -#endif // LLVM_DEMANGLE_ITANIUMDEMANGLE_H +#endif // DEMANGLE_ITANIUMDEMANGLE_H diff --git a/include/llvm/Demangle/MicrosoftDemangle.h b/include/llvm/Demangle/MicrosoftDemangle.h index 97b918fc9459..382e79401c43 100644 --- a/include/llvm/Demangle/MicrosoftDemangle.h +++ b/include/llvm/Demangle/MicrosoftDemangle.h @@ -1,16 +1,15 @@ //===------------------------- MicrosoftDemangle.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. +// 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_DEMANGLE_MICROSOFT_DEMANGLE_H #define LLVM_DEMANGLE_MICROSOFT_DEMANGLE_H -#include "llvm/Demangle/Compiler.h" +#include "llvm/Demangle/DemangleConfig.h" #include "llvm/Demangle/MicrosoftDemangleNodes.h" #include "llvm/Demangle/StringView.h" #include "llvm/Demangle/Utility.h" @@ -56,24 +55,21 @@ public: } } - char *allocUnalignedBuffer(size_t Length) { - uint8_t *Buf = Head->Buf + Head->Used; - - Head->Used += Length; - if (Head->Used > Head->Capacity) { - // It's possible we need a buffer which is larger than our default unit - // size, so we need to be careful to add a node with capacity that is at - // least as large as what we need. - addNode(std::max(AllocUnit, Length)); - Head->Used = Length; - Buf = Head->Buf; - } + char *allocUnalignedBuffer(size_t Size) { + assert(Head && Head->Buf); + + uint8_t *P = Head->Buf + Head->Used; + + Head->Used += Size; + if (Head->Used <= Head->Capacity) + return reinterpret_cast<char *>(P); - return reinterpret_cast<char *>(Buf); + addNode(std::max(AllocUnit, Size)); + Head->Used = Size; + return reinterpret_cast<char *>(Head->Buf); } template <typename T, typename... Args> T *allocArray(size_t Count) { - size_t Size = Count * sizeof(T); assert(Head && Head->Buf); @@ -84,17 +80,16 @@ public: size_t Adjustment = AlignedP - P; Head->Used += Size + Adjustment; - if (Head->Used < Head->Capacity) + if (Head->Used <= Head->Capacity) return new (PP) T[Count](); - addNode(AllocUnit); + addNode(std::max(AllocUnit, Size)); Head->Used = Size; return new (Head->Buf) T[Count](); } template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) { - - size_t Size = sizeof(T); + constexpr size_t Size = sizeof(T); assert(Head && Head->Buf); size_t P = (size_t)Head->Buf + Head->Used; @@ -104,9 +99,10 @@ public: size_t Adjustment = AlignedP - P; Head->Used += Size + Adjustment; - if (Head->Used < Head->Capacity) + if (Head->Used <= Head->Capacity) return new (PP) T(std::forward<Args>(ConstructorArgs)...); + static_assert(Size < AllocUnit, ""); addNode(AllocUnit); Head->Used = Size; return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...); @@ -160,6 +156,8 @@ public: private: SymbolNode *demangleEncodedSymbol(StringView &MangledName, QualifiedNameNode *QN); + SymbolNode *demangleDeclarator(StringView &MangledName); + SymbolNode *demangleMD5Name(StringView &MangledName); VariableSymbolNode *demangleVariableEncoding(StringView &MangledName, StorageClass SC); @@ -179,8 +177,9 @@ private: ArrayTypeNode *demangleArrayType(StringView &MangledName); + NodeArrayNode *demangleFunctionParameterList(StringView &MangledName, + bool &IsVariadic); NodeArrayNode *demangleTemplateParameterList(StringView &MangledName); - NodeArrayNode *demangleFunctionParameterList(StringView &MangledName); std::pair<uint64_t, bool> demangleNumber(StringView &MangledName); uint64_t demangleUnsigned(StringView &MangledName); @@ -207,6 +206,8 @@ private: NamedIdentifierNode *demangleBackRefName(StringView &MangledName); IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName, NameBackrefBehavior NBB); + IntrinsicFunctionKind + translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group); IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName); IdentifierNode * demangleFunctionIdentifierCode(StringView &MangledName, @@ -223,7 +224,7 @@ private: demangleSpecialTableSymbolNode(StringView &MangledName, SpecialIntrinsicKind SIK); LocalStaticGuardVariableNode * - demangleLocalStaticGuard(StringView &MangledName); + demangleLocalStaticGuard(StringView &MangledName, bool IsThread); VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena, StringView &MangledName, StringView VariableName); diff --git a/include/llvm/Demangle/MicrosoftDemangleNodes.h b/include/llvm/Demangle/MicrosoftDemangleNodes.h index 9e3478e9fd29..da9d9d5bfdc0 100644 --- a/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -1,11 +1,30 @@ +//===- MicrosoftDemangleNodes.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 AST nodes used in the MSVC demangler. +// +//===----------------------------------------------------------------------===// + #ifndef LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H #define LLVM_SUPPORT_MICROSOFTDEMANGLENODES_H -#include "llvm/Demangle/Compiler.h" +#include "llvm/Demangle/DemangleConfig.h" #include "llvm/Demangle/StringView.h" #include <array> +namespace llvm { +namespace itanium_demangle { class OutputStream; +} +} + +using llvm::itanium_demangle::OutputStream; +using llvm::itanium_demangle::StringView; namespace llvm { namespace ms_demangle { @@ -63,6 +82,7 @@ enum class PrimitiveKind { Char, Schar, Uchar, + Char8, Char16, Char32, Short, @@ -151,8 +171,8 @@ enum class IntrinsicFunctionKind : uint8_t { VectorCopyCtorIter, // ?__G vector copy constructor iterator VectorVbaseCopyCtorIter, // ?__H vector vbase copy constructor iterator ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy constructor - CoAwait, // ?__L co_await - Spaceship, // operator<=> + CoAwait, // ?__L operator co_await + Spaceship, // ?__M operator<=> MaxIntrinsic }; @@ -324,7 +344,7 @@ struct FunctionSignatureNode : public TypeNode { // Function parameters NodeArrayNode *Params = nullptr; - // True if the function type is noexcept + // True if the function type is noexcept. bool IsNoexcept = false; }; @@ -389,6 +409,7 @@ struct LocalStaticGuardIdentifierNode : public IdentifierNode { void output(OutputStream &OS, OutputFlags Flags) const override; + bool IsThread = false; uint32_t ScopeIndex = 0; }; @@ -494,7 +515,7 @@ struct NodeArrayNode : public Node { void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const; - Node **Nodes = 0; + Node **Nodes = nullptr; size_t Count = 0; }; @@ -602,4 +623,4 @@ struct FunctionSymbolNode : public SymbolNode { } // namespace ms_demangle } // namespace llvm -#endif
\ No newline at end of file +#endif diff --git a/include/llvm/Demangle/README.txt b/include/llvm/Demangle/README.txt new file mode 100644 index 000000000000..514ff6dd16f2 --- /dev/null +++ b/include/llvm/Demangle/README.txt @@ -0,0 +1,52 @@ +Itanium Name Demangler Library +============================== + +Introduction +------------ + +This directory contains the generic itanium name demangler library. The main +purpose of the library is to demangle C++ symbols, i.e. convert the string +"_Z1fv" into "f()". You can also use the CRTP base ManglingParser to perform +some simple analysis on the mangled name, or (in LLVM) use the opaque +ItaniumPartialDemangler to query the demangled AST. + +Why are there multiple copies of the this library in the source tree? +--------------------------------------------------------------------- + +This directory is mirrored between libcxxabi/demangle and +llvm/include/llvm/Demangle. The simple reason for this is that both projects +need to demangle symbols, but neither can depend on each other. libcxxabi needs +the demangler to implement __cxa_demangle, which is part of the itanium ABI +spec. LLVM needs a copy for a bunch of places, but doesn't want to use the +system's __cxa_demangle because it a) might not be available (i.e., on Windows), +and b) probably isn't that up-to-date on the latest language features. + +The copy of the demangler in LLVM has some extra stuff that aren't needed in +libcxxabi (ie, the MSVC demangler, ItaniumPartialDemangler), which depend on the +shared generic components. Despite these differences, we want to keep the "core" +generic demangling library identical between both copies to simplify development +and testing. + +If you're working on the generic library, then do the work first in libcxxabi, +then run the cp-to-llvm.sh script in src/demangle. This script takes as an +argument the path to llvm, and re-copies the changes you made to libcxxabi over. +Note that this script just blindly overwrites all changes to the generic library +in llvm, so be careful. + +Because the core demangler needs to work in libcxxabi, everything needs to be +declared in an anonymous namespace (see DEMANGLE_NAMESPACE_BEGIN), and you can't +introduce any code that depends on the libcxx dylib. + +Hopefully, when LLVM becomes a monorepo, we can de-duplicate this code, and have +both LLVM and libcxxabi depend on a shared demangler library. + +Testing +------- + +The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and +llvm/unittest/Demangle. The llvm directory should only get tests for stuff not +included in the core library. In the future though, we should probably move all +the tests to LLVM. + +It is also a really good idea to run libFuzzer after non-trivial changes, see +libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html. diff --git a/include/llvm/Demangle/StringView.h b/include/llvm/Demangle/StringView.h index a89deda694c2..ceb6c7958066 100644 --- a/include/llvm/Demangle/StringView.h +++ b/include/llvm/Demangle/StringView.h @@ -1,22 +1,25 @@ //===--- StringView.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure +// 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 is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// // +// FIXME: Use std::string_view instead when we support C++17. // -// This file contains a limited version of LLVM's StringView class. It is -// copied here so that LLVMDemangle need not take a dependency on LLVMSupport. //===----------------------------------------------------------------------===// -#ifndef LLVM_DEMANGLE_STRINGVIEW_H -#define LLVM_DEMANGLE_STRINGVIEW_H +#ifndef DEMANGLE_STRINGVIEW_H +#define DEMANGLE_STRINGVIEW_H +#include "DemangleConfig.h" #include <algorithm> #include <cassert> #include <cstring> +DEMANGLE_NAMESPACE_BEGIN + class StringView { const char *First; const char *Last; @@ -43,7 +46,7 @@ public: if (FindBegin < size()) { // Just forward to memchr, which is faster than a hand-rolled loop. if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin)) - return static_cast<const char *>(P) - First; + return size_t(static_cast<const char *>(P) - First); } return npos; } @@ -118,4 +121,6 @@ inline bool operator==(const StringView &LHS, const StringView &RHS) { std::equal(LHS.begin(), LHS.end(), RHS.begin()); } +DEMANGLE_NAMESPACE_END + #endif diff --git a/include/llvm/Demangle/Utility.h b/include/llvm/Demangle/Utility.h index 1d1601c81635..ec23859af46a 100644 --- a/include/llvm/Demangle/Utility.h +++ b/include/llvm/Demangle/Utility.h @@ -1,25 +1,27 @@ //===--- Utility.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure +// 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 is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// // +// Provide some utility classes for use in the demangler(s). // -// This file contains several utility classes used by the demangle library. //===----------------------------------------------------------------------===// -#ifndef LLVM_DEMANGLE_UTILITY_H -#define LLVM_DEMANGLE_UTILITY_H +#ifndef DEMANGLE_UTILITY_H +#define DEMANGLE_UTILITY_H #include "StringView.h" - #include <cstdint> #include <cstdlib> #include <cstring> #include <iterator> #include <limits> +DEMANGLE_NAMESPACE_BEGIN + // Stream that AST nodes write their string representation into after the AST // has been parsed. class OutputStream { @@ -184,4 +186,6 @@ inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, return true; } +DEMANGLE_NAMESPACE_END + #endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index b61cb24fa5fb..4fb6dad96387 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -1,9 +1,8 @@ //===- ExecutionEngine.h - Abstract Execution Engine Interface --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,6 +21,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Module.h" #include "llvm/Object/Binary.h" @@ -635,7 +635,13 @@ public: } // Use OrcMCJITReplacement instead of MCJIT. Off by default. - void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { + LLVM_ATTRIBUTE_DEPRECATED( + inline void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement), + "ORCv1 utilities (including OrcMCJITReplacement) are deprecated. Please " + "use ORCv2/LLJIT instead (see docs/ORCv2.rst)"); + + void setUseOrcMCJITReplacement(ORCv1DeprecationAcknowledgement, + bool UseOrcMCJITReplacement) { this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; } @@ -659,6 +665,10 @@ public: ExecutionEngine *create(TargetMachine *TM); }; +void EngineBuilder::setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { + this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; +} + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h index 504e30a018b6..1ca989da1b7e 100644 --- a/include/llvm/ExecutionEngine/GenericValue.h +++ b/include/llvm/ExecutionEngine/GenericValue.h @@ -1,9 +1,8 @@ //===- GenericValue.h - Represent any type of LLVM value --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Interpreter.h b/include/llvm/ExecutionEngine/Interpreter.h index a14707840ad8..0749409766e3 100644 --- a/include/llvm/ExecutionEngine/Interpreter.h +++ b/include/llvm/ExecutionEngine/Interpreter.h @@ -1,9 +1,8 @@ //===-- Interpreter.h - Abstract Execution Engine Interface -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index 1b08379b8c3b..606b6f7cc128 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -1,9 +1,8 @@ //===- JITEventListener.h - Exposes events from JIT compilation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h b/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h new file mode 100644 index 000000000000..8d2f641254b3 --- /dev/null +++ b/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h @@ -0,0 +1,80 @@ +//===--------- EHFrameSupport.h - JITLink eh-frame utils --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// EHFrame registration support for JITLink. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H +#define LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H + +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace jitlink { + +/// Registers all FDEs in the given eh-frame section with the current process. +Error registerEHFrameSection(const void *EHFrameSectionAddr); + +/// Deregisters all FDEs in the given eh-frame section with the current process. +Error deregisterEHFrameSection(const void *EHFrameSectionAddr); + +/// Supports registration/deregistration of EH-frames in a target process. +class EHFrameRegistrar { +public: + virtual ~EHFrameRegistrar(); + virtual Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) = 0; + virtual Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) = 0; +}; + +/// Registers / Deregisters EH-frames in the current process. +class InProcessEHFrameRegistrar final : public EHFrameRegistrar { +public: + /// Get a reference to the InProcessEHFrameRegistrar singleton. + static InProcessEHFrameRegistrar &getInstance(); + + InProcessEHFrameRegistrar(const InProcessEHFrameRegistrar &) = delete; + InProcessEHFrameRegistrar & + operator=(const InProcessEHFrameRegistrar &) = delete; + + InProcessEHFrameRegistrar(InProcessEHFrameRegistrar &&) = delete; + InProcessEHFrameRegistrar &operator=(InProcessEHFrameRegistrar &&) = delete; + + Error registerEHFrames(JITTargetAddress EHFrameSectionAddr) override { + return registerEHFrameSection( + jitTargetAddressToPointer<void *>(EHFrameSectionAddr)); + } + + Error deregisterEHFrames(JITTargetAddress EHFrameSectionAddr) override { + return deregisterEHFrameSection( + jitTargetAddressToPointer<void *>(EHFrameSectionAddr)); + } + +private: + InProcessEHFrameRegistrar(); +}; + +using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>; + +/// Creates a pass that records the address of the EH frame section. If no +/// eh-frame section is found, it will set EHFrameAddr to zero. +/// +/// Authors of JITLinkContexts can use this function to register a post-fixup +/// pass that records the address of the eh-frame section. This address can +/// be used after finalization to register and deregister the frame. +AtomGraphPassFunction +createEHFrameRecorderPass(const Triple &TT, + StoreFrameAddressFunction StoreFrameAddress); + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H diff --git a/include/llvm/ExecutionEngine/JITLink/JITLink.h b/include/llvm/ExecutionEngine/JITLink/JITLink.h new file mode 100644 index 000000000000..be80d44ccf51 --- /dev/null +++ b/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -0,0 +1,930 @@ +//===------------ JITLink.h - JIT linker functionality ----------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Contains generic JIT-linker types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H +#define LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H + +#include "JITLinkMemoryManager.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/MemoryBuffer.h" + +#include <map> +#include <string> +#include <system_error> + +namespace llvm { +namespace jitlink { + +/// Base class for errors originating in JIT linker, e.g. missing relocation +/// support. +class JITLinkError : public ErrorInfo<JITLinkError> { +public: + static char ID; + + JITLinkError(Twine ErrMsg) : ErrMsg(ErrMsg.str()) {} + + void log(raw_ostream &OS) const override; + const std::string &getErrorMessage() const { return ErrMsg; } + std::error_code convertToErrorCode() const override; + +private: + std::string ErrMsg; +}; + +// Forward declare the Atom class. +class Atom; + +/// Edge class. Represents both object file relocations, as well as layout and +/// keep-alive constraints. +class Edge { +public: + using Kind = uint8_t; + + using GenericEdgeKind = enum : Kind { + Invalid, // Invalid edge value. + FirstKeepAlive, // Keeps target alive. Offset/addend zero. + KeepAlive = FirstKeepAlive, // Tag first edge kind that preserves liveness. + LayoutNext, // Layout constraint. Offset/Addend zero. + FirstRelocation // First architecture specific relocation. + }; + + using OffsetT = uint32_t; + using AddendT = int64_t; + + Edge(Kind K, OffsetT Offset, Atom &Target, AddendT Addend) + : Target(&Target), Offset(Offset), Addend(Addend), K(K) {} + + OffsetT getOffset() const { return Offset; } + Kind getKind() const { return K; } + void setKind(Kind K) { this->K = K; } + bool isRelocation() const { return K >= FirstRelocation; } + Kind getRelocation() const { + assert(isRelocation() && "Not a relocation edge"); + return K - FirstRelocation; + } + bool isKeepAlive() const { return K >= FirstKeepAlive; } + Atom &getTarget() const { return *Target; } + void setTarget(Atom &Target) { this->Target = &Target; } + AddendT getAddend() const { return Addend; } + void setAddend(AddendT Addend) { this->Addend = Addend; } + +private: + Atom *Target; + OffsetT Offset; + AddendT Addend; + Kind K = 0; +}; + +using EdgeVector = std::vector<Edge>; + +const StringRef getGenericEdgeKindName(Edge::Kind K); + +/// Base Atom class. Used by absolute and undefined atoms. +class Atom { + friend class AtomGraph; + +protected: + /// Create a named (as yet unresolved) atom. + Atom(StringRef Name) + : Name(Name), IsDefined(false), IsLive(false), ShouldDiscard(false), + IsGlobal(false), IsAbsolute(false), IsCallable(false), + IsExported(false), IsWeak(false), HasLayoutNext(false), + IsCommon(false) {} + + /// Create an absolute symbol atom. + Atom(StringRef Name, JITTargetAddress Address) + : Name(Name), Address(Address), IsDefined(true), IsLive(false), + ShouldDiscard(false), IsGlobal(false), IsAbsolute(false), + IsCallable(false), IsExported(false), IsWeak(false), + HasLayoutNext(false), IsCommon(false) {} + +public: + /// Returns true if this atom has a name. + bool hasName() const { return Name != StringRef(); } + + /// Returns the name of this atom. + StringRef getName() const { return Name; } + + /// Returns the current target address of this atom. + /// The initial target address (for atoms that have one) will be taken from + /// the input object file's virtual address space. During the layout phase + /// of JIT linking the atom's address will be updated to point to its final + /// address in the JIT'd process. + JITTargetAddress getAddress() const { return Address; } + + /// Set the current target address of this atom. + void setAddress(JITTargetAddress Address) { this->Address = Address; } + + /// Returns true if this is a defined atom. + bool isDefined() const { return IsDefined; } + + /// Returns true if this atom is marked as live. + bool isLive() const { return IsLive; } + + /// Mark this atom as live. + /// + /// Note: Only defined and absolute atoms can be marked live. + void setLive(bool IsLive) { + assert((IsDefined || IsAbsolute || !IsLive) && + "Only defined and absolute atoms can be marked live"); + this->IsLive = IsLive; + } + + /// Returns true if this atom should be discarded during pruning. + bool shouldDiscard() const { return ShouldDiscard; } + + /// Mark this atom to be discarded. + /// + /// Note: Only defined and absolute atoms can be marked live. + void setShouldDiscard(bool ShouldDiscard) { + assert((IsDefined || IsAbsolute || !ShouldDiscard) && + "Only defined and absolute atoms can be marked live"); + this->ShouldDiscard = ShouldDiscard; + } + + /// Returns true if this definition is global (i.e. visible outside this + /// linkage unit). + /// + /// Note: This is distict from Exported, which means visibile outside the + /// JITDylib that this graph is being linked in to. + bool isGlobal() const { return IsGlobal; } + + /// Mark this atom as global. + void setGlobal(bool IsGlobal) { this->IsGlobal = IsGlobal; } + + /// Returns true if this atom represents an absolute symbol. + bool isAbsolute() const { return IsAbsolute; } + + /// Returns true if this atom is known to be callable. + /// + /// Primarily provided for easy interoperability with ORC, which uses the + /// JITSymbolFlags::Common flag to identify symbols that can be interposed + /// with stubs. + bool isCallable() const { return IsCallable; } + + /// Mark this atom as callable. + void setCallable(bool IsCallable) { + assert((IsDefined || IsAbsolute || !IsCallable) && + "Callable atoms must be defined or absolute"); + this->IsCallable = IsCallable; + } + + /// Returns true if this atom should appear in the symbol table of a final + /// linked image. + bool isExported() const { return IsExported; } + + /// Mark this atom as exported. + void setExported(bool IsExported) { + assert((!IsExported || ((IsDefined || IsAbsolute) && hasName())) && + "Exported atoms must have names"); + this->IsExported = IsExported; + } + + /// Returns true if this is a weak symbol. + bool isWeak() const { return IsWeak; } + + /// Mark this atom as weak. + void setWeak(bool IsWeak) { this->IsWeak = IsWeak; } + +private: + StringRef Name; + JITTargetAddress Address = 0; + + bool IsDefined : 1; + bool IsLive : 1; + bool ShouldDiscard : 1; + + bool IsGlobal : 1; + bool IsAbsolute : 1; + bool IsCallable : 1; + bool IsExported : 1; + bool IsWeak : 1; + +protected: + // These flags only make sense for DefinedAtom, but we can minimize the size + // of DefinedAtom by defining them here. + bool HasLayoutNext : 1; + bool IsCommon : 1; +}; + +// Forward declare DefinedAtom. +class DefinedAtom; + +raw_ostream &operator<<(raw_ostream &OS, const Atom &A); +void printEdge(raw_ostream &OS, const Atom &FixupAtom, const Edge &E, + StringRef EdgeKindName); + +/// Represents a section address range via a pair of DefinedAtom pointers to +/// the first and last atoms in the section. +class SectionRange { +public: + SectionRange() = default; + SectionRange(DefinedAtom *First, DefinedAtom *Last) + : First(First), Last(Last) {} + DefinedAtom *getFirstAtom() const { + assert((!Last || First) && "First can not be null if end is non-null"); + return First; + } + DefinedAtom *getLastAtom() const { + assert((First || !Last) && "Last can not be null if start is non-null"); + return Last; + } + bool isEmpty() const { + assert((First || !Last) && "Last can not be null if start is non-null"); + return !First; + } + JITTargetAddress getStart() const; + JITTargetAddress getEnd() const; + uint64_t getSize() const; + +private: + DefinedAtom *First = nullptr; + DefinedAtom *Last = nullptr; +}; + +/// Represents an object file section. +class Section { + friend class AtomGraph; + +private: + Section(StringRef Name, uint32_t Alignment, sys::Memory::ProtectionFlags Prot, + unsigned Ordinal, bool IsZeroFill) + : Name(Name), Alignment(Alignment), Prot(Prot), Ordinal(Ordinal), + IsZeroFill(IsZeroFill) { + assert(isPowerOf2_32(Alignment) && "Alignments must be a power of 2"); + } + + using DefinedAtomSet = DenseSet<DefinedAtom *>; + +public: + using atom_iterator = DefinedAtomSet::iterator; + using const_atom_iterator = DefinedAtomSet::const_iterator; + + ~Section(); + StringRef getName() const { return Name; } + uint32_t getAlignment() const { return Alignment; } + sys::Memory::ProtectionFlags getProtectionFlags() const { return Prot; } + unsigned getSectionOrdinal() const { return Ordinal; } + size_t getNextAtomOrdinal() { return ++NextAtomOrdinal; } + + bool isZeroFill() const { return IsZeroFill; } + + /// Returns an iterator over the atoms in the section (in no particular + /// order). + iterator_range<atom_iterator> atoms() { + return make_range(DefinedAtoms.begin(), DefinedAtoms.end()); + } + + /// Returns an iterator over the atoms in the section (in no particular + /// order). + iterator_range<const_atom_iterator> atoms() const { + return make_range(DefinedAtoms.begin(), DefinedAtoms.end()); + } + + /// Return the number of atoms in this section. + DefinedAtomSet::size_type atoms_size() { return DefinedAtoms.size(); } + + /// Return true if this section contains no atoms. + bool atoms_empty() const { return DefinedAtoms.empty(); } + + /// Returns the range of this section as the pair of atoms with the lowest + /// and highest target address. This operation is expensive, as it + /// must traverse all atoms in the section. + /// + /// Note: If the section is empty, both values will be null. The section + /// address will evaluate to null, and the size to zero. If the section + /// contains a single atom both values will point to it, the address will + /// evaluate to the address of that atom, and the size will be the size of + /// that atom. + SectionRange getRange() const; + +private: + void addAtom(DefinedAtom &DA) { + assert(!DefinedAtoms.count(&DA) && "Atom is already in this section"); + DefinedAtoms.insert(&DA); + } + + void removeAtom(DefinedAtom &DA) { + assert(DefinedAtoms.count(&DA) && "Atom is not in this section"); + DefinedAtoms.erase(&DA); + } + + StringRef Name; + uint32_t Alignment = 0; + sys::Memory::ProtectionFlags Prot; + unsigned Ordinal = 0; + unsigned NextAtomOrdinal = 0; + bool IsZeroFill = false; + DefinedAtomSet DefinedAtoms; +}; + +/// Defined atom class. Suitable for use by defined named and anonymous +/// atoms. +class DefinedAtom : public Atom { + friend class AtomGraph; + +private: + DefinedAtom(Section &Parent, JITTargetAddress Address, uint32_t Alignment) + : Atom("", Address), Parent(Parent), Ordinal(Parent.getNextAtomOrdinal()), + Alignment(Alignment) { + assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two"); + } + + DefinedAtom(Section &Parent, StringRef Name, JITTargetAddress Address, + uint32_t Alignment) + : Atom(Name, Address), Parent(Parent), + Ordinal(Parent.getNextAtomOrdinal()), Alignment(Alignment) { + assert(isPowerOf2_32(Alignment) && "Alignments must be a power of two"); + } + +public: + using edge_iterator = EdgeVector::iterator; + + Section &getSection() const { return Parent; } + + uint64_t getSize() const { return Size; } + + StringRef getContent() const { + assert(!Parent.isZeroFill() && "Trying to get content for zero-fill atom"); + assert(Size <= std::numeric_limits<size_t>::max() && + "Content size too large"); + return {ContentPtr, static_cast<size_t>(Size)}; + } + void setContent(StringRef Content) { + assert(!Parent.isZeroFill() && "Calling setContent on zero-fill atom?"); + ContentPtr = Content.data(); + Size = Content.size(); + } + + bool isZeroFill() const { return Parent.isZeroFill(); } + + void setZeroFill(uint64_t Size) { + assert(Parent.isZeroFill() && !ContentPtr && + "Can't set zero-fill length of a non zero-fill atom"); + this->Size = Size; + } + + uint64_t getZeroFillSize() const { + assert(Parent.isZeroFill() && + "Can't get zero-fill length of a non zero-fill atom"); + return Size; + } + + uint32_t getAlignment() const { return Alignment; } + + bool hasLayoutNext() const { return HasLayoutNext; } + void setLayoutNext(DefinedAtom &Next) { + assert(!HasLayoutNext && "Atom already has layout-next constraint"); + HasLayoutNext = true; + Edges.push_back(Edge(Edge::LayoutNext, 0, Next, 0)); + } + DefinedAtom &getLayoutNext() { + assert(HasLayoutNext && "Atom does not have a layout-next constraint"); + DefinedAtom *Next = nullptr; + for (auto &E : edges()) + if (E.getKind() == Edge::LayoutNext) { + assert(E.getTarget().isDefined() && + "layout-next target atom must be a defined atom"); + Next = static_cast<DefinedAtom *>(&E.getTarget()); + break; + } + assert(Next && "Missing LayoutNext edge"); + return *Next; + } + + bool isCommon() const { return IsCommon; } + + void addEdge(Edge::Kind K, Edge::OffsetT Offset, Atom &Target, + Edge::AddendT Addend) { + assert(K != Edge::LayoutNext && + "Layout edges should be added via setLayoutNext"); + Edges.push_back(Edge(K, Offset, Target, Addend)); + } + + iterator_range<edge_iterator> edges() { + return make_range(Edges.begin(), Edges.end()); + } + size_t edges_size() const { return Edges.size(); } + bool edges_empty() const { return Edges.empty(); } + + unsigned getOrdinal() const { return Ordinal; } + +private: + void setCommon(uint64_t Size) { + assert(ContentPtr == 0 && "Atom already has content?"); + IsCommon = true; + setZeroFill(Size); + } + + EdgeVector Edges; + uint64_t Size = 0; + Section &Parent; + const char *ContentPtr = nullptr; + unsigned Ordinal = 0; + uint32_t Alignment = 0; +}; + +inline JITTargetAddress SectionRange::getStart() const { + return First ? First->getAddress() : 0; +} + +inline JITTargetAddress SectionRange::getEnd() const { + return Last ? Last->getAddress() + Last->getSize() : 0; +} + +inline uint64_t SectionRange::getSize() const { return getEnd() - getStart(); } + +inline SectionRange Section::getRange() const { + if (atoms_empty()) + return SectionRange(); + DefinedAtom *First = *DefinedAtoms.begin(), *Last = *DefinedAtoms.begin(); + for (auto *DA : atoms()) { + if (DA->getAddress() < First->getAddress()) + First = DA; + if (DA->getAddress() > Last->getAddress()) + Last = DA; + } + return SectionRange(First, Last); +} + +class AtomGraph { +private: + using SectionList = std::vector<std::unique_ptr<Section>>; + using AddressToAtomMap = std::map<JITTargetAddress, DefinedAtom *>; + using NamedAtomMap = DenseMap<StringRef, Atom *>; + using ExternalAtomSet = DenseSet<Atom *>; + +public: + using external_atom_iterator = ExternalAtomSet::iterator; + + using section_iterator = pointee_iterator<SectionList::iterator>; + using const_section_iterator = pointee_iterator<SectionList::const_iterator>; + + template <typename SecItrT, typename AtomItrT, typename T> + class defined_atom_iterator_impl + : public iterator_facade_base< + defined_atom_iterator_impl<SecItrT, AtomItrT, T>, + std::forward_iterator_tag, T> { + public: + defined_atom_iterator_impl() = default; + + defined_atom_iterator_impl(SecItrT SI, SecItrT SE) + : SI(SI), SE(SE), + AI(SI != SE ? SI->atoms().begin() : Section::atom_iterator()) { + moveToNextAtomOrEnd(); + } + + bool operator==(const defined_atom_iterator_impl &RHS) const { + return (SI == RHS.SI) && (AI == RHS.AI); + } + + T operator*() const { + assert(AI != SI->atoms().end() && "Dereferencing end?"); + return *AI; + } + + defined_atom_iterator_impl operator++() { + ++AI; + moveToNextAtomOrEnd(); + return *this; + } + + private: + void moveToNextAtomOrEnd() { + while (SI != SE && AI == SI->atoms().end()) { + ++SI; + if (SI == SE) + AI = Section::atom_iterator(); + else + AI = SI->atoms().begin(); + } + } + + SecItrT SI, SE; + AtomItrT AI; + }; + + using defined_atom_iterator = + defined_atom_iterator_impl<section_iterator, Section::atom_iterator, + DefinedAtom *>; + + using const_defined_atom_iterator = + defined_atom_iterator_impl<const_section_iterator, + Section::const_atom_iterator, + const DefinedAtom *>; + + AtomGraph(std::string Name, unsigned PointerSize, + support::endianness Endianness) + : Name(std::move(Name)), PointerSize(PointerSize), + Endianness(Endianness) {} + + /// Returns the name of this graph (usually the name of the original + /// underlying MemoryBuffer). + const std::string &getName() { return Name; } + + /// Returns the pointer size for use in this graph. + unsigned getPointerSize() const { return PointerSize; } + + /// Returns the endianness of atom-content in this graph. + support::endianness getEndianness() const { return Endianness; } + + /// Create a section with the given name, protection flags, and alignment. + Section &createSection(StringRef Name, uint32_t Alignment, + sys::Memory::ProtectionFlags Prot, bool IsZeroFill) { + std::unique_ptr<Section> Sec( + new Section(Name, Alignment, Prot, Sections.size(), IsZeroFill)); + Sections.push_back(std::move(Sec)); + return *Sections.back(); + } + + /// Add an external atom representing an undefined symbol in this graph. + Atom &addExternalAtom(StringRef Name) { + assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted"); + Atom *A = reinterpret_cast<Atom *>( + AtomAllocator.Allocate(sizeof(Atom), alignof(Atom))); + new (A) Atom(Name); + ExternalAtoms.insert(A); + NamedAtoms[Name] = A; + return *A; + } + + /// Add an external atom representing an absolute symbol. + Atom &addAbsoluteAtom(StringRef Name, JITTargetAddress Addr) { + assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted"); + Atom *A = reinterpret_cast<Atom *>( + AtomAllocator.Allocate(sizeof(Atom), alignof(Atom))); + new (A) Atom(Name, Addr); + AbsoluteAtoms.insert(A); + NamedAtoms[Name] = A; + return *A; + } + + /// Add an anonymous defined atom to the graph. + /// + /// Anonymous atoms have content but no name. They must have an address. + DefinedAtom &addAnonymousAtom(Section &Parent, JITTargetAddress Address, + uint32_t Alignment) { + DefinedAtom *A = reinterpret_cast<DefinedAtom *>( + AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom))); + new (A) DefinedAtom(Parent, Address, Alignment); + Parent.addAtom(*A); + getAddrToAtomMap()[A->getAddress()] = A; + return *A; + } + + /// Add a defined atom to the graph. + /// + /// Allocates and constructs a DefinedAtom instance with the given parent, + /// name, address, and alignment. + DefinedAtom &addDefinedAtom(Section &Parent, StringRef Name, + JITTargetAddress Address, uint32_t Alignment) { + assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted"); + DefinedAtom *A = reinterpret_cast<DefinedAtom *>( + AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom))); + new (A) DefinedAtom(Parent, Name, Address, Alignment); + Parent.addAtom(*A); + getAddrToAtomMap()[A->getAddress()] = A; + NamedAtoms[Name] = A; + return *A; + } + + /// Add a common symbol atom to the graph. + /// + /// Adds a common-symbol atom to the graph with the given parent, name, + /// address, alignment and size. + DefinedAtom &addCommonAtom(Section &Parent, StringRef Name, + JITTargetAddress Address, uint32_t Alignment, + uint64_t Size) { + assert(!NamedAtoms.count(Name) && "Duplicate named atom inserted"); + DefinedAtom *A = reinterpret_cast<DefinedAtom *>( + AtomAllocator.Allocate(sizeof(DefinedAtom), alignof(DefinedAtom))); + new (A) DefinedAtom(Parent, Name, Address, Alignment); + A->setCommon(Size); + Parent.addAtom(*A); + NamedAtoms[Name] = A; + return *A; + } + + iterator_range<section_iterator> sections() { + return make_range(section_iterator(Sections.begin()), + section_iterator(Sections.end())); + } + + /// Returns the section with the given name if it exists, otherwise returns + /// null. + Section *findSectionByName(StringRef Name) { + for (auto &S : sections()) + if (S.getName() == Name) + return &S; + return nullptr; + } + + iterator_range<external_atom_iterator> external_atoms() { + return make_range(ExternalAtoms.begin(), ExternalAtoms.end()); + } + + iterator_range<external_atom_iterator> absolute_atoms() { + return make_range(AbsoluteAtoms.begin(), AbsoluteAtoms.end()); + } + + iterator_range<defined_atom_iterator> defined_atoms() { + return make_range(defined_atom_iterator(Sections.begin(), Sections.end()), + defined_atom_iterator(Sections.end(), Sections.end())); + } + + iterator_range<const_defined_atom_iterator> defined_atoms() const { + return make_range( + const_defined_atom_iterator(Sections.begin(), Sections.end()), + const_defined_atom_iterator(Sections.end(), Sections.end())); + } + + /// Returns the atom with the given name, which must exist in this graph. + Atom &getAtomByName(StringRef Name) { + auto I = NamedAtoms.find(Name); + assert(I != NamedAtoms.end() && "Name not in NamedAtoms map"); + return *I->second; + } + + /// Returns the atom with the given name, which must exist in this graph and + /// be a DefinedAtom. + DefinedAtom &getDefinedAtomByName(StringRef Name) { + auto &A = getAtomByName(Name); + assert(A.isDefined() && "Atom is not a defined atom"); + return static_cast<DefinedAtom &>(A); + } + + /// Search for the given atom by name. + /// Returns the atom (if found) or an error (if no atom with this name + /// exists). + Expected<Atom &> findAtomByName(StringRef Name) { + auto I = NamedAtoms.find(Name); + if (I == NamedAtoms.end()) + return make_error<JITLinkError>("No atom named " + Name); + return *I->second; + } + + /// Search for the given defined atom by name. + /// Returns the defined atom (if found) or an error (if no atom with this + /// name exists, or if one exists but is not a defined atom). + Expected<DefinedAtom &> findDefinedAtomByName(StringRef Name) { + auto I = NamedAtoms.find(Name); + if (I == NamedAtoms.end()) + return make_error<JITLinkError>("No atom named " + Name); + if (!I->second->isDefined()) + return make_error<JITLinkError>("Atom " + Name + + " exists but is not a " + "defined atom"); + return static_cast<DefinedAtom &>(*I->second); + } + + /// Returns the atom covering the given address, or an error if no such atom + /// exists. + /// + /// Returns null if no atom exists at the given address. + DefinedAtom *getAtomByAddress(JITTargetAddress Address) { + refreshAddrToAtomCache(); + + // If there are no defined atoms, bail out early. + if (AddrToAtomCache->empty()) + return nullptr; + + // Find the atom *after* the given address. + auto I = AddrToAtomCache->upper_bound(Address); + + // If this address falls before any known atom, bail out. + if (I == AddrToAtomCache->begin()) + return nullptr; + + // The atom we're looking for is the one before the atom we found. + --I; + + // Otherwise range check the atom that was found. + assert(!I->second->getContent().empty() && "Atom content not set"); + if (Address >= I->second->getAddress() + I->second->getContent().size()) + return nullptr; + + return I->second; + } + + /// Like getAtomByAddress, but returns an Error if the given address is not + /// covered by an atom, rather than a null pointer. + Expected<DefinedAtom &> findAtomByAddress(JITTargetAddress Address) { + if (auto *DA = getAtomByAddress(Address)) + return *DA; + return make_error<JITLinkError>("No atom at address " + + formatv("{0:x16}", Address)); + } + + // Remove the given external atom from the graph. + void removeExternalAtom(Atom &A) { + assert(!A.isDefined() && !A.isAbsolute() && "A is not an external atom"); + assert(ExternalAtoms.count(&A) && "A is not in the external atoms set"); + ExternalAtoms.erase(&A); + A.~Atom(); + } + + /// Remove the given absolute atom from the graph. + void removeAbsoluteAtom(Atom &A) { + assert(A.isAbsolute() && "A is not an absolute atom"); + assert(AbsoluteAtoms.count(&A) && "A is not in the absolute atoms set"); + AbsoluteAtoms.erase(&A); + A.~Atom(); + } + + /// Remove the given defined atom from the graph. + void removeDefinedAtom(DefinedAtom &DA) { + if (AddrToAtomCache) { + assert(AddrToAtomCache->count(DA.getAddress()) && + "Cache exists, but does not contain atom"); + AddrToAtomCache->erase(DA.getAddress()); + } + if (DA.hasName()) { + assert(NamedAtoms.count(DA.getName()) && "Named atom not in map"); + NamedAtoms.erase(DA.getName()); + } + DA.getSection().removeAtom(DA); + DA.~DefinedAtom(); + } + + /// Invalidate the atom-to-address map. + void invalidateAddrToAtomMap() { AddrToAtomCache = None; } + + /// Dump the graph. + /// + /// If supplied, the EdgeKindToName function will be used to name edge + /// kinds in the debug output. Otherwise raw edge kind numbers will be + /// displayed. + void dump(raw_ostream &OS, + std::function<StringRef(Edge::Kind)> EdegKindToName = + std::function<StringRef(Edge::Kind)>()); + +private: + AddressToAtomMap &getAddrToAtomMap() { + refreshAddrToAtomCache(); + return *AddrToAtomCache; + } + + const AddressToAtomMap &getAddrToAtomMap() const { + refreshAddrToAtomCache(); + return *AddrToAtomCache; + } + + void refreshAddrToAtomCache() const { + if (!AddrToAtomCache) { + AddrToAtomCache = AddressToAtomMap(); + for (auto *DA : defined_atoms()) + (*AddrToAtomCache)[DA->getAddress()] = const_cast<DefinedAtom *>(DA); + } + } + + // Put the BumpPtrAllocator first so that we don't free any of the atoms in + // it until all of their destructors have been run. + BumpPtrAllocator AtomAllocator; + + std::string Name; + unsigned PointerSize; + support::endianness Endianness; + SectionList Sections; + NamedAtomMap NamedAtoms; + ExternalAtomSet ExternalAtoms; + ExternalAtomSet AbsoluteAtoms; + mutable Optional<AddressToAtomMap> AddrToAtomCache; +}; + +/// A function for mutating AtomGraphs. +using AtomGraphPassFunction = std::function<Error(AtomGraph &)>; + +/// A list of atom graph passes. +using AtomGraphPassList = std::vector<AtomGraphPassFunction>; + +/// An atom graph pass configuration, consisting of a list of pre-prune, +/// post-prune, and post-fixup passes. +struct PassConfiguration { + + /// Pre-prune passes. + /// + /// These passes are called on the graph after it is built, and before any + /// atoms have been pruned. + /// + /// Notable use cases: Marking atoms live or should-discard. + AtomGraphPassList PrePrunePasses; + + /// Post-prune passes. + /// + /// These passes are called on the graph after dead and should-discard atoms + /// have been removed, but before fixups are applied. + /// + /// Notable use cases: Building GOT, stub, and TLV atoms. + AtomGraphPassList PostPrunePasses; + + /// Post-fixup passes. + /// + /// These passes are called on the graph after atom contents has been copied + /// to working memory, and fixups applied. + /// + /// Notable use cases: Testing and validation. + AtomGraphPassList PostFixupPasses; +}; + +/// A map of symbol names to resolved addresses. +using AsyncLookupResult = DenseMap<StringRef, JITEvaluatedSymbol>; + +/// A function to call with a resolved symbol map (See AsyncLookupResult) or an +/// error if resolution failed. +using JITLinkAsyncLookupContinuation = + std::function<void(Expected<AsyncLookupResult> LR)>; + +/// An asynchronous symbol lookup. Performs a search (possibly asynchronously) +/// for the given symbols, calling the given continuation with either the result +/// (if the lookup succeeds), or an error (if the lookup fails). +using JITLinkAsyncLookupFunction = + std::function<void(const DenseSet<StringRef> &Symbols, + JITLinkAsyncLookupContinuation LookupContinuation)>; + +/// Holds context for a single jitLink invocation. +class JITLinkContext { +public: + /// Destroy a JITLinkContext. + virtual ~JITLinkContext(); + + /// Return the MemoryManager to be used for this link. + virtual JITLinkMemoryManager &getMemoryManager() = 0; + + /// Returns a StringRef for the object buffer. + /// This method can not be called once takeObjectBuffer has been called. + virtual MemoryBufferRef getObjectBuffer() const = 0; + + /// Notify this context that linking failed. + /// Called by JITLink if linking cannot be completed. + virtual void notifyFailed(Error Err) = 0; + + /// Called by JITLink to resolve external symbols. This method is passed a + /// lookup continutation which it must call with a result to continue the + /// linking process. + virtual void lookup(const DenseSet<StringRef> &Symbols, + JITLinkAsyncLookupContinuation LookupContinuation) = 0; + + /// Called by JITLink once all defined atoms in the graph have been assigned + /// their final memory locations in the target process. At this point he + /// atom graph can be, inspected to build a symbol table however the atom + /// content will not generally have been copied to the target location yet. + virtual void notifyResolved(AtomGraph &G) = 0; + + /// Called by JITLink to notify the context that the object has been + /// finalized (i.e. emitted to memory and memory permissions set). If all of + /// this objects dependencies have also been finalized then the code is ready + /// to run. + virtual void + notifyFinalized(std::unique_ptr<JITLinkMemoryManager::Allocation> A) = 0; + + /// Called by JITLink prior to linking to determine whether default passes for + /// the target should be added. The default implementation returns true. + /// If subclasses override this method to return false for any target then + /// they are required to fully configure the pass pipeline for that target. + virtual bool shouldAddDefaultTargetPasses(const Triple &TT) const; + + /// Returns the mark-live pass to be used for this link. If no pass is + /// returned (the default) then the target-specific linker implementation will + /// choose a conservative default (usually marking all atoms live). + /// This function is only called if shouldAddDefaultTargetPasses returns true, + /// otherwise the JITContext is responsible for adding a mark-live pass in + /// modifyPassConfig. + virtual AtomGraphPassFunction getMarkLivePass(const Triple &TT) const; + + /// Called by JITLink to modify the pass pipeline prior to linking. + /// The default version performs no modification. + virtual Error modifyPassConfig(const Triple &TT, PassConfiguration &Config); +}; + +/// Marks all atoms in a graph live. This can be used as a default, conservative +/// mark-live implementation. +Error markAllAtomsLive(AtomGraph &G); + +/// Basic JITLink implementation. +/// +/// This function will use sensible defaults for GOT and Stub handling. +void jitLink(std::unique_ptr<JITLinkContext> Ctx); + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H diff --git a/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h new file mode 100644 index 000000000000..9d0b37fe4a4d --- /dev/null +++ b/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h @@ -0,0 +1,99 @@ +//===-- JITLinkMemoryManager.h - JITLink mem manager 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 +// +//===----------------------------------------------------------------------===// +// +// Contains the JITLinkMemoryManager interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Memory.h" +#include <cstdint> + +namespace llvm { +namespace jitlink { + +/// Manages allocations of JIT memory. +/// +/// Instances of this class may be accessed concurrently from multiple threads +/// and their implemetations should include any necessary synchronization. +class JITLinkMemoryManager { +public: + using ProtectionFlags = sys::Memory::ProtectionFlags; + + class SegmentRequest { + public: + SegmentRequest() = default; + SegmentRequest(size_t ContentSize, unsigned ContentAlign, + uint64_t ZeroFillSize, unsigned ZeroFillAlign) + : ContentSize(ContentSize), ZeroFillSize(ZeroFillSize), + ContentAlign(ContentAlign), ZeroFillAlign(ZeroFillAlign) {} + size_t getContentSize() const { return ContentSize; } + unsigned getContentAlignment() const { return ContentAlign; } + uint64_t getZeroFillSize() const { return ZeroFillSize; } + unsigned getZeroFillAlignment() const { return ZeroFillAlign; } + + private: + size_t ContentSize = 0; + uint64_t ZeroFillSize = 0; + unsigned ContentAlign = 0; + unsigned ZeroFillAlign = 0; + }; + + using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>; + + /// Represents an allocation created by the memory manager. + /// + /// An allocation object is responsible for allocating and owning jit-linker + /// working and target memory, and for transfering from working to target + /// memory. + /// + class Allocation { + public: + using FinalizeContinuation = std::function<void(Error)>; + + virtual ~Allocation(); + + /// Should return the address of linker working memory for the segment with + /// the given protection flags. + virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0; + + /// Should return the final address in the target process where the segment + /// will reside. + virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0; + + /// Should transfer from working memory to target memory, and release + /// working memory. + virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0; + + /// Should deallocate target memory. + virtual Error deallocate() = 0; + }; + + virtual ~JITLinkMemoryManager(); + + /// Create an Allocation object. + virtual Expected<std::unique_ptr<Allocation>> + allocate(const SegmentsRequestMap &Request) = 0; +}; + +/// A JITLinkMemoryManager that allocates in-process memory. +class InProcessMemoryManager : public JITLinkMemoryManager { +public: + Expected<std::unique_ptr<Allocation>> + allocate(const SegmentsRequestMap &Request) override; +}; + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINK_H diff --git a/include/llvm/ExecutionEngine/JITLink/MachO.h b/include/llvm/ExecutionEngine/JITLink/MachO.h new file mode 100644 index 000000000000..7facb657a51c --- /dev/null +++ b/include/llvm/ExecutionEngine/JITLink/MachO.h @@ -0,0 +1,30 @@ +//===------- MachO.h - Generic JIT link function for MachO ------*- 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 jit-link functions for MachO. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_MACHO_H +#define LLVM_EXECUTIONENGINE_JITLINK_MACHO_H + +#include "llvm/ExecutionEngine/JITLink/JITLink.h" + +namespace llvm { +namespace jitlink { + +/// jit-link the given ObjBuffer, which must be a MachO object file. +/// +/// Uses conservative defaults for GOT and stub handling based on the target +/// platform. +void jitLink_MachO(std::unique_ptr<JITLinkContext> Ctx); + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_MACHO_H diff --git a/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h new file mode 100644 index 000000000000..1d5b586afc32 --- /dev/null +++ b/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h @@ -0,0 +1,63 @@ +//===--- MachO_x86_64.h - JIT link functions for MachO/x86-64 ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// jit-link functions for MachO/x86-64. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H +#define LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H + +#include "llvm/ExecutionEngine/JITLink/JITLink.h" + +namespace llvm { +namespace jitlink { + +namespace MachO_x86_64_Edges { + +enum MachOX86RelocationKind : Edge::Kind { + Branch32 = Edge::FirstRelocation, + Pointer64, + Pointer64Anon, + PCRel32, + PCRel32Minus1, + PCRel32Minus2, + PCRel32Minus4, + PCRel32Anon, + PCRel32Minus1Anon, + PCRel32Minus2Anon, + PCRel32Minus4Anon, + PCRel32GOTLoad, + PCRel32GOT, + PCRel32TLV, + Delta32, + Delta64, + NegDelta32, + NegDelta64, +}; + +} // namespace MachO_x86_64_Edges + +/// jit-link the given object buffer, which must be a MachO x86-64 object file. +/// +/// If PrePrunePasses is empty then a default mark-live pass will be inserted +/// that will mark all exported atoms live. If PrePrunePasses is not empty, the +/// caller is responsible for including a pass to mark atoms as live. +/// +/// If PostPrunePasses is empty then a default GOT-and-stubs insertion pass will +/// be inserted. If PostPrunePasses is not empty then the caller is responsible +/// for including a pass to insert GOT and stub edges. +void jitLink_MachO_x86_64(std::unique_ptr<JITLinkContext> Ctx); + +/// Return the string name of the given MachO x86-64 edge kind. +StringRef getMachOX86RelocationKindName(Edge::Kind R); + +} // end namespace jitlink +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_JITLINK_MACHO_X86_64_H diff --git a/include/llvm/ExecutionEngine/JITSymbol.h b/include/llvm/ExecutionEngine/JITSymbol.h index 05c9590726df..b14154c5b5e8 100644 --- a/include/llvm/ExecutionEngine/JITSymbol.h +++ b/include/llvm/ExecutionEngine/JITSymbol.h @@ -1,9 +1,8 @@ //===- JITSymbol.h - JIT symbol abstraction ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -56,7 +55,7 @@ template <typename T> JITTargetAddress pointerToJITTargetAddress(T *Ptr) { class JITSymbolFlags { public: using UnderlyingType = uint8_t; - using TargetFlagsType = uint64_t; + using TargetFlagsType = uint8_t; enum FlagNames : UnderlyingType { None = 0, @@ -66,15 +65,9 @@ public: Absolute = 1U << 3, Exported = 1U << 4, Callable = 1U << 5, - Lazy = 1U << 6, - Materializing = 1U << 7, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Materializing) + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable) }; - static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) { - return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing); - } - /// Default-construct a JITSymbolFlags instance. JITSymbolFlags() = default; @@ -84,7 +77,7 @@ public: /// Construct a JITSymbolFlags instance from the given flags and target /// flags. JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags) - : Flags(Flags), TargetFlags(TargetFlags) {} + : TargetFlags(TargetFlags), Flags(Flags) {} /// Implicitly convert to bool. Returs true if any flag is set. explicit operator bool() const { return Flags != None || TargetFlags != 0; } @@ -111,19 +104,6 @@ public: return (Flags & HasError) == HasError; } - /// Returns true if this is a lazy symbol. - /// This flag is used internally by the JIT APIs to track - /// materialization states. - bool isLazy() const { return Flags & Lazy; } - - /// Returns true if this symbol is in the process of being - /// materialized. - bool isMaterializing() const { return Flags & Materializing; } - - /// Returns true if this symbol is fully materialized. - /// (i.e. neither lazy, nor materializing). - bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); } - /// Returns true if the Weak flag is set. bool isWeak() const { return (Flags & Weak) == Weak; @@ -168,8 +148,8 @@ public: fromObjectSymbol(const object::SymbolRef &Symbol); private: - FlagNames Flags = None; TargetFlagsType TargetFlags = 0; + FlagNames Flags = None; }; inline JITSymbolFlags operator&(const JITSymbolFlags &LHS, diff --git a/include/llvm/ExecutionEngine/MCJIT.h b/include/llvm/ExecutionEngine/MCJIT.h index 66ddb7cdb875..8253bf98963b 100644 --- a/include/llvm/ExecutionEngine/MCJIT.h +++ b/include/llvm/ExecutionEngine/MCJIT.h @@ -1,9 +1,8 @@ //===-- MCJIT.h - MC-Based Just-In-Time Execution Engine --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/OProfileWrapper.h b/include/llvm/ExecutionEngine/OProfileWrapper.h index 05da594a94a8..b13d7f6e245b 100644 --- a/include/llvm/ExecutionEngine/OProfileWrapper.h +++ b/include/llvm/ExecutionEngine/OProfileWrapper.h @@ -1,9 +1,8 @@ //===-- OProfileWrapper.h - OProfile JIT API Wrapper ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 OProfileWrapper object that detects if the oprofile diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index 077044408e09..47e94f18a1c7 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -1,9 +1,8 @@ //===-- ObjectCache.h - Class definition for the ObjectCache ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 884878925cde..5f593a27cad6 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -1,9 +1,8 @@ //===- CompileOnDemandLayer.h - Compile each function on demand -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -265,13 +264,26 @@ public: std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>; /// Construct a compile-on-demand layer instance. - LegacyCompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer, - SymbolResolverGetter GetSymbolResolver, - SymbolResolverSetter SetSymbolResolver, - PartitioningFtor Partition, - CompileCallbackMgrT &CallbackMgr, - IndirectStubsManagerBuilderT CreateIndirectStubsManager, - bool CloneStubsIntoPartitions = true) + LLVM_ATTRIBUTE_DEPRECATED( + LegacyCompileOnDemandLayer( + ExecutionSession &ES, BaseLayerT &BaseLayer, + SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, + CompileCallbackMgrT &CallbackMgr, + IndirectStubsManagerBuilderT CreateIndirectStubsManager, + bool CloneStubsIntoPartitions = true), + "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " + "use " + "the ORCv2 LegacyCompileOnDemandLayer instead"); + + /// Legacy layer constructor with deprecation acknowledgement. + LegacyCompileOnDemandLayer( + ORCv1DeprecationAcknowledgement, ExecutionSession &ES, + BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, + CompileCallbackMgrT &CallbackMgr, + IndirectStubsManagerBuilderT CreateIndirectStubsManager, + bool CloneStubsIntoPartitions = true) : ES(ES), BaseLayer(BaseLayer), GetSymbolResolver(std::move(GetSymbolResolver)), SetSymbolResolver(std::move(SetSymbolResolver)), @@ -730,8 +742,24 @@ private: bool CloneStubsIntoPartitions; }; -} // end namespace orc +template <typename BaseLayerT, typename CompileCallbackMgrT, + typename IndirectStubsMgrT> +LegacyCompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT, IndirectStubsMgrT>:: + LegacyCompileOnDemandLayer( + ExecutionSession &ES, BaseLayerT &BaseLayer, + SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition, + CompileCallbackMgrT &CallbackMgr, + IndirectStubsManagerBuilderT CreateIndirectStubsManager, + bool CloneStubsIntoPartitions) + : ES(ES), BaseLayer(BaseLayer), + GetSymbolResolver(std::move(GetSymbolResolver)), + SetSymbolResolver(std::move(SetSymbolResolver)), + Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), + CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), + CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} +} // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/include/llvm/ExecutionEngine/Orc/CompileUtils.h index f34f88311ba5..eb6d84e8cbb4 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileUtils.h +++ b/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -1,9 +1,8 @@ //===- CompileUtils.h - Utilities for compiling IR in the JIT ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,28 +13,21 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H #define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H -#include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Object/Binary.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SmallVectorMemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include <algorithm> #include <memory> namespace llvm { class MCContext; +class MemoryBuffer; class Module; +class ObjectCache; +class TargetMachine; namespace orc { +class JITTargetMachineBuilder; + /// Simple compile functor: Takes a single IR module and returns an ObjectFile. /// This compiler supports a single compilation thread and LLVMContext only. /// For multithreaded compilation, use ConcurrentIRCompiler below. @@ -51,56 +43,32 @@ public: void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } /// Compile a Module to an ObjectFile. - CompileResult operator()(Module &M) { - CompileResult CachedObject = tryToLoadFromObjectCache(M); - if (CachedObject) - return CachedObject; - - SmallVector<char, 0> ObjBufferSV; - - { - raw_svector_ostream ObjStream(ObjBufferSV); - - legacy::PassManager PM; - MCContext *Ctx; - if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) - llvm_unreachable("Target does not support MC emission."); - PM.run(M); - } - - auto ObjBuffer = - llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV)); - auto Obj = - object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); - - if (Obj) { - notifyObjectCompiled(M, *ObjBuffer); - return std::move(ObjBuffer); - } - - // TODO: Actually report errors helpfully. - consumeError(Obj.takeError()); - return nullptr; - } + CompileResult operator()(Module &M); private: - - CompileResult tryToLoadFromObjectCache(const Module &M) { - if (!ObjCache) - return CompileResult(); - - return ObjCache->getObject(&M); - } - - void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) { - if (ObjCache) - ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef()); - } + CompileResult tryToLoadFromObjectCache(const Module &M); + void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer); TargetMachine &TM; ObjectCache *ObjCache = nullptr; }; +/// A SimpleCompiler that owns its TargetMachine. +/// +/// This convenient for clients who don't want to own their TargetMachines, +/// e.g. LLJIT. +class TMOwningSimpleCompiler : public SimpleCompiler { +public: + TMOwningSimpleCompiler(std::unique_ptr<TargetMachine> TM, + ObjectCache *ObjCache = nullptr) + : SimpleCompiler(*TM, ObjCache), TM(std::move(TM)) {} + +private: + // FIXME: shared because std::functions (and consequently + // IRCompileLayer::CompileFunction) are not moveable. + std::shared_ptr<llvm::TargetMachine> TM; +}; + /// A thread-safe version of SimpleCompiler. /// /// This class creates a new TargetMachine and SimpleCompiler instance for each @@ -108,16 +76,11 @@ private: class ConcurrentIRCompiler { public: ConcurrentIRCompiler(JITTargetMachineBuilder JTMB, - ObjectCache *ObjCache = nullptr) - : JTMB(std::move(JTMB)), ObjCache(ObjCache) {} + ObjectCache *ObjCache = nullptr); void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; } - std::unique_ptr<MemoryBuffer> operator()(Module &M) { - auto TM = cantFail(JTMB.createTargetMachine()); - SimpleCompiler C(*TM, ObjCache); - return C(M); - } + std::unique_ptr<MemoryBuffer> operator()(Module &M); private: JITTargetMachineBuilder JTMB; diff --git a/include/llvm/ExecutionEngine/Orc/Core.h b/include/llvm/ExecutionEngine/Orc/Core.h index 39d306e0bd4c..94a5618233e4 100644 --- a/include/llvm/ExecutionEngine/Orc/Core.h +++ b/include/llvm/ExecutionEngine/Orc/Core.h @@ -1,9 +1,8 @@ //===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,6 +16,7 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" +#include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" @@ -34,6 +34,7 @@ class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; +enum class SymbolState : uint8_t; /// VModuleKey provides a unique identifier (allocated and managed by /// ExecutionSessions) for a module added to the JIT. @@ -57,6 +58,18 @@ using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>; /// A list of (JITDylib*, bool) pairs. using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>; +struct SymbolAliasMapEntry { + SymbolAliasMapEntry() = default; + SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) + : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} + + SymbolStringPtr Aliasee; + JITSymbolFlags AliasFlags; +}; + +/// A map of Symbols to (Symbol, Flags) pairs. +using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; + /// Render a SymbolStringPtr. raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym); @@ -88,12 +101,15 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU); /// Render a JITDylibSearchList. raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs); +/// Render a SymbolAliasMap. +raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases); + +/// Render a SymbolState. +raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S); + /// Callback to notify client that symbols have been resolved. using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>; -/// Callback to notify client that symbols are ready for execution. -using SymbolsReadyCallback = std::function<void(Error)>; - /// Callback to register the dependencies for a given query. using RegisterDependenciesFunction = std::function<void(const SymbolDependenceMap &)>; @@ -175,7 +191,7 @@ public: /// Note: The returned flags may have transient flags (Lazy, Materializing) /// set. These should be stripped with JITSymbolFlags::stripTransientFlags /// before using. - const SymbolFlagsMap &getSymbols() { return SymbolFlags; } + const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } /// Returns the names of any symbols covered by this /// MaterializationResponsibility object that have queries pending. This @@ -189,12 +205,12 @@ public: /// symbols must be ones covered by this MaterializationResponsibility /// instance. Individual calls to this method may resolve a subset of the /// symbols, but all symbols must have been resolved prior to calling emit. - void resolve(const SymbolMap &Symbols); + void notifyResolved(const SymbolMap &Symbols); /// Notifies the target JITDylib (and any pending queries on that JITDylib) /// that all symbols covered by this MaterializationResponsibility instance /// have been emitted. - void emit(); + void notifyEmitted(); /// Adds new symbols to the JITDylib and this responsibility instance. /// JITDylib entries start out in the materializing state. @@ -334,18 +350,6 @@ absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { std::move(Symbols), std::move(K)); } -struct SymbolAliasMapEntry { - SymbolAliasMapEntry() = default; - SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) - : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} - - SymbolStringPtr Aliasee; - JITSymbolFlags AliasFlags; -}; - -/// A map of Symbols to (Symbol, Flags) pairs. -using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>; - /// A materialization unit for symbol aliases. Allows existing symbols to be /// aliased with alternate flags. class ReExportsMaterializationUnit : public MaterializationUnit { @@ -419,7 +423,7 @@ public: ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false, SymbolPredicate Allow = SymbolPredicate()); - SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names); + Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names); private: JITDylib &SourceJD; @@ -427,6 +431,15 @@ private: SymbolPredicate Allow; }; +/// Represents the state that a symbol has reached during materialization. +enum class SymbolState : uint8_t { + Invalid, /// No symbol should be in this state. + NeverSearched, /// Added to the symbol table, never queried. + Materializing, /// Queried, materialization begun. + Resolved, /// Assigned address, still materializing. + Ready = 0x3f /// Ready and safe for clients to access. +}; + /// A symbol query that returns results via a callback when results are /// ready. /// @@ -437,38 +450,30 @@ class AsynchronousSymbolQuery { friend class JITSymbolResolverAdapter; public: - - /// Create a query for the given symbols, notify-resolved and - /// notify-ready callbacks. + /// Create a query for the given symbols. The NotifyComplete + /// callback will be called once all queried symbols reach the given + /// minimum state. AsynchronousSymbolQuery(const SymbolNameSet &Symbols, - SymbolsResolvedCallback NotifySymbolsResolved, - SymbolsReadyCallback NotifySymbolsReady); + SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete); - /// Set the resolved symbol information for the given symbol name. - void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); + /// Notify the query that a requested symbol has reached the required state. + void notifySymbolMetRequiredState(const SymbolStringPtr &Name, + JITEvaluatedSymbol Sym); /// Returns true if all symbols covered by this query have been /// resolved. - bool isFullyResolved() const { return NotYetResolvedCount == 0; } + bool isComplete() const { return OutstandingSymbolsCount == 0; } - /// Call the NotifySymbolsResolved callback. + /// Call the NotifyComplete callback. /// - /// This should only be called if all symbols covered by the query have been - /// resolved. - void handleFullyResolved(); - - /// Notify the query that a requested symbol is ready for execution. - void notifySymbolReady(); - - /// Returns true if all symbols covered by this query are ready. - bool isFullyReady() const { return NotYetReadyCount == 0; } - - /// Calls the NotifySymbolsReady callback. - /// - /// This should only be called if all symbols covered by this query are ready. - void handleFullyReady(); + /// This should only be called if all symbols covered by the query have + /// reached the specified state. + void handleComplete(); private: + SymbolState getRequiredState() { return RequiredState; } + void addQueryDependence(JITDylib &JD, SymbolStringPtr Name); void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name); @@ -479,12 +484,11 @@ private: void detach(); - SymbolsResolvedCallback NotifySymbolsResolved; - SymbolsReadyCallback NotifySymbolsReady; + SymbolsResolvedCallback NotifyComplete; SymbolDependenceMap QueryRegistrations; SymbolMap ResolvedSymbols; - size_t NotYetResolvedCount; - size_t NotYetReadyCount; + size_t OutstandingSymbolsCount; + SymbolState RequiredState; }; /// A symbol table that supports asynchoronous symbol queries. @@ -498,7 +502,7 @@ class JITDylib { friend class ExecutionSession; friend class MaterializationResponsibility; public: - using GeneratorFunction = std::function<SymbolNameSet( + using GeneratorFunction = std::function<Expected<SymbolNameSet>( JITDylib &Parent, const SymbolNameSet &Names)>; using AsynchronousSymbolQuerySet = @@ -596,7 +600,7 @@ public: /// Search the given JITDylib for the symbols in Symbols. If found, store /// the flags for each symbol in Flags. Returns any unresolved symbols. - SymbolFlagsMap lookupFlags(const SymbolNameSet &Names); + Expected<SymbolFlagsMap> lookupFlags(const SymbolNameSet &Names); /// Dump current JITDylib state to OS. void dump(raw_ostream &OS); @@ -609,8 +613,8 @@ public: /// and the query will not be applied. The Query is not failed and can be /// re-used in a subsequent lookup once the symbols have been added, or /// manually failed. - SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Names); + Expected<SymbolNameSet> + legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names); private: using AsynchronousSymbolQueryList = @@ -627,40 +631,92 @@ private: DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; struct MaterializingInfo { - AsynchronousSymbolQueryList PendingQueries; SymbolDependenceMap Dependants; SymbolDependenceMap UnemittedDependencies; bool IsEmitted = false; + + void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q); + void removeQuery(const AsynchronousSymbolQuery &Q); + AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState); + AsynchronousSymbolQueryList takeAllQueries(); + bool hasQueriesPending() const { return !PendingQueries.empty(); } + const AsynchronousSymbolQueryList &pendingQueries() const { + return PendingQueries; + } + + private: + AsynchronousSymbolQueryList PendingQueries; }; using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>; - using LookupImplActionFlags = enum { - None = 0, - NotifyFullyResolved = 1 << 0U, - NotifyFullyReady = 1 << 1U, - LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady) + class SymbolTableEntry { + public: + SymbolTableEntry() = default; + SymbolTableEntry(JITSymbolFlags Flags) + : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)), + MaterializerAttached(false), PendingRemoval(false) {} + + JITTargetAddress getAddress() const { return Addr; } + JITSymbolFlags getFlags() const { return Flags; } + SymbolState getState() const { return static_cast<SymbolState>(State); } + + bool isInMaterializationPhase() const { + return getState() == SymbolState::Materializing || + getState() == SymbolState::Resolved; + } + + bool hasMaterializerAttached() const { return MaterializerAttached; } + bool isPendingRemoval() const { return PendingRemoval; } + + void setAddress(JITTargetAddress Addr) { this->Addr = Addr; } + void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; } + void setState(SymbolState State) { + assert(static_cast<uint8_t>(State) < (1 << 6) && + "State does not fit in bitfield"); + this->State = static_cast<uint8_t>(State); + } + + void setMaterializerAttached(bool MaterializerAttached) { + this->MaterializerAttached = MaterializerAttached; + } + + void setPendingRemoval(bool PendingRemoval) { + this->PendingRemoval = PendingRemoval; + } + + JITEvaluatedSymbol getSymbol() const { + return JITEvaluatedSymbol(Addr, Flags); + } + + private: + JITTargetAddress Addr = 0; + JITSymbolFlags Flags; + uint8_t State : 6; + uint8_t MaterializerAttached : 1; + uint8_t PendingRemoval : 1; }; + using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>; + JITDylib(ExecutionSession &ES, std::string Name); Error defineImpl(MaterializationUnit &MU); - SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags, - const SymbolNameSet &Names); + Expected<SymbolNameSet> lookupFlagsImpl(SymbolFlagsMap &Flags, + const SymbolNameSet &Names); - void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, - SymbolNameSet &Unresolved, bool MatchNonExported, - MaterializationUnitList &MUs); + Error lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, + SymbolNameSet &Unresolved, bool MatchNonExported, + MaterializationUnitList &MUs); void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved, bool MatchNonExported, MaterializationUnitList &MUs); - LookupImplActionFlags - lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, - std::vector<std::unique_ptr<MaterializationUnit>> &MUs, - SymbolNameSet &Unresolved); + bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, + std::vector<std::unique_ptr<MaterializationUnit>> &MUs, + SymbolNameSet &Unresolved); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -686,7 +742,7 @@ private: ExecutionSession &ES; std::string JITDylibName; - SymbolMap Symbols; + SymbolTable Symbols; UnmaterializedInfosMap UnmaterializedInfos; MaterializingInfosMap MaterializingInfos; GeneratorFunction DefGenerator; @@ -727,7 +783,15 @@ public: /// the ExecutionSession. JITDylib &getMainJITDylib(); + /// Return a pointer to the "name" JITDylib. + /// Ownership of JITDylib remains within Execution Session + JITDylib *getJITDylibByName(StringRef Name); + /// Add a new JITDylib to this ExecutionSession. + /// + /// The JITDylib Name is required to be unique. Clients should verify that + /// names are not being re-used (e.g. by calling getJITDylibByName) if names + /// are based on user input. JITDylib &createJITDylib(std::string Name, bool AddToMainDylibSearchOrder = true); @@ -769,7 +833,7 @@ public: /// Do not use -- this will be removed soon. Expected<SymbolMap> legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - bool WaiUntilReady, + SymbolState RequiredState, RegisterDependenciesFunction RegisterDependencies); /// Search the given JITDylib list for the given symbols. @@ -779,11 +843,8 @@ public: /// (hidden visibility) symbols in that dylib (true means match against /// non-exported symbols, false means do not match). /// - /// The OnResolve callback will be called once all requested symbols are - /// resolved, or if an error occurs prior to resolution. - /// - /// The OnReady callback will be called once all requested symbols are ready, - /// or if an error occurs after resolution but before all symbols are ready. + /// The NotifyComplete callback will be called once all requested symbols + /// reach the required state. /// /// If all symbols are found, the RegisterDependencies function will be called /// while the session lock is held. This gives clients a chance to register @@ -795,7 +856,7 @@ public: /// client to get an address to call) then the value NoDependenciesToRegister /// can be used. void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies); /// Blocking version of lookup above. Returns the resolved symbol map. @@ -807,9 +868,9 @@ public: /// error will be reported via reportErrors. Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols, + SymbolState RequiredState = SymbolState::Ready, RegisterDependenciesFunction RegisterDependencies = - NoDependenciesToRegister, - bool WaitUntilReady = true); + NoDependenciesToRegister); /// Convenience version of blocking lookup. /// Searches each of the JITDylibs in the search order in turn for the given @@ -832,10 +893,11 @@ public: /// Materialize the given unit. void dispatchMaterialization(JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) { - LLVM_DEBUG(runSessionLocked([&]() { - dbgs() << "Compiling, for " << JD.getName() << ", " << *MU - << "\n"; - });); + LLVM_DEBUG({ + runSessionLocked([&]() { + dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n"; + }); + }); DispatchMaterialization(JD, std::move(MU)); } diff --git a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index 88559f822e5d..75865920c741 100644 --- a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -1,9 +1,8 @@ //===- ExecutionUtils.h - Utilities for executing code in Orc ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -98,7 +97,14 @@ class LegacyCtorDtorRunner { public: /// Construct a CtorDtorRunner for the given range using the given /// name mangling function. - LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K) + LLVM_ATTRIBUTE_DEPRECATED( + LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, + VModuleKey K), + "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " + "Please use the ORCv2 CtorDtorRunner utility instead"); + + LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement, + std::vector<std::string> CtorDtorNames, VModuleKey K) : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} /// Run the recorded constructors/destructors through the given JIT @@ -129,6 +135,11 @@ private: orc::VModuleKey K; }; +template <typename JITLayerT> +LegacyCtorDtorRunner<JITLayerT>::LegacyCtorDtorRunner( + std::vector<std::string> CtorDtorNames, VModuleKey K) + : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} + class CtorDtorRunner { public: CtorDtorRunner(JITDylib &JD) : JD(JD) {} @@ -181,7 +192,14 @@ class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { public: /// Create a runtime-overrides class. template <typename MangleFtorT> - LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle) { + LLVM_ATTRIBUTE_DEPRECATED( + LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle), + "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. " + "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead"); + + template <typename MangleFtorT> + LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement, + const MangleFtorT &Mangle) { addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); } @@ -202,6 +220,13 @@ private: StringMap<JITTargetAddress> CXXRuntimeOverrides; }; +template <typename MangleFtorT> +LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides( + const MangleFtorT &Mangle) { + addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); + addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); +} + class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { public: Error enable(JITDylib &JD, MangleAndInterner &Mangler); @@ -218,28 +243,29 @@ public: /// Create a DynamicLibrarySearchGenerator that searches for symbols in the /// given sys::DynamicLibrary. + /// /// If the Allow predicate is given then only symbols matching the predicate - /// will be searched for in the DynamicLibrary. If the predicate is not given - /// then all symbols will be searched for. - DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, const DataLayout &DL, + /// will be searched for. If the predicate is not given then all symbols will + /// be searched for. + DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow = SymbolPredicate()); /// Permanently loads the library at the given path and, on success, returns /// a DynamicLibrarySearchGenerator that will search it for symbol definitions /// in the library. On failure returns the reason the library failed to load. static Expected<DynamicLibrarySearchGenerator> - Load(const char *FileName, const DataLayout &DL, + Load(const char *FileName, char GlobalPrefix, SymbolPredicate Allow = SymbolPredicate()); /// Creates a DynamicLibrarySearchGenerator that searches for symbols in /// the current process. static Expected<DynamicLibrarySearchGenerator> - GetForCurrentProcess(const DataLayout &DL, + GetForCurrentProcess(char GlobalPrefix, SymbolPredicate Allow = SymbolPredicate()) { - return Load(nullptr, DL, std::move(Allow)); + return Load(nullptr, GlobalPrefix, std::move(Allow)); } - SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names); + Expected<SymbolNameSet> operator()(JITDylib &JD, const SymbolNameSet &Names); private: sys::DynamicLibrary Dylib; diff --git a/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h index a8a88d7cb2d2..a4e43d4e1c9c 100644 --- a/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h @@ -1,9 +1,8 @@ //===- GlobalMappingLayer.h - Run all IR through a functor ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index 30d71e69cd70..52223a83ad42 100644 --- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -1,9 +1,8 @@ //===- IRCompileLayer.h -- Eagerly compile IR for JIT -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -64,8 +63,18 @@ public: /// Construct an LegacyIRCompileLayer with the given BaseLayer, which must /// implement the ObjectLayer concept. + LLVM_ATTRIBUTE_DEPRECATED( + LegacyIRCompileLayer( + BaseLayerT &BaseLayer, CompileFtor Compile, + NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()), + "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " + "use " + "the ORCv2 IRCompileLayer instead"); + + /// Legacy layer constructor with deprecation acknowledgement. LegacyIRCompileLayer( - BaseLayerT &BaseLayer, CompileFtor Compile, + ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, + CompileFtor Compile, NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()) : BaseLayer(BaseLayer), Compile(std::move(Compile)), NotifyCompiled(std::move(NotifyCompiled)) {} @@ -123,8 +132,14 @@ private: NotifyCompiledCallback NotifyCompiled; }; -} // end namespace orc +template <typename BaseLayerT, typename CompileFtor> +LegacyIRCompileLayer<BaseLayerT, CompileFtor>::LegacyIRCompileLayer( + BaseLayerT &BaseLayer, CompileFtor Compile, + NotifyCompiledCallback NotifyCompiled) + : BaseLayer(BaseLayer), Compile(std::move(Compile)), + NotifyCompiled(std::move(NotifyCompiled)) {} +} // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 49e65b9f2a80..1b4c8b6cd95f 100644 --- a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -1,9 +1,8 @@ //===- IRTransformLayer.h - Run all IR through a functor --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -57,9 +56,17 @@ class LegacyIRTransformLayer { public: /// Construct an LegacyIRTransformLayer with the given BaseLayer - LegacyIRTransformLayer(BaseLayerT &BaseLayer, - TransformFtor Transform = TransformFtor()) - : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + LLVM_ATTRIBUTE_DEPRECATED( + LegacyIRTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()), + "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " + "use " + "the ORCv2 IRTransformLayer instead"); + + /// Legacy layer constructor with deprecation acknowledgement. + LegacyIRTransformLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} /// Apply the transform functor to the module, then add the module to /// the layer below, along with the memory manager and symbol resolver. @@ -109,6 +116,11 @@ private: TransformFtor Transform; }; +template <typename BaseLayerT, typename TransformFtor> +LegacyIRTransformLayer<BaseLayerT, TransformFtor>::LegacyIRTransformLayer( + BaseLayerT &BaseLayer, TransformFtor Transform) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + } // end namespace orc } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index c2527802f6a7..a7ed5372d1e4 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -1,9 +1,8 @@ //===- IndirectionUtils.h - Utilities for adding indirections ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -147,13 +146,13 @@ private: std::error_code EC; auto TrampolineBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - sys::Process::getPageSize(), nullptr, + sys::Process::getPageSizeEstimate(), nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); if (EC) return errorCodeToError(EC); unsigned NumTrampolines = - (sys::Process::getPageSize() - ORCABI::PointerSize) / + (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) / ORCABI::TrampolineSize; uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base()); diff --git a/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h b/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h index eb9b6bf2dea6..bcbd72e68f15 100644 --- a/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h +++ b/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h @@ -1,9 +1,8 @@ //===- JITTargetMachineBuilder.h - Build TargetMachines for JIT -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/LLJIT.h b/include/llvm/ExecutionEngine/Orc/LLJIT.h index ce3e5d519c73..0aac1916423f 100644 --- a/include/llvm/ExecutionEngine/Orc/LLJIT.h +++ b/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -1,9 +1,8 @@ //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for 3Bdetails. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,35 +20,49 @@ #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" -#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h" #include "llvm/Support/ThreadPool.h" namespace llvm { namespace orc { +class LLJITBuilderState; +class LLLazyJITBuilderState; + /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. +/// +/// Create instances using LLJITBuilder. class LLJIT { + template <typename, typename, typename> friend class LLJITBuilderSetters; + public: + static Expected<std::unique_ptr<LLJIT>> Create(LLJITBuilderState &S); /// Destruct this instance. If a multi-threaded instance, waits for all /// compile threads to complete. ~LLJIT(); - /// Create an LLJIT instance. - /// If NumCompileThreads is not equal to zero, creates a multi-threaded - /// LLJIT with the given number of compile threads. - static Expected<std::unique_ptr<LLJIT>> - Create(JITTargetMachineBuilder JTMB, DataLayout DL, - unsigned NumCompileThreads = 0); - /// Returns the ExecutionSession for this instance. ExecutionSession &getExecutionSession() { return *ES; } + /// Returns a reference to the DataLayout for this instance. + const DataLayout &getDataLayout() const { return DL; } + /// Returns a reference to the JITDylib representing the JIT'd main program. JITDylib &getMainJITDylib() { return Main; } + /// Returns the JITDylib with the given name, or nullptr if no JITDylib with + /// that name exists. + JITDylib *getJITDylibByName(StringRef Name) { + return ES->getJITDylibByName(Name); + } + /// Create a new JITDylib with the given name and return a reference to it. + /// + /// JITDylib names must be unique. If the given name is derived from user + /// input or elsewhere in the environment then the client should check + /// (e.g. by calling getJITDylibByName) that the given name is not already in + /// use. JITDylib &createJITDylib(std::string Name) { return ES->createJITDylib(std::move(Name)); } @@ -57,8 +70,6 @@ public: /// Convenience method for defining an absolute symbol. Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address); - /// Convenience method for defining an - /// Adds an IR module to the given JITDylib. Error addIRModule(JITDylib &JD, ThreadSafeModule TSM); @@ -104,17 +115,17 @@ public: Error runDestructors() { return DtorRunner.run(); } /// Returns a reference to the ObjLinkingLayer - RTDyldObjectLinkingLayer &getObjLinkingLayer() { return ObjLinkingLayer; } + ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; } protected: + static std::unique_ptr<ObjectLayer> + createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES); - /// Create an LLJIT instance with a single compile thread. - LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM, - DataLayout DL); + static Expected<IRCompileLayer::CompileFunction> + createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB); - /// Create an LLJIT instance with multiple compile threads. - LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, - DataLayout DL, unsigned NumCompileThreads); + /// Create an LLJIT instance with a single compile thread. + LLJIT(LLJITBuilderState &S, Error &Err); std::string mangle(StringRef UnmangledName); @@ -128,8 +139,8 @@ protected: DataLayout DL; std::unique_ptr<ThreadPool> CompileThreads; - RTDyldObjectLinkingLayer ObjLinkingLayer; - IRCompileLayer CompileLayer; + std::unique_ptr<ObjectLayer> ObjLinkingLayer; + std::unique_ptr<IRCompileLayer> CompileLayer; CtorDtorRunner CtorRunner, DtorRunner; }; @@ -137,25 +148,20 @@ protected: /// An extended version of LLJIT that supports lazy function-at-a-time /// compilation of LLVM IR. class LLLazyJIT : public LLJIT { -public: + template <typename, typename, typename> friend class LLJITBuilderSetters; - /// Create an LLLazyJIT instance. - /// If NumCompileThreads is not equal to zero, creates a multi-threaded - /// LLLazyJIT with the given number of compile threads. - static Expected<std::unique_ptr<LLLazyJIT>> - Create(JITTargetMachineBuilder JTMB, DataLayout DL, - JITTargetAddress ErrorAddr, unsigned NumCompileThreads = 0); +public: /// Set an IR transform (e.g. pass manager pipeline) to run on each function /// when it is compiled. void setLazyCompileTransform(IRTransformLayer::TransformFunction Transform) { - TransformLayer.setTransform(std::move(Transform)); + TransformLayer->setTransform(std::move(Transform)); } /// Sets the partition function. void setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) { - CODLayer.setPartitionFunction(std::move(Partition)); + CODLayer->setPartitionFunction(std::move(Partition)); } /// Add a module to be lazily compiled to JITDylib JD. @@ -169,24 +175,160 @@ public: private: // Create a single-threaded LLLazyJIT instance. - LLLazyJIT(std::unique_ptr<ExecutionSession> ES, - std::unique_ptr<TargetMachine> TM, DataLayout DL, - std::unique_ptr<LazyCallThroughManager> LCTMgr, - std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder); + LLLazyJIT(LLLazyJITBuilderState &S, Error &Err); + + std::unique_ptr<LazyCallThroughManager> LCTMgr; + std::unique_ptr<IRTransformLayer> TransformLayer; + std::unique_ptr<CompileOnDemandLayer> CODLayer; +}; + +class LLJITBuilderState { +public: + using ObjectLinkingLayerCreator = + std::function<std::unique_ptr<ObjectLayer>(ExecutionSession &)>; + + using CompileFunctionCreator = + std::function<Expected<IRCompileLayer::CompileFunction>( + JITTargetMachineBuilder JTMB)>; + + std::unique_ptr<ExecutionSession> ES; + Optional<JITTargetMachineBuilder> JTMB; + ObjectLinkingLayerCreator CreateObjectLinkingLayer; + CompileFunctionCreator CreateCompileFunction; + unsigned NumCompileThreads = 0; - // Create a multi-threaded LLLazyJIT instance. - LLLazyJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB, - DataLayout DL, unsigned NumCompileThreads, - std::unique_ptr<LazyCallThroughManager> LCTMgr, - std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder); + /// Called prior to JIT class construcion to fix up defaults. + Error prepareForConstruction(); +}; + +template <typename JITType, typename SetterImpl, typename State> +class LLJITBuilderSetters { +public: + /// Set the JITTargetMachineBuilder for this instance. + /// + /// If this method is not called, JITTargetMachineBuilder::detectHost will be + /// used to construct a default target machine builder for the host platform. + SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) { + impl().JTMB = std::move(JTMB); + return impl(); + } + + /// Return a reference to the JITTargetMachineBuilder. + /// + Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() { + return impl().JTMB; + } + /// Set an ObjectLinkingLayer creation function. + /// + /// If this method is not called, a default creation function will be used + /// that will construct an RTDyldObjectLinkingLayer. + SetterImpl &setObjectLinkingLayerCreator( + LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) { + impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer); + return impl(); + } + + /// Set a CompileFunctionCreator. + /// + /// If this method is not called, a default creation function wil be used + /// that will construct a basic IR compile function that is compatible with + /// the selected number of threads (SimpleCompiler for '0' compile threads, + /// ConcurrentIRCompiler otherwise). + SetterImpl &setCompileFunctionCreator( + LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) { + impl().CreateCompileFunction = std::move(CreateCompileFunction); + return impl(); + } + + /// Set the number of compile threads to use. + /// + /// If set to zero, compilation will be performed on the execution thread when + /// JITing in-process. If set to any other number N, a thread pool of N + /// threads will be created for compilation. + /// + /// If this method is not called, behavior will be as if it were called with + /// a zero argument. + SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) { + impl().NumCompileThreads = NumCompileThreads; + return impl(); + } + + /// Create an instance of the JIT. + Expected<std::unique_ptr<JITType>> create() { + if (auto Err = impl().prepareForConstruction()) + return std::move(Err); + + Error Err = Error::success(); + std::unique_ptr<JITType> J(new JITType(impl(), Err)); + if (Err) + return std::move(Err); + return std::move(J); + } + +protected: + SetterImpl &impl() { return static_cast<SetterImpl &>(*this); } +}; + +/// Constructs LLJIT instances. +class LLJITBuilder + : public LLJITBuilderState, + public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {}; + +class LLLazyJITBuilderState : public LLJITBuilderState { + friend class LLLazyJIT; + +public: + using IndirectStubsManagerBuilderFunction = + std::function<std::unique_ptr<IndirectStubsManager>()>; + + Triple TT; + JITTargetAddress LazyCompileFailureAddr = 0; std::unique_ptr<LazyCallThroughManager> LCTMgr; - std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder; + IndirectStubsManagerBuilderFunction ISMBuilder; + + Error prepareForConstruction(); +}; + +template <typename JITType, typename SetterImpl, typename State> +class LLLazyJITBuilderSetters + : public LLJITBuilderSetters<JITType, SetterImpl, State> { +public: + /// Set the address in the target address to call if a lazy compile fails. + /// + /// If this method is not called then the value will default to 0. + SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) { + this->impl().LazyCompileFailureAddr = Addr; + return this->impl(); + } + + /// Set the lazy-callthrough manager. + /// + /// If this method is not called then a default, in-process lazy callthrough + /// manager for the host platform will be used. + SetterImpl & + setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) { + this->impl().LCTMgr = std::move(LCTMgr); + return this->impl(); + } - IRTransformLayer TransformLayer; - CompileOnDemandLayer CODLayer; + /// Set the IndirectStubsManager builder function. + /// + /// If this method is not called then a default, in-process + /// IndirectStubsManager builder for the host platform will be used. + SetterImpl &setIndirectStubsManagerBuilder( + LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) { + this->impl().ISMBuilder = std::move(ISMBuilder); + return this->impl(); + } }; +/// Constructs LLLazyJIT instances. +class LLLazyJITBuilder + : public LLLazyJITBuilderState, + public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder, + LLLazyJITBuilderState> {}; + } // End namespace orc } // End namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h index 7b6f3d2f92ab..855e31b33549 100644 --- a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -1,9 +1,8 @@ //===- LambdaResolverMM - Redirect symbol lookup via a functor --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,7 +24,15 @@ namespace orc { template <typename DylibLookupFtorT, typename ExternalLookupFtorT> class LambdaResolver : public LegacyJITSymbolResolver { public: - LambdaResolver(DylibLookupFtorT DylibLookupFtor, + LLVM_ATTRIBUTE_DEPRECATED( + LambdaResolver(DylibLookupFtorT DylibLookupFtor, + ExternalLookupFtorT ExternalLookupFtor), + "ORCv1 utilities (including resolvers) are deprecated and will be " + "removed " + "in the next release. Please use ORCv2 (see docs/ORCv2.rst)"); + + LambdaResolver(ORCv1DeprecationAcknowledgement, + DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) : DylibLookupFtor(DylibLookupFtor), ExternalLookupFtor(ExternalLookupFtor) {} @@ -43,6 +50,12 @@ private: ExternalLookupFtorT ExternalLookupFtor; }; +template <typename DylibLookupFtorT, typename ExternalLookupFtorT> +LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>::LambdaResolver( + DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) + : DylibLookupFtor(DylibLookupFtor), ExternalLookupFtor(ExternalLookupFtor) { +} + template <typename DylibLookupFtorT, typename ExternalLookupFtorT> std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>> @@ -53,6 +66,17 @@ createLambdaResolver(DylibLookupFtorT DylibLookupFtor, std::move(ExternalLookupFtor)); } +template <typename DylibLookupFtorT, typename ExternalLookupFtorT> +std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>> +createLambdaResolver(ORCv1DeprecationAcknowledgement, + DylibLookupFtorT DylibLookupFtor, + ExternalLookupFtorT ExternalLookupFtor) { + using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>; + return make_unique<LR>(AcknowledgeORCv1Deprecation, + std::move(DylibLookupFtor), + std::move(ExternalLookupFtor)); +} + } // end namespace orc } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/Layer.h b/include/llvm/ExecutionEngine/Orc/Layer.h index cd797445a2e6..8f9bd704395e 100644 --- a/include/llvm/ExecutionEngine/Orc/Layer.h +++ b/include/llvm/ExecutionEngine/Orc/Layer.h @@ -1,9 +1,8 @@ //===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index 46761b0ca7e1..16202d89f861 100644 --- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -1,9 +1,8 @@ //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,8 +34,8 @@ namespace orc { /// Lazy-emitting IR layer. /// -/// This layer accepts LLVM IR Modules (via addModule), but does not -/// immediately emit them the layer below. Instead, emissing to the base layer +/// This layer accepts LLVM IR Modules (via addModule) but does not +/// immediately emit them the layer below. Instead, emission to the base layer /// is deferred until the first time the client requests the address (via /// JITSymbol::getAddress) for a symbol contained in this layer. template <typename BaseLayerT> class LazyEmittingLayer { @@ -197,7 +196,14 @@ private: public: /// Construct a lazy emitting layer. - LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + LLVM_ATTRIBUTE_DEPRECATED( + LazyEmittingLayer(BaseLayerT &BaseLayer), + "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " + "ORCv2, where lazy emission is the default"); + + /// Construct a lazy emitting layer. + LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer) + : BaseLayer(BaseLayer) {} /// Add the given module to the lazy emitting layer. Error addModule(VModuleKey K, std::unique_ptr<Module> M) { @@ -255,6 +261,10 @@ public: } }; +template <typename BaseLayerT> +LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer) + : BaseLayer(BaseLayer) {} + } // end namespace orc } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/include/llvm/ExecutionEngine/Orc/LazyReexports.h index b5041325bce2..9fdd1d15f782 100644 --- a/include/llvm/ExecutionEngine/Orc/LazyReexports.h +++ b/include/llvm/ExecutionEngine/Orc/LazyReexports.h @@ -1,9 +1,8 @@ //===------ LazyReexports.h -- Utilities for lazy reexports -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/Legacy.h b/include/llvm/ExecutionEngine/Orc/Legacy.h index 4c6162ac4b8b..f9cbbf6ff180 100644 --- a/include/llvm/ExecutionEngine/Orc/Legacy.h +++ b/include/llvm/ExecutionEngine/Orc/Legacy.h @@ -1,9 +1,8 @@ //===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -149,8 +148,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, for (auto &S : Symbols) { if (JITSymbol Sym = FindSymbol(*S)) { if (auto Addr = Sym.getAddress()) { - Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - Query.notifySymbolReady(); + Query.notifySymbolMetRequiredState( + S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); NewSymbolsResolved = true; } else { ES.legacyFailQuery(Query, Addr.takeError()); @@ -163,11 +162,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, SymbolsNotFound.insert(S); } - if (NewSymbolsResolved && Query.isFullyResolved()) - Query.handleFullyResolved(); - - if (NewSymbolsResolved && Query.isFullyReady()) - Query.handleFullyReady(); + if (NewSymbolsResolved && Query.isComplete()) + Query.handleComplete(); return SymbolsNotFound; } diff --git a/include/llvm/ExecutionEngine/Orc/NullResolver.h b/include/llvm/ExecutionEngine/Orc/NullResolver.h index 03fefb69a928..ffa37a13d064 100644 --- a/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ b/include/llvm/ExecutionEngine/Orc/NullResolver.h @@ -1,9 +1,8 @@ //===------ NullResolver.h - Reject symbol lookup requests ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h new file mode 100644 index 000000000000..c1e7d27f446e --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -0,0 +1,165 @@ +//===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- 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 +// +//===----------------------------------------------------------------------===// +// +// Contains the definition for an JITLink-based, in-process object linking +// layer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/JITLink/JITLink.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cassert> +#include <functional> +#include <list> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +namespace llvm { + +namespace jitlink { +class EHFrameRegistrar; +} // namespace jitlink + +namespace object { +class ObjectFile; +} // namespace object + +namespace orc { + +class ObjectLinkingLayerJITLinkContext; + +/// An ObjectLayer implementation built on JITLink. +/// +/// Clients can use this class to add relocatable object files to an +/// ExecutionSession, and it typically serves as the base layer (underneath +/// a compiling layer like IRCompileLayer) for the rest of the JIT. +class ObjectLinkingLayer : public ObjectLayer { + friend class ObjectLinkingLayerJITLinkContext; + +public: + /// Plugin instances can be added to the ObjectLinkingLayer to receive + /// callbacks when code is loaded or emitted, and when JITLink is being + /// configured. + class Plugin { + public: + virtual ~Plugin(); + virtual void modifyPassConfig(MaterializationResponsibility &MR, + const Triple &TT, + jitlink::PassConfiguration &Config) {} + virtual void notifyLoaded(MaterializationResponsibility &MR) {} + virtual Error notifyEmitted(MaterializationResponsibility &MR) { + return Error::success(); + } + virtual Error notifyRemovingModule(VModuleKey K) { + return Error::success(); + } + virtual Error notifyRemovingAllModules() { return Error::success(); } + }; + + /// Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// and NotifyEmitted functors. + ObjectLinkingLayer(ExecutionSession &ES, + jitlink::JITLinkMemoryManager &MemMgr); + + /// Destruct an ObjectLinkingLayer. + ~ObjectLinkingLayer(); + + /// Add a pass-config modifier. + ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) { + std::lock_guard<std::mutex> Lock(LayerMutex); + Plugins.push_back(std::move(P)); + return *this; + } + + /// Emit the object. + void emit(MaterializationResponsibility R, + std::unique_ptr<MemoryBuffer> O) override; + + /// Instructs this ObjectLinkingLayer instance to override the symbol flags + /// found in the AtomGraph with the flags supplied by the + /// MaterializationResponsibility instance. This is a workaround to support + /// symbol visibility in COFF, which does not use the libObject's + /// SF_Exported flag. Use only when generating / adding COFF object files. + /// + /// FIXME: We should be able to remove this if/when COFF properly tracks + /// exported symbols. + ObjectLinkingLayer & + setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) { + this->OverrideObjectFlags = OverrideObjectFlags; + return *this; + } + + /// If set, this ObjectLinkingLayer instance will claim responsibility + /// for any symbols provided by a given object file that were not already in + /// the MaterializationResponsibility instance. Setting this flag allows + /// higher-level program representations (e.g. LLVM IR) to be added based on + /// only a subset of the symbols they provide, without having to write + /// intervening layers to scan and add the additional symbols. This trades + /// diagnostic quality for convenience however: If all symbols are enumerated + /// up-front then clashes can be detected and reported early (and usually + /// deterministically). If this option is set, clashes for the additional + /// symbols may not be detected until late, and detection may depend on + /// the flow of control through JIT'd code. Use with care. + ObjectLinkingLayer & + setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) { + this->AutoClaimObjectSymbols = AutoClaimObjectSymbols; + return *this; + } + +private: + using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>; + + void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + jitlink::PassConfiguration &PassConfig); + void notifyLoaded(MaterializationResponsibility &MR); + Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc); + + Error removeModule(VModuleKey K); + Error removeAllModules(); + + mutable std::mutex LayerMutex; + jitlink::JITLinkMemoryManager &MemMgr; + bool OverrideObjectFlags = false; + bool AutoClaimObjectSymbols = false; + DenseMap<VModuleKey, AllocPtr> TrackedAllocs; + std::vector<AllocPtr> UntrackedAllocs; + std::vector<std::unique_ptr<Plugin>> Plugins; +}; + +class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin { +public: + EHFrameRegistrationPlugin(jitlink::EHFrameRegistrar &Registrar); + Error notifyEmitted(MaterializationResponsibility &MR) override; + void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, + jitlink::PassConfiguration &PassConfig) override; + Error notifyRemovingModule(VModuleKey K) override; + Error notifyRemovingAllModules() override; + +private: + jitlink::EHFrameRegistrar &Registrar; + DenseMap<MaterializationResponsibility *, JITTargetAddress> InProcessLinks; + DenseMap<VModuleKey, JITTargetAddress> TrackedEHFrameAddrs; + std::vector<JITTargetAddress> UntrackedEHFrameAddrs; +}; + +} // end namespace orc +} // end namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index 44d6b490e19d..eac1cc3e097a 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -1,9 +1,8 @@ //===- ObjectTransformLayer.h - Run all objects through functor -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -49,7 +48,16 @@ template <typename BaseLayerT, typename TransformFtor> class LegacyObjectTransformLayer { public: /// Construct an ObjectTransformLayer with the given BaseLayer - LegacyObjectTransformLayer(BaseLayerT &BaseLayer, + LLVM_ATTRIBUTE_DEPRECATED( + LegacyObjectTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()), + "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " + "use " + "the ORCv2 ObjectTransformLayer instead"); + + /// Legacy layer constructor with deprecation acknowledgement. + LegacyObjectTransformLayer(ORCv1DeprecationAcknowledgement, + BaseLayerT &BaseLayer, TransformFtor Transform = TransformFtor()) : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} @@ -108,6 +116,11 @@ private: TransformFtor Transform; }; +template <typename BaseLayerT, typename TransformFtor> +LegacyObjectTransformLayer<BaseLayerT, TransformFtor>:: + LegacyObjectTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + } // end namespace orc } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index a70fc373713d..38246bc480b6 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -1,9 +1,8 @@ //===- OrcABISupport.h - ABI support code -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/OrcError.h b/include/llvm/ExecutionEngine/Orc/OrcError.h index dc60e8d74e97..e5d6a3eca85f 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/include/llvm/ExecutionEngine/Orc/OrcError.h @@ -1,9 +1,8 @@ //===------ OrcError.h - Reject symbol lookup requests ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index 3e07f5cf3742..8b875b7906e1 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -1,9 +1,8 @@ //===- OrcRemoteTargetClient.h - Orc Remote-target Client -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h index 8db9e317a18a..e7b598d8f812 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h +++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h @@ -1,9 +1,8 @@ //===- OrcRemoteTargetRPCAPI.h - Orc Remote-target RPC API ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index acbc1682fa5d..4c8e2ea1a7be 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -1,9 +1,8 @@ //===- OrcRemoteTargetServer.h - Orc Remote-target Server -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -300,13 +299,13 @@ private: std::error_code EC; auto TrampolineBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - sys::Process::getPageSize(), nullptr, + sys::Process::getPageSizeEstimate(), nullptr, sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); if (EC) return errorCodeToError(EC); uint32_t NumTrampolines = - (sys::Process::getPageSize() - TargetT::PointerSize) / + (sys::Process::getPageSizeEstimate() - TargetT::PointerSize) / TargetT::TrampolineSize; uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base()); @@ -336,7 +335,7 @@ private: handleGetRemoteInfo() { std::string ProcessTriple = sys::getProcessTriple(); uint32_t PointerSize = TargetT::PointerSize; - uint32_t PageSize = sys::Process::getPageSize(); + uint32_t PageSize = sys::Process::getPageSizeEstimate(); uint32_t TrampolineSize = TargetT::TrampolineSize; uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize; LLVM_DEBUG(dbgs() << " Remote info:\n" diff --git a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h index 1e5f6ced597a..07c7471afc6a 100644 --- a/include/llvm/ExecutionEngine/Orc/RPCSerialization.h +++ b/include/llvm/ExecutionEngine/Orc/RPCSerialization.h @@ -1,9 +1,8 @@ //===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -128,123 +127,85 @@ template <typename T> class RPCTypeName<Expected<T>> { public: static const char* getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "Expected<" << RPCTypeNameSequence<T>() << ">"; + return Name; + }(); return Name.data(); } - -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename T> -std::mutex RPCTypeName<Expected<T>>::NameMutex; - -template <typename T> -std::string RPCTypeName<Expected<T>>::Name; - template <typename T1, typename T2> class RPCTypeName<std::pair<T1, T2>> { public: static const char* getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>() << ">"; + return Name; + }(); return Name.data(); } -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename T1, typename T2> -std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex; -template <typename T1, typename T2> -std::string RPCTypeName<std::pair<T1, T2>>::Name; - template <typename... ArgTs> class RPCTypeName<std::tuple<ArgTs...>> { public: static const char* getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "std::tuple<" << RPCTypeNameSequence<ArgTs...>() << ">"; + return Name; + }(); return Name.data(); } -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename... ArgTs> -std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex; -template <typename... ArgTs> -std::string RPCTypeName<std::tuple<ArgTs...>>::Name; - template <typename T> class RPCTypeName<std::vector<T>> { public: static const char*getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName() << ">"; + return Name; + }(); return Name.data(); } - -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename T> -std::mutex RPCTypeName<std::vector<T>>::NameMutex; -template <typename T> -std::string RPCTypeName<std::vector<T>>::Name; - template <typename T> class RPCTypeName<std::set<T>> { public: static const char *getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "std::set<" << RPCTypeName<T>::getName() << ">"; + return Name; + }(); return Name.data(); } - -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename T> std::mutex RPCTypeName<std::set<T>>::NameMutex; -template <typename T> std::string RPCTypeName<std::set<T>>::Name; - template <typename K, typename V> class RPCTypeName<std::map<K, V>> { public: static const char *getName() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << "std::map<" << RPCTypeNameSequence<K, V>() << ">"; + return Name; + }(); return Name.data(); } - -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename K, typename V> -std::mutex RPCTypeName<std::map<K, V>>::NameMutex; -template <typename K, typename V> std::string RPCTypeName<std::map<K, V>>::Name; - /// The SerializationTraits<ChannelT, T> class describes how to serialize and /// deserialize an instance of type T to/from an abstract channel of type /// ChannelT. It also provides a representation of the type's name via the diff --git a/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/include/llvm/ExecutionEngine/Orc/RPCUtils.h index 953b73e10e43..3b11e1b283de 100644 --- a/include/llvm/ExecutionEngine/Orc/RPCUtils.h +++ b/include/llvm/ExecutionEngine/Orc/RPCUtils.h @@ -1,9 +1,8 @@ -//===------- RPCUTils.h - Utilities for building RPC APIs -------*- C++ -*-===// +//===- RPCUtils.h - Utilities for building RPC APIs -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -152,25 +151,17 @@ public: /// Returns the full function prototype as a string. static const char *getPrototype() { - std::lock_guard<std::mutex> Lock(NameMutex); - if (Name.empty()) + static std::string Name = [] { + std::string Name; raw_string_ostream(Name) << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName() << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")"; + return Name; + }(); return Name.data(); } - -private: - static std::mutex NameMutex; - static std::string Name; }; -template <typename DerivedFunc, typename RetT, typename... ArgTs> -std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex; - -template <typename DerivedFunc, typename RetT, typename... ArgTs> -std::string Function<DerivedFunc, RetT(ArgTs...)>::Name; - /// Allocates RPC function ids during autonegotiation. /// Specializations of this class must provide four members: /// diff --git a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 6f90f0380d95..d9535ce5f21f 100644 --- a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -1,9 +1,8 @@ //===- RTDyldObjectLinkingLayer.h - RTDyld-based jit linking ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -44,22 +43,34 @@ public: const RuntimeDyld::LoadedObjectInfo &)>; /// Functor for receiving finalization notifications. - using NotifyEmittedFunction = std::function<void(VModuleKey)>; + using NotifyEmittedFunction = + std::function<void(VModuleKey, std::unique_ptr<MemoryBuffer>)>; using GetMemoryManagerFunction = std::function<std::unique_ptr<RuntimeDyld::MemoryManager>()>; /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyEmitted functors. - RTDyldObjectLinkingLayer( - ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager, - NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(), - NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction()); + RTDyldObjectLinkingLayer(ExecutionSession &ES, + GetMemoryManagerFunction GetMemoryManager); /// Emit the object. void emit(MaterializationResponsibility R, std::unique_ptr<MemoryBuffer> O) override; + /// Set the NotifyLoaded callback. + RTDyldObjectLinkingLayer &setNotifyLoaded(NotifyLoadedFunction NotifyLoaded) { + this->NotifyLoaded = std::move(NotifyLoaded); + return *this; + } + + /// Set the NotifyEmitted callback. + RTDyldObjectLinkingLayer & + setNotifyEmitted(NotifyEmittedFunction NotifyEmitted) { + this->NotifyEmitted = std::move(NotifyEmitted); + return *this; + } + /// Set the 'ProcessAllSections' flag. /// /// If set to true, all sections in each object file will be allocated using @@ -109,7 +120,8 @@ private: std::map<StringRef, JITEvaluatedSymbol> Resolved, std::set<StringRef> &InternalSymbols); - void onObjEmit(VModuleKey K, MaterializationResponsibility &R, Error Err); + void onObjEmit(VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer, + MaterializationResponsibility &R, Error Err); mutable std::mutex RTDyldLayerMutex; GetMemoryManagerFunction GetMemoryManager; @@ -341,17 +353,27 @@ public: /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyFinalized functors. + LLVM_ATTRIBUTE_DEPRECATED( + LegacyRTDyldObjectLinkingLayer( + ExecutionSession &ES, ResourcesGetter GetResources, + NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), + NotifyFreedFtor NotifyFreed = NotifyFreedFtor()), + "ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please " + "use " + "ORCv2 (see docs/ORCv2.rst)"); + + // Legacy layer constructor with deprecation acknowledgement. LegacyRTDyldObjectLinkingLayer( - ExecutionSession &ES, ResourcesGetter GetResources, + ORCv1DeprecationAcknowledgement, ExecutionSession &ES, + ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), NotifyFreedFtor NotifyFreed = NotifyFreedFtor()) : ES(ES), GetResources(std::move(GetResources)), NotifyLoaded(std::move(NotifyLoaded)), NotifyFinalized(std::move(NotifyFinalized)), - NotifyFreed(std::move(NotifyFreed)), - ProcessAllSections(false) { - } + NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {} /// Set the 'ProcessAllSections' flag. /// diff --git a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h index db810f4ef2e5..46b7c59450e6 100644 --- a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h +++ b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h @@ -1,9 +1,8 @@ //===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h index 955e77607a18..b87cf697a81e 100644 --- a/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h +++ b/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h @@ -1,9 +1,8 @@ //===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,9 +13,10 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H #define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/ExecutionEngine/Orc/LambdaResolver.h" #include <map> namespace llvm { @@ -313,7 +313,14 @@ public: /// /// The ReportError functor can be used locally log errors that are intended /// to be sent sent - RemoteObjectClientLayer(RPCEndpoint &Remote, + LLVM_ATTRIBUTE_DEPRECATED( + RemoteObjectClientLayer(RPCEndpoint &Remote, + std::function<void(Error)> ReportError), + "ORCv1 layers (including RemoteObjectClientLayer) are deprecated. Please " + "use " + "ORCv2 (see docs/ORCv2.rst)"); + + RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement, RPCEndpoint &Remote, std::function<void(Error)> ReportError) : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) { using ThisT = RemoteObjectClientLayer<RPCEndpoint>; @@ -418,11 +425,18 @@ public: /// Create a RemoteObjectServerLayer with the given base layer (which must be /// an object layer), RPC endpoint, and error reporter function. - RemoteObjectServerLayer(BaseLayerT &BaseLayer, - RPCEndpoint &Remote, + LLVM_ATTRIBUTE_DEPRECATED( + RemoteObjectServerLayer(BaseLayerT &BaseLayer, RPCEndpoint &Remote, + std::function<void(Error)> ReportError), + "ORCv1 layers (including RemoteObjectServerLayer) are deprecated. Please " + "use " + "ORCv2 (see docs/ORCv2.rst)"); + + RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement, + BaseLayerT &BaseLayer, RPCEndpoint &Remote, std::function<void(Error)> ReportError) - : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)), - BaseLayer(BaseLayer), HandleIdMgr(1) { + : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)), + BaseLayer(BaseLayer), HandleIdMgr(1) { using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>; Remote.template addHandler<AddObject>(*this, &ThisT::addObject); @@ -463,6 +477,7 @@ private: assert(!BaseLayerHandles.count(Id) && "Id already in use?"); auto Resolver = createLambdaResolver( + AcknowledgeORCv1Deprecation, [this, Id](const std::string &Name) { return lookup(Id, Name); }, [this, Id](const std::string &Name) { return lookupInLogicalDylib(Id, Name); @@ -523,6 +538,31 @@ private: std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles; }; +template <typename RPCEndpoint> +RemoteObjectClientLayer<RPCEndpoint>::RemoteObjectClientLayer( + RPCEndpoint &Remote, std::function<void(Error)> ReportError) + : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) { + using ThisT = RemoteObjectClientLayer<RPCEndpoint>; + Remote.template addHandler<Lookup>(*this, &ThisT::lookup); + Remote.template addHandler<LookupInLogicalDylib>( + *this, &ThisT::lookupInLogicalDylib); +} + +template <typename BaseLayerT, typename RPCEndpoint> +RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>::RemoteObjectServerLayer( + BaseLayerT &BaseLayer, RPCEndpoint &Remote, + std::function<void(Error)> ReportError) + : RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)), + BaseLayer(BaseLayer), HandleIdMgr(1) { + using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>; + + Remote.template addHandler<AddObject>(*this, &ThisT::addObject); + Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject); + Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol); + Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn); + Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize); +} + } // end namespace orc } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h index 717076e25609..c354f6c3559c 100644 --- a/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h +++ b/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h @@ -1,9 +1,8 @@ //===- SymbolStringPool.h - Multi-threaded pool for JIT symbols -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -51,25 +50,20 @@ private: class SymbolStringPtr { friend class SymbolStringPool; friend struct DenseMapInfo<SymbolStringPtr>; - friend bool operator==(const SymbolStringPtr &LHS, - const SymbolStringPtr &RHS); - friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS); - - static SymbolStringPool::PoolMapEntry Tombstone; public: SymbolStringPtr() = default; SymbolStringPtr(const SymbolStringPtr &Other) : S(Other.S) { - if (S) + if (isRealPoolEntry(S)) ++S->getValue(); } SymbolStringPtr& operator=(const SymbolStringPtr &Other) { - if (S) + if (isRealPoolEntry(S)) --S->getValue(); S = Other.S; - if (S) + if (isRealPoolEntry(S)) ++S->getValue(); return *this; } @@ -79,7 +73,7 @@ public: } SymbolStringPtr& operator=(SymbolStringPtr &&Other) { - if (S) + if (isRealPoolEntry(S)) --S->getValue(); S = nullptr; std::swap(S, Other.S); @@ -87,34 +81,64 @@ public: } ~SymbolStringPtr() { - if (S) + if (isRealPoolEntry(S)) --S->getValue(); } StringRef operator*() const { return S->first(); } + friend bool operator==(const SymbolStringPtr &LHS, + const SymbolStringPtr &RHS) { + return LHS.S == RHS.S; + } + + friend bool operator!=(const SymbolStringPtr &LHS, + const SymbolStringPtr &RHS) { + return !(LHS == RHS); + } + + friend bool operator<(const SymbolStringPtr &LHS, + const SymbolStringPtr &RHS) { + return LHS.S < RHS.S; + } + private: + using PoolEntryPtr = SymbolStringPool::PoolMapEntry *; SymbolStringPtr(SymbolStringPool::PoolMapEntry *S) : S(S) { - if (S) + if (isRealPoolEntry(S)) ++S->getValue(); } - SymbolStringPool::PoolMapEntry *S = nullptr; -}; + // Returns false for null, empty, and tombstone values, true otherwise. + bool isRealPoolEntry(PoolEntryPtr P) { + return ((reinterpret_cast<uintptr_t>(P) - 1) & InvalidPtrMask) != + InvalidPtrMask; + } -inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { - return LHS.S == RHS.S; -} + static SymbolStringPtr getEmptyVal() { + return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(EmptyBitPattern)); + } -inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { - return !(LHS == RHS); -} + static SymbolStringPtr getTombstoneVal() { + return SymbolStringPtr(reinterpret_cast<PoolEntryPtr>(TombstoneBitPattern)); + } -inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { - return LHS.S < RHS.S; -} + constexpr static uintptr_t EmptyBitPattern = + std::numeric_limits<uintptr_t>::max() + << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable; + + constexpr static uintptr_t TombstoneBitPattern = + (std::numeric_limits<uintptr_t>::max() - 1) + << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable; + + constexpr static uintptr_t InvalidPtrMask = + (std::numeric_limits<uintptr_t>::max() - 3) + << PointerLikeTypeTraits<PoolEntryPtr>::NumLowBitsAvailable; + + PoolEntryPtr S = nullptr; +}; inline SymbolStringPool::~SymbolStringPool() { #ifndef NDEBUG @@ -151,16 +175,15 @@ template <> struct DenseMapInfo<orc::SymbolStringPtr> { static orc::SymbolStringPtr getEmptyKey() { - return orc::SymbolStringPtr(); + return orc::SymbolStringPtr::getEmptyVal(); } static orc::SymbolStringPtr getTombstoneKey() { - return orc::SymbolStringPtr(&orc::SymbolStringPtr::Tombstone); + return orc::SymbolStringPtr::getTombstoneVal(); } - static unsigned getHashValue(orc::SymbolStringPtr V) { - uintptr_t IV = reinterpret_cast<uintptr_t>(V.S); - return unsigned(IV) ^ unsigned(IV >> 9); + static unsigned getHashValue(const orc::SymbolStringPtr &V) { + return DenseMapInfo<orc::SymbolStringPtr::PoolEntryPtr>::getHashValue(V.S); } static bool isEqual(const orc::SymbolStringPtr &LHS, diff --git a/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h b/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h index bf946de532d3..5787500387c4 100644 --- a/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h +++ b/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h @@ -1,9 +1,8 @@ //===----------- ThreadSafeModule.h -- Layer interfaces ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h index 4cd5648b2fc2..6cca1933f39f 100644 --- a/include/llvm/ExecutionEngine/OrcMCJITReplacement.h +++ b/include/llvm/ExecutionEngine/OrcMCJITReplacement.h @@ -1,9 +1,8 @@ //===---- OrcMCJITReplacement.h - Orc-based MCJIT replacement ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/OrcV1Deprecation.h b/include/llvm/ExecutionEngine/OrcV1Deprecation.h new file mode 100644 index 000000000000..7ed254b3ee04 --- /dev/null +++ b/include/llvm/ExecutionEngine/OrcV1Deprecation.h @@ -0,0 +1,22 @@ +//===------ OrcV1Deprecation.h - Memory manager for MC-JIT ------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Tag for suppressing ORCv1 deprecation warnings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORCV1DEPRECATION_H +#define LLVM_EXECUTIONENGINE_ORCV1DEPRECATION_H + +namespace llvm { + +enum ORCv1DeprecationAcknowledgement { AcknowledgeORCv1Deprecation }; + +} // namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORCV1DEPRECATION_H diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 23d651f6d1b6..c7c87ecdfa09 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -1,9 +1,8 @@ //===-- RTDyldMemoryManager.cpp - Memory manager for MC-JIT -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index e419ee05e566..b2b4eba47074 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -1,9 +1,8 @@ //===- RuntimeDyld.h - Run-time dynamic linker for MC-JIT -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -53,18 +52,19 @@ private: std::string ErrMsg; }; -class RuntimeDyldCheckerImpl; class RuntimeDyldImpl; class RuntimeDyld { - friend class RuntimeDyldCheckerImpl; - protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + using NotifyStubEmittedFunction = std::function<void( + StringRef FileName, StringRef SectionName, StringRef SymbolName, + unsigned SectionID, uint32_t StubOffset)>; + /// Information about the loaded object. class LoadedObjectInfo : public llvm::LoadedObjectInfo { friend class RuntimeDyldImpl; @@ -185,6 +185,9 @@ public: /// and resolve relocatons based on where they put it). void *getSymbolLocalAddress(StringRef Name) const; + /// Get the section ID for the section containing the given symbol. + unsigned getSymbolSectionID(StringRef Name) const; + /// Get the target address and flags for the named symbol. /// This address is the one used for relocation. JITEvaluatedSymbol getSymbol(StringRef Name) const; @@ -205,6 +208,19 @@ public: /// This is the address which will be used for relocation resolution. void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress); + /// Returns the section's working memory. + StringRef getSectionContent(unsigned SectionID) const; + + /// If the section was loaded, return the section's load address, + /// otherwise return None. + uint64_t getSectionLoadAddress(unsigned SectionID) const; + + /// Set the NotifyStubEmitted callback. This is used for debugging + /// purposes. A callback is made for each stub that is generated. + void setNotifyStubEmitted(NotifyStubEmittedFunction NotifyStubEmitted) { + this->NotifyStubEmitted = std::move(NotifyStubEmitted); + } + /// Register any EH frame sections that have been loaded but not previously /// registered with the memory manager. Note, RuntimeDyld is responsible /// for identifying the EH frame and calling the memory manager with the @@ -266,7 +282,7 @@ private: MemoryManager &MemMgr; JITSymbolResolver &Resolver; bool ProcessAllSections; - RuntimeDyldCheckerImpl *Checker; + NotifyStubEmittedFunction NotifyStubEmitted; }; // Asynchronous JIT link for ORC. diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 13fc5fd5a3e7..93ea09107bd1 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -1,16 +1,18 @@ //===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H #define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/Support/Endian.h" #include <cstdint> #include <memory> @@ -58,7 +60,8 @@ class raw_ostream; /// /// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' /// | 'next_pc' '(' symbol ')' -/// | 'stub_addr' '(' file-name ',' section-name ',' symbol ')' +/// | 'stub_addr' '(' stub-container-name ',' symbol ')' +/// | 'got_addr' '(' stub-container-name ',' symbol ')' /// | symbol /// /// binary_expr = expr '+' expr @@ -70,15 +73,84 @@ class raw_ostream; /// class RuntimeDyldChecker { public: - RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, - MCInstPrinter *InstPrinter, raw_ostream &ErrStream); - ~RuntimeDyldChecker(); + class MemoryRegionInfo { + public: + MemoryRegionInfo() = default; + + /// Constructor for symbols/sections with content. + MemoryRegionInfo(StringRef Content, JITTargetAddress TargetAddress) + : ContentPtr(Content.data()), Size(Content.size()), + TargetAddress(TargetAddress) {} + + /// Constructor for zero-fill symbols/sections. + MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress) + : Size(Size), TargetAddress(TargetAddress) {} + + /// Returns true if this is a zero-fill symbol/section. + bool isZeroFill() const { + assert(Size && "setContent/setZeroFill must be called first"); + return !ContentPtr; + } + + /// Set the content for this memory region. + void setContent(StringRef Content) { + assert(!ContentPtr && !Size && "Content/zero-fill already set"); + ContentPtr = Content.data(); + Size = Content.size(); + } + + /// Set a zero-fill length for this memory region. + void setZeroFill(uint64_t Size) { + assert(!ContentPtr && !this->Size && "Content/zero-fill already set"); + this->Size = Size; + } - // Get the associated RTDyld instance. - RuntimeDyld& getRTDyld(); + /// Returns the content for this section if there is any. + StringRef getContent() const { + assert(!isZeroFill() && "Can't get content for a zero-fill section"); + return StringRef(ContentPtr, static_cast<size_t>(Size)); + } - // Get the associated RTDyld instance. - const RuntimeDyld& getRTDyld() const; + /// Returns the zero-fill length for this section. + uint64_t getZeroFillLength() const { + assert(isZeroFill() && "Can't get zero-fill length for content section"); + return Size; + } + + /// Set the target address for this region. + void setTargetAddress(JITTargetAddress TargetAddress) { + assert(!this->TargetAddress && "TargetAddress already set"); + this->TargetAddress = TargetAddress; + } + + /// Return the target address for this region. + JITTargetAddress getTargetAddress() const { return TargetAddress; } + + private: + const char *ContentPtr = 0; + uint64_t Size = 0; + JITTargetAddress TargetAddress = 0; + }; + + using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>; + using GetSymbolInfoFunction = + std::function<Expected<MemoryRegionInfo>(StringRef SymbolName)>; + using GetSectionInfoFunction = std::function<Expected<MemoryRegionInfo>( + StringRef FileName, StringRef SectionName)>; + using GetStubInfoFunction = std::function<Expected<MemoryRegionInfo>( + StringRef StubContainer, StringRef TargetName)>; + using GetGOTInfoFunction = std::function<Expected<MemoryRegionInfo>( + StringRef GOTContainer, StringRef TargetName)>; + + RuntimeDyldChecker(IsSymbolValidFunction IsSymbolValid, + GetSymbolInfoFunction GetSymbolInfo, + GetSectionInfoFunction GetSectionInfo, + GetStubInfoFunction GetStubInfo, + GetGOTInfoFunction GetGOTInfo, + support::endianness Endianness, + MCDisassembler *Disassembler, MCInstPrinter *InstPrinter, + raw_ostream &ErrStream); + ~RuntimeDyldChecker(); /// Check a single expression against the attached RuntimeDyld /// instance. @@ -100,7 +172,7 @@ public: bool LocalAddress); /// If there is a section at the given local address, return its load - /// address, otherwise return none. + /// address, otherwise return none. Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const; private: diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index 3cf131c27778..d7316425da2f 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -1,9 +1,8 @@ //===- SectionMemoryManager.h - Memory manager for MCJIT/RtDyld -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/FuzzerCLI.h b/include/llvm/FuzzMutate/FuzzerCLI.h index 3333e96db166..2a16e43a6ab3 100644 --- a/include/llvm/FuzzMutate/FuzzerCLI.h +++ b/include/llvm/FuzzMutate/FuzzerCLI.h @@ -1,9 +1,8 @@ //===-- FuzzerCLI.h - Common logic for CLIs of fuzzers ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/IRMutator.h b/include/llvm/FuzzMutate/IRMutator.h index 9aa9d6d6a4bc..40a1ce8aeec9 100644 --- a/include/llvm/FuzzMutate/IRMutator.h +++ b/include/llvm/FuzzMutate/IRMutator.h @@ -1,9 +1,8 @@ //===-- IRMutator.h - Mutation engine for fuzzing IR ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/OpDescriptor.h b/include/llvm/FuzzMutate/OpDescriptor.h index dd30fda99bea..d6c98cd949a2 100644 --- a/include/llvm/FuzzMutate/OpDescriptor.h +++ b/include/llvm/FuzzMutate/OpDescriptor.h @@ -1,9 +1,8 @@ //===-- OpDescriptor.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/Operations.h b/include/llvm/FuzzMutate/Operations.h index 668bd952ebb2..2eb4c38c2aeb 100644 --- a/include/llvm/FuzzMutate/Operations.h +++ b/include/llvm/FuzzMutate/Operations.h @@ -1,9 +1,8 @@ //===-- Operations.h - ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/Random.h b/include/llvm/FuzzMutate/Random.h index 3a5f46a07554..615b15f04ceb 100644 --- a/include/llvm/FuzzMutate/Random.h +++ b/include/llvm/FuzzMutate/Random.h @@ -1,9 +1,8 @@ //===--- Random.h - Utilities for random sampling -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/FuzzMutate/RandomIRBuilder.h b/include/llvm/FuzzMutate/RandomIRBuilder.h index 5cf3f0b22709..f3b609702e9d 100644 --- a/include/llvm/FuzzMutate/RandomIRBuilder.h +++ b/include/llvm/FuzzMutate/RandomIRBuilder.h @@ -1,9 +1,8 @@ -//===-- Mutator.h - Utils for randomly mutation IR --------------*- C++ -*-===// +//===- RandomIRBuilder.h - Utils for randomly mutation IR -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 497dca44547c..5f514b9c47d2 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -1,9 +1,8 @@ //===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -79,6 +78,9 @@ public: /// If this is a byval or inalloca argument, return its alignment. unsigned getParamAlignment() const; + /// If this is a byval argument, return its type. + Type *getParamByValType() const; + /// Return true if this argument has the nest attribute. bool hasNestAttr() const; @@ -91,6 +93,9 @@ public: /// Return true if this argument has the sret attribute. bool hasStructRetAttr() const; + /// Return true if this argument has the inreg attribute. + bool hasInRegAttr() const; + /// Return true if this argument has the returned attribute. bool hasReturnedAttr() const; @@ -119,6 +124,8 @@ public: /// Check if an argument has a given attribute. bool hasAttribute(Attribute::AttrKind Kind) const; + Attribute getAttribute(Attribute::AttrKind Kind) const; + /// Method for support type inquiry through isa, cast, and dyn_cast. static bool classof(const Value *V) { return V->getValueID() == ArgumentVal; diff --git a/include/llvm/IR/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h index 6e1f5c43e12e..3fd3c57a6796 100644 --- a/include/llvm/IR/AssemblyAnnotationWriter.h +++ b/include/llvm/IR/AssemblyAnnotationWriter.h @@ -1,9 +1,8 @@ //===-- AssemblyAnnotationWriter.h - Annotation .ll files -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 9fc4614af010..06cc09e1cfc7 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -1,9 +1,8 @@ //===- llvm/Attributes.h - Container for Attributes -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -91,6 +90,7 @@ public: static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); static Attribute get(LLVMContext &Context, StringRef Kind, StringRef Val = StringRef()); + static Attribute get(LLVMContext &Context, AttrKind Kind, Type *Ty); /// Return a uniquified Attribute object that has the specific /// alignment set. @@ -103,6 +103,7 @@ public: static Attribute getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, const Optional<unsigned> &NumElemsArg); + static Attribute getWithByValType(LLVMContext &Context, Type *Ty); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -118,6 +119,9 @@ public: /// attribute. bool isStringAttribute() const; + /// Return true if the attribute is a type attribute. + bool isTypeAttribute() const; + /// Return true if the attribute is present. bool hasAttribute(AttrKind Val) const; @@ -140,6 +144,10 @@ public: /// attribute to be a string attribute. StringRef getValueAsString() const; + /// Return the attribute's value as a Type. This requires the attribute to be + /// a type attribute. + Type *getValueAsType() const; + /// Returns the alignment field of an attribute as a byte alignment /// value. unsigned getAlignment() const; @@ -280,6 +288,7 @@ public: unsigned getStackAlignment() const; uint64_t getDereferenceableBytes() const; uint64_t getDereferenceableOrNullBytes() const; + Type *getByValType() const; std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; std::string getAsString(bool InAttrGrp = false) const; @@ -599,6 +608,9 @@ public: /// Return the alignment for the specified function parameter. unsigned getParamAlignment(unsigned ArgNo) const; + /// Return the byval type for the specified function parameter. + Type *getParamByValType(unsigned ArgNo) const; + /// Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; @@ -698,6 +710,7 @@ class AttrBuilder { uint64_t DerefBytes = 0; uint64_t DerefOrNullBytes = 0; uint64_t AllocSizeArgs = 0; + Type *ByValType = nullptr; public: AttrBuilder() = default; @@ -773,6 +786,9 @@ public: /// dereferenceable_or_null attribute exists (zero is returned otherwise). uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// Retrieve the byval type. + Type *getByValType() const { return ByValType; } + /// Retrieve the allocsize args, if the allocsize attribute exists. If it /// doesn't exist, pair(0, 0) is returned. std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; @@ -797,6 +813,9 @@ public: AttrBuilder &addAllocSizeAttr(unsigned ElemSizeArg, const Optional<unsigned> &NumElemsArg); + /// This turns a byval type into the form used internally in Attribute. + AttrBuilder &addByValAttr(Type *Ty); + /// Add an allocsize attribute, using the representation returned by /// Attribute.getIntValue(). AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr); diff --git a/include/llvm/IR/Attributes.td b/include/llvm/IR/Attributes.td index e786d85d05a8..153046d2311c 100644 --- a/include/llvm/IR/Attributes.td +++ b/include/llvm/IR/Attributes.td @@ -85,6 +85,9 @@ def NoCapture : EnumAttr<"nocapture">; /// Call cannot be duplicated. def NoDuplicate : EnumAttr<"noduplicate">; +/// Function does not deallocate memory. +def NoFree : EnumAttr<"nofree">; + /// Disable implicit floating point insts. def NoImplicitFloat : EnumAttr<"noimplicitfloat">; @@ -106,6 +109,9 @@ def NoRedZone : EnumAttr<"noredzone">; /// Mark the function as not returning. def NoReturn : EnumAttr<"noreturn">; +/// Function does not synchronize. +def NoSync : EnumAttr<"nosync">; + /// Disable Indirect Branch Tracking. def NoCfCheck : EnumAttr<"nocf_check">; @@ -130,6 +136,9 @@ def ReadOnly : EnumAttr<"readonly">; /// Return value is always equal to this argument. def Returned : EnumAttr<"returned">; +/// Parameter is required to be a trivial constant. +def ImmArg : EnumAttr<"immarg">; + /// Function can return twice. def ReturnsTwice : EnumAttr<"returns_twice">; @@ -176,6 +185,9 @@ def SanitizeMemory : EnumAttr<"sanitize_memory">; /// HWAddressSanitizer is on. def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">; +/// MemTagSanitizer is on. +def SanitizeMemTag : EnumAttr<"sanitize_memtag">; + /// Speculative Load Hardening is enabled. /// /// Note that this uses the default compatibility (always compatible during @@ -193,6 +205,9 @@ def SwiftSelf : EnumAttr<"swiftself">; /// Function must be in a unwind table. def UWTable : EnumAttr<"uwtable">; +/// Function always comes back to callsite. +def WillReturn : EnumAttr<"willreturn">; + /// Function only writes to memory. def WriteOnly : EnumAttr<"writeonly">; @@ -221,6 +236,7 @@ def : CompatRule<"isEqual<SanitizeAddressAttr>">; def : CompatRule<"isEqual<SanitizeThreadAttr>">; def : CompatRule<"isEqual<SanitizeMemoryAttr>">; def : CompatRule<"isEqual<SanitizeHWAddressAttr>">; +def : CompatRule<"isEqual<SanitizeMemTagAttr>">; def : CompatRule<"isEqual<SafeStackAttr>">; def : CompatRule<"isEqual<ShadowCallStackAttr>">; diff --git a/include/llvm/IR/AutoUpgrade.h b/include/llvm/IR/AutoUpgrade.h index 8cf574c6a138..017ad93d8a2a 100644 --- a/include/llvm/IR/AutoUpgrade.h +++ b/include/llvm/IR/AutoUpgrade.h @@ -1,9 +1,8 @@ //===- AutoUpgrade.h - AutoUpgrade Helpers ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -47,9 +46,9 @@ namespace llvm { /// so that it can update all calls to the old function. void UpgradeCallsToIntrinsic(Function* F); - /// This checks for global variables which should be upgraded. It returns true - /// if it requires upgrading. - bool UpgradeGlobalVariable(GlobalVariable *GV); + /// This checks for global variables which should be upgraded. It it requires + /// upgrading, returns a pointer to the upgraded variable. + GlobalVariable *UpgradeGlobalVariable(GlobalVariable *GV); /// This checks for module flags which should be upgraded. It returns true if /// module is modified. diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 99eac33f742e..69555af50e1f 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -1,9 +1,8 @@ //===- llvm/BasicBlock.h - Represent a basic block in the VM ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -363,7 +362,7 @@ public: /// This is actually not used to update the Predecessor list, but is actually /// used to update the PHI nodes that reside in the block. Note that this /// should be called while the predecessor still refers to this block. - void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs = false); bool canSplitPredecessors() const; @@ -391,6 +390,14 @@ public: /// direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + /// Update all phi nodes in this basic block to refer to basic block \p New + /// instead of basic block \p Old. + void replacePhiUsesWith(BasicBlock *Old, BasicBlock *New); + + /// Update all phi nodes in this basic block's successors to refer to basic + /// block \p New instead of basic block \p Old. + void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New); + /// Update all phi nodes in this basic block's successors to refer to basic /// block \p New instead of to it. void replaceSuccessorsPhiUsesWith(BasicBlock *New); diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index 8385c4647e12..55aff7137e86 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -1,9 +1,8 @@ //===- CFG.h ----------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -238,10 +237,6 @@ public: } }; -template <typename T, typename U> struct isPodLike<SuccIterator<T, U>> { - static const bool value = isPodLike<T>::value; -}; - using succ_iterator = SuccIterator<Instruction, BasicBlock>; using succ_const_iterator = SuccIterator<const Instruction, const BasicBlock>; using succ_range = iterator_range<succ_iterator>; diff --git a/include/llvm/IR/CFGDiff.h b/include/llvm/IR/CFGDiff.h index da4373f7bce2..57b62dd66a47 100644 --- a/include/llvm/IR/CFGDiff.h +++ b/include/llvm/IR/CFGDiff.h @@ -1,9 +1,8 @@ //===- CFGDiff.h - Define a CFG snapshot. -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index a3e78049f4be..b47a96c5d5fa 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -1,15 +1,14 @@ //===- CallSite.h - Abstract Call & Invoke instrs ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 CallSite class, which is a handy wrapper for code that -// wants to treat Call and Invoke instructions in a generic way. When in non- -// mutation context (e.g. an analysis) ImmutableCallSite should be used. +// wants to treat Call, Invoke and CallBr instructions in a generic way. When +// in non-mutation context (e.g. an analysis) ImmutableCallSite should be used. // Finally, when some degree of customization is necessary between these two // extremes, CallSiteBase<> can be supplied with fine-tuned parameters. // @@ -18,7 +17,7 @@ // They are efficiently copyable, assignable and constructable, with cost // equivalent to copying a pointer (notice that they have only a single data // member). The internal representation carries a flag which indicates which of -// the two variants is enclosed. This allows for cheaper checks when various +// the three variants is enclosed. This allows for cheaper checks when various // accessors of CallSite are employed. // //===----------------------------------------------------------------------===// @@ -49,45 +48,50 @@ namespace Intrinsic { enum ID : unsigned; } -template <typename FunTy = const Function, - typename BBTy = const BasicBlock, - typename ValTy = const Value, - typename UserTy = const User, - typename UseTy = const Use, - typename InstrTy = const Instruction, +template <typename FunTy = const Function, typename BBTy = const BasicBlock, + typename ValTy = const Value, typename UserTy = const User, + typename UseTy = const Use, typename InstrTy = const Instruction, typename CallTy = const CallInst, typename InvokeTy = const InvokeInst, + typename CallBrTy = const CallBrInst, typename IterTy = User::const_op_iterator> class CallSiteBase { protected: - PointerIntPair<InstrTy*, 1, bool> I; + PointerIntPair<InstrTy *, 2, int> I; CallSiteBase() = default; - CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } - CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } + CallSiteBase(CallTy *CI) : I(CI, 1) { assert(CI); } + CallSiteBase(InvokeTy *II) : I(II, 0) { assert(II); } + CallSiteBase(CallBrTy *CBI) : I(CBI, 2) { assert(CBI); } explicit CallSiteBase(ValTy *II) { *this = get(II); } private: /// This static method is like a constructor. It will create an appropriate - /// call site for a Call or Invoke instruction, but it can also create a null - /// initialized CallSiteBase object for something which is NOT a call site. + /// call site for a Call, Invoke or CallBr instruction, but it can also create + /// a null initialized CallSiteBase object for something which is NOT a call + /// site. static CallSiteBase get(ValTy *V) { if (InstrTy *II = dyn_cast<InstrTy>(V)) { if (II->getOpcode() == Instruction::Call) return CallSiteBase(static_cast<CallTy*>(II)); - else if (II->getOpcode() == Instruction::Invoke) + if (II->getOpcode() == Instruction::Invoke) return CallSiteBase(static_cast<InvokeTy*>(II)); + if (II->getOpcode() == Instruction::CallBr) + return CallSiteBase(static_cast<CallBrTy *>(II)); } return CallSiteBase(); } public: - /// Return true if a CallInst is enclosed. Note that !isCall() does not mean - /// an InvokeInst is enclosed. It may also signify a NULL instruction pointer. - bool isCall() const { return I.getInt(); } + /// Return true if a CallInst is enclosed. + bool isCall() const { return I.getInt() == 1; } + + /// Return true if a InvokeInst is enclosed. !I.getInt() may also signify a + /// NULL instruction pointer, so check that. + bool isInvoke() const { return getInstruction() && I.getInt() == 0; } - /// Return true if a InvokeInst is enclosed. - bool isInvoke() const { return getInstruction() && !I.getInt(); } + /// Return true if a CallBrInst is enclosed. + bool isCallBr() const { return I.getInt() == 2; } InstrTy *getInstruction() const { return I.getPointer(); } InstrTy *operator->() const { return I.getPointer(); } @@ -98,7 +102,7 @@ public: /// Return the pointer to function that is being called. ValTy *getCalledValue() const { - assert(getInstruction() && "Not a call or invoke instruction!"); + assert(getInstruction() && "Not a call, invoke or callbr instruction!"); return *getCallee(); } @@ -115,16 +119,19 @@ public: return false; if (isa<FunTy>(V) || isa<Constant>(V)) return false; - if (const CallInst *CI = dyn_cast<CallInst>(getInstruction())) { - if (CI->isInlineAsm()) + if (const CallBase *CB = dyn_cast<CallBase>(getInstruction())) + if (CB->isInlineAsm()) return false; - } return true; } - /// Set the callee to the specified value. + /// Set the callee to the specified value. Unlike the function of the same + /// name on CallBase, does not modify the type! void setCalledFunction(Value *V) { - assert(getInstruction() && "Not a call or invoke instruction!"); + assert(getInstruction() && "Not a call, callbr, or invoke instruction!"); + assert(cast<PointerType>(V->getType())->getElementType() == + cast<CallBase>(getInstruction())->getFunctionType() && + "New callee type does not match FunctionType on call"); *getCallee() = V; } @@ -189,7 +196,7 @@ public: } void setArgument(unsigned ArgNo, Value* newVal) { - assert(getInstruction() && "Not a call or invoke instruction!"); + assert(getInstruction() && "Not a call, invoke or callbr instruction!"); assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); getInstruction()->setOperand(ArgNo, newVal); } @@ -203,7 +210,7 @@ public: /// Given a use for an argument, get the argument number that corresponds to /// it. unsigned getArgumentNo(const Use *U) const { - assert(getInstruction() && "Not a call or invoke instruction!"); + assert(getInstruction() && "Not a call, invoke or callbr instruction!"); assert(isArgOperand(U) && "Argument # out of range!"); return U - arg_begin(); } @@ -227,7 +234,7 @@ public: /// Given a use for a data operand, get the data operand number that /// corresponds to it. unsigned getDataOperandNo(const Use *U) const { - assert(getInstruction() && "Not a call or invoke instruction!"); + assert(getInstruction() && "Not a call, invoke or callbr instruction!"); assert(isDataOperand(U) && "Data operand # out of range!"); return U - data_operands_begin(); } @@ -237,18 +244,19 @@ public: using data_operand_iterator = IterTy; /// data_operands_begin/data_operands_end - Return iterators iterating over - /// the call / invoke argument list and bundle operands. For invokes, this is - /// the set of instruction operands except the invoke target and the two - /// successor blocks; and for calls this is the set of instruction operands - /// except the call target. + /// the call / invoke / callbr argument list and bundle operands. For invokes, + /// this is the set of instruction operands except the invoke target and the + /// two successor blocks; for calls this is the set of instruction operands + /// except the call target; for callbrs the number of labels to skip must be + /// determined first. IterTy data_operands_begin() const { assert(getInstruction() && "Not a call or invoke instruction!"); - return (*this)->op_begin(); + return cast<CallBase>(getInstruction())->data_operands_begin(); } IterTy data_operands_end() const { assert(getInstruction() && "Not a call or invoke instruction!"); - return (*this)->op_end() - (isCall() ? 1 : 3); + return cast<CallBase>(getInstruction())->data_operands_end(); } iterator_range<IterTy> data_ops() const { return make_range(data_operands_begin(), data_operands_end()); @@ -277,17 +285,19 @@ public: return isCall() && cast<CallInst>(getInstruction())->isTailCall(); } -#define CALLSITE_DELEGATE_GETTER(METHOD) \ - InstrTy *II = getInstruction(); \ - return isCall() \ - ? cast<CallInst>(II)->METHOD \ - : cast<InvokeInst>(II)->METHOD +#define CALLSITE_DELEGATE_GETTER(METHOD) \ + InstrTy *II = getInstruction(); \ + return isCall() ? cast<CallInst>(II)->METHOD \ + : isCallBr() ? cast<CallBrInst>(II)->METHOD \ + : cast<InvokeInst>(II)->METHOD -#define CALLSITE_DELEGATE_SETTER(METHOD) \ - InstrTy *II = getInstruction(); \ - if (isCall()) \ - cast<CallInst>(II)->METHOD; \ - else \ +#define CALLSITE_DELEGATE_SETTER(METHOD) \ + InstrTy *II = getInstruction(); \ + if (isCall()) \ + cast<CallInst>(II)->METHOD; \ + else if (isCallBr()) \ + cast<CallBrInst>(II)->METHOD; \ + else \ cast<InvokeInst>(II)->METHOD unsigned getNumArgOperands() const { @@ -303,9 +313,7 @@ public: } bool isInlineAsm() const { - if (isCall()) - return cast<CallInst>(getInstruction())->isInlineAsm(); - return false; + return cast<CallBase>(getInstruction())->isInlineAsm(); } /// Get the calling convention of the call. @@ -389,10 +397,10 @@ public: /// Return true if the data operand at index \p i directly or indirectly has /// the attribute \p A. /// - /// Normal call or invoke arguments have per operand attributes, as specified - /// in the attribute set attached to this instruction, while operand bundle - /// operands may have some attributes implied by the type of its containing - /// operand bundle. + /// Normal call, invoke or callbr arguments have per operand attributes, as + /// specified in the attribute set attached to this instruction, while operand + /// bundle operands may have some attributes implied by the type of its + /// containing operand bundle. bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const { CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, Kind)); } @@ -407,6 +415,11 @@ public: CALLSITE_DELEGATE_GETTER(getParamAlignment(ArgNo)); } + /// Extract the byval type for a call or parameter (nullptr=unknown). + Type *getParamByValType(unsigned ArgNo) const { + CALLSITE_DELEGATE_GETTER(getParamByValType(ArgNo)); + } + /// Extract the number of dereferenceable bytes for a call or parameter /// (0=unknown). uint64_t getDereferenceableBytes(unsigned i) const { @@ -580,13 +593,9 @@ public: #undef CALLSITE_DELEGATE_SETTER void getOperandBundlesAsDefs(SmallVectorImpl<OperandBundleDef> &Defs) const { - const Instruction *II = getInstruction(); // Since this is actually a getter that "looks like" a setter, don't use the // above macros to avoid confusion. - if (isCall()) - cast<CallInst>(II)->getOperandBundlesAsDefs(Defs); - else - cast<InvokeInst>(II)->getOperandBundlesAsDefs(Defs); + cast<CallBase>(getInstruction())->getOperandBundlesAsDefs(Defs); } /// Determine whether this data operand is not captured. @@ -662,12 +671,13 @@ private: class CallSite : public CallSiteBase<Function, BasicBlock, Value, User, Use, Instruction, CallInst, InvokeInst, - User::op_iterator> { + CallBrInst, User::op_iterator> { public: CallSite() = default; CallSite(CallSiteBase B) : CallSiteBase(B) {} CallSite(CallInst *CI) : CallSiteBase(CI) {} CallSite(InvokeInst *II) : CallSiteBase(II) {} + CallSite(CallBrInst *CBI) : CallSiteBase(CBI) {} explicit CallSite(Instruction *II) : CallSiteBase(II) {} explicit CallSite(Value *V) : CallSiteBase(V) {} @@ -683,6 +693,182 @@ private: User::op_iterator getCallee() const; }; +/// AbstractCallSite +/// +/// An abstract call site is a wrapper that allows to treat direct, +/// indirect, and callback calls the same. If an abstract call site +/// represents a direct or indirect call site it behaves like a stripped +/// down version of a normal call site object. The abstract call site can +/// also represent a callback call, thus the fact that the initially +/// called function (=broker) may invoke a third one (=callback callee). +/// In this case, the abstract call site hides the middle man, hence the +/// broker function. The result is a representation of the callback call, +/// inside the broker, but in the context of the original call to the broker. +/// +/// There are up to three functions involved when we talk about callback call +/// sites. The caller (1), which invokes the broker function. The broker +/// function (2), that will invoke the callee zero or more times. And finally +/// the callee (3), which is the target of the callback call. +/// +/// The abstract call site will handle the mapping from parameters to arguments +/// depending on the semantic of the broker function. However, it is important +/// to note that the mapping is often partial. Thus, some arguments of the +/// call/invoke instruction are mapped to parameters of the callee while others +/// are not. +class AbstractCallSite { +public: + + /// The encoding of a callback with regards to the underlying instruction. + struct CallbackInfo { + + /// For direct/indirect calls the parameter encoding is empty. If it is not, + /// the abstract call site represents a callback. In that case, the first + /// element of the encoding vector represents which argument of the call + /// site CS is the callback callee. The remaining elements map parameters + /// (identified by their position) to the arguments that will be passed + /// through (also identified by position but in the call site instruction). + /// + /// NOTE that we use LLVM argument numbers (starting at 0) and not + /// clang/source argument numbers (starting at 1). The -1 entries represent + /// unknown values that are passed to the callee. + using ParameterEncodingTy = SmallVector<int, 0>; + ParameterEncodingTy ParameterEncoding; + + }; + +private: + + /// The underlying call site: + /// caller -> callee, if this is a direct or indirect call site + /// caller -> broker function, if this is a callback call site + CallSite CS; + + /// The encoding of a callback with regards to the underlying instruction. + CallbackInfo CI; + +public: + /// Sole constructor for abstract call sites (ACS). + /// + /// An abstract call site can only be constructed through a llvm::Use because + /// each operand (=use) of an instruction could potentially be a different + /// abstract call site. Furthermore, even if the value of the llvm::Use is the + /// same, and the user is as well, the abstract call sites might not be. + /// + /// If a use is not associated with an abstract call site the constructed ACS + /// will evaluate to false if converted to a boolean. + /// + /// If the use is the callee use of a call or invoke instruction, the + /// constructed abstract call site will behave as a llvm::CallSite would. + /// + /// If the use is not a callee use of a call or invoke instruction, the + /// callback metadata is used to determine the argument <-> parameter mapping + /// as well as the callee of the abstract call site. + AbstractCallSite(const Use *U); + + /// Conversion operator to conveniently check for a valid/initialized ACS. + explicit operator bool() const { return (bool)CS; } + + /// Return the underlying instruction. + Instruction *getInstruction() const { return CS.getInstruction(); } + + /// Return the call site abstraction for the underlying instruction. + CallSite getCallSite() const { return CS; } + + /// Return true if this ACS represents a direct call. + bool isDirectCall() const { + return !isCallbackCall() && !CS.isIndirectCall(); + } + + /// Return true if this ACS represents an indirect call. + bool isIndirectCall() const { + return !isCallbackCall() && CS.isIndirectCall(); + } + + /// Return true if this ACS represents a callback call. + bool isCallbackCall() const { + // For a callback call site the callee is ALWAYS stored first in the + // transitive values vector. Thus, a non-empty vector indicates a callback. + return !CI.ParameterEncoding.empty(); + } + + /// Return true if @p UI is the use that defines the callee of this ACS. + bool isCallee(Value::const_user_iterator UI) const { + return isCallee(&UI.getUse()); + } + + /// Return true if @p U is the use that defines the callee of this ACS. + bool isCallee(const Use *U) const { + if (isDirectCall()) + return CS.isCallee(U); + + assert(!CI.ParameterEncoding.empty() && + "Callback without parameter encoding!"); + + return (int)CS.getArgumentNo(U) == CI.ParameterEncoding[0]; + } + + /// Return the number of parameters of the callee. + unsigned getNumArgOperands() const { + if (isDirectCall()) + return CS.getNumArgOperands(); + // Subtract 1 for the callee encoding. + return CI.ParameterEncoding.size() - 1; + } + + /// Return the operand index of the underlying instruction associated with @p + /// Arg. + int getCallArgOperandNo(Argument &Arg) const { + return getCallArgOperandNo(Arg.getArgNo()); + } + + /// Return the operand index of the underlying instruction associated with + /// the function parameter number @p ArgNo or -1 if there is none. + int getCallArgOperandNo(unsigned ArgNo) const { + if (isDirectCall()) + return ArgNo; + // Add 1 for the callee encoding. + return CI.ParameterEncoding[ArgNo + 1]; + } + + /// Return the operand of the underlying instruction associated with @p Arg. + Value *getCallArgOperand(Argument &Arg) const { + return getCallArgOperand(Arg.getArgNo()); + } + + /// Return the operand of the underlying instruction associated with the + /// function parameter number @p ArgNo or nullptr if there is none. + Value *getCallArgOperand(unsigned ArgNo) const { + if (isDirectCall()) + return CS.getArgOperand(ArgNo); + // Add 1 for the callee encoding. + return CI.ParameterEncoding[ArgNo + 1] >= 0 + ? CS.getArgOperand(CI.ParameterEncoding[ArgNo + 1]) + : nullptr; + } + + /// Return the operand index of the underlying instruction associated with the + /// callee of this ACS. Only valid for callback calls! + int getCallArgOperandNoForCallee() const { + assert(isCallbackCall()); + assert(CI.ParameterEncoding.size() && CI.ParameterEncoding[0] > 0); + return CI.ParameterEncoding[0]; + } + + /// Return the pointer to function that is being called. + Value *getCalledValue() const { + if (isDirectCall()) + return CS.getCalledValue(); + return CS.getArgOperand(getCallArgOperandNoForCallee()); + } + + /// Return the function being called if this is a direct call, otherwise + /// return null (if it's an indirect call). + Function *getCalledFunction() const { + Value *V = getCalledValue(); + return V ? dyn_cast<Function>(V->stripPointerCasts()) : nullptr; + } +}; + template <> struct DenseMapInfo<CallSite> { using BaseInfo = DenseMapInfo<decltype(CallSite::I)>; @@ -713,6 +899,7 @@ public: ImmutableCallSite() = default; ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {} ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {} + ImmutableCallSite(const CallBrInst *CBI) : CallSiteBase(CBI) {} explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {} explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {} ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 49c3be960373..399c6ad521fa 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -1,9 +1,8 @@ //===- llvm/CallingConv.h - LLVM Calling Conventions ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h index 555121e928f7..f712a16dd318 100644 --- a/include/llvm/IR/Comdat.h +++ b/include/llvm/IR/Comdat.h @@ -1,9 +1,8 @@ //===- llvm/IR/Comdat.h - Comdat definitions --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 98437f8eff1f..931576651224 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -1,9 +1,8 @@ //===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -91,6 +90,10 @@ public: /// elements. bool containsUndefElement() const; + /// Return true if this is a vector constant that includes any constant + /// expressions. + bool containsConstantExpression() const; + /// Return true if evaluation of this constant could trap. This is true for /// things like constant expressions that could divide by zero. bool canTrap() const; diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index da5bba7ba141..5a5cabfd0206 100644 --- a/include/llvm/IR/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -1,9 +1,8 @@ //===- ConstantFolder.h - Constant folding helper ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -135,6 +134,10 @@ public: return ConstantExpr::getNot(C); } + Constant *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { + return ConstantExpr::get(Opc, C); + } + //===--------------------------------------------------------------------===// // Memory Instructions //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 1adda3269abc..91f3f31abe17 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -1,9 +1,8 @@ //===- ConstantRange.h - Represent a range ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -42,14 +41,25 @@ namespace llvm { class MDNode; class raw_ostream; +struct KnownBits; /// This class represents a range of values. class LLVM_NODISCARD ConstantRange { APInt Lower, Upper; + /// Create empty constant range with same bitwidth. + ConstantRange getEmpty() const { + return ConstantRange(getBitWidth(), false); + } + + /// Create full constant range with same bitwidth. + ConstantRange getFull() const { + return ConstantRange(getBitWidth(), true); + } + public: - /// Initialize a full (the default) or empty set for the specified bit width. - explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true); + /// Initialize a full or empty set for the specified bit width. + explicit ConstantRange(uint32_t BitWidth, bool isFullSet); /// Initialize a range to hold the single specified value. ConstantRange(APInt Value); @@ -59,6 +69,29 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APInt Lower, APInt Upper); + /// Create empty constant range with the given bit width. + static ConstantRange getEmpty(uint32_t BitWidth) { + return ConstantRange(BitWidth, false); + } + + /// Create full constant range with the given bit width. + static ConstantRange getFull(uint32_t BitWidth) { + return ConstantRange(BitWidth, true); + } + + /// Create non-empty constant range with the given bounds. If Lower and + /// Upper are the same, a full range is returned. + static ConstantRange getNonEmpty(APInt Lower, APInt Upper) { + if (Lower == Upper) + return getFull(Lower.getBitWidth()); + return ConstantRange(std::move(Lower), std::move(Upper)); + } + + /// Initialize a range based on a known bits constraint. The IsSigned flag + /// indicates whether the constant range should not wrap in the signed or + /// unsigned domain. + static ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned); + /// Produce the smallest range such that all values that may satisfy the given /// predicate with any value contained within Other is contained in the /// returned range. Formally, this returns a superset of @@ -91,14 +124,12 @@ public: static ConstantRange makeExactICmpRegion(CmpInst::Predicate Pred, const APInt &Other); - /// Return the largest range containing all X such that "X BinOpC Y" is - /// guaranteed not to wrap (overflow) for all Y in Other. + /// Produce the largest range containing all X such that "X BinOp Y" is + /// guaranteed not to wrap (overflow) for *all* Y in Other. However, there may + /// be *some* Y in Other for which additional X not contained in the result + /// also do not overflow. /// - /// NB! The returned set does *not* contain **all** possible values of X for - /// which "X BinOpC Y" does not wrap -- some viable values of X may be - /// missing, so you cannot use this to constrain X's range. E.g. in the - /// fourth example, "(-2) + 1" is both nsw and nuw (so the "X" could be -2), - /// but (-2) is not in the set returned. + /// NoWrapKind must be one of OBO::NoUnsignedWrap or OBO::NoSignedWrap. /// /// Examples: /// typedef OverflowingBinaryOperator OBO; @@ -106,17 +137,19 @@ public: /// MGNR(Add, [i8 1, 2), OBO::NoSignedWrap) == [-128, 127) /// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap) == [0, -1) /// MGNR(Add, [i8 0, 1), OBO::NoUnsignedWrap) == Full Set - /// MGNR(Add, [i8 1, 2), OBO::NoUnsignedWrap | OBO::NoSignedWrap) - /// == [0,INT_MAX) /// MGNR(Add, [i8 -1, 6), OBO::NoSignedWrap) == [INT_MIN+1, INT_MAX-4) /// MGNR(Sub, [i8 1, 2), OBO::NoSignedWrap) == [-127, 128) /// MGNR(Sub, [i8 1, 2), OBO::NoUnsignedWrap) == [1, 0) - /// MGNR(Sub, [i8 1, 2), OBO::NoUnsignedWrap | OBO::NoSignedWrap) - /// == [1,INT_MAX) static ConstantRange makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, const ConstantRange &Other, unsigned NoWrapKind); + /// Produce the range that contains X if and only if "X BinOp Other" does + /// not wrap. + static ConstantRange makeExactNoWrapRegion(Instruction::BinaryOps BinOp, + const APInt &Other, + unsigned NoWrapKind); + /// Set up \p Pred and \p RHS such that /// ConstantRange::makeExactICmpRegion(Pred, RHS) == *this. Return true if /// successful. @@ -138,14 +171,32 @@ public: /// Return true if this set contains no members. bool isEmptySet() const; - /// Return true if this set wraps around the top of the range. - /// For example: [100, 8). + /// Return true if this set wraps around the unsigned domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, 0) == [X, Max]: Not wrapped. bool isWrappedSet() const; - /// Return true if this set wraps around the INT_MIN of - /// its bitwidth. For example: i8 [120, 140). + /// Return true if the exclusive upper bound wraps around the unsigned + /// domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, 0): Wrapped. + bool isUpperWrapped() const; + + /// Return true if this set wraps around the signed domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, SignedMin) == [X, SignedMax]: Not wrapped. bool isSignWrappedSet() const; + /// Return true if the (exclusive) upper bound wraps around the signed + /// domain. Special cases: + /// * Empty set: Not wrapped. + /// * Full set: Not wrapped. + /// * [X, SignedMin): Wrapped. + bool isUpperSignWrapped() const; + /// Return true if the specified value is in the set. bool contains(const APInt &Val) const; @@ -170,15 +221,18 @@ public: /// Return true if this set contains exactly one member. bool isSingleElement() const { return getSingleElement() != nullptr; } - /// Return the number of elements in this set. - APInt getSetSize() const; - /// Compare set size of this range with the range CR. bool isSizeStrictlySmallerThan(const ConstantRange &CR) const; - // Compare set size of this range with Value. + /// Compare set size of this range with Value. bool isSizeLargerThan(uint64_t MaxSize) const; + /// Return true if all values in this range are negative. + bool isAllNegative() const; + + /// Return true if all values in this range are non-negative. + bool isAllNonNegative() const; + /// Return the largest unsigned value contained in the ConstantRange. APInt getUnsignedMax() const; @@ -206,20 +260,30 @@ public: /// the sets). ConstantRange difference(const ConstantRange &CR) const; - /// Return the range that results from the intersection of - /// this range with another range. The resultant range is guaranteed to - /// include all elements contained in both input ranges, and to have the - /// smallest possible set size that does so. Because there may be two - /// intersections with the same set size, A.intersectWith(B) might not - /// be equal to B.intersectWith(A). - ConstantRange intersectWith(const ConstantRange &CR) const; + /// If represented precisely, the result of some range operations may consist + /// of multiple disjoint ranges. As only a single range may be returned, any + /// range covering these disjoint ranges constitutes a valid result, but some + /// may be more useful than others depending on context. The preferred range + /// type specifies whether a range that is non-wrapping in the unsigned or + /// signed domain, or has the smallest size, is preferred. If a signedness is + /// preferred but all ranges are non-wrapping or all wrapping, then the + /// smallest set size is preferred. If there are multiple smallest sets, any + /// one of them may be returned. + enum PreferredRangeType { Smallest, Unsigned, Signed }; + + /// Return the range that results from the intersection of this range with + /// another range. If the intersection is disjoint, such that two results + /// are possible, the preferred range is determined by the PreferredRangeType. + ConstantRange intersectWith(const ConstantRange &CR, + PreferredRangeType Type = Smallest) const; /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included /// in either set before. - ConstantRange unionWith(const ConstantRange &CR) const; + ConstantRange unionWith(const ConstantRange &CR, + PreferredRangeType Type = Smallest) const; /// Return a new range representing the possible values resulting /// from an application of the specified cast operator to this range. \p @@ -301,6 +365,23 @@ public: ConstantRange udiv(const ConstantRange &Other) const; /// Return a new range representing the possible values resulting + /// from a signed division of a value in this range and a value in + /// \p Other. Division by zero and division of SignedMin by -1 are considered + /// undefined behavior, in line with IR, and do not contribute towards the + /// result. + ConstantRange sdiv(const ConstantRange &Other) const; + + /// Return a new range representing the possible values resulting + /// from an unsigned remainder operation of a value in this range and a + /// value in \p Other. + ConstantRange urem(const ConstantRange &Other) const; + + /// Return a new range representing the possible values resulting + /// from a signed remainder operation of a value in this range and a + /// value in \p Other. + ConstantRange srem(const ConstantRange &Other) const; + + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; @@ -321,9 +402,53 @@ public: /// arithmetic right shift of a value in this range and a value in \p Other. ConstantRange ashr(const ConstantRange &Other) const; + /// Perform an unsigned saturating addition of two constant ranges. + ConstantRange uadd_sat(const ConstantRange &Other) const; + + /// Perform a signed saturating addition of two constant ranges. + ConstantRange sadd_sat(const ConstantRange &Other) const; + + /// Perform an unsigned saturating subtraction of two constant ranges. + ConstantRange usub_sat(const ConstantRange &Other) const; + + /// Perform a signed saturating subtraction of two constant ranges. + ConstantRange ssub_sat(const ConstantRange &Other) const; + /// Return a new range that is the logical not of the current set. ConstantRange inverse() const; + /// Calculate absolute value range. If the original range contains signed + /// min, then the resulting range will also contain signed min. + ConstantRange abs() const; + + /// Represents whether an operation on the given constant range is known to + /// always or never overflow. + enum class OverflowResult { + /// Always overflows in the direction of signed/unsigned min value. + AlwaysOverflowsLow, + /// Always overflows in the direction of signed/unsigned max value. + AlwaysOverflowsHigh, + /// May or may not overflow. + MayOverflow, + /// Never overflows. + NeverOverflows, + }; + + /// Return whether unsigned add of the two ranges always/never overflows. + OverflowResult unsignedAddMayOverflow(const ConstantRange &Other) const; + + /// Return whether signed add of the two ranges always/never overflows. + OverflowResult signedAddMayOverflow(const ConstantRange &Other) const; + + /// Return whether unsigned sub of the two ranges always/never overflows. + OverflowResult unsignedSubMayOverflow(const ConstantRange &Other) const; + + /// Return whether signed sub of the two ranges always/never overflows. + OverflowResult signedSubMayOverflow(const ConstantRange &Other) const; + + /// Return whether unsigned mul of the two ranges always/never overflows. + OverflowResult unsignedMulMayOverflow(const ConstantRange &Other) const; + /// Print out the bounds to a stream. void print(raw_ostream &OS) const; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index afc93cd61d47..ca56e8b9328c 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -1,9 +1,8 @@ //===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 443332b1b23c..ad9a35b55414 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -1,9 +1,8 @@ //===- DIBuilder.h - Debug Information Builder ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -707,6 +706,16 @@ namespace llvm { DITemplateParameterArray TParams = nullptr, DITypeArray ThrownTypes = nullptr); + /// Create common block entry for a Fortran common block. + /// \param Scope Scope of this common block. + /// \param decl Global variable declaration. + /// \param Name The name of this common block. + /// \param File The file this common block is defined. + /// \param LineNo Line number. + DICommonBlock *createCommonBlock(DIScope *Scope, DIGlobalVariable *decl, + StringRef Name, DIFile *File, + unsigned LineNo); + /// This creates new descriptor for a namespace with the specified /// parent scope. /// \param Scope Namespace scope diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index c144d1c13c34..ac9770a15120 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -1,9 +1,8 @@ //===- llvm/DataLayout.h - Data size & alignment info -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -109,6 +108,13 @@ struct PointerAlignElem { /// generating LLVM IR is required to generate the right target data for the /// target being codegen'd to. class DataLayout { +public: + enum class FunctionPtrAlignType { + /// The function pointer alignment is independent of the function alignment. + Independent, + /// The function pointer alignment is a multiple of the function alignment. + MultipleOfFunctionAlign, + }; private: /// Defaults to false. bool BigEndian; @@ -117,6 +123,9 @@ private: unsigned StackNaturalAlign; unsigned ProgramAddrSpace; + unsigned FunctionPtrAlign; + FunctionPtrAlignType TheFunctionPtrAlignType; + enum ManglingModeT { MM_None, MM_ELF, @@ -200,6 +209,8 @@ public: BigEndian = DL.isBigEndian(); AllocaAddrSpace = DL.AllocaAddrSpace; StackNaturalAlign = DL.StackNaturalAlign; + FunctionPtrAlign = DL.FunctionPtrAlign; + TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType; ProgramAddrSpace = DL.ProgramAddrSpace; ManglingMode = DL.ManglingMode; LegalIntWidths = DL.LegalIntWidths; @@ -257,6 +268,17 @@ public: unsigned getStackAlignment() const { return StackNaturalAlign; } unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } + /// Returns the alignment of function pointers, which may or may not be + /// related to the alignment of functions. + /// \see getFunctionPtrAlignType + unsigned getFunctionPtrAlign() const { return FunctionPtrAlign; } + + /// Return the type of function pointer alignment. + /// \see getFunctionPtrAlign + FunctionPtrAlignType getFunctionPtrAlignType() const { + return TheFunctionPtrAlignType; + } + unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } bool hasMicrosoftFastStdCallMangling() const { @@ -346,10 +368,13 @@ public: return NonIntegralAddressSpaces; } - bool isNonIntegralPointerType(PointerType *PT) const { + bool isNonIntegralAddressSpace(unsigned AddrSpace) const { ArrayRef<unsigned> NonIntegralSpaces = getNonIntegralAddressSpaces(); - return find(NonIntegralSpaces, PT->getAddressSpace()) != - NonIntegralSpaces.end(); + return find(NonIntegralSpaces, AddrSpace) != NonIntegralSpaces.end(); + } + + bool isNonIntegralPointerType(PointerType *PT) const { + return isNonIntegralAddressSpace(PT->getAddressSpace()); } bool isNonIntegralPointerType(Type *Ty) const { @@ -428,6 +453,14 @@ public: return 8 * getTypeStoreSize(Ty); } + /// Returns true if no extra padding bits are needed when storing the + /// specified type. + /// + /// For example, returns false for i19 that has a 24-bit store size. + bool typeSizeEqualsStoreSize(Type *Ty) const { + return getTypeSizeInBits(Ty) == getTypeStoreSizeInBits(Ty); + } + /// Returns the offset in bytes between successive objects of the /// specified type, including alignment padding. /// diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 01178af3c9ff..171e1621889f 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -1,9 +1,8 @@ //===- DebugInfo.h - Debug Information Helpers ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def index ce117aa452aa..07e3d6bdc9e5 100644 --- a/include/llvm/IR/DebugInfoFlags.def +++ b/include/llvm/IR/DebugInfoFlags.def @@ -1,9 +1,8 @@ //===- llvm/IR/DebugInfoFlags.def - Debug info flag definitions -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -51,12 +50,12 @@ HANDLE_DI_FLAG((3 << 16), VirtualInheritance) HANDLE_DI_FLAG((1 << 18), IntroducedVirtual) HANDLE_DI_FLAG((1 << 19), BitField) HANDLE_DI_FLAG((1 << 20), NoReturn) -HANDLE_DI_FLAG((1 << 21), MainSubprogram) +HANDLE_DI_FLAG((1 << 21), ArgumentNotModified) HANDLE_DI_FLAG((1 << 22), TypePassByValue) HANDLE_DI_FLAG((1 << 23), TypePassByReference) HANDLE_DI_FLAG((1 << 24), EnumClass) HANDLE_DI_FLAG((1 << 25), Thunk) -HANDLE_DI_FLAG((1 << 26), Trivial) +HANDLE_DI_FLAG((1 << 26), NonTrivial) HANDLE_DI_FLAG((1 << 27), BigEndian) HANDLE_DI_FLAG((1 << 28), LittleEndian) HANDLE_DI_FLAG((1 << 29), AllCallsDescribed) @@ -85,11 +84,15 @@ HANDLE_DISP_FLAG(2u, PureVirtual) HANDLE_DISP_FLAG((1u << 2), LocalToUnit) HANDLE_DISP_FLAG((1u << 3), Definition) HANDLE_DISP_FLAG((1u << 4), Optimized) +HANDLE_DISP_FLAG((1u << 5), Pure) +HANDLE_DISP_FLAG((1u << 6), Elemental) +HANDLE_DISP_FLAG((1u << 7), Recursive) +HANDLE_DISP_FLAG((1u << 8), MainSubprogram) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 4), Largest) +HANDLE_DISP_FLAG((1 << 8), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index a461d1bd4fe8..9dc6dfbb0f68 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1,9 +1,8 @@ //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -61,44 +60,6 @@ namespace llvm { -/// Holds a subclass of DINode. -/// -/// FIXME: This class doesn't currently make much sense. Previously it was a -/// union beteen MDString (for ODR-uniqued types) and things like DIType. To -/// support CodeView work, it wasn't deleted outright when MDString-based type -/// references were deleted; we'll soon need a similar concept for CodeView -/// DITypeIndex. -template <class T> class TypedDINodeRef { - const Metadata *MD = nullptr; - -public: - TypedDINodeRef() = default; - TypedDINodeRef(std::nullptr_t) {} - TypedDINodeRef(const T *MD) : MD(MD) {} - - explicit TypedDINodeRef(const Metadata *MD) : MD(MD) { - assert((!MD || isa<T>(MD)) && "Expected valid type ref"); - } - - template <class U> - TypedDINodeRef( - const TypedDINodeRef<U> &X, - typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = - nullptr) - : MD(X) {} - - operator Metadata *() const { return const_cast<Metadata *>(MD); } - - T *resolve() const { return const_cast<T *>(cast_or_null<T>(MD)); } - - bool operator==(const TypedDINodeRef<T> &X) const { return MD == X.MD; } - bool operator!=(const TypedDINodeRef<T> &X) const { return MD != X.MD; } -}; - -using DINodeRef = TypedDINodeRef<DINode>; -using DIScopeRef = TypedDINodeRef<DIScope>; -using DITypeRef = TypedDINodeRef<DIType>; - class DITypeRefArray { const MDTuple *N = nullptr; @@ -115,17 +76,19 @@ public: // FIXME: Fix callers and remove condition on N. unsigned size() const { return N ? N->getNumOperands() : 0u; } - DITypeRef operator[](unsigned I) const { return DITypeRef(N->getOperand(I)); } + DIType *operator[](unsigned I) const { + return cast_or_null<DIType>(N->getOperand(I)); + } - class iterator : std::iterator<std::input_iterator_tag, DITypeRef, - std::ptrdiff_t, void, DITypeRef> { + class iterator : std::iterator<std::input_iterator_tag, DIType *, + std::ptrdiff_t, void, DIType *> { MDNode::op_iterator I = nullptr; public: iterator() = default; explicit iterator(MDNode::op_iterator I) : I(I) {} - DITypeRef operator*() const { return DITypeRef(*I); } + DIType *operator*() const { return cast_or_null<DIType>(*I); } iterator &operator++() { ++I; @@ -228,6 +191,7 @@ public: case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DITemplateTypeParameterKind: case DITemplateValueParameterKind: case DIGlobalVariableKind: @@ -241,18 +205,6 @@ public: } }; -template <class T> struct simplify_type<const TypedDINodeRef<T>> { - using SimpleType = Metadata *; - - static SimpleType getSimplifiedValue(const TypedDINodeRef<T> &MD) { - return MD; - } -}; - -template <class T> -struct simplify_type<TypedDINodeRef<T>> - : simplify_type<const TypedDINodeRef<T>> {}; - /// Generic tagged DWARF-like metadata node. /// /// An un-specialized DWARF-like metadata node. The first operand is a @@ -459,7 +411,7 @@ public: inline Optional<StringRef> getSource() const; StringRef getName() const; - DIScopeRef getScope() const; + DIScope *getScope() const; /// Return the raw underlying file. /// @@ -486,6 +438,7 @@ public: case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: + case DICommonBlockKind: case DIModuleKind: return true; } @@ -672,7 +625,7 @@ public: uint64_t getOffsetInBits() const { return OffsetInBits; } DIFlags getFlags() const { return Flags; } - DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } StringRef getName() const { return getStringOperand(2); } @@ -817,14 +770,12 @@ class DIDerivedType : public DIType { DWARFAddressSpace(DWARFAddressSpace) {} ~DIDerivedType() = default; - static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, DIFile *File, unsigned Line, - DIScopeRef Scope, DITypeRef BaseType, - uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, - Optional<unsigned> DWARFAddressSpace, - DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate = true) { + static DIDerivedType * + getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, + unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, + Optional<unsigned> DWARFAddressSpace, DIFlags Flags, + Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); @@ -858,7 +809,7 @@ public: ExtraData)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, - DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, + DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, DIFlags Flags, Metadata *ExtraData = nullptr), @@ -869,7 +820,7 @@ public: TempDIDerivedType clone() const { return cloneImpl(); } /// Get the base type this is derived from. - DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } Metadata *getRawBaseType() const { return getOperand(3); } /// \returns The DWARF address space of the memory pointed to or referenced by @@ -889,9 +840,9 @@ public: /// Get casted version of extra data. /// @{ - DITypeRef getClassType() const { + DIType *getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return DITypeRef(getExtraData()); + return cast_or_null<DIType>(getExtraData()); } DIObjCProperty *getObjCProperty() const { @@ -963,12 +914,12 @@ class DICompositeType : public DIType { static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, DIScopeRef Scope, DITypeRef BaseType, - uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, - DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, - StringRef Identifier, DIDerivedType *Discriminator, - StorageType Storage, bool ShouldCreate = true) { + unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, + DITemplateParameterArray TemplateParams, StringRef Identifier, + DIDerivedType *Discriminator, StorageType Storage, + bool ShouldCreate = true) { return getImpl( Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), @@ -995,12 +946,13 @@ class DICompositeType : public DIType { public: DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, - DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, - DITypeRef VTableHolder, + DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, + DINodeArray Elements, unsigned RuntimeLang, + DIType *VTableHolder, DITemplateParameterArray TemplateParams = nullptr, - StringRef Identifier = "", DIDerivedType *Discriminator = nullptr), + StringRef Identifier = "", + DIDerivedType *Discriminator = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier, Discriminator)) @@ -1053,11 +1005,13 @@ public: unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator); - DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } DINodeArray getElements() const { return cast_or_null<MDTuple>(getRawElements()); } - DITypeRef getVTableHolder() const { return DITypeRef(getRawVTableHolder()); } + DIType *getVTableHolder() const { + return cast_or_null<DIType>(getRawVTableHolder()); + } DITemplateParameterArray getTemplateParams() const { return cast_or_null<MDTuple>(getRawTemplateParams()); } @@ -1087,7 +1041,7 @@ public: replaceOperandWith(4, Elements.get()); } - void replaceVTableHolder(DITypeRef VTableHolder) { + void replaceVTableHolder(DIType *VTableHolder) { replaceOperandWith(5, VTableHolder); } @@ -1541,9 +1495,6 @@ public: /// /// For precise control over the data being encoded in the discriminator, /// use encodeDiscriminator/decodeDiscriminator. - /// - /// Use {get|set}BaseDiscriminator and cloneWithDuplicationFactor after reading - /// their documentation, as their behavior has side-effects. inline unsigned getDiscriminator() const; @@ -1554,7 +1505,7 @@ public: /// base discriminator is set in the new DILocation, the other encoded values /// are elided. /// If the discriminator cannot be encoded, the function returns None. - inline Optional<const DILocation *> setBaseDiscriminator(unsigned BD) const; + inline Optional<const DILocation *> cloneWithBaseDiscriminator(unsigned BD) const; /// Returns the duplication factor stored in the discriminator, or 1 if no /// duplication factor (or 0) is encoded. @@ -1570,7 +1521,7 @@ public: /// duplication factor encoded in the discriminator. The current duplication /// factor is as defined by getDuplicationFactor(). /// Returns None if encoding failed. - inline Optional<const DILocation *> cloneWithDuplicationFactor(unsigned DF) const; + inline Optional<const DILocation *> cloneByMultiplyingDuplicationFactor(unsigned DF) const; /// When two instructions are combined into a single instruction we also /// need to combine the original locations into a single location. @@ -1594,10 +1545,11 @@ public: return getUnsignedFromPrefixEncoding(D); } - /// Raw encoding of the discriminator. APIs such as setBaseDiscriminator or - /// cloneWithDuplicationFactor have certain side-effects. This API, in - /// conjunction with cloneWithDiscriminator, may be used to encode precisely - /// the values provided. \p BD: base discriminator \p DF: duplication factor + /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor + /// have certain special case behavior (e.g. treating empty duplication factor + /// as the value '1'). + /// This API, in conjunction with cloneWithDiscriminator, may be used to encode + /// the raw values provided. \p BD: base discriminator \p DF: duplication factor /// \p CI: copy index /// The return is None if the values cannot be encoded in 32 bits - for /// example, values for BD or DF larger than 12 bits. Otherwise, the return @@ -1638,9 +1590,6 @@ public: }; /// Subprogram description. -/// -/// TODO: Remove DisplayName. It's always equal to Name. -/// TODO: Split up flags. class DISubprogram : public DILocalScope { friend class LLVMContextImpl; friend class MDNode; @@ -1678,7 +1627,8 @@ public: // Helper for converting old bitfields to new flags word. static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, - unsigned Virtuality = SPFlagNonvirtual) { + unsigned Virtuality = SPFlagNonvirtual, + bool IsMainSubprogram = false) { // We're assuming virtuality is the low-order field. static_assert( int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && @@ -1688,7 +1638,8 @@ public: (Virtuality & SPFlagVirtuality) | (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | (IsDefinition ? SPFlagDefinition : SPFlagZero) | - (IsOptimized ? SPFlagOptimized : SPFlagZero)); + (IsOptimized ? SPFlagOptimized : SPFlagZero) | + (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); } private: @@ -1707,9 +1658,9 @@ private: ~DISubprogram() = default; static DISubprogram * - getImpl(LLVMContext &Context, DIScopeRef Scope, StringRef Name, + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned Line, - DISubroutineType *Type, unsigned ScopeLine, DITypeRef ContainingType, + DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, @@ -1744,9 +1695,9 @@ private: public: DEFINE_MDNODE_GET( DISubprogram, - (DIScopeRef Scope, StringRef Name, StringRef LinkageName, DIFile *File, + (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned Line, DISubroutineType *Type, unsigned ScopeLine, - DITypeRef ContainingType, unsigned VirtualIndex, int ThisAdjustment, + DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, @@ -1787,6 +1738,7 @@ public: bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } + bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } bool isArtificial() const { return getFlags() & FlagArtificial; } bool isPrivate() const { @@ -1803,7 +1755,9 @@ public: bool areAllCallsDescribed() const { return getFlags() & FlagAllCallsDescribed; } - bool isMainSubprogram() const { return getFlags() & FlagMainSubprogram; } + bool isPure() const { return getSPFlags() & SPFlagPure; } + bool isElemental() const { return getSPFlags() & SPFlagElemental; } + bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } /// Check if this is reference-qualified. /// @@ -1827,7 +1781,7 @@ public: // Returns true if this subprogram is a thunk generated by the compiler. bool isThunk() const { return getFlags() & FlagThunk; } - DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } StringRef getName() const { return getStringOperand(2); } StringRef getLinkageName() const { return getStringOperand(3); } @@ -1835,8 +1789,8 @@ public: DISubroutineType *getType() const { return cast_or_null<DISubroutineType>(getRawType()); } - DITypeRef getContainingType() const { - return DITypeRef(getRawContainingType()); + DIType *getContainingType() const { + return cast_or_null<DIType>(getRawContainingType()); } DICompileUnit *getUnit() const { @@ -2039,15 +1993,17 @@ unsigned DILocation::getCopyIdentifier() const { return getCopyIdentifierFromDiscriminator(getDiscriminator()); } -Optional<const DILocation *> DILocation::setBaseDiscriminator(unsigned D) const { - if (D == 0) +Optional<const DILocation *> DILocation::cloneWithBaseDiscriminator(unsigned D) const { + unsigned BD, DF, CI; + decodeDiscriminator(getDiscriminator(), BD, DF, CI); + if (D == BD) return this; - if (D > 0xfff) - return None; - return cloneWithDiscriminator(encodeComponent(D)); + if (Optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) + return cloneWithDiscriminator(*Encoded); + return None; } -Optional<const DILocation *> DILocation::cloneWithDuplicationFactor(unsigned DF) const { +Optional<const DILocation *> DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { DF *= getDuplicationFactor(); if (DF <= 1) return this; @@ -2179,7 +2135,7 @@ protected: public: StringRef getName() const { return getStringOperand(0); } - DITypeRef getType() const { return DITypeRef(getRawType()); } + DIType *getType() const { return cast_or_null<DIType>(getRawType()); } MDString *getRawName() const { return getOperandAs<MDString>(0); } Metadata *getRawType() const { return getOperand(1); } @@ -2201,7 +2157,7 @@ class DITemplateTypeParameter : public DITemplateParameter { ~DITemplateTypeParameter() = default; static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - DITypeRef Type, StorageType Storage, + DIType *Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, ShouldCreate); @@ -2215,7 +2171,7 @@ class DITemplateTypeParameter : public DITemplateParameter { } public: - DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DITypeRef Type), + DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DIType *Type), (Name, Type)) DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type), (Name, Type)) @@ -2238,7 +2194,7 @@ class DITemplateValueParameter : public DITemplateParameter { ~DITemplateValueParameter() = default; static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, DITypeRef Type, + StringRef Name, DIType *Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, @@ -2255,8 +2211,9 @@ class DITemplateValueParameter : public DITemplateParameter { } public: - DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, StringRef Name, - DITypeRef Type, Metadata *Value), + DEFINE_MDNODE_GET(DITemplateValueParameter, + (unsigned Tag, StringRef Name, DIType *Type, + Metadata *Value), (Tag, Name, Type, Value)) DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value), @@ -2288,7 +2245,7 @@ public: DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } StringRef getName() const { return getStringOperand(1); } DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } - DITypeRef getType() const { return DITypeRef(getRawType()); } + DIType *getType() const { return cast_or_null<DIType>(getRawType()); } uint32_t getAlignInBits() const { return AlignInBits; } uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } /// Determines the size of the variable's type. @@ -2297,7 +2254,7 @@ public: /// Return the signedness of this variable's type, or None if this type is /// neither signed nor unsigned. Optional<DIBasicType::Signedness> getSignedness() const { - if (auto *BT = dyn_cast<DIBasicType>(getType().resolve())) + if (auto *BT = dyn_cast<DIBasicType>(getType())) return BT->getSignedness(); return None; } @@ -2504,6 +2461,13 @@ public: /// Return whether this is a piece of an aggregate variable. bool isFragment() const { return getFragmentInfo().hasValue(); } + /// Return whether this is an implicit location description. + bool isImplicit() const; + + /// Return whether the location is computed on the expression stack, meaning + /// it cannot be a simple register location. + bool isComplex() const; + /// Append \p Ops with operations to apply the \p Offset. static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); @@ -2511,20 +2475,32 @@ public: /// return true with an offset of zero. bool extractIfOffset(int64_t &Offset) const; - /// Constants for DIExpression::prepend. - enum { NoDeref = false, WithDeref = true, WithStackValue = true }; + /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF + /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address + /// Space>. + static const DIExpression *extractAddressClass(const DIExpression *Expr, + unsigned &AddrClass); + + /// Used for DIExpression::prepend. + enum PrependOps : uint8_t { + ApplyOffset = 0, + DerefBefore = 1 << 0, + DerefAfter = 1 << 1, + StackValue = 1 << 2, + EntryValue = 1 << 3 + }; /// Prepend \p DIExpr with a deref and offset operation and optionally turn it - /// into a stack value. - static DIExpression *prepend(const DIExpression *Expr, bool DerefBefore, - int64_t Offset = 0, bool DerefAfter = false, - bool StackValue = false); + /// into a stack value or/and an entry value. + static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, + int64_t Offset = 0); /// Prepend \p DIExpr with the given opcodes and optionally turn it into a /// stack value. static DIExpression *prependOpcodes(const DIExpression *Expr, SmallVectorImpl<uint64_t> &Ops, - bool StackValue = false); + bool StackValue = false, + bool EntryValue = false); /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the /// returned expression is a stack value only if \p DIExpr is a stack value. @@ -2553,17 +2529,14 @@ public: createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits); - /// Determine the relative position of the fragments described by this - /// DIExpression and \p Other. + /// Determine the relative position of the fragments passed in. /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, /// 1 if this is entirely after Other. - int fragmentCmp(const DIExpression *Other) const { - auto Fragment1 = *getFragmentInfo(); - auto Fragment2 = *Other->getFragmentInfo(); - unsigned l1 = Fragment1.OffsetInBits; - unsigned l2 = Fragment2.OffsetInBits; - unsigned r1 = l1 + Fragment1.SizeInBits; - unsigned r2 = l2 + Fragment2.SizeInBits; + static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { + uint64_t l1 = A.OffsetInBits; + uint64_t l2 = B.OffsetInBits; + uint64_t r1 = l1 + A.SizeInBits; + uint64_t r2 = l2 + B.SizeInBits; if (r1 <= l2) return -1; else if (r2 <= l1) @@ -2572,12 +2545,59 @@ public: return 0; } + /// Check if fragments overlap between a pair of FragmentInfos. + static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { + return fragmentCmp(A, B) == 0; + } + + /// Determine the relative position of the fragments described by this + /// DIExpression and \p Other. Calls static fragmentCmp implementation. + int fragmentCmp(const DIExpression *Other) const { + auto Fragment1 = *getFragmentInfo(); + auto Fragment2 = *Other->getFragmentInfo(); + return fragmentCmp(Fragment1, Fragment2); + } + /// Check if fragments overlap between this DIExpression and \p Other. bool fragmentsOverlap(const DIExpression *Other) const { if (!isFragment() || !Other->isFragment()) return true; return fragmentCmp(Other) == 0; } + + /// Check if the expression consists of exactly one entry value operand. + /// (This is the only configuration of entry values that is supported.) + bool isEntryValue() const { + return getNumElements() > 0 && + getElement(0) == dwarf::DW_OP_entry_value; + } +}; + +inline bool operator==(const DIExpression::FragmentInfo &A, + const DIExpression::FragmentInfo &B) { + return std::tie(A.SizeInBits, A.OffsetInBits) == + std::tie(B.SizeInBits, B.OffsetInBits); +} + +inline bool operator<(const DIExpression::FragmentInfo &A, + const DIExpression::FragmentInfo &B) { + return std::tie(A.SizeInBits, A.OffsetInBits) < + std::tie(B.SizeInBits, B.OffsetInBits); +} + +template <> struct DenseMapInfo<DIExpression::FragmentInfo> { + using FragInfo = DIExpression::FragmentInfo; + static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); + + static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } + + static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } + + static unsigned getHashValue(const FragInfo &Frag) { + return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); + } + + static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } }; /// Global variables. @@ -2599,7 +2619,7 @@ class DIGlobalVariable : public DIVariable { static DIGlobalVariable * getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, - StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type, + StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { @@ -2626,7 +2646,7 @@ class DIGlobalVariable : public DIVariable { public: DEFINE_MDNODE_GET(DIGlobalVariable, (DIScope * Scope, StringRef Name, StringRef LinkageName, - DIFile *File, unsigned Line, DITypeRef Type, + DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, uint32_t AlignInBits), @@ -2663,6 +2683,65 @@ public: } }; +class DICommonBlock : public DIScope { + unsigned LineNo; + + friend class LLVMContextImpl; + friend class MDNode; + + DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, + ArrayRef<Metadata *> Ops) + : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, + Ops), LineNo(LineNo) {} + + static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, + DIGlobalVariable *Decl, StringRef Name, + DIFile *File, unsigned LineNo, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), + File, LineNo, Storage, ShouldCreate); + } + static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *Decl, MDString *Name, Metadata *File, + unsigned LineNo, + StorageType Storage, bool ShouldCreate = true); + + TempDICommonBlock cloneImpl() const { + return getTemporary(getContext(), getScope(), getDecl(), getName(), + getFile(), getLineNo()); + } + +public: + DEFINE_MDNODE_GET(DICommonBlock, + (DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, + DIFile *File, unsigned LineNo), + (Scope, Decl, Name, File, LineNo)) + DEFINE_MDNODE_GET(DICommonBlock, + (Metadata *Scope, Metadata *Decl, MDString *Name, + Metadata *File, unsigned LineNo), + (Scope, Decl, Name, File, LineNo)) + + TempDICommonBlock clone() const { return cloneImpl(); } + + DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } + DIGlobalVariable *getDecl() const { + return cast_or_null<DIGlobalVariable>(getRawDecl()); + } + StringRef getName() const { return getStringOperand(2); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + unsigned getLineNo() const { return LineNo; } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawDecl() const { return getOperand(1); } + MDString *getRawName() const { return getOperandAs<MDString>(2); } + Metadata *getRawFile() const { return getOperand(3); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICommonBlockKind; + } +}; + /// Local variable. /// /// TODO: Split up flags. @@ -2684,7 +2763,7 @@ class DILocalVariable : public DIVariable { static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, DIFile *File, unsigned Line, - DITypeRef Type, unsigned Arg, DIFlags Flags, + DIType *Type, unsigned Arg, DIFlags Flags, uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, @@ -2705,8 +2784,8 @@ class DILocalVariable : public DIVariable { public: DEFINE_MDNODE_GET(DILocalVariable, (DILocalScope * Scope, StringRef Name, DIFile *File, - unsigned Line, DITypeRef Type, unsigned Arg, - DIFlags Flags, uint32_t AlignInBits), + unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, + uint32_t AlignInBits), (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits)) DEFINE_MDNODE_GET(DILocalVariable, (Metadata * Scope, MDString *Name, Metadata *File, @@ -2730,6 +2809,11 @@ public: bool isArtificial() const { return getFlags() & FlagArtificial; } bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + /// Check that an argument is unmodified. + bool isNotModified() const { return getFlags() & FlagArgumentNotModified; } + /// Set the flag if an argument is unmodified. + void setIsNotModified() { Flags |= FlagArgumentNotModified; } + /// Check that a location is valid for this variable. /// /// Check that \c DL exists, is in the same subprogram, and has the same @@ -2831,7 +2915,7 @@ class DIObjCProperty : public DINode { static DIObjCProperty * getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, unsigned Attributes, - DITypeRef Type, StorageType Storage, bool ShouldCreate = true) { + DIType *Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, getCanonicalMDString(Context, GetterName), getCanonicalMDString(Context, SetterName), Attributes, Type, @@ -2853,7 +2937,7 @@ public: DEFINE_MDNODE_GET(DIObjCProperty, (StringRef Name, DIFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, - unsigned Attributes, DITypeRef Type), + unsigned Attributes, DIType *Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) DEFINE_MDNODE_GET(DIObjCProperty, @@ -2871,7 +2955,7 @@ public: DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } StringRef getGetterName() const { return getStringOperand(2); } StringRef getSetterName() const { return getStringOperand(3); } - DITypeRef getType() const { return DITypeRef(getRawType()); } + DIType *getType() const { return cast_or_null<DIType>(getRawType()); } StringRef getFilename() const { if (auto *F = getFile()) @@ -2915,8 +2999,8 @@ class DIImportedEntity : public DINode { ~DIImportedEntity() = default; static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - DIScope *Scope, DINodeRef Entity, - DIFile *File, unsigned Line, StringRef Name, + DIScope *Scope, DINode *Entity, DIFile *File, + unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, Entity, File, Line, @@ -2935,8 +3019,8 @@ class DIImportedEntity : public DINode { public: DEFINE_MDNODE_GET(DIImportedEntity, - (unsigned Tag, DIScope *Scope, DINodeRef Entity, - DIFile *File, unsigned Line, StringRef Name = ""), + (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, + unsigned Line, StringRef Name = ""), (Tag, Scope, Entity, File, Line, Name)) DEFINE_MDNODE_GET(DIImportedEntity, (unsigned Tag, Metadata *Scope, Metadata *Entity, @@ -2947,7 +3031,7 @@ public: unsigned getLine() const { return Line; } DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } - DINodeRef getEntity() const { return DINodeRef(getRawEntity()); } + DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 4f0d7f51b5f9..780d17a33661 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -1,9 +1,8 @@ //===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 9526d6287d2f..3c1d4278905f 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -1,9 +1,8 @@ //===- llvm/DerivedTypes.h - Classes for handling data types ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -24,6 +23,7 @@ #include "llvm/IR/Type.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ScalableSize.h" #include <cassert> #include <cstdint> @@ -158,6 +158,38 @@ unsigned Type::getFunctionNumParams() const { return cast<FunctionType>(this)->getNumParams(); } +/// A handy container for a FunctionType+Callee-pointer pair, which can be +/// passed around as a single entity. This assists in replacing the use of +/// PointerType::getElementType() to access the function's type, since that's +/// slated for removal as part of the [opaque pointer types] project. +class FunctionCallee { +public: + // Allow implicit conversion from types which have a getFunctionType member + // (e.g. Function and InlineAsm). + template <typename T, typename U = decltype(&T::getFunctionType)> + FunctionCallee(T *Fn) + : FnTy(Fn ? Fn->getFunctionType() : nullptr), Callee(Fn) {} + + FunctionCallee(FunctionType *FnTy, Value *Callee) + : FnTy(FnTy), Callee(Callee) { + assert((FnTy == nullptr) == (Callee == nullptr)); + } + + FunctionCallee(std::nullptr_t) {} + + FunctionCallee() = default; + + FunctionType *getFunctionType() { return FnTy; } + + Value *getCallee() { return Callee; } + + explicit operator bool() { return Callee; } + +private: + FunctionType *FnTy = nullptr; + Value *Callee = nullptr; +}; + /// Common super class of ArrayType, StructType and VectorType. class CompositeType : public Type { protected: @@ -356,6 +388,8 @@ public: SequentialType(const SequentialType &) = delete; SequentialType &operator=(const SequentialType &) = delete; + /// For scalable vectors, this will return the minimum number of elements + /// in the vector. uint64_t getNumElements() const { return NumElements; } Type *getElementType() const { return ContainedType; } @@ -391,14 +425,37 @@ uint64_t Type::getArrayNumElements() const { /// Class to represent vector types. class VectorType : public SequentialType { - VectorType(Type *ElType, unsigned NumEl); + /// A fully specified VectorType is of the form <vscale x n x Ty>. 'n' is the + /// minimum number of elements of type Ty contained within the vector, and + /// 'vscale x' indicates that the total element count is an integer multiple + /// of 'n', where the multiple is either guaranteed to be one, or is + /// statically unknown at compile time. + /// + /// If the multiple is known to be 1, then the extra term is discarded in + /// textual IR: + /// + /// <4 x i32> - a vector containing 4 i32s + /// <vscale x 4 x i32> - a vector containing an unknown integer multiple + /// of 4 i32s + + VectorType(Type *ElType, unsigned NumEl, bool Scalable = false); + VectorType(Type *ElType, ElementCount EC); + + // If true, the total number of elements is an unknown multiple of the + // minimum 'NumElements' from SequentialType. Otherwise the total number + // of elements is exactly equal to 'NumElements'. + bool Scalable; public: VectorType(const VectorType &) = delete; VectorType &operator=(const VectorType &) = delete; /// This static method is the primary way to construct an VectorType. - static VectorType *get(Type *ElementType, unsigned NumElements); + static VectorType *get(Type *ElementType, ElementCount EC); + static VectorType *get(Type *ElementType, unsigned NumElements, + bool Scalable = false) { + return VectorType::get(ElementType, {NumElements, Scalable}); + } /// This static method gets a VectorType with the same number of elements as /// the input type, and the element type is an integer type of the same width @@ -407,7 +464,7 @@ public: unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); assert(EltBits && "Element size must be of a non-zero size"); Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); - return VectorType::get(EltTy, VTy->getNumElements()); + return VectorType::get(EltTy, VTy->getElementCount()); } /// This static method is like getInteger except that the element types are @@ -415,7 +472,7 @@ public: static VectorType *getExtendedElementVectorType(VectorType *VTy) { unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); - return VectorType::get(EltTy, VTy->getNumElements()); + return VectorType::get(EltTy, VTy->getElementCount()); } /// This static method is like getInteger except that the element types are @@ -425,29 +482,45 @@ public: assert((EltBits & 1) == 0 && "Cannot truncate vector element with odd bit-width"); Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); - return VectorType::get(EltTy, VTy->getNumElements()); + return VectorType::get(EltTy, VTy->getElementCount()); } /// This static method returns a VectorType with half as many elements as the /// input type and the same element type. static VectorType *getHalfElementsVectorType(VectorType *VTy) { - unsigned NumElts = VTy->getNumElements(); - assert ((NumElts & 1) == 0 && + auto EltCnt = VTy->getElementCount(); + assert ((EltCnt.Min & 1) == 0 && "Cannot halve vector with odd number of elements."); - return VectorType::get(VTy->getElementType(), NumElts/2); + return VectorType::get(VTy->getElementType(), EltCnt/2); } /// This static method returns a VectorType with twice as many elements as the /// input type and the same element type. static VectorType *getDoubleElementsVectorType(VectorType *VTy) { - unsigned NumElts = VTy->getNumElements(); - return VectorType::get(VTy->getElementType(), NumElts*2); + auto EltCnt = VTy->getElementCount(); + assert((VTy->getNumElements() * 2ull) <= UINT_MAX && + "Too many elements in vector"); + return VectorType::get(VTy->getElementType(), EltCnt*2); } /// Return true if the specified type is valid as a element type. static bool isValidElementType(Type *ElemTy); - /// Return the number of bits in the Vector type. + /// Return an ElementCount instance to represent the (possibly scalable) + /// number of elements in the vector. + ElementCount getElementCount() const { + uint64_t MinimumEltCnt = getNumElements(); + assert(MinimumEltCnt <= UINT_MAX && "Too many elements in vector"); + return { (unsigned)MinimumEltCnt, Scalable }; + } + + /// Returns whether or not this is a scalable vector (meaning the total + /// element count is a multiple of the minimum). + bool isScalable() const { + return Scalable; + } + + /// Return the minimum number of bits in the Vector type. /// Returns zero when the vector is a vector of pointers. unsigned getBitWidth() const { return getNumElements() * getElementType()->getPrimitiveSizeInBits(); @@ -463,6 +536,10 @@ unsigned Type::getVectorNumElements() const { return cast<VectorType>(this)->getNumElements(); } +bool Type::getVectorIsScalable() const { + return cast<VectorType>(this)->isScalable(); +} + /// Class to represent pointers. class PointerType : public Type { explicit PointerType(Type *ElType, unsigned AddrSpace); diff --git a/include/llvm/IR/DerivedUser.h b/include/llvm/IR/DerivedUser.h index 67c483d3c497..a25d316c2d60 100644 --- a/include/llvm/IR/DerivedUser.h +++ b/include/llvm/IR/DerivedUser.h @@ -1,9 +1,8 @@ //===- DerivedUser.h - Base for non-IR Users --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/DiagnosticHandler.h b/include/llvm/IR/DiagnosticHandler.h index 51873bea3d41..55e5e5975808 100644 --- a/include/llvm/IR/DiagnosticHandler.h +++ b/include/llvm/IR/DiagnosticHandler.h @@ -1,9 +1,8 @@ -//===- DiagnosticHandler.h - DiagnosticHandler class for LLVM -*- C++ ---*-===// +//===- DiagnosticHandler.h - DiagnosticHandler class for LLVM ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // Base DiagnosticHandler class declaration. Derive from this class to provide diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 3a55a7dca7f4..373663289dbd 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -1,9 +1,8 @@ //===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -466,12 +465,15 @@ public: virtual bool isEnabled() const = 0; StringRef getPassName() const { return PassName; } + StringRef getRemarkName() const { return RemarkName; } std::string getMsg() const; Optional<uint64_t> getHotness() const { return Hotness; } void setHotness(Optional<uint64_t> H) { Hotness = H; } bool isVerbose() const { return IsVerbose; } + ArrayRef<Argument> getArgs() const { return Args; } + static bool classof(const DiagnosticInfo *DI) { return (DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark) || @@ -501,7 +503,7 @@ protected: const char *PassName; /// Textual identifier for the remark (single-word, camel-case). Can be used - /// by external tools reading the YAML output file for optimization remarks to + /// by external tools reading the output file for optimization remarks to /// identify the remark. StringRef RemarkName; @@ -519,8 +521,6 @@ protected: /// the optimization records and not in the remark printed in the compiler /// output. int FirstExtraArgIndex = -1; - - friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>; }; /// Allow the insertion operator to return the actual remark type rather than a @@ -1002,12 +1002,6 @@ public: void print(DiagnosticPrinter &DP) const override; }; -namespace yaml { -template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> { - static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag); -}; -} // namespace yaml - } // end namespace llvm #endif // LLVM_IR_DIAGNOSTICINFO_H diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h index 25c47cdd1a12..102932ceefa5 100644 --- a/include/llvm/IR/DiagnosticPrinter.h +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -1,9 +1,8 @@ //===- llvm/Support/DiagnosticPrinter.h - Diagnostic Printer ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index f7da47d07663..fef1c6abf8c2 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -1,9 +1,8 @@ //===- Dominators.h - Dominator Info Calculation ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 630f47e8bb57..7fa61e12f431 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -1,9 +1,8 @@ //===- llvm/Function.h - Class to represent a single function ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -297,15 +296,18 @@ public: /// Get the entry count for this function. /// - /// Entry count is the number of times the function was executed based on - /// pgo data. - ProfileCount getEntryCount() const; + /// Entry count is the number of times the function was executed. + /// When AllowSynthetic is false, only pgo_data will be returned. + ProfileCount getEntryCount(bool AllowSynthetic = false) const; /// Return true if the function is annotated with profile data. /// /// Presence of entry counts from a profile run implies the function has - /// profile annotations. - bool hasProfileData() const { return getEntryCount().hasValue(); } + /// profile annotations. If IncludeSynthetic is false, only return true + /// when the profile data is real. + bool hasProfileData(bool IncludeSynthetic = false) const { + return getEntryCount(IncludeSynthetic).hasValue(); + } /// Returns the set of GUIDs that needs to be imported to the function for /// sample PGO, to enable the same inlines as the profiled optimized binary. @@ -399,6 +401,11 @@ public: return getAttributes().hasParamAttribute(ArgNo, Kind); } + /// gets the specified attribute from the list of attributes. + Attribute getParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const { + return getAttributes().getParamAttr(ArgNo, Kind); + } + /// gets the attribute from the list of attributes. Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { return AttributeSets.getAttribute(i, Kind); @@ -429,6 +436,12 @@ public: return AttributeSets.getParamAlignment(ArgNo); } + /// Extract the byval type for a parameter. + Type *getParamByValType(unsigned ArgNo) const { + Type *Ty = AttributeSets.getParamByValType(ArgNo); + return Ty ? Ty : (arg_begin() + ArgNo)->getType()->getPointerElementType(); + } + /// Extract the number of dereferenceable bytes for a call or /// parameter (0=unknown). /// @param i AttributeList index, referring to a return value or argument. @@ -551,6 +564,14 @@ public: addFnAttr(Attribute::Speculatable); } + /// Determine if the call might deallocate memory. + bool doesNotFreeMemory() const { + return onlyReadsMemory() || hasFnAttribute(Attribute::NoFree); + } + void setDoesNotFreeMemory() { + addFnAttr(Attribute::NoFree); + } + /// Determine if the function is known not to recurse, directly or /// indirectly. bool doesNotRecurse() const { @@ -591,12 +612,15 @@ public: addAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); } + /// Do not optimize this function (-O0). + bool hasOptNone() const { return hasFnAttribute(Attribute::OptimizeNone); } + /// Optimize this function for minimum size (-Oz). - bool optForMinSize() const { return hasFnAttribute(Attribute::MinSize); } + bool hasMinSize() const { return hasFnAttribute(Attribute::MinSize); } /// Optimize this function for size (-Os) or minimum size (-Oz). - bool optForSize() const { - return hasFnAttribute(Attribute::OptimizeForSize) || optForMinSize(); + bool hasOptSize() const { + return hasFnAttribute(Attribute::OptimizeForSize) || hasMinSize(); } /// copyAttributesFrom - copy all additional attributes (those not needed to diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 675abeb6ec3a..d62da41ebc29 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -1,9 +1,8 @@ //===- GVMaterializer.h - Interface for GV materializers --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index 3c143ea5f703..9b257abc7c1f 100644 --- a/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/include/llvm/IR/GetElementPtrTypeIterator.h @@ -1,9 +1,8 @@ //===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index 450583baaa3c..3cd405701300 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -1,9 +1,8 @@ //===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/GlobalIFunc.h b/include/llvm/IR/GlobalIFunc.h index ef51315a6f5d..bc0d3c053cce 100644 --- a/include/llvm/IR/GlobalIFunc.h +++ b/include/llvm/IR/GlobalIFunc.h @@ -1,9 +1,8 @@ //===-------- llvm/GlobalIFunc.h - GlobalIFunc class ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/IR/GlobalIndirectSymbol.h b/include/llvm/IR/GlobalIndirectSymbol.h index 22c00686c549..8bc3f90b94aa 100644 --- a/include/llvm/IR/GlobalIndirectSymbol.h +++ b/include/llvm/IR/GlobalIndirectSymbol.h @@ -1,9 +1,8 @@ //===- llvm/GlobalIndirectSymbol.h - GlobalIndirectSymbol class -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 1fd3568100c2..b8ab6140ebe7 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -1,9 +1,8 @@ //===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index c07d4051c803..2209881dbda6 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -1,9 +1,8 @@ //===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -80,15 +79,15 @@ protected: ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), - HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U), - Parent(nullptr) { + HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false), + IntID((Intrinsic::ID)0U), Parent(nullptr) { setLinkage(Linkage); setName(Name); } Type *ValueType; - static const unsigned GlobalValueSubClassDataBits = 17; + static const unsigned GlobalValueSubClassDataBits = 16; // All bitfields use unsigned as the underlying type so that MSVC will pack // them. @@ -109,9 +108,13 @@ protected: /// definition cannot be runtime preempted. unsigned IsDSOLocal : 1; + /// True if this symbol has a partition name assigned (see + /// https://lld.llvm.org/Partitions.html). + unsigned HasPartition : 1; + private: // Give subclasses access to what otherwise would be wasted padding. - // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32. + // (16 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; @@ -281,6 +284,12 @@ public: return IsDSOLocal; } + bool hasPartition() const { + return HasPartition; + } + StringRef getPartition() const; + void setPartition(StringRef Part); + static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; } diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 03b9ec46ebb4..2e2c8c477913 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -1,9 +1,8 @@ //===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index fac2ff46c453..a74364dffb2e 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -1,9 +1,8 @@ //===- llvm/IRBuilder.h - Builder for LLVM Instructions ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -32,7 +31,7 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" @@ -97,12 +96,18 @@ protected: MDNode *DefaultFPMathTag; FastMathFlags FMF; + bool IsFPConstrained; + ConstrainedFPIntrinsic::ExceptionBehavior DefaultConstrainedExcept; + ConstrainedFPIntrinsic::RoundingMode DefaultConstrainedRounding; + ArrayRef<OperandBundleDef> DefaultOperandBundles; public: IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) - : Context(context), DefaultFPMathTag(FPMathTag), + : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false), + DefaultConstrainedExcept(ConstrainedFPIntrinsic::ebStrict), + DefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDynamic), DefaultOperandBundles(OpBundles) { ClearInsertionPoint(); } @@ -219,6 +224,37 @@ public: /// Set the fast-math flags to be used with generated fp-math operators void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + /// Enable/Disable use of constrained floating point math. When + /// enabled the CreateF<op>() calls instead create constrained + /// floating point intrinsic calls. Fast math flags are unaffected + /// by this setting. + void setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; } + + /// Query for the use of constrained floating point math + bool getIsFPConstrained() { return IsFPConstrained; } + + /// Set the exception handling to be used with constrained floating point + void setDefaultConstrainedExcept( + ConstrainedFPIntrinsic::ExceptionBehavior NewExcept) { + DefaultConstrainedExcept = NewExcept; + } + + /// Set the rounding mode handling to be used with constrained floating point + void setDefaultConstrainedRounding( + ConstrainedFPIntrinsic::RoundingMode NewRounding) { + DefaultConstrainedRounding = NewRounding; + } + + /// Get the exception handling used with constrained floating point + ConstrainedFPIntrinsic::ExceptionBehavior getDefaultConstrainedExcept() { + return DefaultConstrainedExcept; + } + + /// Get the rounding mode handling used with constrained floating point + ConstrainedFPIntrinsic::RoundingMode getDefaultConstrainedRounding() { + return DefaultConstrainedRounding; + } + //===--------------------------------------------------------------------===// // RAII helpers. //===--------------------------------------------------------------------===// @@ -906,20 +942,20 @@ public: Name); } - InvokeInst *CreateInvoke(Function *Callee, BasicBlock *NormalDest, + InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> OpBundles, const Twine &Name = "") { - return CreateInvoke(Callee->getFunctionType(), Callee, NormalDest, - UnwindDest, Args, OpBundles, Name); + return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(), + NormalDest, UnwindDest, Args, OpBundles, Name); } - InvokeInst *CreateInvoke(Function *Callee, BasicBlock *NormalDest, + InvokeInst *CreateInvoke(FunctionCallee Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Value *> Args = None, const Twine &Name = "") { - return CreateInvoke(Callee->getFunctionType(), Callee, NormalDest, - UnwindDest, Args, Name); + return CreateInvoke(Callee.getFunctionType(), Callee.getCallee(), + NormalDest, UnwindDest, Args, Name); } // Deprecated [opaque pointer types] @@ -944,6 +980,42 @@ public: Callee, NormalDest, UnwindDest, Args, Name); } + /// \brief Create a callbr instruction. + CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args = None, + const Twine &Name = "") { + return Insert(CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, + Args), Name); + } + CallBrInst *CreateCallBr(FunctionType *Ty, Value *Callee, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> OpBundles, + const Twine &Name = "") { + return Insert( + CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args, + OpBundles), Name); + } + + CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args = None, + const Twine &Name = "") { + return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(), + DefaultDest, IndirectDests, Args, Name); + } + CallBrInst *CreateCallBr(FunctionCallee Callee, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> OpBundles, + const Twine &Name = "") { + return CreateCallBr(Callee.getFunctionType(), Callee.getCallee(), + DefaultDest, IndirectDests, Args, Name); + } + ResumeInst *CreateResume(Value *Exn) { return Insert(ResumeInst::Create(Exn)); } @@ -1004,12 +1076,44 @@ private: } Value *foldConstant(Instruction::BinaryOps Opc, Value *L, - Value *R, const Twine &Name = nullptr) const { + Value *R, const Twine &Name) const { auto *LC = dyn_cast<Constant>(L); auto *RC = dyn_cast<Constant>(R); return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; } + Value *getConstrainedFPRounding( + Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding) { + ConstrainedFPIntrinsic::RoundingMode UseRounding = + DefaultConstrainedRounding; + + if (Rounding.hasValue()) + UseRounding = Rounding.getValue(); + + Optional<StringRef> RoundingStr = + ConstrainedFPIntrinsic::RoundingModeToStr(UseRounding); + assert(RoundingStr.hasValue() && "Garbage strict rounding mode!"); + auto *RoundingMDS = MDString::get(Context, RoundingStr.getValue()); + + return MetadataAsValue::get(Context, RoundingMDS); + } + + Value *getConstrainedFPExcept( + Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except) { + ConstrainedFPIntrinsic::ExceptionBehavior UseExcept = + DefaultConstrainedExcept; + + if (Except.hasValue()) + UseExcept = Except.getValue(); + + Optional<StringRef> ExceptStr = + ConstrainedFPIntrinsic::ExceptionBehaviorToStr(UseExcept); + assert(ExceptStr.hasValue() && "Garbage strict exception behavior!"); + auto *ExceptMDS = MDString::get(Context, ExceptStr.getValue()); + + return MetadataAsValue::get(Context, ExceptMDS); + } + public: Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { @@ -1179,6 +1283,14 @@ public: return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateAnd(ArrayRef<Value*> Ops) { + assert(!Ops.empty()); + Value *Accum = Ops[0]; + for (unsigned i = 1; i < Ops.size(); i++) + Accum = CreateAnd(Accum, Ops[i]); + return Accum; + } + Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { if (auto *RC = dyn_cast<Constant>(RHS)) { if (RC->isNullValue()) @@ -1197,6 +1309,14 @@ public: return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateOr(ArrayRef<Value*> Ops) { + assert(!Ops.empty()); + Value *Accum = Ops[0]; + for (unsigned i = 1; i < Ops.size(); i++) + Accum = CreateOr(Accum, Ops[i]); + return Accum; + } + Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { if (Value *V = foldConstant(Instruction::Xor, LHS, RHS, Name)) return V; return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); @@ -1212,6 +1332,10 @@ public: Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, + L, R, nullptr, Name, FPMD); + if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF); return Insert(I, Name); @@ -1221,6 +1345,10 @@ public: /// default FMF. Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, + L, R, FMFSource, Name); + if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, FMFSource->getFastMathFlags()); @@ -1229,6 +1357,10 @@ public: Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, + L, R, nullptr, Name, FPMD); + if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF); return Insert(I, Name); @@ -1238,6 +1370,10 @@ public: /// default FMF. Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, + L, R, FMFSource, Name); + if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, FMFSource->getFastMathFlags()); @@ -1246,6 +1382,10 @@ public: Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, + L, R, nullptr, Name, FPMD); + if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF); return Insert(I, Name); @@ -1255,6 +1395,10 @@ public: /// default FMF. Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, + L, R, FMFSource, Name); + if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, FMFSource->getFastMathFlags()); @@ -1263,6 +1407,10 @@ public: Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, + L, R, nullptr, Name, FPMD); + if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF); return Insert(I, Name); @@ -1272,6 +1420,10 @@ public: /// default FMF. Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, + L, R, FMFSource, Name); + if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, FMFSource->getFastMathFlags()); @@ -1280,6 +1432,10 @@ public: Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", MDNode *FPMD = nullptr) { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, + L, R, nullptr, Name, FPMD); + if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF); return Insert(I, Name); @@ -1289,6 +1445,10 @@ public: /// default FMF. Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name = "") { + if (IsFPConstrained) + return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, + L, R, FMFSource, Name); + if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, FMFSource->getFastMathFlags()); @@ -1305,6 +1465,23 @@ public: return Insert(BinOp, Name); } + CallInst *CreateConstrainedFPBinOp( + Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr, + const Twine &Name = "", MDNode *FPMathTag = nullptr, + Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding = None, + Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except = None) { + Value *RoundingV = getConstrainedFPRounding(Rounding); + Value *ExceptV = getConstrainedFPExcept(Except); + + FastMathFlags UseFMF = FMF; + if (FMFSource) + UseFMF = FMFSource->getFastMathFlags(); + + CallInst *C = CreateIntrinsic(ID, {L->getType()}, + {L, R, RoundingV, ExceptV}, nullptr, Name); + return cast<CallInst>(setFPAttrs(C, FPMathTag, UseFMF)); + } + Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { if (auto *VC = dyn_cast<Constant>(V)) @@ -1331,12 +1508,54 @@ public: Name); } + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFNegFMF(Value *V, Instruction *FMFSource, + const Twine &Name = "") { + if (auto *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateFNeg(VC), Name); + // TODO: This should return UnaryOperator::CreateFNeg(...) once we are + // confident that they are optimized sufficiently. + return Insert(setFPAttrs(BinaryOperator::CreateFNeg(V), nullptr, + FMFSource->getFastMathFlags()), + Name); + } + Value *CreateNot(Value *V, const Twine &Name = "") { if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateNot(VC), Name); return Insert(BinaryOperator::CreateNot(V), Name); } + Value *CreateUnOp(Instruction::UnaryOps Opc, + Value *V, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + if (auto *VC = dyn_cast<Constant>(V)) + return Insert(Folder.CreateUnOp(Opc, VC), Name); + Instruction *UnOp = UnaryOperator::Create(Opc, V); + if (isa<FPMathOperator>(UnOp)) + UnOp = setFPAttrs(UnOp, FPMathTag, FMF); + return Insert(UnOp, Name); + } + + /// Create either a UnaryOperator or BinaryOperator depending on \p Opc. + /// Correct number of operands must be passed accordingly. + Value *CreateNAryOp(unsigned Opc, ArrayRef<Value *> Ops, + const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + if (Instruction::isBinaryOp(Opc)) { + assert(Ops.size() == 2 && "Invalid number of operands!"); + return CreateBinOp(static_cast<Instruction::BinaryOps>(Opc), + Ops[0], Ops[1], Name, FPMathTag); + } + if (Instruction::isUnaryOp(Opc)) { + assert(Ops.size() == 1 && "Invalid number of operands!"); + return CreateUnOp(static_cast<Instruction::UnaryOps>(Opc), + Ops[0], Name, FPMathTag); + } + llvm_unreachable("Unexpected opcode!"); + } + //===--------------------------------------------------------------------===// // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// @@ -1989,16 +2208,17 @@ public: return Insert(CI, Name); } - CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args = None, + CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args = None, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateCall(Callee->getFunctionType(), Callee, Args, Name, FPMathTag); + return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, Name, + FPMathTag); } - CallInst *CreateCall(Function *Callee, ArrayRef<Value *> Args, + CallInst *CreateCall(FunctionCallee Callee, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> OpBundles, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - return CreateCall(Callee->getFunctionType(), Callee, Args, OpBundles, Name, - FPMathTag); + return CreateCall(Callee.getFunctionType(), Callee.getCallee(), Args, + OpBundles, Name, FPMathTag); } // Deprecated [opaque pointer types] @@ -2031,6 +2251,8 @@ public: MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable); Sel = addBranchMetadata(Sel, Prof, Unpred); } + if (isa<FPMathOperator>(Sel)) + Sel = cast<SelectInst>(setFPAttrs(Sel, nullptr /* MDNode* */, FMF)); return Insert(Sel, Name); } @@ -2231,6 +2453,74 @@ public: return V; } + Value *CreatePreserveArrayAccessIndex(Value *Base, unsigned Dimension, + unsigned LastIndex) { + assert(isa<PointerType>(Base->getType()) && + "Invalid Base ptr type for preserve.array.access.index."); + auto *BaseType = Base->getType(); + + Value *LastIndexV = getInt32(LastIndex); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + SmallVector<Value *, 4> IdxList; + for (unsigned I = 0; I < Dimension; ++I) + IdxList.push_back(Zero); + IdxList.push_back(LastIndexV); + + Type *ResultType = + GetElementPtrInst::getGEPReturnType(Base, IdxList); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); + + Value *DimV = getInt32(Dimension); + CallInst *Fn = + CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); + + return Fn; + } + + Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex, + MDNode *DbgInfo) { + assert(isa<PointerType>(Base->getType()) && + "Invalid Base ptr type for preserve.union.access.index."); + auto *BaseType = Base->getType(); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_union_access_index, {BaseType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = + CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; + } + + Value *CreatePreserveStructAccessIndex(Value *Base, unsigned Index, + unsigned FieldIndex, MDNode *DbgInfo) { + assert(isa<PointerType>(Base->getType()) && + "Invalid Base ptr type for preserve.struct.access.index."); + auto *BaseType = Base->getType(); + + Value *GEPIndex = getInt32(Index); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Type *ResultType = + GetElementPtrInst::getGEPReturnType(Base, {Zero, GEPIndex}); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, + {Base, GEPIndex, DIIndex}); + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; + } + private: /// Helper function that creates an assume intrinsic call that /// represents an alignment assumption on the provided Ptr, Mask, Type @@ -2280,10 +2570,11 @@ public: Value **TheCheck = nullptr) { assert(isa<PointerType>(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); + assert(Alignment != 0 && "Invalid Alignment"); auto *PtrTy = cast<PointerType>(PtrValue->getType()); Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - Value *Mask = ConstantInt::get(IntPtrTy, Alignment > 0 ? Alignment - 1 : 0); + Value *Mask = ConstantInt::get(IntPtrTy, Alignment - 1); return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, OffsetValue, TheCheck); } @@ -2310,15 +2601,10 @@ public: Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); if (Alignment->getType() != IntPtrTy) - Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ true, + Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ false, "alignmentcast"); - Value *IsPositive = - CreateICmp(CmpInst::ICMP_SGT, Alignment, - ConstantInt::get(Alignment->getType(), 0), "ispositive"); - Value *PositiveMask = - CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "positivemask"); - Value *Mask = CreateSelect(IsPositive, PositiveMask, - ConstantInt::get(IntPtrTy, 0), "mask"); + + Value *Mask = CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "mask"); return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, OffsetValue, TheCheck); diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 75f80567dbd5..3be9449c1a93 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -1,9 +1,8 @@ //===- IRPrintingPasses.h - Passes to print out IR constructs ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 1519a45d59e9..2aac807623a9 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -1,9 +1,8 @@ //===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/InstIterator.h b/include/llvm/IR/InstIterator.h index 2988fc935dd5..054fe4e9cbe9 100644 --- a/include/llvm/IR/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -1,9 +1,8 @@ //===- InstIterator.h - Classes for inst iteration --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h index c5b4c6f71d7d..fbeb2caf14e6 100644 --- a/include/llvm/IR/InstVisitor.h +++ b/include/llvm/IR/InstVisitor.h @@ -1,9 +1,8 @@ //===- InstVisitor.h - Instruction visitor templates ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -218,14 +217,17 @@ public: RetTy visitVACopyInst(VACopyInst &I) { DELEGATE(IntrinsicInst); } RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } - // Call and Invoke are slightly different as they delegate first through - // a generic CallSite visitor. + // Call, Invoke and CallBr are slightly different as they delegate first + // through a generic CallSite visitor. RetTy visitCallInst(CallInst &I) { return static_cast<SubClass*>(this)->visitCallSite(&I); } RetTy visitInvokeInst(InvokeInst &I) { return static_cast<SubClass*>(this)->visitCallSite(&I); } + RetTy visitCallBrInst(CallBrInst &I) { + return static_cast<SubClass *>(this)->visitCallSite(&I); + } // While terminators don't have a distinct type modeling them, we support // intercepting them with dedicated a visitor callback. @@ -271,14 +273,14 @@ public: // The next level delegation for `CallBase` is slightly more complex in order // to support visiting cases where the call is also a terminator. RetTy visitCallBase(CallBase &I) { - if (isa<InvokeInst>(I)) + if (isa<InvokeInst>(I) || isa<CallBrInst>(I)) return static_cast<SubClass *>(this)->visitTerminator(I); DELEGATE(Instruction); } - // Provide a legacy visitor for a 'callsite' that visits both calls and - // invokes. + // Provide a legacy visitor for a 'callsite' that visits calls, invokes, + // and calbrs. // // Prefer overriding the type system based `CallBase` instead. RetTy visitCallSite(CallSite CS) { diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 3f384a6ee40c..ca419b50da6b 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -1,9 +1,8 @@ //===- llvm/InstrTypes.h - Important Instruction subclasses -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -28,6 +27,7 @@ #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/OperandTraits.h" @@ -77,7 +77,8 @@ public: // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Alloca || + return I->isUnaryOp() || + I->getOpcode() == Instruction::Alloca || I->getOpcode() == Instruction::Load || I->getOpcode() == Instruction::VAArg || I->getOpcode() == Instruction::ExtractValue || @@ -96,6 +97,91 @@ struct OperandTraits<UnaryInstruction> : DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) //===----------------------------------------------------------------------===// +// UnaryOperator Class +//===----------------------------------------------------------------------===// + +class UnaryOperator : public UnaryInstruction { + void AssertOK(); + +protected: + UnaryOperator(UnaryOps iType, Value *S, Type *Ty, + const Twine &Name, Instruction *InsertBefore); + UnaryOperator(UnaryOps iType, Value *S, Type *Ty, + const Twine &Name, BasicBlock *InsertAtEnd); + + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + + UnaryOperator *cloneImpl() const; + +public: + + /// Construct a unary instruction, given the opcode and an operand. + /// Optionally (if InstBefore is specified) insert the instruction + /// into a BasicBlock right before the specified instruction. The specified + /// Instruction is allowed to be a dereferenced end iterator. + /// + static UnaryOperator *Create(UnaryOps Op, Value *S, + const Twine &Name = Twine(), + Instruction *InsertBefore = nullptr); + + /// Construct a unary instruction, given the opcode and an operand. + /// Also automatically insert this instruction to the end of the + /// BasicBlock specified. + /// + static UnaryOperator *Create(UnaryOps Op, Value *S, + const Twine &Name, + BasicBlock *InsertAtEnd); + + /// These methods just forward to Create, and are useful when you + /// statically know what type of instruction you're going to create. These + /// helpers just save some typing. +#define HANDLE_UNARY_INST(N, OPC, CLASS) \ + static UnaryOperator *Create##OPC(Value *V, const Twine &Name = "") {\ + return Create(Instruction::OPC, V, Name);\ + } +#include "llvm/IR/Instruction.def" +#define HANDLE_UNARY_INST(N, OPC, CLASS) \ + static UnaryOperator *Create##OPC(Value *V, const Twine &Name, \ + BasicBlock *BB) {\ + return Create(Instruction::OPC, V, Name, BB);\ + } +#include "llvm/IR/Instruction.def" +#define HANDLE_UNARY_INST(N, OPC, CLASS) \ + static UnaryOperator *Create##OPC(Value *V, const Twine &Name, \ + Instruction *I) {\ + return Create(Instruction::OPC, V, Name, I);\ + } +#include "llvm/IR/Instruction.def" + + static UnaryOperator *CreateWithCopiedFlags(UnaryOps Opc, + Value *V, + Instruction *CopyO, + const Twine &Name = "") { + UnaryOperator *UO = Create(Opc, V, Name); + UO->copyIRFlags(CopyO); + return UO; + } + + static UnaryOperator *CreateFNegFMF(Value *Op, Instruction *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FNeg, Op, FMFSource, Name); + } + + UnaryOps getOpcode() const { + return static_cast<UnaryOps>(Instruction::getOpcode()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Instruction *I) { + return I->isUnaryOp(); + } + static bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// @@ -162,42 +248,42 @@ public: static BinaryOperator *CreateWithCopiedFlags(BinaryOps Opc, Value *V1, Value *V2, - BinaryOperator *CopyBO, + Instruction *CopyO, const Twine &Name = "") { BinaryOperator *BO = Create(Opc, V1, V2, Name); - BO->copyIRFlags(CopyBO); + BO->copyIRFlags(CopyO); return BO; } static BinaryOperator *CreateFAddFMF(Value *V1, Value *V2, - BinaryOperator *FMFSource, + Instruction *FMFSource, const Twine &Name = "") { return CreateWithCopiedFlags(Instruction::FAdd, V1, V2, FMFSource, Name); } static BinaryOperator *CreateFSubFMF(Value *V1, Value *V2, - BinaryOperator *FMFSource, + Instruction *FMFSource, const Twine &Name = "") { return CreateWithCopiedFlags(Instruction::FSub, V1, V2, FMFSource, Name); } static BinaryOperator *CreateFMulFMF(Value *V1, Value *V2, - BinaryOperator *FMFSource, + Instruction *FMFSource, const Twine &Name = "") { return CreateWithCopiedFlags(Instruction::FMul, V1, V2, FMFSource, Name); } static BinaryOperator *CreateFDivFMF(Value *V1, Value *V2, - BinaryOperator *FMFSource, + Instruction *FMFSource, const Twine &Name = "") { return CreateWithCopiedFlags(Instruction::FDiv, V1, V2, FMFSource, Name); } static BinaryOperator *CreateFRemFMF(Value *V1, Value *V2, - BinaryOperator *FMFSource, + Instruction *FMFSource, const Twine &Name = "") { return CreateWithCopiedFlags(Instruction::FRem, V1, V2, FMFSource, Name); } - static BinaryOperator *CreateFNegFMF(Value *Op, BinaryOperator *FMFSource, + static BinaryOperator *CreateFNegFMF(Value *Op, Instruction *FMFSource, const Twine &Name = "") { Value *Zero = ConstantFP::getNegativeZero(Op->getType()); - return CreateWithCopiedFlags(Instruction::FSub, Zero, Op, FMFSource); + return CreateWithCopiedFlags(Instruction::FSub, Zero, Op, FMFSource, Name); } static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, @@ -1033,16 +1119,23 @@ protected: return 0; case Instruction::Invoke: return 2; + case Instruction::CallBr: + return getNumSubclassExtraOperandsDynamic(); } llvm_unreachable("Invalid opcode!"); } + /// Get the number of extra operands for instructions that don't have a fixed + /// number of extra operands. + unsigned getNumSubclassExtraOperandsDynamic() const; + public: using Instruction::getContext; static bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Call || - I->getOpcode() == Instruction::Invoke; + I->getOpcode() == Instruction::Invoke || + I->getOpcode() == Instruction::CallBr; } static bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); @@ -1096,6 +1189,19 @@ public: return isDataOperand(&UI.getUse()); } + /// Given a value use iterator, return the data operand corresponding to it. + /// Iterator must actually correspond to a data operand. + unsigned getDataOperandNo(Value::const_user_iterator UI) const { + return getDataOperandNo(&UI.getUse()); + } + + /// Given a use for a data operand, get the data operand number that + /// corresponds to it. + unsigned getDataOperandNo(const Use *U) const { + assert(isDataOperand(U) && "Data operand # out of range!"); + return U - data_operands_begin(); + } + /// Return the iterator pointing to the beginning of the argument list. User::op_iterator arg_begin() { return op_begin(); } User::const_op_iterator arg_begin() const { @@ -1199,6 +1305,13 @@ public: return const_cast<CallBase *>(this)->getCaller(); } + /// Tests if this call site must be tail call optimized. Only a CallInst can + /// be tail call optimized. + bool isMustTailCall() const; + + /// Tests if this call site is marked as a tail call. + bool isTailCall() const; + /// Returns the intrinsic ID of the intrinsic called or /// Intrinsic::not_intrinsic if the called function is not an intrinsic, or if /// this is an indirect call. @@ -1207,10 +1320,13 @@ public: void setCalledOperand(Value *V) { Op<CalledOperandOpEndIdx>() = V; } /// Sets the function called, including updating the function type. - void setCalledFunction(Value *Fn) { - setCalledFunction( - cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType()), - Fn); + void setCalledFunction(Function *Fn) { + setCalledFunction(Fn->getFunctionType(), Fn); + } + + /// Sets the function called, including updating the function type. + void setCalledFunction(FunctionCallee Fn) { + setCalledFunction(Fn.getFunctionType(), Fn.getCallee()); } /// Sets the function called, including updating to the specified function @@ -1219,6 +1335,9 @@ public: this->FTy = FTy; assert(FTy == cast<FunctionType>( cast<PointerType>(Fn->getType())->getElementType())); + // This function doesn't mutate the return type, only the function + // type. Seems broken, but I'm just gonna stick an assert in for now. + assert(getType() == FTy->getReturnType()); setCalledOperand(Fn); } @@ -1233,6 +1352,9 @@ public: (ID << 2)); } + /// Check if this call is an inline asm statement. + bool isInlineAsm() const { return isa<InlineAsm>(getCalledOperand()); } + /// \name Attribute API /// /// These methods access and modify attributes on this call (including @@ -1452,6 +1574,12 @@ public: return Attrs.getParamAlignment(ArgNo); } + /// Extract the byval type for a call or parameter. + Type *getParamByValType(unsigned ArgNo) const { + Type *Ty = Attrs.getParamByValType(ArgNo); + return Ty ? Ty : getArgOperand(ArgNo)->getType()->getPointerElementType(); + } + /// Extract the number of dereferenceable bytes for a call or /// parameter (0=unknown). uint64_t getDereferenceableBytes(unsigned i) const { diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def index 58e4e2e1d6cc..41cdf613ad64 100644 --- a/include/llvm/IR/Instruction.def +++ b/include/llvm/IR/Instruction.def @@ -1,9 +1,8 @@ //===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -135,89 +134,90 @@ HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst) HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst) HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst) HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst) - LAST_TERM_INST (10) +HANDLE_TERM_INST (11, CallBr , CallBrInst) // A call-site terminator + LAST_TERM_INST (11) // Standard unary operators... - FIRST_UNARY_INST(11) -HANDLE_UNARY_INST(11, FNeg , UnaryOperator) - LAST_UNARY_INST(11) + FIRST_UNARY_INST(12) +HANDLE_UNARY_INST(12, FNeg , UnaryOperator) + LAST_UNARY_INST(12) // Standard binary operators... - FIRST_BINARY_INST(12) -HANDLE_BINARY_INST(12, Add , BinaryOperator) -HANDLE_BINARY_INST(13, FAdd , BinaryOperator) -HANDLE_BINARY_INST(14, Sub , BinaryOperator) -HANDLE_BINARY_INST(15, FSub , BinaryOperator) -HANDLE_BINARY_INST(16, Mul , BinaryOperator) -HANDLE_BINARY_INST(17, FMul , BinaryOperator) -HANDLE_BINARY_INST(18, UDiv , BinaryOperator) -HANDLE_BINARY_INST(19, SDiv , BinaryOperator) -HANDLE_BINARY_INST(20, FDiv , BinaryOperator) -HANDLE_BINARY_INST(21, URem , BinaryOperator) -HANDLE_BINARY_INST(22, SRem , BinaryOperator) -HANDLE_BINARY_INST(23, FRem , BinaryOperator) + FIRST_BINARY_INST(13) +HANDLE_BINARY_INST(13, Add , BinaryOperator) +HANDLE_BINARY_INST(14, FAdd , BinaryOperator) +HANDLE_BINARY_INST(15, Sub , BinaryOperator) +HANDLE_BINARY_INST(16, FSub , BinaryOperator) +HANDLE_BINARY_INST(17, Mul , BinaryOperator) +HANDLE_BINARY_INST(18, FMul , BinaryOperator) +HANDLE_BINARY_INST(19, UDiv , BinaryOperator) +HANDLE_BINARY_INST(20, SDiv , BinaryOperator) +HANDLE_BINARY_INST(21, FDiv , BinaryOperator) +HANDLE_BINARY_INST(22, URem , BinaryOperator) +HANDLE_BINARY_INST(23, SRem , BinaryOperator) +HANDLE_BINARY_INST(24, FRem , BinaryOperator) // Logical operators (integer operands) -HANDLE_BINARY_INST(24, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(25, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(26, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(27, And , BinaryOperator) -HANDLE_BINARY_INST(28, Or , BinaryOperator) -HANDLE_BINARY_INST(29, Xor , BinaryOperator) - LAST_BINARY_INST(29) +HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(28, And , BinaryOperator) +HANDLE_BINARY_INST(29, Or , BinaryOperator) +HANDLE_BINARY_INST(30, Xor , BinaryOperator) + LAST_BINARY_INST(30) // Memory operators... - FIRST_MEMORY_INST(30) -HANDLE_MEMORY_INST(30, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(31, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(32, Store , StoreInst ) -HANDLE_MEMORY_INST(33, GetElementPtr, GetElementPtrInst) -HANDLE_MEMORY_INST(34, Fence , FenceInst ) -HANDLE_MEMORY_INST(35, AtomicCmpXchg , AtomicCmpXchgInst ) -HANDLE_MEMORY_INST(36, AtomicRMW , AtomicRMWInst ) - LAST_MEMORY_INST(36) + FIRST_MEMORY_INST(31) +HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(33, Store , StoreInst ) +HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(35, Fence , FenceInst ) +HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst ) +HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst ) + LAST_MEMORY_INST(37) // Cast operators ... // NOTE: The order matters here because CastInst::isEliminableCastPair // NOTE: (see Instructions.cpp) encodes a table based on this ordering. - FIRST_CAST_INST(37) -HANDLE_CAST_INST(37, Trunc , TruncInst ) // Truncate integers -HANDLE_CAST_INST(38, ZExt , ZExtInst ) // Zero extend integers -HANDLE_CAST_INST(39, SExt , SExtInst ) // Sign extend integers -HANDLE_CAST_INST(40, FPToUI , FPToUIInst ) // floating point -> UInt -HANDLE_CAST_INST(41, FPToSI , FPToSIInst ) // floating point -> SInt -HANDLE_CAST_INST(42, UIToFP , UIToFPInst ) // UInt -> floating point -HANDLE_CAST_INST(43, SIToFP , SIToFPInst ) // SInt -> floating point -HANDLE_CAST_INST(44, FPTrunc , FPTruncInst ) // Truncate floating point -HANDLE_CAST_INST(45, FPExt , FPExtInst ) // Extend floating point -HANDLE_CAST_INST(46, PtrToInt, PtrToIntInst) // Pointer -> Integer -HANDLE_CAST_INST(47, IntToPtr, IntToPtrInst) // Integer -> Pointer -HANDLE_CAST_INST(48, BitCast , BitCastInst ) // Type cast -HANDLE_CAST_INST(49, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast - LAST_CAST_INST(49) - - FIRST_FUNCLETPAD_INST(50) -HANDLE_FUNCLETPAD_INST(50, CleanupPad, CleanupPadInst) -HANDLE_FUNCLETPAD_INST(51, CatchPad , CatchPadInst) - LAST_FUNCLETPAD_INST(51) + FIRST_CAST_INST(38) +HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast +HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(50) + + FIRST_FUNCLETPAD_INST(51) +HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst) +HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst) + LAST_FUNCLETPAD_INST(52) // Other operators... - FIRST_OTHER_INST(52) -HANDLE_OTHER_INST(52, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(53, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(54, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(55, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(56, Select , SelectInst ) // select instruction -HANDLE_USER_INST (57, UserOp1, Instruction) // May be used internally in a pass -HANDLE_USER_INST (58, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(59, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(60, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(61, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(62, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(63, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(64, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(65, LandingPad, LandingPadInst) // Landing pad instruction. - LAST_OTHER_INST(65) + FIRST_OTHER_INST(53) +HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction +HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass +HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction. + LAST_OTHER_INST(66) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 5e78cb1edf02..6a9a74bd16f0 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -1,9 +1,8 @@ //===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -136,6 +135,9 @@ public: bool isExceptionalTerminator() const { return isExceptionalTerminator(getOpcode()); } + bool isIndirectTerminator() const { + return isIndirectTerminator(getOpcode()); + } static const char* getOpcodeName(unsigned OpCode); @@ -203,6 +205,17 @@ public: } } + /// Returns true if the OpCode is a terminator with indirect targets. + static inline bool isIndirectTerminator(unsigned OpCode) { + switch (OpCode) { + case Instruction::IndirectBr: + case Instruction::CallBr: + return true; + default: + return false; + } + } + //===--------------------------------------------------------------------===// // Metadata manipulation. //===--------------------------------------------------------------------===// @@ -298,9 +311,6 @@ public: /// Returns false if no metadata was found. bool extractProfTotalWeight(uint64_t &TotalVal) const; - /// Updates branch_weights metadata by scaling it by \p S / \p T. - void updateProfWeight(uint64_t S, uint64_t T); - /// Sets the branch_weights metadata to \p W for CallInst. void setProfWeight(uint64_t W); @@ -655,6 +665,10 @@ public: /// instruction must be a terminator. void setSuccessor(unsigned Idx, BasicBlock *BB); + /// Replace specified successor OldBB to point at the provided block. + /// This instruction must be a terminator. + void replaceSuccessorWith(BasicBlock *OldBB, BasicBlock *NewBB); + /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() >= Value::InstructionVal; diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 0ff8f56f213a..215ce45c7b75 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -1,9 +1,8 @@ //===- llvm/Instructions.h - Instruction subclass definitions ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -522,9 +521,11 @@ private: // AtomicCmpXchgInst Class //===----------------------------------------------------------------------===// -/// an instruction that atomically checks whether a +/// An instruction that atomically checks whether a /// specified value is in a memory location, and, if it is, stores a new value -/// there. Returns the value that was loaded. +/// there. The value returned by this instruction is a pair containing the +/// original value as first element, and an i1 indicating success (true) or +/// failure (false) as second element. /// class AtomicCmpXchgInst : public Instruction { void Init(Value *Ptr, Value *Cmp, Value *NewVal, @@ -725,8 +726,14 @@ public: /// *p = old <unsigned v ? old : v UMin, + /// *p = old + v + FAdd, + + /// *p = old - v + FSub, + FIRST_BINOP = Xchg, - LAST_BINOP = UMin, + LAST_BINOP = FSub, BAD_BINOP }; @@ -748,6 +755,16 @@ public: static StringRef getOperationName(BinOp Op); + static bool isFPOperation(BinOp Op) { + switch (Op) { + case AtomicRMWInst::FAdd: + case AtomicRMWInst::FSub: + return true; + default: + return false; + } + } + void setOperation(BinOp Operation) { unsigned short SubclassData = getSubclassDataFromInstruction(); setInstructionSubclassData((SubclassData & 31) | @@ -805,6 +822,10 @@ public: return getPointerOperand()->getType()->getPointerAddressSpace(); } + bool isFloatingPointOperation() const { + return isFPOperation(getOperation()); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { return I->getOpcode() == Instruction::AtomicRMW; @@ -1115,71 +1136,6 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) //===----------------------------------------------------------------------===// -// UnaryOperator Class -//===----------------------------------------------------------------------===// - -/// a unary instruction -class UnaryOperator : public UnaryInstruction { - void AssertOK(); - -protected: - UnaryOperator(UnaryOps iType, Value *S, Type *Ty, - const Twine &Name, Instruction *InsertBefore); - UnaryOperator(UnaryOps iType, Value *S, Type *Ty, - const Twine &Name, BasicBlock *InsertAtEnd); - - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - UnaryOperator *cloneImpl() const; - -public: - - /// Construct a unary instruction, given the opcode and an operand. - /// Optionally (if InstBefore is specified) insert the instruction - /// into a BasicBlock right before the specified instruction. The specified - /// Instruction is allowed to be a dereferenced end iterator. - /// - static UnaryOperator *Create(UnaryOps Op, Value *S, - const Twine &Name = Twine(), - Instruction *InsertBefore = nullptr); - - /// Construct a unary instruction, given the opcode and an operand. - /// Also automatically insert this instruction to the end of the - /// BasicBlock specified. - /// - static UnaryOperator *Create(UnaryOps Op, Value *S, - const Twine &Name, - BasicBlock *InsertAtEnd); - - /// These methods just forward to Create, and are useful when you - /// statically know what type of instruction you're going to create. These - /// helpers just save some typing. -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryInstruction *Create##OPC(Value *V, \ - const Twine &Name = "") {\ - return Create(Instruction::OPC, V, Name);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryInstruction *Create##OPC(Value *V, \ - const Twine &Name, BasicBlock *BB) {\ - return Create(Instruction::OPC, V, Name, BB);\ - } -#include "llvm/IR/Instruction.def" -#define HANDLE_UNARY_INST(N, OPC, CLASS) \ - static UnaryInstruction *Create##OPC(Value *V, \ - const Twine &Name, Instruction *I) {\ - return Create(Instruction::OPC, V, Name, I);\ - } -#include "llvm/IR/Instruction.def" - - UnaryOps getOpcode() const { - return static_cast<UnaryOps>(Instruction::getOpcode()); - } -}; - -//===----------------------------------------------------------------------===// // ICmpInst Class //===----------------------------------------------------------------------===// @@ -1524,25 +1480,44 @@ public: CallInst(Ty, Func, Args, Bundles, NameStr, InsertAtEnd); } - static CallInst *Create(Function *Func, const Twine &NameStr = "", + static CallInst *Create(FunctionCallee Func, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return Create(Func->getFunctionType(), Func, NameStr, InsertBefore); + return Create(Func.getFunctionType(), Func.getCallee(), NameStr, + InsertBefore); } - static CallInst *Create(Function *Func, ArrayRef<Value *> Args, + static CallInst *Create(FunctionCallee Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles = None, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return Create(Func->getFunctionType(), Func, Args, NameStr, InsertBefore); + return Create(Func.getFunctionType(), Func.getCallee(), Args, Bundles, + NameStr, InsertBefore); } - static CallInst *Create(Function *Func, const Twine &NameStr, + static CallInst *Create(FunctionCallee Func, ArrayRef<Value *> Args, + const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + return Create(Func.getFunctionType(), Func.getCallee(), Args, NameStr, + InsertBefore); + } + + static CallInst *Create(FunctionCallee Func, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func->getFunctionType(), Func, NameStr, InsertAtEnd); + return Create(Func.getFunctionType(), Func.getCallee(), NameStr, + InsertAtEnd); } - static CallInst *Create(Function *Func, ArrayRef<Value *> Args, + static CallInst *Create(FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func->getFunctionType(), Func, Args, NameStr, InsertAtEnd); + return Create(Func.getFunctionType(), Func.getCallee(), Args, NameStr, + InsertAtEnd); + } + + static CallInst *Create(FunctionCallee Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return Create(Func.getFunctionType(), Func.getCallee(), Args, Bundles, + NameStr, InsertAtEnd); } // Deprecated [opaque pointer types] @@ -1684,9 +1659,6 @@ public: addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice); } - /// Check if this call is an inline asm statement. - bool isInlineAsm() const { return isa<InlineAsm>(getCalledOperand()); } - // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Call; @@ -1695,6 +1667,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } + /// Updates profile metadata by scaling it by \p S / \p T. + void updateProfWeight(uint64_t S, uint64_t T); + private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -2008,6 +1983,10 @@ public: return User::operator new(s, 3); } + /// Swap the first 2 operands and adjust the mask to preserve the semantics + /// of the instruction. + void commute(); + /// Return true if a shufflevector instruction can be /// formed with the specified operands. static bool isValidOperands(const Value *V1, const Value *V2, @@ -2696,6 +2675,14 @@ public: block_begin()[i] = BB; } + /// Replace every incoming basic block \p Old to basic block \p New. + void replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) { + assert(New && Old && "PHI node got a null basic block!"); + for (unsigned Op = 0, NumOps = getNumOperands(); Op != NumOps; ++Op) + if (getIncomingBlock(Op) == Old) + setIncomingBlock(Op, New); + } + /// Add an incoming value to the end of the PHI list /// void addIncoming(Value *V, BasicBlock *BB) { @@ -2739,6 +2726,19 @@ public: return getIncomingValue(Idx); } + /// Set every incoming value(s) for block \p BB to \p V. + void setIncomingValueForBlock(const BasicBlock *BB, Value *V) { + assert(BB && "PHI node got a null basic block!"); + bool Found = false; + for (unsigned Op = 0, NumOps = getNumOperands(); Op != NumOps; ++Op) + if (getIncomingBlock(Op) == BB) { + Found = true; + setIncomingValue(Op, V); + } + (void)Found; + assert(Found && "Invalid basic block argument to set!"); + } + /// If the specified PHI node always merges together the /// same value, return the value, otherwise return null. Value *hasConstantValue() const; @@ -3450,6 +3450,60 @@ public: } }; +/// A wrapper class to simplify modification of SwitchInst cases along with +/// their prof branch_weights metadata. +class SwitchInstProfUpdateWrapper { + SwitchInst &SI; + Optional<SmallVector<uint32_t, 8> > Weights = None; + + // Sticky invalid state is needed to safely ignore operations with prof data + // in cases where SwitchInstProfUpdateWrapper is created from SwitchInst + // with inconsistent prof data. TODO: once we fix all prof data + // inconsistencies we can turn invalid state to assertions. + enum { + Invalid, + Initialized, + Changed + } State = Invalid; + +protected: + static MDNode *getProfBranchWeightsMD(const SwitchInst &SI); + + MDNode *buildProfBranchWeightsMD(); + + void init(); + +public: + using CaseWeightOpt = Optional<uint32_t>; + SwitchInst *operator->() { return &SI; } + SwitchInst &operator*() { return SI; } + operator SwitchInst *() { return &SI; } + + SwitchInstProfUpdateWrapper(SwitchInst &SI) : SI(SI) { init(); } + + ~SwitchInstProfUpdateWrapper() { + if (State == Changed) + SI.setMetadata(LLVMContext::MD_prof, buildProfBranchWeightsMD()); + } + + /// Delegate the call to the underlying SwitchInst::removeCase() and remove + /// correspondent branch weight. + SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I); + + /// Delegate the call to the underlying SwitchInst::addCase() and set the + /// specified branch weight for the added case. + void addCase(ConstantInt *OnVal, BasicBlock *Dest, CaseWeightOpt W); + + /// Delegate the call to the underlying SwitchInst::eraseFromParent() and mark + /// this object to not touch the underlying SwitchInst in destructor. + SymbolTableList<Instruction>::iterator eraseFromParent(); + + void setSuccessorWeight(unsigned idx, CaseWeightOpt W); + CaseWeightOpt getSuccessorWeight(unsigned idx); + + static CaseWeightOpt getSuccessorWeight(const SwitchInst &SI, unsigned idx); +}; + template <> struct OperandTraits<SwitchInst> : public HungoffOperandTraits<2> { }; @@ -3688,36 +3742,36 @@ public: NameStr, InsertAtEnd); } - static InvokeInst *Create(Function *Func, BasicBlock *IfNormal, + static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore = nullptr) { - return Create(Func->getFunctionType(), Func, IfNormal, IfException, Args, - None, NameStr, InsertBefore); + return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, + IfException, Args, None, NameStr, InsertBefore); } - static InvokeInst *Create(Function *Func, BasicBlock *IfNormal, + static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles = None, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return Create(Func->getFunctionType(), Func, IfNormal, IfException, Args, - Bundles, NameStr, InsertBefore); + return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, + IfException, Args, Bundles, NameStr, InsertBefore); } - static InvokeInst *Create(Function *Func, BasicBlock *IfNormal, + static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func->getFunctionType(), Func, IfNormal, IfException, Args, - NameStr, InsertAtEnd); + return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, + IfException, Args, NameStr, InsertAtEnd); } - static InvokeInst *Create(Function *Func, BasicBlock *IfNormal, + static InvokeInst *Create(FunctionCallee Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, BasicBlock *InsertAtEnd) { - return Create(Func->getFunctionType(), Func, IfNormal, IfException, Args, - Bundles, NameStr, InsertAtEnd); + return Create(Func.getFunctionType(), Func.getCallee(), IfNormal, + IfException, Args, Bundles, NameStr, InsertAtEnd); } // Deprecated [opaque pointer types] @@ -3852,6 +3906,249 @@ InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, } //===----------------------------------------------------------------------===// +// CallBrInst Class +//===----------------------------------------------------------------------===// + +/// CallBr instruction, tracking function calls that may not return control but +/// instead transfer it to a third location. The SubclassData field is used to +/// hold the calling convention of the call. +/// +class CallBrInst : public CallBase { + + unsigned NumIndirectDests; + + CallBrInst(const CallBrInst &BI); + + /// Construct a CallBrInst given a range of arguments. + /// + /// Construct a CallBrInst from a range of arguments + inline CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, int NumOperands, + const Twine &NameStr, Instruction *InsertBefore); + + inline CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, int NumOperands, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + void init(FunctionType *FTy, Value *Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr); + + /// Compute the number of operands to allocate. + static int ComputeNumOperands(int NumArgs, int NumIndirectDests, + int NumBundleInputs = 0) { + // We need one operand for the called function, plus our extra operands and + // the input operand counts provided. + return 2 + NumIndirectDests + NumArgs + NumBundleInputs; + } + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + + CallBrInst *cloneImpl() const; + +public: + static CallBrInst *Create(FunctionType *Ty, Value *Func, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size()); + return new (NumOperands) + CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, None, + NumOperands, NameStr, InsertBefore); + } + + static CallBrInst *Create(FunctionType *Ty, Value *Func, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size(), + CountBundleInputs(Bundles)); + unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (NumOperands, DescriptorBytes) + CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, + NumOperands, NameStr, InsertBefore); + } + + static CallBrInst *Create(FunctionType *Ty, Value *Func, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size()); + return new (NumOperands) + CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, None, + NumOperands, NameStr, InsertAtEnd); + } + + static CallBrInst *Create(FunctionType *Ty, Value *Func, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + int NumOperands = ComputeNumOperands(Args.size(), IndirectDests.size(), + CountBundleInputs(Bundles)); + unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (NumOperands, DescriptorBytes) + CallBrInst(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, + NumOperands, NameStr, InsertAtEnd); + } + + static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, + IndirectDests, Args, NameStr, InsertBefore); + } + + static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, + IndirectDests, Args, Bundles, NameStr, InsertBefore); + } + + static CallBrInst *Create(FunctionCallee Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, + IndirectDests, Args, NameStr, InsertAtEnd); + } + + static CallBrInst *Create(FunctionCallee Func, + BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return Create(Func.getFunctionType(), Func.getCallee(), DefaultDest, + IndirectDests, Args, Bundles, NameStr, InsertAtEnd); + } + + /// Create a clone of \p CBI with a different set of operand bundles and + /// insert it before \p InsertPt. + /// + /// The returned callbr instruction is identical to \p CBI in every way + /// except that the operand bundles for the new instruction are set to the + /// operand bundles in \p Bundles. + static CallBrInst *Create(CallBrInst *CBI, + ArrayRef<OperandBundleDef> Bundles, + Instruction *InsertPt = nullptr); + + /// Return the number of callbr indirect dest labels. + /// + unsigned getNumIndirectDests() const { return NumIndirectDests; } + + /// getIndirectDestLabel - Return the i-th indirect dest label. + /// + Value *getIndirectDestLabel(unsigned i) const { + assert(i < getNumIndirectDests() && "Out of bounds!"); + return getOperand(i + getNumArgOperands() + getNumTotalBundleOperands() + + 1); + } + + Value *getIndirectDestLabelUse(unsigned i) const { + assert(i < getNumIndirectDests() && "Out of bounds!"); + return getOperandUse(i + getNumArgOperands() + getNumTotalBundleOperands() + + 1); + } + + // Return the destination basic blocks... + BasicBlock *getDefaultDest() const { + return cast<BasicBlock>(*(&Op<-1>() - getNumIndirectDests() - 1)); + } + BasicBlock *getIndirectDest(unsigned i) const { + return cast<BasicBlock>(*(&Op<-1>() - getNumIndirectDests() + i)); + } + SmallVector<BasicBlock *, 16> getIndirectDests() const { + SmallVector<BasicBlock *, 16> IndirectDests; + for (unsigned i = 0, e = getNumIndirectDests(); i < e; ++i) + IndirectDests.push_back(getIndirectDest(i)); + return IndirectDests; + } + void setDefaultDest(BasicBlock *B) { + *(&Op<-1>() - getNumIndirectDests() - 1) = reinterpret_cast<Value *>(B); + } + void setIndirectDest(unsigned i, BasicBlock *B) { + *(&Op<-1>() - getNumIndirectDests() + i) = reinterpret_cast<Value *>(B); + } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < getNumSuccessors() + 1 && + "Successor # out of range for callbr!"); + return i == 0 ? getDefaultDest() : getIndirectDest(i - 1); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumIndirectDests() + 1 && + "Successor # out of range for callbr!"); + *(&Op<-1>() - getNumIndirectDests() -1 + idx) = + reinterpret_cast<Value *>(NewSucc); + } + + unsigned getNumSuccessors() const { return getNumIndirectDests() + 1; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::CallBr); + } + static bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + +private: + + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +CallBrInst::CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, int NumOperands, + const Twine &NameStr, Instruction *InsertBefore) + : CallBase(Ty->getReturnType(), Instruction::CallBr, + OperandTraits<CallBase>::op_end(this) - NumOperands, NumOperands, + InsertBefore) { + init(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, NameStr); +} + +CallBrInst::CallBrInst(FunctionType *Ty, Value *Func, BasicBlock *DefaultDest, + ArrayRef<BasicBlock *> IndirectDests, + ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, int NumOperands, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : CallBase( + cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::CallBr, + OperandTraits<CallBase>::op_end(this) - NumOperands, NumOperands, + InsertAtEnd) { + init(Ty, Func, DefaultDest, IndirectDests, Args, Bundles, NameStr); +} + +//===----------------------------------------------------------------------===// // ResumeInst Class //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 80a7a7052574..438bdb29b706 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -1,9 +1,8 @@ //===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -209,26 +208,47 @@ namespace llvm { /// This is the common base class for constrained floating point intrinsics. class ConstrainedFPIntrinsic : public IntrinsicInst { public: - enum RoundingMode { - rmInvalid, - rmDynamic, - rmToNearest, - rmDownward, - rmUpward, - rmTowardZero + /// Specifies the rounding mode to be assumed. This is only used when + /// when constrained floating point is enabled. See the LLVM Language + /// Reference Manual for details. + enum RoundingMode : uint8_t { + rmDynamic, ///< This corresponds to "fpround.dynamic". + rmToNearest, ///< This corresponds to "fpround.tonearest". + rmDownward, ///< This corresponds to "fpround.downward". + rmUpward, ///< This corresponds to "fpround.upward". + rmTowardZero ///< This corresponds to "fpround.tozero". }; - enum ExceptionBehavior { - ebInvalid, - ebIgnore, - ebMayTrap, - ebStrict + /// Specifies the required exception behavior. This is only used when + /// when constrained floating point is used. See the LLVM Language + /// Reference Manual for details. + enum ExceptionBehavior : uint8_t { + ebIgnore, ///< This corresponds to "fpexcept.ignore". + ebMayTrap, ///< This corresponds to "fpexcept.maytrap". + ebStrict ///< This corresponds to "fpexcept.strict". }; bool isUnaryOp() const; bool isTernaryOp() const; - RoundingMode getRoundingMode() const; - ExceptionBehavior getExceptionBehavior() const; + Optional<RoundingMode> getRoundingMode() const; + Optional<ExceptionBehavior> getExceptionBehavior() const; + + /// Returns a valid RoundingMode enumerator when given a string + /// that is valid as input in constrained intrinsic rounding mode + /// metadata. + static Optional<RoundingMode> StrToRoundingMode(StringRef); + + /// For any RoundingMode enumerator, returns a string valid as input in + /// constrained intrinsic rounding mode metadata. + static Optional<StringRef> RoundingModeToStr(RoundingMode); + + /// Returns a valid ExceptionBehavior enumerator when given a string + /// valid as input in constrained intrinsic exception behavior metadata. + static Optional<ExceptionBehavior> StrToExceptionBehavior(StringRef); + + /// For any ExceptionBehavior enumerator, returns a string valid as + /// input in constrained intrinsic exception behavior metadata. + static Optional<StringRef> ExceptionBehaviorToStr(ExceptionBehavior); // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const IntrinsicInst *I) { @@ -239,6 +259,8 @@ namespace llvm { case Intrinsic::experimental_constrained_fdiv: case Intrinsic::experimental_constrained_frem: case Intrinsic::experimental_constrained_fma: + case Intrinsic::experimental_constrained_fptrunc: + case Intrinsic::experimental_constrained_fpext: case Intrinsic::experimental_constrained_sqrt: case Intrinsic::experimental_constrained_pow: case Intrinsic::experimental_constrained_powi: @@ -266,6 +288,84 @@ namespace llvm { } }; + /// This class represents an intrinsic that is based on a binary operation. + /// This includes op.with.overflow and saturating add/sub intrinsics. + class BinaryOpIntrinsic : public IntrinsicInst { + public: + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::uadd_sat: + case Intrinsic::sadd_sat: + case Intrinsic::usub_sat: + case Intrinsic::ssub_sat: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + Value *getLHS() const { return const_cast<Value*>(getArgOperand(0)); } + Value *getRHS() const { return const_cast<Value*>(getArgOperand(1)); } + + /// Returns the binary operation underlying the intrinsic. + Instruction::BinaryOps getBinaryOp() const; + + /// Whether the intrinsic is signed or unsigned. + bool isSigned() const; + + /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap. + unsigned getNoWrapKind() const; + }; + + /// Represents an op.with.overflow intrinsic. + class WithOverflowInst : public BinaryOpIntrinsic { + public: + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// Represents a saturating add/sub intrinsic. + class SaturatingInst : public BinaryOpIntrinsic { + public: + static bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::uadd_sat: + case Intrinsic::sadd_sat: + case Intrinsic::usub_sat: + case Intrinsic::ssub_sat: + return true; + default: + return false; + } + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + /// Common base class for all memory intrinsics. Simply provides /// common methods. /// Written as CRTP to avoid a common base class amongst the diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index e1e17f983ff8..f38f92022d21 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -1,9 +1,8 @@ -//===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- C++ -*-===// +//===- Intrinsics.h - LLVM Intrinsic Function Handling ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -100,7 +99,8 @@ namespace Intrinsic { Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Quad, Integer, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, - SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt + SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt, + VecElementArgument } Kind; union { @@ -117,20 +117,22 @@ namespace Intrinsic { AK_AnyInteger, AK_AnyFloat, AK_AnyVector, - AK_AnyPointer + AK_AnyPointer, + AK_MatchType = 7 }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || Kind == SameVecWidthArgument || Kind == PtrToArgument || - Kind == PtrToElt); + Kind == PtrToElt || Kind == VecElementArgument); return Argument_Info >> 3; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || Kind == TruncArgument || Kind == HalfVecArgument || - Kind == SameVecWidthArgument || Kind == PtrToArgument); + Kind == SameVecWidthArgument || Kind == PtrToArgument || + Kind == VecElementArgument); return (ArgKind)(Argument_Info & 7); } @@ -162,14 +164,21 @@ namespace Intrinsic { /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T); - /// Match the specified type (which comes from an intrinsic argument or return - /// value) with the type constraints specified by the .td file. If the given - /// type is an overloaded type it is pushed to the ArgTys vector. + enum MatchIntrinsicTypesResult { + MatchIntrinsicTypes_Match = 0, + MatchIntrinsicTypes_NoMatchRet = 1, + MatchIntrinsicTypes_NoMatchArg = 2, + }; + + /// Match the specified function type with the type constraints specified by + /// the .td file. If the given type is an overloaded type it is pushed to the + /// ArgTys vector. /// /// Returns false if the given type matches with the constraints, true /// otherwise. - bool matchIntrinsicType(Type *Ty, ArrayRef<IITDescriptor> &Infos, - SmallVectorImpl<Type*> &ArgTys); + MatchIntrinsicTypesResult + matchIntrinsicSignature(FunctionType *FTy, ArrayRef<IITDescriptor> &Infos, + SmallVectorImpl<Type *> &ArgTys); /// Verify if the intrinsic has variable arguments. This method is intended to /// be called after all the fixed arguments have been matched first. diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 64603d8ea030..d660f8278437 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -1,9 +1,8 @@ //===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -70,6 +69,11 @@ class Returned<int argNo> : IntrinsicProperty { int ArgNo = argNo; } +// ImmArg - The specified argument must be an immediate. +class ImmArg<int argNo> : IntrinsicProperty { + int ArgNo = argNo; +} + // ReadOnly - The specified argument pointer is not written to through the // pointer by the intrinsic. class ReadOnly<int argNo> : IntrinsicProperty { @@ -90,6 +94,8 @@ class ReadNone<int argNo> : IntrinsicProperty { def IntrNoReturn : IntrinsicProperty; +def IntrWillReturn : IntrinsicProperty; + // IntrCold - Calls to this intrinsic are cold. // Parallels the cold attribute on LLVM IR functions. def IntrCold : IntrinsicProperty; @@ -157,13 +163,19 @@ class LLVMMatchType<int num> // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType<int num> : LLVMMatchType<num>; class LLVMTruncatedType<int num> : LLVMMatchType<num>; -class LLVMVectorSameWidth<int num, LLVMType elty> - : LLVMMatchType<num> { + +// Match the scalar/vector of another intrinsic parameter but with a different +// element type. Either both are scalars or both are vectors with the same +// number of elements. +class LLVMScalarOrSameVectorWidth<int idx, LLVMType elty> + : LLVMMatchType<idx> { ValueType ElTy = elty.VT; } + class LLVMPointerTo<int num> : LLVMMatchType<num>; class LLVMPointerToElt<int num> : LLVMMatchType<num>; class LLVMVectorOfAnyPointersToElt<int num> : LLVMMatchType<num>; +class LLVMVectorElementType<int num> : LLVMMatchType<num>; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many @@ -251,6 +263,7 @@ def llvm_v2f32_ty : LLVMType<v2f32>; // 2 x float def llvm_v4f32_ty : LLVMType<v4f32>; // 4 x float def llvm_v8f32_ty : LLVMType<v8f32>; // 8 x float def llvm_v16f32_ty : LLVMType<v16f32>; // 16 x float +def llvm_v32f32_ty : LLVMType<v32f32>; // 32 x float def llvm_v1f64_ty : LLVMType<v1f64>; // 1 x double def llvm_v2f64_ty : LLVMType<v2f64>; // 2 x double def llvm_v4f64_ty : LLVMType<v4f64>; // 4 x double @@ -393,9 +406,9 @@ def int_objc_arc_annotation_bottomup_bbend : Intrinsic<[], //===--------------------- Code Generator Intrinsics ----------------------===// // -def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_addressofreturnaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; -def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_sponentry : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrReadMem], "llvm.read_register">; @@ -413,7 +426,7 @@ def int_localescape : Intrinsic<[], [llvm_vararg_ty]>; // to an escaped allocation indicated by the index. def int_localrecover : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; // Given the frame pointer passed into an SEH filter function, returns a // pointer to the local variable area suitable for use with llvm.localrecover. @@ -439,7 +452,8 @@ def int_thread_pointer : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>, // memory while not impeding optimization. def int_prefetch : Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], - [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0> ]>; + [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0>, + ImmArg<1>, ImmArg<2>]>; def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; @@ -480,16 +494,17 @@ def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, - WriteOnly<0>, ReadOnly<1>]>; + WriteOnly<0>, ReadOnly<1>, ImmArg<3>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, - ReadOnly<1>]>; + ReadOnly<1>, ImmArg<3>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty], - [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>; + [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, + ImmArg<3>]>; // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. @@ -527,6 +542,11 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_canonicalize : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + + def int_lround : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; + def int_llround : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; + def int_lrint : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; + def int_llrint : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; } def int_minnum : Intrinsic<[llvm_anyfloat_ty], @@ -554,8 +574,9 @@ def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; // Internal interface for object size checking def int_objectsize : Intrinsic<[llvm_anyint_ty], - [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable]>, + [llvm_anyptr_ty, llvm_i1_ty, + llvm_i1_ty, llvm_i1_ty], + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>, ImmArg<3>]>, GCCBuiltin<"__builtin_object_size">; //===--------------- Constrained Floating Point Intrinsics ----------------===// @@ -595,6 +616,15 @@ let IntrProperties = [IntrInaccessibleMemOnly] in { llvm_metadata_ty, llvm_metadata_ty ]>; + def int_experimental_constrained_fptrunc : Intrinsic<[ llvm_anyfloat_ty ], + [ llvm_anyfloat_ty, + llvm_metadata_ty, + llvm_metadata_ty ]>; + + def int_experimental_constrained_fpext : Intrinsic<[ llvm_anyfloat_ty ], + [ llvm_anyfloat_ty, + llvm_metadata_ty ]>; + // These intrinsics are sensitive to the rounding mode so we need constrained // versions of each of them. When strict rounding and exception control are // not required the non-constrained versions of these intrinsics should be @@ -676,14 +706,12 @@ let IntrProperties = [IntrInaccessibleMemOnly] in { llvm_metadata_ty, llvm_metadata_ty ]>; } -// FIXME: Add intrinsics for fcmp, fptrunc, fpext, fptoui and fptosi. -// FIXME: Add intrinsics for fabs and copysign? - +// FIXME: Add intrinsics for fcmp, fptoui and fptosi. //===------------------------- Expect Intrinsics --------------------------===// // -def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, - LLVMMatchType<0>], [IntrNoMem]>; +def int_expect : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; //===-------------------- Bit Manipulation Intrinsics ---------------------===// // @@ -692,8 +720,6 @@ def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; - def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; - def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; def int_bitreverse : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_fshl : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; @@ -701,6 +727,11 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; } +let IntrProperties = [IntrNoMem, IntrSpeculatable, ImmArg<1>] in { + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; +} + //===------------------------ Debugger Intrinsics -------------------------===// // @@ -797,24 +828,30 @@ def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], // // Expose the carry flag from add operations on two integrals. -def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; -def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; -def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; -def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; -def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; -def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], +def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; @@ -837,23 +874,33 @@ def int_usub_sat : Intrinsic<[llvm_anyint_ty], // def int_smul_fix : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable, Commutative]>; + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; + +def int_umul_fix : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; + +//===------------------- Fixed Point Saturation Arithmetic Intrinsics ----------------===// +// +def int_smul_fix_sat : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; //===------------------------- Memory Use Markers -------------------------===// // def int_lifetime_start : Intrinsic<[], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture<1>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_lifetime_end : Intrinsic<[], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture<1>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_invariant_start : Intrinsic<[llvm_descriptor_ty], [llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture<1>]>; + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; def int_invariant_end : Intrinsic<[], [llvm_descriptor_ty, llvm_i64_ty, llvm_anyptr_ty], - [IntrArgMemOnly, NoCapture<2>]>; + [IntrArgMemOnly, NoCapture<2>, ImmArg<1>]>; // launder.invariant.group can't be marked with 'readnone' (IntrNoMem), // because it would cause CSE of two barriers with the same argument. @@ -900,13 +947,13 @@ def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty], [llvm_i64_ty, llvm_i32_ty, llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty], - [Throws]>; + [Throws, ImmArg<0>, ImmArg<1>, ImmArg<3>, ImmArg<4>]>; def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_token_ty], [IntrReadMem]>; def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty], [llvm_token_ty, llvm_i32_ty, llvm_i32_ty], - [IntrReadMem]>; + [IntrReadMem, ImmArg<1>, ImmArg<2>]>; //===------------------------ Coroutine Intrinsics ---------------===// // These are documented in docs/Coroutines.rst @@ -996,41 +1043,41 @@ def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], // Intrinsic to detect whether its argument is a constant. def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem], "llvm.is.constant">; - //===-------------------------- Masked Intrinsics -------------------------===// // def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty, - LLVMVectorSameWidth<0, llvm_i1_ty>], - [IntrArgMemOnly]>; + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [IntrArgMemOnly, ImmArg<2>]>; def int_masked_load : Intrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty, - LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem, IntrArgMemOnly]>; + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_masked_gather: Intrinsic<[llvm_anyvector_ty], [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, - LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], - [IntrReadMem]>; + [IntrReadMem, ImmArg<1>]>; def int_masked_scatter: Intrinsic<[], [llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, - LLVMVectorSameWidth<0, llvm_i1_ty>]>; + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [ImmArg<2>]>; def int_masked_expandload: Intrinsic<[llvm_anyvector_ty], [LLVMPointerToElt<0>, - LLVMVectorSameWidth<0, llvm_i1_ty>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem]>; def int_masked_compressstore: Intrinsic<[], [llvm_anyvector_ty, LLVMPointerToElt<0>, - LLVMVectorSameWidth<0, llvm_i1_ty>], + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrArgMemOnly]>; // Test whether a pointer is associated with a type metadata identifier. @@ -1049,6 +1096,9 @@ def int_icall_branch_funnel : Intrinsic<[], [llvm_vararg_ty], []>; def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], [IntrReadMem, IntrArgMemOnly]>; +def int_hwasan_check_memaccess : + Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], [IntrInaccessibleMemOnly, ImmArg<2>]>; + // Xray intrinsics //===----------------------------------------------------------------------===// // Custom event logging for x-ray. @@ -1072,7 +1122,7 @@ def int_memcpy_element_unordered_atomic ], [ IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, - ReadOnly<1> + ReadOnly<1>, ImmArg<3> ]>; // @llvm.memmove.element.unordered.atomic.*(dest, src, length, elementsize) @@ -1083,62 +1133,105 @@ def int_memmove_element_unordered_atomic ], [ IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, - ReadOnly<1> + ReadOnly<1>, ImmArg<3> ]>; // @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize) def int_memset_element_unordered_atomic : Intrinsic<[], [ llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty ], - [ IntrArgMemOnly, NoCapture<0>, WriteOnly<0> ]>; + [ IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, ImmArg<3> ]>; //===------------------------ Reduction Intrinsics ------------------------===// // -def int_experimental_vector_reduce_fadd : Intrinsic<[llvm_anyfloat_ty], - [llvm_anyfloat_ty, - llvm_anyvector_ty], - [IntrNoMem]>; -def int_experimental_vector_reduce_fmul : Intrinsic<[llvm_anyfloat_ty], - [llvm_anyfloat_ty, - llvm_anyvector_ty], - [IntrNoMem]>; -def int_experimental_vector_reduce_add : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_v2_fadd : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, + llvm_anyvector_ty], + [IntrNoMem]>; +def int_experimental_vector_reduce_v2_fmul : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, + llvm_anyvector_ty], + [IntrNoMem]>; +def int_experimental_vector_reduce_add : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_mul : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_mul : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_and : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_and : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_or : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_or : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_xor : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_xor : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_smax : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_smax : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_smin : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_smin : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_umax : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_umax : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_umin : Intrinsic<[llvm_anyint_ty], +def int_experimental_vector_reduce_umin : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_fmax : Intrinsic<[llvm_anyfloat_ty], +def int_experimental_vector_reduce_fmax : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; -def int_experimental_vector_reduce_fmin : Intrinsic<[llvm_anyfloat_ty], +def int_experimental_vector_reduce_fmin : Intrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty], [IntrNoMem]>; +//===---------- Intrinsics to control hardware supported loops ----------===// + +// Specify that the value given is the number of iterations that the next loop +// will execute. +def int_set_loop_iterations : + Intrinsic<[], [llvm_anyint_ty], [IntrNoDuplicate]>; + +// Specify that the value given is the number of iterations that the next loop +// will execute. Also test that the given count is not zero, allowing it to +// control entry to a 'while' loop. +def int_test_set_loop_iterations : + Intrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; + +// Decrement loop counter by the given argument. Return false if the loop +// should exit. +def int_loop_decrement : + Intrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; + +// Decrement the first operand (the loop counter) by the second operand (the +// maximum number of elements processed in an iteration). Return the remaining +// number of iterations still to be executed. This is effectively a sub which +// can be used with a phi, icmp and br to control the number of iterations +// executed, as usual. +def int_loop_decrement_reg : + Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_anyint_ty], [IntrNoDuplicate]>; + //===----- Intrinsics that are used to provide predicate information -----===// def int_ssa_copy : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem, Returned<0>]>; + +//===------- Intrinsics that are used to preserve debug information -------===// + +def int_preserve_array_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<2>]>; +def int_preserve_union_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; +def int_preserve_struct_access_index : Intrinsic<[llvm_anyptr_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty], + [IntrNoMem, ImmArg<1>, + ImmArg<2>]>; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index ff25750fe399..832aca4fd30f 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -1,9 +1,8 @@ //===- IntrinsicsAARCH64.td - Defines AARCH64 intrinsics ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -32,6 +31,8 @@ def int_aarch64_sdiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, def int_aarch64_udiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; +def int_aarch64_fjcvtzs : Intrinsic<[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>; + //===----------------------------------------------------------------------===// // HINT @@ -290,6 +291,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { // Pairwise Add def int_aarch64_neon_addp : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_faddp : AdvSIMD_2VectorArg_Intrinsic; // Long Pairwise Add // FIXME: In theory, we shouldn't need intrinsics for saddlp or @@ -462,12 +464,12 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". [IntrArgMemOnly, NoCapture<2>]>; class AdvSIMD_2Vec_Load_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + : Intrinsic<[LLVMMatchType<0>, llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_2Vec_Load_Lane_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [LLVMMatchType<0>, LLVMMatchType<0>, + : Intrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_2Vec_Store_Intrinsic @@ -480,12 +482,12 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". [IntrArgMemOnly, NoCapture<3>]>; class AdvSIMD_3Vec_Load_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>], + : Intrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_3Vec_Load_Lane_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, + : Intrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_3Vec_Store_Intrinsic @@ -499,15 +501,15 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". [IntrArgMemOnly, NoCapture<4>]>; class AdvSIMD_4Vec_Load_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], + : Intrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_4Vec_Load_Lane_Intrinsic - : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + : Intrinsic<[LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty], [IntrReadMem, IntrArgMemOnly]>; class AdvSIMD_4Vec_Store_Intrinsic @@ -684,3 +686,50 @@ def int_aarch64_crc32x : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], def int_aarch64_crc32cx : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], [IntrNoMem]>; } + +//===----------------------------------------------------------------------===// +// Memory Tagging Extensions (MTE) Intrinsics +let TargetPrefix = "aarch64" in { +def int_aarch64_irg : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], + [IntrInaccessibleMemOnly]>; +def int_aarch64_addg : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty], + [IntrNoMem]>; +def int_aarch64_gmi : Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], + [IntrNoMem]>; +def int_aarch64_ldg : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], + [IntrReadMem]>; +def int_aarch64_stg : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [IntrWriteMem]>; +def int_aarch64_subp : Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; + +// The following are codegen-only intrinsics for stack instrumentation. + +// Generate a randomly tagged stack base pointer. +def int_aarch64_irg_sp : Intrinsic<[llvm_ptr_ty], [llvm_i64_ty], + [IntrInaccessibleMemOnly]>; + +// Transfer pointer tag with offset. +// ptr1 = tagp(ptr0, baseptr, tag_offset) returns a pointer where +// * address is the address in ptr0 +// * tag is a function of (tag in baseptr, tag_offset). +// Address bits in baseptr and tag bits in ptr0 are ignored. +// When offset between ptr0 and baseptr is a compile time constant, this can be emitted as +// ADDG ptr1, baseptr, (ptr0 - baseptr), tag_offset +// It is intended that ptr0 is an alloca address, and baseptr is the direct output of llvm.aarch64.irg.sp. +def int_aarch64_tagp : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_ptr_ty, llvm_i64_ty], + [IntrNoMem, ImmArg<2>]>; + +// Update allocation tags for the memory range to match the tag in the pointer argument. +def int_aarch64_settag : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], + [IntrWriteMem, IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>; + +// Update allocation tags for the memory range to match the tag in the pointer argument, +// and set memory contents to zero. +def int_aarch64_settag_zero : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], + [IntrWriteMem, IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>; + +// Update allocation tags for 16-aligned, 16-sized memory region, and store a pair 8-byte values. +def int_aarch64_stgp : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i64_ty], + [IntrWriteMem, IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>; +} diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td index 7913ce828fbc..3982444b5401 100644 --- a/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/include/llvm/IR/IntrinsicsAMDGPU.td @@ -1,9 +1,8 @@ //===- IntrinsicsAMDGPU.td - Defines AMDGPU intrinsics -----*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -178,7 +177,7 @@ def int_amdgcn_implicit_buffer_ptr : // This is always moved to the beginning of the basic block. def int_amdgcn_init_exec : Intrinsic<[], [llvm_i64_ty], // 64-bit literal constant - [IntrConvergent]>; + [IntrConvergent, ImmArg<0>]>; // Set EXEC according to a thread count packed in an SGPR input: // thread_count = (input >> bitoffset) & 0x7f; @@ -188,6 +187,10 @@ def int_amdgcn_init_exec_from_input : Intrinsic<[], llvm_i32_ty], // bit offset of the thread count [IntrConvergent]>; +def int_amdgcn_wavefrontsize : + GCCBuiltin<"__builtin_amdgcn_wavefrontsize">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>; + //===----------------------------------------------------------------------===// // Instruction Intrinsics @@ -196,9 +199,9 @@ def int_amdgcn_init_exec_from_input : Intrinsic<[], // The first parameter is s_sendmsg immediate (i16), // the second one is copied to m0 def int_amdgcn_s_sendmsg : GCCBuiltin<"__builtin_amdgcn_s_sendmsg">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], []>; + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, IntrInaccessibleMemOnly]>; def int_amdgcn_s_sendmsghalt : GCCBuiltin<"__builtin_amdgcn_s_sendmsghalt">, - Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], []>; + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, IntrInaccessibleMemOnly]>; def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">, Intrinsic<[], [], [IntrConvergent]>; @@ -207,7 +210,7 @@ def int_amdgcn_wave_barrier : GCCBuiltin<"__builtin_amdgcn_wave_barrier">, Intrinsic<[], [], [IntrConvergent]>; def int_amdgcn_s_waitcnt : GCCBuiltin<"__builtin_amdgcn_s_waitcnt">, - Intrinsic<[], [llvm_i32_ty], []>; + Intrinsic<[], [llvm_i32_ty], [ImmArg<0>]>; def int_amdgcn_div_scale : Intrinsic< // 1st parameter: Numerator @@ -216,7 +219,7 @@ def int_amdgcn_div_scale : Intrinsic< // second. (0 = first, 1 = second). [llvm_anyfloat_ty, llvm_i1_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<2>] >; def int_amdgcn_div_fmas : Intrinsic<[llvm_anyfloat_ty], @@ -293,29 +296,33 @@ def int_amdgcn_fract : Intrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_cvt_pkrtz : Intrinsic< - [llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable] +def int_amdgcn_cvt_pkrtz : GCCBuiltin<"__builtin_amdgcn_cvt_pkrtz">, + Intrinsic<[llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_cvt_pknorm_i16 : Intrinsic< - [llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable] +def int_amdgcn_cvt_pknorm_i16 : + GCCBuiltin<"__builtin_amdgcn_cvt_pknorm_i16">, + Intrinsic<[llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_cvt_pknorm_u16 : Intrinsic< - [llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], - [IntrNoMem, IntrSpeculatable] +def int_amdgcn_cvt_pknorm_u16 : + GCCBuiltin<"__builtin_amdgcn_cvt_pknorm_u16">, + Intrinsic<[llvm_v2i16_ty], [llvm_float_ty, llvm_float_ty], + [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_cvt_pk_i16 : Intrinsic< +def int_amdgcn_cvt_pk_i16 : + GCCBuiltin<"__builtin_amdgcn_cvt_pk_i16">, + Intrinsic< [llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_cvt_pk_u16 : Intrinsic< - [llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable] +def int_amdgcn_cvt_pk_u16 : GCCBuiltin<"__builtin_amdgcn_cvt_pk_u16">, + Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable] >; def int_amdgcn_class : Intrinsic< @@ -374,7 +381,7 @@ class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty], llvm_i32_ty, // ordering llvm_i32_ty, // scope llvm_i1_ty], // isVolatile - [IntrArgMemOnly, NoCapture<0>], "", + [IntrArgMemOnly, NoCapture<0>, ImmArg<2>, ImmArg<3>, ImmArg<4>], "", [SDNPMemOperand] >; @@ -389,9 +396,45 @@ class AMDGPULDSF32Intrin<string clang_builtin> : llvm_i32_ty, // ordering llvm_i32_ty, // scope llvm_i1_ty], // isVolatile - [IntrArgMemOnly, NoCapture<0>] + [IntrArgMemOnly, NoCapture<0>, ImmArg<2>, ImmArg<3>, ImmArg<4>] +>; + +// FIXME: The m0 argument should be moved after the normal arguments +class AMDGPUDSOrderedIntrinsic : Intrinsic< + [llvm_i32_ty], + // M0 = {hi16:address, lo16:waveID}. Allow passing M0 as a pointer, so that + // the bit packing can be optimized at the IR level. + [LLVMQualPointerType<llvm_i32_ty, 2>, // IntToPtr(M0) + llvm_i32_ty, // value to add or swap + llvm_i32_ty, // ordering + llvm_i32_ty, // scope + llvm_i1_ty, // isVolatile + llvm_i32_ty, // ordered count index (OA index), also added to the address + // gfx10: bits 24-27 indicate the number of active threads/dwords + llvm_i1_ty, // wave release, usually set to 1 + llvm_i1_ty], // wave done, set to 1 for the last ordered instruction + [NoCapture<0>, + ImmArg<2>, ImmArg<3>, ImmArg<4>, + ImmArg<5>, ImmArg<6>, ImmArg<7> + ] +>; + +class AMDGPUDSAppendConsumedIntrinsic : Intrinsic< + [llvm_i32_ty], + [llvm_anyptr_ty, // LDS or GDS ptr + llvm_i1_ty], // isVolatile + [IntrConvergent, IntrArgMemOnly, NoCapture<0>, ImmArg<1>], + "", + [SDNPMemOperand] >; +def int_amdgcn_ds_ordered_add : AMDGPUDSOrderedIntrinsic; +def int_amdgcn_ds_ordered_swap : AMDGPUDSOrderedIntrinsic; + +// The pointer argument is assumed to be dynamically uniform if a VGPR. +def int_amdgcn_ds_append : AMDGPUDSAppendConsumedIntrinsic; +def int_amdgcn_ds_consume : AMDGPUDSAppendConsumedIntrinsic; + def int_amdgcn_ds_fadd : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_faddf">; def int_amdgcn_ds_fmin : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fminf">; def int_amdgcn_ds_fmax : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fmaxf">; @@ -442,9 +485,12 @@ class arglistconcat<list<list<AMDGPUArg>> arglists, int shift = 0> { } // Represent texture/image types / dimensionality. -class AMDGPUDimProps<string name, list<string> coord_names, list<string> slice_names> { +class AMDGPUDimProps<bits<3> enc, string name, string asmsuffix, + list<string> coord_names, list<string> slice_names> { AMDGPUDimProps Dim = !cast<AMDGPUDimProps>(NAME); string Name = name; // e.g. "2darraymsaa" + string AsmSuffix = asmsuffix; // e.g. 2D_MSAA_ARRAY (used in assembly strings) + bits<3> Encoding = enc; bit DA = 0; // DA bit in MIMG encoding list<AMDGPUArg> CoordSliceArgs = @@ -460,17 +506,17 @@ class AMDGPUDimProps<string name, list<string> coord_names, list<string> slice_n bits<8> NumGradients = !size(GradientArgs); } -def AMDGPUDim1D : AMDGPUDimProps<"1d", ["s"], []>; -def AMDGPUDim2D : AMDGPUDimProps<"2d", ["s", "t"], []>; -def AMDGPUDim3D : AMDGPUDimProps<"3d", ["s", "t", "r"], []>; +def AMDGPUDim1D : AMDGPUDimProps<0x0, "1d", "1D", ["s"], []>; +def AMDGPUDim2D : AMDGPUDimProps<0x1, "2d", "2D", ["s", "t"], []>; +def AMDGPUDim3D : AMDGPUDimProps<0x2, "3d", "3D", ["s", "t", "r"], []>; let DA = 1 in { - def AMDGPUDimCube : AMDGPUDimProps<"cube", ["s", "t"], ["face"]>; - def AMDGPUDim1DArray : AMDGPUDimProps<"1darray", ["s"], ["slice"]>; - def AMDGPUDim2DArray : AMDGPUDimProps<"2darray", ["s", "t"], ["slice"]>; + def AMDGPUDimCube : AMDGPUDimProps<0x3, "cube", "CUBE", ["s", "t"], ["face"]>; + def AMDGPUDim1DArray : AMDGPUDimProps<0x4, "1darray", "1D_ARRAY", ["s"], ["slice"]>; + def AMDGPUDim2DArray : AMDGPUDimProps<0x5, "2darray", "2D_ARRAY", ["s", "t"], ["slice"]>; } -def AMDGPUDim2DMsaa : AMDGPUDimProps<"2dmsaa", ["s", "t"], ["fragid"]>; +def AMDGPUDim2DMsaa : AMDGPUDimProps<0x6, "2dmsaa", "2D_MSAA", ["s", "t"], ["fragid"]>; let DA = 1 in { - def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<"2darraymsaa", ["s", "t"], ["slice", "fragid"]>; + def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<0x7, "2darraymsaa", "2D_MSAA_ARRAY", ["s", "t"], ["slice", "fragid"]>; } def AMDGPUDims { @@ -621,6 +667,19 @@ class AMDGPUDimGetResInfoProfile<AMDGPUDimProps dim> : AMDGPUDimProfile<"GET_RES let LodClampMip = "mip"; } +// Helper class for figuring out image intrinsic argument indexes. +class AMDGPUImageDimIntrinsicEval<AMDGPUDimProfile P_> { + int NumDataArgs = !size(P_.DataArgs); + int NumDmaskArgs = !if(P_.IsAtomic, 0, 1); + int NumVAddrArgs = !size(P_.AddrArgs); + int NumRSrcArgs = 1; + int NumSampArgs = !if(P_.IsSample, 2, 0); + int DmaskArgIndex = NumDataArgs; + int UnormArgIndex = !add(NumDataArgs, NumDmaskArgs, NumVAddrArgs, NumRSrcArgs, 1); + int TexFailCtrlArgIndex = !add(NumDataArgs, NumDmaskArgs, NumVAddrArgs, NumRSrcArgs, NumSampArgs); + int CachePolicyArgIndex = !add(TexFailCtrlArgIndex, 1); +} + // All dimension-aware intrinsics are derived from this class. class AMDGPUImageDimIntrinsic<AMDGPUDimProfile P_, list<IntrinsicProperty> props, @@ -634,8 +693,13 @@ class AMDGPUImageDimIntrinsic<AMDGPUDimProfile P_, !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR) llvm_i1_ty], []), // unorm(imm) [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe) - llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - props, "", sdnodeprops>, + llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc) + !listconcat(props, + !if(P_.IsAtomic, [], [ImmArg<AMDGPUImageDimIntrinsicEval<P_>.DmaskArgIndex>]), + !if(P_.IsSample, [ImmArg<AMDGPUImageDimIntrinsicEval<P_>.UnormArgIndex>], []), + [ImmArg<AMDGPUImageDimIntrinsicEval<P_>.TexFailCtrlArgIndex>, + ImmArg<AMDGPUImageDimIntrinsicEval<P_>.CachePolicyArgIndex>]), + "", sdnodeprops>, AMDGPURsrcIntrinsic<!add(!size(P_.DataArgs), !size(P_.AddrTypes), !if(P_.IsAtomic, 0, 1)), 1> { AMDGPUDimProfile P = P_; @@ -791,13 +855,13 @@ let TargetPrefix = "amdgcn" in { defset list<AMDGPURsrcIntrinsic> AMDGPUBufferIntrinsics = { class AMDGPUBufferLoad : Intrinsic < - [llvm_anyfloat_ty], + [llvm_any_ty], [llvm_v4i32_ty, // rsrc(SGPR) llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrReadMem], "", [SDNPMemOperand]>, + [IntrReadMem, ImmArg<3>, ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_buffer_load_format : AMDGPUBufferLoad; def int_amdgcn_buffer_load : AMDGPUBufferLoad; @@ -805,20 +869,20 @@ def int_amdgcn_buffer_load : AMDGPUBufferLoad; def int_amdgcn_s_buffer_load : Intrinsic < [llvm_any_ty], [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // byte offset(SGPR/VGPR/imm) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc) - [IntrNoMem]>, + llvm_i32_ty, // byte offset(SGPR/imm) + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 2 = dlc) + [IntrNoMem, ImmArg<2>]>, AMDGPURsrcIntrinsic<0>; class AMDGPUBufferStore : Intrinsic < [], - [llvm_anyfloat_ty, // vdata(VGPR) -- can currently only select f32, v2f32, v4f32 + [llvm_any_ty, // vdata(VGPR) llvm_v4i32_ty, // rsrc(SGPR) llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrWriteMem], "", [SDNPMemOperand]>, + [IntrWriteMem, ImmArg<4>, ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_buffer_store_format : AMDGPUBufferStore; def int_amdgcn_buffer_store : AMDGPUBufferStore; @@ -835,8 +899,8 @@ class AMDGPURawBufferLoad : Intrinsic < [llvm_v4i32_ty, // rsrc(SGPR) llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrReadMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrReadMem, ImmArg<3>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_raw_buffer_load_format : AMDGPURawBufferLoad; def int_amdgcn_raw_buffer_load : AMDGPURawBufferLoad; @@ -847,8 +911,8 @@ class AMDGPUStructBufferLoad : Intrinsic < llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrReadMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrReadMem, ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_buffer_load_format : AMDGPUStructBufferLoad; def int_amdgcn_struct_buffer_load : AMDGPUStructBufferLoad; @@ -859,8 +923,8 @@ class AMDGPURawBufferStore : Intrinsic < llvm_v4i32_ty, // rsrc(SGPR) llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrWriteMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrWriteMem, ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_raw_buffer_store_format : AMDGPURawBufferStore; def int_amdgcn_raw_buffer_store : AMDGPURawBufferStore; @@ -872,8 +936,8 @@ class AMDGPUStructBufferStore : Intrinsic < llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrWriteMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrWriteMem, ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_struct_buffer_store_format : AMDGPUStructBufferStore; def int_amdgcn_struct_buffer_store : AMDGPUStructBufferStore; @@ -885,7 +949,7 @@ class AMDGPURawBufferAtomic : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [], "", [SDNPMemOperand]>, + [ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1, 0>; def int_amdgcn_raw_buffer_atomic_swap : AMDGPURawBufferAtomic; def int_amdgcn_raw_buffer_atomic_add : AMDGPURawBufferAtomic; @@ -905,7 +969,7 @@ def int_amdgcn_raw_buffer_atomic_cmpswap : Intrinsic< llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [], "", [SDNPMemOperand]>, + [ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<2, 0>; class AMDGPUStructBufferAtomic : Intrinsic < @@ -916,7 +980,7 @@ class AMDGPUStructBufferAtomic : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [], "", [SDNPMemOperand]>, + [ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1, 0>; def int_amdgcn_struct_buffer_atomic_swap : AMDGPUStructBufferAtomic; def int_amdgcn_struct_buffer_atomic_add : AMDGPUStructBufferAtomic; @@ -937,7 +1001,7 @@ def int_amdgcn_struct_buffer_atomic_cmpswap : Intrinsic< llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty], // cachepolicy(imm; bit 1 = slc) - [], "", [SDNPMemOperand]>, + [ImmArg<6>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<2, 0>; // Obsolescent tbuffer intrinsics. @@ -952,7 +1016,8 @@ def int_amdgcn_tbuffer_load : Intrinsic < llvm_i32_ty, // nfmt(imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrReadMem], "", [SDNPMemOperand]>, + [IntrReadMem, ImmArg<4>, ImmArg<5>, ImmArg<6>, + ImmArg<7>, ImmArg<8>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_tbuffer_store : Intrinsic < @@ -967,7 +1032,8 @@ def int_amdgcn_tbuffer_store : Intrinsic < llvm_i32_ty, // nfmt(imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrWriteMem], "", [SDNPMemOperand]>, + [IntrWriteMem, ImmArg<5>, ImmArg<6>, ImmArg<7>, + ImmArg<8>, ImmArg<9>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; // New tbuffer intrinsics, with: @@ -980,8 +1046,8 @@ def int_amdgcn_raw_tbuffer_load : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrReadMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrReadMem, ImmArg<3>, ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_raw_tbuffer_store : Intrinsic < @@ -991,8 +1057,8 @@ def int_amdgcn_raw_tbuffer_store : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrWriteMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrWriteMem, ImmArg<4>, ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_struct_tbuffer_load : Intrinsic < @@ -1002,8 +1068,8 @@ def int_amdgcn_struct_tbuffer_load : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrReadMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrReadMem, ImmArg<4>, ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_tbuffer_store : Intrinsic < @@ -1014,18 +1080,18 @@ def int_amdgcn_struct_tbuffer_store : Intrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc) - [IntrWriteMem], "", [SDNPMemOperand]>, + llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc on gfx10+) + [IntrWriteMem, ImmArg<5>, ImmArg<6>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; class AMDGPUBufferAtomic : Intrinsic < - [llvm_i32_ty], - [llvm_i32_ty, // vdata(VGPR) + [llvm_anyint_ty], + [LLVMMatchType<0>, // vdata(VGPR) llvm_v4i32_ty, // rsrc(SGPR) llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>, + [ImmArg<4>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1, 0>; def int_amdgcn_buffer_atomic_swap : AMDGPUBufferAtomic; def int_amdgcn_buffer_atomic_add : AMDGPUBufferAtomic; @@ -1045,7 +1111,7 @@ def int_amdgcn_buffer_atomic_cmpswap : Intrinsic< llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>, + [ImmArg<5>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<2, 0>; } // defset AMDGPUBufferIntrinsics @@ -1062,7 +1128,7 @@ def int_amdgcn_exp : Intrinsic <[], [ llvm_i1_ty, // done llvm_i1_ty // vm ], - [] + [ImmArg<0>, ImmArg<1>, ImmArg<6>, ImmArg<7>, IntrInaccessibleMemOnly] >; // exp with compr bit set. @@ -1073,7 +1139,7 @@ def int_amdgcn_exp_compr : Intrinsic <[], [ LLVMMatchType<0>, // src1 llvm_i1_ty, // done llvm_i1_ty], // vm - [] + [ImmArg<0>, ImmArg<1>, ImmArg<4>, ImmArg<5>, IntrInaccessibleMemOnly] >; def int_amdgcn_buffer_wbinvl1_sc : @@ -1090,27 +1156,27 @@ def int_amdgcn_s_dcache_inv : def int_amdgcn_s_memtime : GCCBuiltin<"__builtin_amdgcn_s_memtime">, - Intrinsic<[llvm_i64_ty], [], [IntrReadMem]>; + Intrinsic<[llvm_i64_ty], []>; def int_amdgcn_s_sleep : GCCBuiltin<"__builtin_amdgcn_s_sleep">, - Intrinsic<[], [llvm_i32_ty], []> { + Intrinsic<[], [llvm_i32_ty], [ImmArg<0>]> { } def int_amdgcn_s_incperflevel : GCCBuiltin<"__builtin_amdgcn_s_incperflevel">, - Intrinsic<[], [llvm_i32_ty], []> { + Intrinsic<[], [llvm_i32_ty], [ImmArg<0>]> { } def int_amdgcn_s_decperflevel : GCCBuiltin<"__builtin_amdgcn_s_decperflevel">, - Intrinsic<[], [llvm_i32_ty], []> { + Intrinsic<[], [llvm_i32_ty], [ImmArg<0>]> { } def int_amdgcn_s_getreg : GCCBuiltin<"__builtin_amdgcn_s_getreg">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], - [IntrReadMem, IntrSpeculatable] + [IntrInaccessibleMemOnly, IntrReadMem, IntrSpeculatable, ImmArg<0>] >; // int_amdgcn_s_getpc is provided to allow a specific style of position @@ -1129,7 +1195,7 @@ def int_amdgcn_interp_mov : GCCBuiltin<"__builtin_amdgcn_interp_mov">, Intrinsic<[llvm_float_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable]>; + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>]>; // __builtin_amdgcn_interp_p1 <i>, <attr_chan>, <attr>, <m0> // This intrinsic reads from lds, but the memory values are constant, @@ -1138,16 +1204,30 @@ def int_amdgcn_interp_p1 : GCCBuiltin<"__builtin_amdgcn_interp_p1">, Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable]>; + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>]>; // __builtin_amdgcn_interp_p2 <p1>, <j>, <attr_chan>, <attr>, <m0> def int_amdgcn_interp_p2 : GCCBuiltin<"__builtin_amdgcn_interp_p2">, Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable]>; + [IntrNoMem, IntrSpeculatable, ImmArg<2>, ImmArg<3>]>; // See int_amdgcn_v_interp_p1 for why this is IntrNoMem. +// __builtin_amdgcn_interp_p1_f16 <i>, <attr_chan>, <attr>, <high>, <m0> +def int_amdgcn_interp_p1_f16 : + GCCBuiltin<"__builtin_amdgcn_interp_p1_f16">, + Intrinsic<[llvm_float_ty], + [llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>, ImmArg<3>]>; + +// __builtin_amdgcn_interp_p2_f16 <p1>, <j>, <attr_chan>, <attr>, <high>, <m0> +def int_amdgcn_interp_p2_f16 : + GCCBuiltin<"__builtin_amdgcn_interp_p2_f16">, + Intrinsic<[llvm_half_ty], + [llvm_float_ty, llvm_float_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, ImmArg<2>, ImmArg<3>, ImmArg<4>]>; + // Pixel shaders only: whether the current pixel is live (i.e. not a helper // invocation for derivative computation). def int_amdgcn_ps_live : Intrinsic < @@ -1166,16 +1246,17 @@ def int_amdgcn_mbcnt_hi : // llvm.amdgcn.ds.swizzle src offset def int_amdgcn_ds_swizzle : GCCBuiltin<"__builtin_amdgcn_ds_swizzle">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrConvergent, ImmArg<1>]>; def int_amdgcn_ubfe : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable] + [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable] >; def int_amdgcn_sbfe : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem, IntrSpeculatable] + [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable] >; def int_amdgcn_lerp : @@ -1233,12 +1314,12 @@ def int_amdgcn_cvt_pk_u8_f32 : >; def int_amdgcn_icmp : - Intrinsic<[llvm_i64_ty], [llvm_anyint_ty, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrConvergent]>; + Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>, llvm_i32_ty], + [IntrNoMem, IntrConvergent, ImmArg<2>]>; def int_amdgcn_fcmp : - Intrinsic<[llvm_i64_ty], [llvm_anyfloat_ty, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem, IntrConvergent]>; + Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, LLVMMatchType<1>, llvm_i32_ty], + [IntrNoMem, IntrConvergent, ImmArg<2>]>; def int_amdgcn_readfirstlane : GCCBuiltin<"__builtin_amdgcn_readfirstlane">, @@ -1263,16 +1344,86 @@ def int_amdgcn_writelane : [IntrNoMem, IntrConvergent] >; -def int_amdgcn_alignbit : Intrinsic<[llvm_i32_ty], +def int_amdgcn_alignbit : + GCCBuiltin<"__builtin_amdgcn_alignbit">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable] >; -def int_amdgcn_alignbyte : Intrinsic<[llvm_i32_ty], - [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], +def int_amdgcn_alignbyte : GCCBuiltin<"__builtin_amdgcn_alignbyte">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable] >; +def int_amdgcn_mul_i24 : Intrinsic<[llvm_i32_ty], + [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable] +>; + +def int_amdgcn_mul_u24 : Intrinsic<[llvm_i32_ty], + [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable] +>; + +// llvm.amdgcn.ds.gws.init(i32 bar_val, i32 resource_id) +// +// bar_val is the total number of waves that will wait on this +// barrier, minus 1. +def int_amdgcn_ds_gws_init : + GCCBuiltin<"__builtin_amdgcn_ds_gws_init">, + Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrWriteMem, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + +// llvm.amdgcn.ds.gws.barrier(i32 vsrc0, i32 resource_id) +// bar_val is the total number of waves that will wait on this +// barrier, minus 1. +def int_amdgcn_ds_gws_barrier : + GCCBuiltin<"__builtin_amdgcn_ds_gws_barrier">, + Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + +// llvm.amdgcn.ds.gws.sema.v(i32 resource_id) +def int_amdgcn_ds_gws_sema_v : + GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_v">, + Intrinsic<[], + [llvm_i32_ty], + [IntrConvergent, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + +// llvm.amdgcn.ds.gws.sema.br(i32 vsrc, i32 resource_id) +def int_amdgcn_ds_gws_sema_br : + GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_br">, + Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + +// llvm.amdgcn.ds.gws.sema.p(i32 resource_id) +def int_amdgcn_ds_gws_sema_p : + GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_p">, + Intrinsic<[], + [llvm_i32_ty], + [IntrConvergent, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + +// llvm.amdgcn.ds.gws.sema.release.all(i32 resource_id) +def int_amdgcn_ds_gws_sema_release_all : + GCCBuiltin<"__builtin_amdgcn_ds_gws_sema_release_all">, + Intrinsic<[], + [llvm_i32_ty], + [IntrConvergent, IntrInaccessibleMemOnly], "", + [SDNPMemOperand] +>; + // Copies the source value to the destination value, with the guarantee that // the source value is computed as if the entire program were executed in WQM. @@ -1295,7 +1446,7 @@ def int_amdgcn_kill : Intrinsic<[], [llvm_i1_ty], []>; // enabled, with a few exceptions: - Phi nodes with require WWM return an // undefined value. def int_amdgcn_wwm : Intrinsic<[llvm_any_ty], - [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable] + [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrConvergent] >; // Given a value, copies it while setting all the inactive lanes to a given @@ -1328,7 +1479,8 @@ def int_amdgcn_buffer_wbinvl1_vol : def int_amdgcn_mov_dpp : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i1_ty], [IntrNoMem, IntrConvergent]>; + llvm_i1_ty], [IntrNoMem, IntrConvergent, ImmArg<1>, + ImmArg<2>, ImmArg<3>, ImmArg<4>]>; // llvm.amdgcn.update.dpp.i32 <old> <src> <dpp_ctrl> <row_mask> <bank_mask> <bound_ctrl> // Should be equivalent to: @@ -1336,8 +1488,10 @@ def int_amdgcn_mov_dpp : // v_mov_b32 <dest> <src> <dpp_ctrl> <row_mask> <bank_mask> <bound_ctrl> def int_amdgcn_update_dpp : Intrinsic<[llvm_anyint_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i1_ty], [IntrNoMem, IntrConvergent]>; + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i1_ty], + [IntrNoMem, IntrConvergent, + ImmArg<2>, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; def int_amdgcn_s_dcache_wb : GCCBuiltin<"__builtin_amdgcn_s_dcache_wb">, @@ -1349,7 +1503,7 @@ def int_amdgcn_s_dcache_wb_vol : def int_amdgcn_s_memrealtime : GCCBuiltin<"__builtin_amdgcn_s_memrealtime">, - Intrinsic<[llvm_i64_ty], [], [IntrReadMem]>; + Intrinsic<[llvm_i64_ty]>; // llvm.amdgcn.ds.permute <index> <src> def int_amdgcn_ds_permute : @@ -1362,6 +1516,34 @@ def int_amdgcn_ds_bpermute : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>; //===----------------------------------------------------------------------===// +// GFX10 Intrinsics +//===----------------------------------------------------------------------===// + +// llvm.amdgcn.permlane16 <old> <src0> <src1> <src2> <fi> <bound_control> +def int_amdgcn_permlane16 : GCCBuiltin<"__builtin_amdgcn_permlane16">, + Intrinsic<[llvm_i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i1_ty], + [IntrNoMem, IntrConvergent, ImmArg<4>, ImmArg<5>]>; + +// llvm.amdgcn.permlanex16 <old> <src0> <src1> <src2> <fi> <bound_control> +def int_amdgcn_permlanex16 : GCCBuiltin<"__builtin_amdgcn_permlanex16">, + Intrinsic<[llvm_i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty, llvm_i1_ty], + [IntrNoMem, IntrConvergent, ImmArg<4>, ImmArg<5>]>; + +// llvm.amdgcn.mov.dpp8.i32 <src> <sel> +// <sel> is a 32-bit constant whose high 8 bits must be zero which selects +// the lanes to read from. +def int_amdgcn_mov_dpp8 : + Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem, IntrConvergent, ImmArg<1>]>; + +def int_amdgcn_s_get_waveid_in_workgroup : + GCCBuiltin<"__builtin_amdgcn_s_get_waveid_in_workgroup">, + Intrinsic<[llvm_i32_ty], [], [IntrReadMem, IntrInaccessibleMemOnly]>; + +//===----------------------------------------------------------------------===// // Deep learning intrinsics. //===----------------------------------------------------------------------===// @@ -1377,7 +1559,7 @@ def int_amdgcn_fdot2 : llvm_float_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // i32 %r = llvm.amdgcn.sdot2(v2i16 %a, v2i16 %b, i32 %c, i1 %clamp) @@ -1392,7 +1574,7 @@ def int_amdgcn_sdot2 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // u32 %r = llvm.amdgcn.udot2(v2u16 %a, v2u16 %b, u32 %c, i1 %clamp) @@ -1407,7 +1589,7 @@ def int_amdgcn_udot2 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // i32 %r = llvm.amdgcn.sdot4(v4i8 (as i32) %a, v4i8 (as i32) %b, i32 %c, i1 %clamp) @@ -1422,7 +1604,7 @@ def int_amdgcn_sdot4 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // u32 %r = llvm.amdgcn.udot4(v4u8 (as u32) %a, v4u8 (as u32) %b, u32 %c, i1 %clamp) @@ -1437,7 +1619,7 @@ def int_amdgcn_udot4 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // i32 %r = llvm.amdgcn.sdot8(v8i4 (as i32) %a, v8i4 (as i32) %b, i32 %c, i1 %clamp) @@ -1453,7 +1635,7 @@ def int_amdgcn_sdot8 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; // u32 %r = llvm.amdgcn.udot8(v8u4 (as u32) %a, v8u4 (as u32) %b, u32 %c, i1 %clamp) @@ -1469,30 +1651,154 @@ def int_amdgcn_udot8 : llvm_i32_ty, // %c llvm_i1_ty // %clamp ], - [IntrNoMem, IntrSpeculatable] + [IntrNoMem, IntrSpeculatable, ImmArg<3>] >; //===----------------------------------------------------------------------===// +// gfx908 intrinsics +// ===----------------------------------------------------------------------===// + +class AMDGPUBufferAtomicNoRtn : Intrinsic < + [], + [llvm_anyfloat_ty, // vdata(VGPR) + llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(SGPR/VGPR/imm) + llvm_i1_ty], // slc(imm) + [], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<1, 0>; + +class AMDGPUGlobalAtomicNoRtn : Intrinsic < + [], + [llvm_anyptr_ty, // vaddr + llvm_anyfloat_ty], // vdata(VGPR) + [IntrArgMemOnly, NoCapture<0>], "", [SDNPMemOperand]>; + +def int_amdgcn_buffer_atomic_fadd : AMDGPUBufferAtomicNoRtn; +def int_amdgcn_global_atomic_fadd : AMDGPUGlobalAtomicNoRtn; + +// llvm.amdgcn.mfma.f32.* vdst, srcA, srcB, srcC, cbsz, abid, blgp +def int_amdgcn_mfma_f32_32x32x1f32 : Intrinsic<[llvm_v32f32_ty], + [llvm_float_ty, llvm_float_ty, llvm_v32f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x1f32 : Intrinsic<[llvm_v16f32_ty], + [llvm_float_ty, llvm_float_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_4x4x1f32 : Intrinsic<[llvm_v4f32_ty], + [llvm_float_ty, llvm_float_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_32x32x2f32 : Intrinsic<[llvm_v16f32_ty], + [llvm_float_ty, llvm_float_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x4f32 : Intrinsic<[llvm_v4f32_ty], + [llvm_float_ty, llvm_float_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_32x32x4f16 : Intrinsic<[llvm_v32f32_ty], + [llvm_v4f16_ty, llvm_v4f16_ty, llvm_v32f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x4f16 : Intrinsic<[llvm_v16f32_ty], + [llvm_v4f16_ty, llvm_v4f16_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_4x4x4f16 : Intrinsic<[llvm_v4f32_ty], + [llvm_v4f16_ty, llvm_v4f16_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_32x32x8f16 : Intrinsic<[llvm_v16f32_ty], + [llvm_v4f16_ty, llvm_v4f16_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x16f16 : Intrinsic<[llvm_v4f32_ty], + [llvm_v4f16_ty, llvm_v4f16_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_i32_32x32x4i8 : Intrinsic<[llvm_v32i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_v32i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_i32_16x16x4i8 : Intrinsic<[llvm_v16i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_v16i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_i32_4x4x4i8 : Intrinsic<[llvm_v4i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_v4i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_i32_32x32x8i8 : Intrinsic<[llvm_v16i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_v16i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_i32_16x16x16i8 : Intrinsic<[llvm_v4i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_v4i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_32x32x2bf16 : Intrinsic<[llvm_v32f32_ty], + [llvm_v2i16_ty, llvm_v2i16_ty, llvm_v32f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x2bf16 : Intrinsic<[llvm_v16f32_ty], + [llvm_v2i16_ty, llvm_v2i16_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_4x4x2bf16 : Intrinsic<[llvm_v4f32_ty], + [llvm_v2i16_ty, llvm_v2i16_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_32x32x4bf16 : Intrinsic<[llvm_v16f32_ty], + [llvm_v2i16_ty, llvm_v2i16_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +def int_amdgcn_mfma_f32_16x16x8bf16 : Intrinsic<[llvm_v4f32_ty], + [llvm_v2i16_ty, llvm_v2i16_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrConvergent, IntrNoMem, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; + +//===----------------------------------------------------------------------===// // Special Intrinsics for backend internal use only. No frontend // should emit calls to these. // ===----------------------------------------------------------------------===// -def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_i64_ty], +def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_anyint_ty], [llvm_i1_ty], [IntrConvergent] >; -def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_i64_ty], - [llvm_i64_ty], [IntrConvergent] +def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_anyint_ty], + [llvm_anyint_ty], [IntrConvergent] >; -def int_amdgcn_if_break : Intrinsic<[llvm_i64_ty], - [llvm_i1_ty, llvm_i64_ty], [IntrNoMem, IntrConvergent] +def int_amdgcn_if_break : Intrinsic<[llvm_anyint_ty], + [llvm_i1_ty, llvm_anyint_ty], [IntrNoMem, IntrConvergent] >; def int_amdgcn_loop : Intrinsic<[llvm_i1_ty], - [llvm_i64_ty], [IntrConvergent] + [llvm_anyint_ty], [IntrConvergent] >; -def int_amdgcn_end_cf : Intrinsic<[], [llvm_i64_ty], [IntrConvergent]>; +def int_amdgcn_end_cf : Intrinsic<[], [llvm_anyint_ty], [IntrConvergent]>; // Represent unreachable in a divergent region. def int_amdgcn_unreachable : Intrinsic<[], [], [IntrConvergent]>; diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 4e11f9c29dd0..4792af097d95 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -1,9 +1,8 @@ //===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,7 +19,7 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". // A space-consuming intrinsic primarily for testing ARMConstantIslands. The // first argument is the number of bytes this "instruction" takes up, the second // and return value are essentially chains, used to force ordering during ISel. -def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; +def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>; // 16-bit multiplications def int_arm_smulbb : GCCBuiltin<"__builtin_arm_smulbb">, @@ -263,59 +262,59 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], // Coprocessor def int_arm_ldc : GCCBuiltin<"__builtin_arm_ldc">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_ldcl : GCCBuiltin<"__builtin_arm_ldcl">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_ldc2 : GCCBuiltin<"__builtin_arm_ldc2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_ldc2l : GCCBuiltin<"__builtin_arm_ldc2l">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_stc : GCCBuiltin<"__builtin_arm_stc">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_stcl : GCCBuiltin<"__builtin_arm_stcl">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_stc2 : GCCBuiltin<"__builtin_arm_stc2">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; def int_arm_stc2l : GCCBuiltin<"__builtin_arm_stc2l">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], [ImmArg<0>, ImmArg<1>]>; // Move to coprocessor def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; // Move from coprocessor def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, MSBuiltin<"_MoveFromCoprocessor">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>, ImmArg<3>, ImmArg<4>]>; def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, MSBuiltin<"_MoveFromCoprocessor2">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>, ImmArg<3>, ImmArg<4>]>; // Coprocessor data processing def int_arm_cdp : GCCBuiltin<"__builtin_arm_cdp">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; def int_arm_cdp2 : GCCBuiltin<"__builtin_arm_cdp2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>, ImmArg<3>, ImmArg<4>, ImmArg<5>]>; // Move from two registers to coprocessor def int_arm_mcrr : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<4>]>; def int_arm_mcrr2 : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<4>]>; def int_arm_mrrc : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>]>; def int_arm_mrrc2 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty, - llvm_i32_ty, llvm_i32_ty], []>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<0>, ImmArg<1>, ImmArg<2>]>; //===----------------------------------------------------------------------===// // CRC32 @@ -334,6 +333,18 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; //===----------------------------------------------------------------------===// +// CMSE + +def int_arm_cmse_tt : GCCBuiltin<"__builtin_arm_cmse_TT">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; +def int_arm_cmse_ttt : GCCBuiltin<"__builtin_arm_cmse_TTT">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; +def int_arm_cmse_tta : GCCBuiltin<"__builtin_arm_cmse_TTA">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; +def int_arm_cmse_ttat : GCCBuiltin<"__builtin_arm_cmse_TTAT">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// // HINT def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td index 94eca8e40332..d7595a2a7700 100644 --- a/include/llvm/IR/IntrinsicsBPF.td +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -1,9 +1,8 @@ //===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index ecc69a679553..2abc1dc07ebd 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -1,8 +1,7 @@ //===- IntrinsicsHexagon.td - Defines Hexagon intrinsics ---*- tablegen -*-===// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -52,19 +51,19 @@ class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, ImmArg<3>]>; class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrWriteMem]>; + [IntrWriteMem, ImmArg<3>]>; class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrWriteMem]>; + [IntrWriteMem, ImmArg<3>]>; // // BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) @@ -554,16 +553,18 @@ class Hexagon_v32i32_v32i32v32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vaslw_acc -class Hexagon_v16i32_v16i32v16i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v16i32_v16i32v16i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vaslw_acc -class Hexagon_v32i32_v32i32v32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v32i32v32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vmux class Hexagon_v16i32_v512i1v16i32v16i32_Intrinsic<string GCCIntSuffix> @@ -581,7 +582,7 @@ class Hexagon_v32i32_v1024i1v32i32v32i32_Intrinsic<string GCCIntSuffix> class Hexagon_i32_i32i32i32i32_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; // tag : V6_vandnqrt_acc class Hexagon_v16i32_v16i32v512i1i32_Intrinsic<string GCCIntSuffix> @@ -596,58 +597,62 @@ class Hexagon_v32i32_v32i32v1024i1i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vrmpybusi -class Hexagon_v32i32_v32i32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v32i32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vrmpybusi -class Hexagon_v64i32_v64i32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v64i32_v64i32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vsubb_dv -class Hexagon_v64i32_v64i32v64i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v64i32_v64i32v64i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : M2_mpysu_up -class Hexagon_i32_i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : M2_mpyud_acc_ll_s0 -class Hexagon_i64_i64i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i64i32i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i64_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : S2_lsr_i_r_nac -class Hexagon_i32_i32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_i32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : M2_cmpysc_s0 -class Hexagon_i64_i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i32i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_lo -class Hexagon_v16i32_v32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v16i32_v32i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v16i32_ty], [llvm_v32i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_lo -class Hexagon_v32i32_v64i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v64i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v64i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : S2_shuffoh class Hexagon_i64_i64i64_Intrinsic<string GCCIntSuffix> @@ -698,10 +703,10 @@ class Hexagon_v32i32_v32i32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : A4_vcmphgti -class Hexagon_i32_i64i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_i64i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i64_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : class Hexagon_v32i32_v16i32i32_Intrinsic<string GCCIntSuffix> @@ -710,10 +715,11 @@ class Hexagon_v32i32_v16i32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : S6_rol_i_p_or -class Hexagon_i64_i64i64i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i64i64i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vgtuh_and class Hexagon_v512i1_v512i1v16i32v16i32_Intrinsic<string GCCIntSuffix> @@ -728,16 +734,18 @@ class Hexagon_v1024i1_v1024i1v32i32v32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : A2_abssat -class Hexagon_i32_i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : A2_vcmpwgtu -class Hexagon_i32_i64i64_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_i64i64_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_i64_ty,llvm_i64_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vtmpybus_acc class Hexagon_v64i32_v64i32v64i32i32_Intrinsic<string GCCIntSuffix> @@ -764,16 +772,18 @@ class Hexagon_v1024i1_v1024i1v1024i1_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : S2_asr_i_p_rnd_goodsyntax -class Hexagon_i64_i64i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i64i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i64_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : F2_conv_w2df -class Hexagon_double_i32_Intrinsic<string GCCIntSuffix> +class Hexagon_double_i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_double_ty], [llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vunpackuh class Hexagon_v32i32_v16i32_Intrinsic<string GCCIntSuffix> @@ -866,16 +876,18 @@ class Hexagon_i32_v32i32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vlutvwhi -class Hexagon_v32i32_v16i32v16i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v16i32v16i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vlutvwhi -class Hexagon_v64i32_v32i32v32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v64i32_v32i32v32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v64i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vgtuh class Hexagon_v512i1_v16i32v16i32_Intrinsic<string GCCIntSuffix> @@ -902,10 +914,11 @@ class Hexagon_double_i64_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : S2_vzxthw -class Hexagon_i64_i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vtmpyhb class Hexagon_v64i32_v64i32i32_Intrinsic<string GCCIntSuffix> @@ -944,10 +957,11 @@ class Hexagon_v16i32_v16i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : F2_conv_uw2sf -class Hexagon_float_i32_Intrinsic<string GCCIntSuffix> +class Hexagon_float_i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_float_ty], [llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vswap class Hexagon_v32i32_v512i1v16i32v16i32_Intrinsic<string GCCIntSuffix> @@ -1022,16 +1036,17 @@ class Hexagon_v32i32_v32i32v32i32v1024i1_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vlutvvb_oracc -class Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vlutvvb_oracc -class Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<string GCCIntSuffix, list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vrmpybub_rtt class Hexagon_v32i32_v16i32i64_Intrinsic<string GCCIntSuffix> @@ -1052,16 +1067,18 @@ class Hexagon_i64i32_i64i64i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vrsadubi_acc -class Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vrsadubi_acc -class Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : F2_conv_df2sf class Hexagon_float_double_Intrinsic<string GCCIntSuffix> @@ -1166,10 +1183,11 @@ class Hexagon_v32i32_v32i32v32i32v32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : S2_insertp -class Hexagon_i64_i64i64i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_i64_i64i64i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty,llvm_i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : F2_sfinvsqrta class Hexagon_floati32_float_Intrinsic<string GCCIntSuffix> @@ -1190,16 +1208,18 @@ class Hexagon_v32i32v32i32_v32i32v32i32i32_Intrinsic<string GCCIntSuffix> [IntrNoMem]>; // tag : V6_vlutvwh_oracc -class Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : V6_vlutvwh_oracc -class Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<string GCCIntSuffix> +class Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty], - [IntrNoMem]>; + !listconcat([IntrNoMem], intr_properties)>; // tag : F2_dfcmpge class Hexagon_i32_doubledouble_Intrinsic<string GCCIntSuffix> @@ -1223,7 +1243,7 @@ class Hexagon_i32_float_Intrinsic<string GCCIntSuffix> class Hexagon_i32_floati32_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_float_ty,llvm_i32_ty], - [IntrNoMem, Throws]>; + [IntrNoMem, Throws, ImmArg<1>]>; // tag : F2_conv_sf2ud_chop class Hexagon_i64_float_Intrinsic<string GCCIntSuffix> @@ -1292,10 +1312,11 @@ class Hexagon_float_floatfloatfloati32_Intrinsic<string GCCIntSuffix> [IntrNoMem, Throws]>; // tag : F2_dfclass -class Hexagon_i32_doublei32_Intrinsic<string GCCIntSuffix> +class Hexagon_i32_doublei32_Intrinsic<string GCCIntSuffix, + list<IntrinsicProperty> intr_properties = []> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i32_ty], [llvm_double_ty,llvm_i32_ty], - [IntrNoMem, Throws]>; + !listconcat([IntrNoMem, Throws], intr_properties)>; // tag : V6_vd0 class Hexagon_v16i32__Intrinsic<string GCCIntSuffix> @@ -1393,13 +1414,13 @@ def int_hexagon_A2_vabswsat : Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vabswsat">; def int_hexagon_S2_asr_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r", [ImmArg<1>]>; def int_hexagon_S2_asr_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p", [ImmArg<1>]>; def int_hexagon_A4_combineri : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineri">; +Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineri", [ImmArg<1>]>; def int_hexagon_M2_mpy_nac_sat_hl_s1 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_hl_s1">; @@ -1450,7 +1471,7 @@ def int_hexagon_A2_maxup : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_maxup">; def int_hexagon_A4_vcmphgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgti">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgti", [ImmArg<1>]>; def int_hexagon_S2_interleave : Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_interleave">; @@ -1471,10 +1492,10 @@ def int_hexagon_C2_cmpgtp : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpgtp">; def int_hexagon_A4_cmphgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgtui">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgtui", [ImmArg<1>]>; def int_hexagon_C2_cmpgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgti">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgti", [ImmArg<1>]>; def int_hexagon_M2_mpyi : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyi">; @@ -1492,16 +1513,16 @@ def int_hexagon_M2_mpy_lh_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_lh_s0">; def int_hexagon_S2_lsr_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_xacc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_xacc", [ImmArg<2>]>; def int_hexagon_S2_vrcnegh : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vrcnegh">; def int_hexagon_S2_extractup : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S2_extractup">; +Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S2_extractup", [ImmArg<1>, ImmArg<2>]>; def int_hexagon_S2_asr_i_p_rnd_goodsyntax : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd_goodsyntax">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd_goodsyntax", [ImmArg<1>]>; def int_hexagon_S4_ntstbit_r : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_ntstbit_r">; @@ -1528,10 +1549,10 @@ def int_hexagon_S2_asr_r_r_and : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_and">; def int_hexagon_A4_rcmpneqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpneqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpneqi", [ImmArg<1>]>; def int_hexagon_S2_asl_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_nac">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_nac", [ImmArg<2>]>; def int_hexagon_M2_subacc : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_subacc">; @@ -1546,10 +1567,10 @@ def int_hexagon_M2_mpy_acc_sat_lh_s1 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_lh_s1">; def int_hexagon_S2_asr_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vh">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vh", [ImmArg<1>]>; def int_hexagon_S2_asr_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vw">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_vw", [ImmArg<1>]>; def int_hexagon_A4_cmpbgtu : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgtu">; @@ -1558,7 +1579,7 @@ def int_hexagon_A4_vcmpbeq_any : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A4_vcmpbeq_any">; def int_hexagon_A4_cmpbgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgti">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgti", [ImmArg<1>]>; def int_hexagon_M2_mpyd_lh_s1 : Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_lh_s1">; @@ -1567,7 +1588,7 @@ def int_hexagon_S2_asl_r_p_nac : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_nac">; def int_hexagon_S2_lsr_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_nac">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_nac", [ImmArg<2>]>; def int_hexagon_A2_addsp : Hexagon_i64_i32i64_Intrinsic<"HEXAGON_A2_addsp">; @@ -1576,7 +1597,7 @@ def int_hexagon_S4_vxsubaddw : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxsubaddw">; def int_hexagon_A4_vcmpheqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpheqi">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpheqi", [ImmArg<1>]>; def int_hexagon_S4_vxsubaddh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S4_vxsubaddh">; @@ -1603,16 +1624,16 @@ def int_hexagon_A2_pxorf : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_A2_pxorf">; def int_hexagon_C2_cmpgei : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgei">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgei", [ImmArg<1>]>; def int_hexagon_A2_vsubub : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vsubub">; def int_hexagon_S2_asl_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_p">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_p", [ImmArg<1>]>; def int_hexagon_S2_asl_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r", [ImmArg<1>]>; def int_hexagon_A4_vrminuw : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminuw">; @@ -1642,10 +1663,10 @@ def int_hexagon_C2_bitsset : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsset">; def int_hexagon_M2_mpysip : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysip">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysip", [ImmArg<1>]>; def int_hexagon_M2_mpysin : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysin">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysin", [ImmArg<1>]>; def int_hexagon_A4_boundscheck : Hexagon_i32_i32i64_Intrinsic<"HEXAGON_A4_boundscheck">; @@ -1684,10 +1705,10 @@ def int_hexagon_A2_vnavgw : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavgw">; def int_hexagon_S2_asl_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_acc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_acc", [ImmArg<2>]>; def int_hexagon_S4_subi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_lsr_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_lsr_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_S2_vzxthw : Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vzxthw">; @@ -1714,7 +1735,7 @@ def int_hexagon_S2_packhl : Hexagon_i64_i32i32_Intrinsic<"HEXAGON_S2_packhl">; def int_hexagon_A4_vcmpwgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgti">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgti", [ImmArg<1>]>; def int_hexagon_A2_vavguwr : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguwr">; @@ -1735,7 +1756,7 @@ def int_hexagon_F2_conv_d2df : Hexagon_double_i64_Intrinsic<"HEXAGON_F2_conv_d2df">; def int_hexagon_C2_cmpgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgtui">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgtui", [ImmArg<1>]>; def int_hexagon_A2_vconj : Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_vconj">; @@ -1765,7 +1786,7 @@ def int_hexagon_S2_togglebit_r : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_togglebit_r">; def int_hexagon_S2_togglebit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_togglebit_i">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_togglebit_i", [ImmArg<1>]>; def int_hexagon_F2_conv_uw2sf : Hexagon_float_i32_Intrinsic<"HEXAGON_F2_conv_uw2sf">; @@ -1801,10 +1822,10 @@ def int_hexagon_S2_asl_r_r_nac : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_nac">; def int_hexagon_S2_asl_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_acc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_acc", [ImmArg<2>]>; def int_hexagon_A4_vcmpwgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgtui">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpwgtui", [ImmArg<1>]>; def int_hexagon_M4_vrmpyoh_acc_s0 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyoh_acc_s0">; @@ -1831,7 +1852,7 @@ def int_hexagon_A2_vavgwcr : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgwcr">; def int_hexagon_S2_asl_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_xacc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_xacc", [ImmArg<2>]>; def int_hexagon_A4_vrmaxw : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxw">; @@ -1843,22 +1864,22 @@ def int_hexagon_M4_cmpyi_wh : Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyi_wh">; def int_hexagon_A2_tfrsi : -Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfrsi">; +Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfrsi", [ImmArg<0>]>; def int_hexagon_S2_asr_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_acc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_acc", [ImmArg<2>]>; def int_hexagon_A2_svnavgh : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svnavgh">; def int_hexagon_S2_lsr_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r", [ImmArg<1>]>; def int_hexagon_M2_vmac2 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_vmac2">; def int_hexagon_A4_vcmphgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgtui">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmphgtui", [ImmArg<1>]>; def int_hexagon_A2_svavgh : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svavgh">; @@ -1870,7 +1891,7 @@ def int_hexagon_M4_vrmpyeh_acc_s1 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M4_vrmpyeh_acc_s1">; def int_hexagon_S2_lsr_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p", [ImmArg<1>]>; def int_hexagon_A2_combine_hl : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_combine_hl">; @@ -1909,7 +1930,7 @@ def int_hexagon_M2_mmpyul_rs0 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_rs0">; def int_hexagon_S2_asr_i_r_rnd_goodsyntax : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd_goodsyntax">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd_goodsyntax", [ImmArg<1>]>; def int_hexagon_S2_lsr_r_p_nac : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_nac">; @@ -1924,10 +1945,10 @@ def int_hexagon_M4_or_and : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_or_and">; def int_hexagon_M4_mpyrr_addi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyrr_addi">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyrr_addi", [ImmArg<0>]>; def int_hexagon_S4_or_andi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andi">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andi", [ImmArg<2>]>; def int_hexagon_M2_mpy_sat_hl_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_hl_s0">; @@ -2032,7 +2053,7 @@ def int_hexagon_F2_sffms_lib : Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffms_lib">; def int_hexagon_C4_cmpneqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpneqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpneqi", [ImmArg<1>]>; def int_hexagon_M4_and_xor : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_and_xor">; @@ -2056,7 +2077,7 @@ def int_hexagon_A2_vrsadub_acc : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_A2_vrsadub_acc">; def int_hexagon_C2_bitsclri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsclri">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_bitsclri", [ImmArg<1>]>; def int_hexagon_A2_subh_h16_sat_hh : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_h16_sat_hh">; @@ -2158,10 +2179,10 @@ def int_hexagon_S2_parityp : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_S2_parityp">; def int_hexagon_S2_lsr_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_and">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_and", [ImmArg<2>]>; def int_hexagon_S2_asr_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_or">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_or", [ImmArg<2>]>; def int_hexagon_M2_mpyu_nac_ll_s0 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_ll_s0">; @@ -2191,7 +2212,7 @@ def int_hexagon_M2_cnacsc_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cnacsc_s0">; def int_hexagon_S4_subaddi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subaddi">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subaddi", [ImmArg<1>]>; def int_hexagon_M2_mpyud_nac_hl_s1 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s1">; @@ -2200,13 +2221,13 @@ def int_hexagon_M2_mpyud_nac_hl_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_hl_s0">; def int_hexagon_S5_vasrhrnd_goodsyntax : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S5_vasrhrnd_goodsyntax">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S5_vasrhrnd_goodsyntax", [ImmArg<1>]>; def int_hexagon_S2_tstbit_r : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_tstbit_r">; def int_hexagon_S4_vrcrotate : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate">; +Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate", [ImmArg<2>]>; def int_hexagon_M2_mmachs_s1 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_s1">; @@ -2215,7 +2236,7 @@ def int_hexagon_M2_mmachs_s0 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmachs_s0">; def int_hexagon_S2_tstbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_tstbit_i">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_tstbit_i", [ImmArg<1>]>; def int_hexagon_M2_mpy_up_s1 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_up_s1">; @@ -2227,7 +2248,7 @@ def int_hexagon_M2_mmpyuh_rs0 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_rs0">; def int_hexagon_S2_lsr_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vw">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vw", [ImmArg<1>]>; def int_hexagon_M2_mpy_rnd_ll_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_ll_s0">; @@ -2266,16 +2287,16 @@ def int_hexagon_A2_subh_l16_sat_hl : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_sat_hl">; def int_hexagon_C2_cmpeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpeqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpeqi", [ImmArg<1>]>; def int_hexagon_S2_asl_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_and">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_and", [ImmArg<2>]>; def int_hexagon_S2_vcnegh : Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_vcnegh">; def int_hexagon_A4_vcmpweqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpweqi">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpweqi", [ImmArg<1>]>; def int_hexagon_M2_vdmpyrs_s0 : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_M2_vdmpyrs_s0">; @@ -2308,7 +2329,7 @@ def int_hexagon_S2_cl0p : Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_cl0p">; def int_hexagon_S2_valignib : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_valignib">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_valignib", [ImmArg<2>]>; def int_hexagon_F2_sffixupd : Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sffixupd">; @@ -2338,7 +2359,7 @@ def int_hexagon_M2_mmpyul_rs1 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyul_rs1">; def int_hexagon_S4_ntstbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_ntstbit_i">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_ntstbit_i", [ImmArg<1>]> ; def int_hexagon_F2_sffixupr : Hexagon_float_float_Intrinsic<"HEXAGON_F2_sffixupr">; @@ -2362,7 +2383,7 @@ def int_hexagon_M2_vmpy2s_s0pack : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_vmpy2s_s0pack">; def int_hexagon_S4_addaddi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addaddi">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addaddi", [ImmArg<2>]>; def int_hexagon_M2_mpyd_acc_ll_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_ll_s0">; @@ -2371,13 +2392,13 @@ def int_hexagon_M2_mpy_acc_sat_hl_s1 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hl_s1">; def int_hexagon_A4_rcmpeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpeqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_rcmpeqi", [ImmArg<1>]>; def int_hexagon_M4_xor_and : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_xor_and">; def int_hexagon_S2_asl_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_and">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_and", [ImmArg<2>]>; def int_hexagon_M2_mmpyuh_rs1 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyuh_rs1">; @@ -2386,7 +2407,7 @@ def int_hexagon_S2_asr_r_r_or : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_or">; def int_hexagon_A4_round_ri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri", [ImmArg<1>]>; def int_hexagon_A2_max : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_max">; @@ -2395,10 +2416,10 @@ def int_hexagon_A4_round_rr : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_rr">; def int_hexagon_A4_combineii : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineii">; +Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineii", [ImmArg<0>, ImmArg<1>]>; def int_hexagon_A4_combineir : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineir">; +Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_combineir", [ImmArg<0>]>; def int_hexagon_C4_and_orn : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_orn">; @@ -2413,7 +2434,7 @@ def int_hexagon_M4_cmpyr_whc : Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyr_whc">; def int_hexagon_S2_lsr_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_acc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_acc", [ImmArg<2>]>; def int_hexagon_S2_vzxtbh : Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vzxtbh">; @@ -2440,7 +2461,7 @@ def int_hexagon_S2_asl_r_p_or : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_r_p_or">; def int_hexagon_S4_ori_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_asl_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_asl_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_C4_nbitsset : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsset">; @@ -2476,10 +2497,10 @@ def int_hexagon_M2_mpyd_acc_hh_s1 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hh_s1">; def int_hexagon_F2_sfimm_p : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_p">; +Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_p", [ImmArg<0>]>; def int_hexagon_F2_sfimm_n : -Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_n">; +Hexagon_float_i32_Intrinsic<"HEXAGON_F2_sfimm_n", [ImmArg<0>]>; def int_hexagon_M4_cmpyr_wh : Hexagon_i32_i64i32_Intrinsic<"HEXAGON_M4_cmpyr_wh">; @@ -2497,7 +2518,7 @@ def int_hexagon_A2_vavguh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguh">; def int_hexagon_A4_cmpbeqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbeqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbeqi", [ImmArg<1>]>; def int_hexagon_F2_sfcmpuo : Hexagon_i32_floatfloat_Intrinsic<"HEXAGON_F2_sfcmpuo">; @@ -2506,7 +2527,7 @@ def int_hexagon_A2_vavguw : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavguw">; def int_hexagon_S2_asr_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_nac">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_nac", [ImmArg<2>]>; def int_hexagon_S2_vsatwh_nopack : Hexagon_i64_i64_Intrinsic<"HEXAGON_S2_vsatwh_nopack">; @@ -2533,7 +2554,7 @@ def int_hexagon_A2_minp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_minp">; def int_hexagon_S4_or_andix : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andix">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_andix", [ImmArg<2>]>; def int_hexagon_M2_mpy_rnd_lh_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_rnd_lh_s0">; @@ -2584,19 +2605,19 @@ def int_hexagon_S2_lsl_r_r_or : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_or">; def int_hexagon_C4_cmplteui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplteui">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplteui", [ImmArg<1>]>; def int_hexagon_S4_addi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_lsr_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_lsr_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_A4_tfrcpp : Hexagon_i64_i64_Intrinsic<"HEXAGON_A4_tfrcpp">; def int_hexagon_S2_asr_i_svw_trun : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S2_asr_i_svw_trun">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S2_asr_i_svw_trun", [ImmArg<1>]>; def int_hexagon_A4_cmphgti : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgti">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgti", [ImmArg<1>]>; def int_hexagon_A4_vrminh : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrminh">; @@ -2614,7 +2635,7 @@ def int_hexagon_A2_vnavghcr : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vnavghcr">; def int_hexagon_S4_subi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_asl_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_subi_asl_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_S2_lsl_r_vh : Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsl_r_vh">; @@ -2638,7 +2659,7 @@ def int_hexagon_C2_cmpltu : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpltu">; def int_hexagon_S2_insertp : -Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S2_insertp">; +Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S2_insertp", [ImmArg<2>, ImmArg<3>]>; def int_hexagon_M2_mpyd_rnd_ll_s1 : Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s1">; @@ -2647,7 +2668,7 @@ def int_hexagon_M2_mpyd_rnd_ll_s0 : Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_mpyd_rnd_ll_s0">; def int_hexagon_S2_lsr_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_nac">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_nac", [ImmArg<2>]>; def int_hexagon_S2_extractup_rp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_extractup_rp">; @@ -2749,7 +2770,7 @@ def int_hexagon_M2_dpmpyss_rnd_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_rnd_s0">; def int_hexagon_C2_muxri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxri", [ImmArg<1>]>; def int_hexagon_M2_vmac2es_s0 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_vmac2es_s0">; @@ -2767,7 +2788,7 @@ def int_hexagon_M2_mpyu_lh_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpyu_lh_s0">; def int_hexagon_S2_asl_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_or">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_or", [ImmArg<2>]>; def int_hexagon_M2_mpyd_acc_hl_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_acc_hl_s0">; @@ -2782,7 +2803,7 @@ def int_hexagon_A2_vaddw : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddw">; def int_hexagon_S2_asr_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_and">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_and", [ImmArg<2>]>; def int_hexagon_A2_vaddh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vaddh">; @@ -2797,22 +2818,22 @@ def int_hexagon_C2_cmpeqp : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpeqp">; def int_hexagon_M4_mpyri_addi : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addi">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addi", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_A2_not : Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_not">; def int_hexagon_S4_andi_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_lsr_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_lsr_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_M2_macsip : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsip">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsip", [ImmArg<2>]>; def int_hexagon_A2_tfrcrr : Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfrcrr">; def int_hexagon_M2_macsin : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsin">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_macsin", [ImmArg<2>]>; def int_hexagon_C2_orn : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_orn">; @@ -2875,7 +2896,7 @@ def int_hexagon_F2_dfcmpge : Hexagon_i32_doubledouble_Intrinsic<"HEXAGON_F2_dfcmpge">; def int_hexagon_M2_accii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_accii">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_accii", [ImmArg<2>]>; def int_hexagon_A5_vaddhubs : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A5_vaddhubs">; @@ -2893,10 +2914,10 @@ def int_hexagon_S2_vsxthw : Hexagon_i64_i32_Intrinsic<"HEXAGON_S2_vsxthw">; def int_hexagon_S4_andi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_asl_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_andi_asl_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_S2_asl_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_nac">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_nac", [ImmArg<2>]>; def int_hexagon_S2_lsl_r_p_xor : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsl_r_p_xor">; @@ -2929,7 +2950,7 @@ def int_hexagon_M4_xor_andn : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_xor_andn">; def int_hexagon_S2_addasl_rrri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_addasl_rrri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_addasl_rrri", [ImmArg<2>]>; def int_hexagon_M5_vdmpybsu : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M5_vdmpybsu">; @@ -2941,7 +2962,7 @@ def int_hexagon_M2_mpyu_nac_hh_s1 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpyu_nac_hh_s1">; def int_hexagon_A2_addi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addi", [ImmArg<1>]>; def int_hexagon_A2_addp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_addp">; @@ -2962,7 +2983,7 @@ def int_hexagon_S2_shuffeh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_S2_shuffeh">; def int_hexagon_S2_lsr_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_and">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_and", [ImmArg<2>]>; def int_hexagon_M2_mpy_sat_rnd_hh_s1 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_hh_s1">; @@ -3064,13 +3085,13 @@ def int_hexagon_S5_popcountp : Hexagon_i32_i64_Intrinsic<"HEXAGON_S5_popcountp">; def int_hexagon_S4_extractp : -Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_extractp">; +Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_S4_extractp", [ImmArg<1>, ImmArg<2>]>; def int_hexagon_S2_cl0 : Hexagon_i32_i32_Intrinsic<"HEXAGON_S2_cl0">; def int_hexagon_A4_vcmpbgti : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgti">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgti", [ImmArg<1>]>; def int_hexagon_M2_mmacls_s1 : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M2_mmacls_s1">; @@ -3118,7 +3139,7 @@ def int_hexagon_A2_vmaxuh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxuh">; def int_hexagon_A4_bitspliti : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_bitspliti">; +Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A4_bitspliti", [ImmArg<1>]>; def int_hexagon_A2_vmaxub : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vmaxub">; @@ -3145,13 +3166,13 @@ def int_hexagon_S2_asr_r_r_nac : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_nac">; def int_hexagon_F2_dfimm_n : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_n">; +Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_n", [ImmArg<0>]>; def int_hexagon_A4_cmphgt : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmphgt">; def int_hexagon_F2_dfimm_p : -Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_p">; +Hexagon_double_i32_Intrinsic<"HEXAGON_F2_dfimm_p", [ImmArg<0>]>; def int_hexagon_M2_mpyud_acc_lh_s1 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_acc_lh_s1">; @@ -3160,7 +3181,7 @@ def int_hexagon_M2_vcmpy_s1_sat_r : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_r">; def int_hexagon_M4_mpyri_addr_u2 : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr_u2">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr_u2", [ImmArg<1>]>; def int_hexagon_M2_vcmpy_s1_sat_i : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s1_sat_i">; @@ -3172,10 +3193,10 @@ def int_hexagon_M5_vrmacbuu : Hexagon_i64_i64i64i64_Intrinsic<"HEXAGON_M5_vrmacbuu">; def int_hexagon_S5_asrhub_rnd_sat_goodsyntax : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_rnd_sat_goodsyntax">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_rnd_sat_goodsyntax", [ImmArg<1>]>; def int_hexagon_S2_vspliceib : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vspliceib">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_vspliceib", [ImmArg<2>]>; def int_hexagon_M2_dpmpyss_acc_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_dpmpyss_acc_s0">; @@ -3193,25 +3214,25 @@ def int_hexagon_A2_maxp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_maxp">; def int_hexagon_A2_andir : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_andir">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_andir", [ImmArg<1>]>; def int_hexagon_F2_sfrecipa : Hexagon_floati32_floatfloat_Intrinsic<"HEXAGON_F2_sfrecipa">; def int_hexagon_A2_combineii : -Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A2_combineii">; +Hexagon_i64_i32i32_Intrinsic<"HEXAGON_A2_combineii", [ImmArg<0>, ImmArg<1>]>; def int_hexagon_A4_orn : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_orn">; def int_hexagon_A4_cmpbgtui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgtui">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpbgtui", [ImmArg<1>]>; def int_hexagon_S2_lsr_r_r_or : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_r_r_or">; def int_hexagon_A4_vcmpbeqi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbeqi">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbeqi", [ImmArg<1>]>; def int_hexagon_S2_lsl_r_r : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r">; @@ -3247,19 +3268,19 @@ def int_hexagon_M2_vrcmpys_s1 : Hexagon_i64_i64i32_Intrinsic<"HEXAGON_M2_vrcmpys_s1">; def int_hexagon_S4_or_ori : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_ori">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_or_ori", [ImmArg<2>]>; def int_hexagon_C4_fastcorner9_not : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_fastcorner9_not">; def int_hexagon_A2_tfrih : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfrih">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfrih", [ImmArg<1>]>; def int_hexagon_A2_tfril : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfril">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_tfril", [ImmArg<1>]>; def int_hexagon_M4_mpyri_addr : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mpyri_addr", [ImmArg<2>]>; def int_hexagon_S2_vtrunehb : Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vtrunehb">; @@ -3274,16 +3295,16 @@ def int_hexagon_F2_sfsub : Hexagon_float_floatfloat_Intrinsic<"HEXAGON_F2_sfsub">; def int_hexagon_C2_muxii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxii">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxii", [ImmArg<1>, ImmArg<2>]>; def int_hexagon_C2_muxir : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxir">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C2_muxir", [ImmArg<2>]>; def int_hexagon_A2_swiz : Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_swiz">; def int_hexagon_S2_asr_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_and">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_and", [ImmArg<2>]>; def int_hexagon_M2_cmpyrsc_s0 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrsc_s0">; @@ -3313,7 +3334,7 @@ def int_hexagon_M2_mpy_nac_sat_ll_s0 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_sat_ll_s0">; def int_hexagon_S4_extract : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_extract">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_extract", [ImmArg<1>, ImmArg<2>]>; def int_hexagon_A2_vcmpweq : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_A2_vcmpweq">; @@ -3322,10 +3343,10 @@ def int_hexagon_M2_acci : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_acci">; def int_hexagon_S2_lsr_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_acc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_acc", [ImmArg<2>]>; def int_hexagon_S2_lsr_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_or">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_or", [ImmArg<2>]>; def int_hexagon_F2_conv_ud2sf : Hexagon_float_i64_Intrinsic<"HEXAGON_F2_conv_ud2sf">; @@ -3334,10 +3355,10 @@ def int_hexagon_A2_tfr : Hexagon_i32_i32_Intrinsic<"HEXAGON_A2_tfr">; def int_hexagon_S2_asr_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_or">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_or", [ImmArg<2>]>; def int_hexagon_A2_subri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subri">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subri", [ImmArg<0>]>; def int_hexagon_A4_vrmaxuw : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxuw">; @@ -3349,7 +3370,7 @@ def int_hexagon_A4_vrmaxuh : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_A4_vrmaxuh">; def int_hexagon_S2_asl_i_vw : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vw">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vw", [ImmArg<1>]>; def int_hexagon_A2_vavgw : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgw">; @@ -3361,13 +3382,13 @@ def int_hexagon_A2_vavgh : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vavgh">; def int_hexagon_S2_clrbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_clrbit_i">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_clrbit_i", [ImmArg<1>]>; def int_hexagon_S2_asl_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vh">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asl_i_vh", [ImmArg<1>]>; def int_hexagon_S2_lsr_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_or">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsr_i_r_or", [ImmArg<2>]>; def int_hexagon_S2_lsl_r_r_nac : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_lsl_r_r_nac">; @@ -3385,7 +3406,7 @@ def int_hexagon_M2_mmpyl_s1 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_mmpyl_s1">; def int_hexagon_M2_naccii : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_naccii">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_naccii", [ImmArg<2>]>; def int_hexagon_S2_vrndpackwhs : Hexagon_i32_i64_Intrinsic<"HEXAGON_S2_vrndpackwhs">; @@ -3406,7 +3427,7 @@ def int_hexagon_M4_mac_up_s1_sat : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M4_mac_up_s1_sat">; def int_hexagon_S4_vrcrotate_acc : -Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate_acc">; +Hexagon_i64_i64i64i32i32_Intrinsic<"HEXAGON_S4_vrcrotate_acc", [ImmArg<3>]>; def int_hexagon_F2_conv_uw2df : Hexagon_double_i32_Intrinsic<"HEXAGON_F2_conv_uw2df">; @@ -3418,7 +3439,7 @@ def int_hexagon_S2_asr_r_r_acc : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_r_r_acc">; def int_hexagon_A2_orir : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_orir">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_orir", [ImmArg<1>]>; def int_hexagon_A2_andp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_andp">; @@ -3430,7 +3451,7 @@ def int_hexagon_A2_min : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_min">; def int_hexagon_M2_mpysmi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysmi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpysmi", [ImmArg<1>]>; def int_hexagon_M2_vcmpy_s0_sat_r : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vcmpy_s0_sat_r">; @@ -3466,10 +3487,10 @@ def int_hexagon_F2_conv_df2w : Hexagon_i32_double_Intrinsic<"HEXAGON_F2_conv_df2w">; def int_hexagon_S5_asrhub_sat : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_sat">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S5_asrhub_sat", [ImmArg<1>]>; def int_hexagon_S2_asl_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_xacc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_xacc", [ImmArg<2>]>; def int_hexagon_F2_conv_df2d : Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2d">; @@ -3505,7 +3526,7 @@ def int_hexagon_F2_sffma_sc : Hexagon_float_floatfloatfloati32_Intrinsic<"HEXAGON_F2_sffma_sc">; def int_hexagon_F2_dfclass : -Hexagon_i32_doublei32_Intrinsic<"HEXAGON_F2_dfclass">; +Hexagon_i32_doublei32_Intrinsic<"HEXAGON_F2_dfclass", [ImmArg<1>]>; def int_hexagon_F2_conv_df2ud : Hexagon_i64_double_Intrinsic<"HEXAGON_F2_conv_df2ud">; @@ -3520,7 +3541,7 @@ def int_hexagon_M2_cmpyrs_s1 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_cmpyrs_s1">; def int_hexagon_C4_cmpltei : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpltei">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmpltei", [ImmArg<1>]>; def int_hexagon_C4_cmplteu : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_cmplteu">; @@ -3532,7 +3553,7 @@ def int_hexagon_A2_subh_l16_ll : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_subh_l16_ll">; def int_hexagon_S2_asr_i_r_rnd : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_rnd", [ImmArg<1>]>; def int_hexagon_M2_vrmpy_s0 : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrmpy_s0">; @@ -3577,7 +3598,7 @@ def int_hexagon_M2_vrcmpyi_s0c : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_M2_vrcmpyi_s0c">; def int_hexagon_S2_asr_i_p_rnd : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_rnd", [ImmArg<1>]>; def int_hexagon_A2_addpsat : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_addpsat">; @@ -3586,7 +3607,7 @@ def int_hexagon_A2_svaddhs : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svaddhs">; def int_hexagon_S4_ori_lsr_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_lsr_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_ori_lsr_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_M2_mpy_sat_rnd_ll_s1 : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_M2_mpy_sat_rnd_ll_s1">; @@ -3619,7 +3640,7 @@ def int_hexagon_S2_asl_r_r_or : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asl_r_r_or">; def int_hexagon_S4_lsli : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_lsli">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_lsli", [ImmArg<0>]>; def int_hexagon_S2_lsl_r_vw : Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsl_r_vw">; @@ -3664,7 +3685,7 @@ def int_hexagon_A2_negp : Hexagon_i64_i64_Intrinsic<"HEXAGON_A2_negp">; def int_hexagon_S2_asl_i_r_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_sat">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_asl_i_r_sat", [ImmArg<1>]>; def int_hexagon_A2_addh_l16_sat_hl : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_addh_l16_sat_hl">; @@ -3682,10 +3703,10 @@ def int_hexagon_C2_cmpgtup : Hexagon_i32_i64i64_Intrinsic<"HEXAGON_C2_cmpgtup">; def int_hexagon_A4_cround_ri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cround_ri">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cround_ri", [ImmArg<1>]>; def int_hexagon_S4_clbpaddi : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S4_clbpaddi">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_S4_clbpaddi", [ImmArg<1>]>; def int_hexagon_A4_cround_rr : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cround_rr">; @@ -3715,13 +3736,13 @@ def int_hexagon_A2_vminub : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A2_vminub">; def int_hexagon_S2_extractu : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_extractu">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_extractu", [ImmArg<1>, ImmArg<2>]>; def int_hexagon_A2_svsubh : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A2_svsubh">; def int_hexagon_S4_clbaddi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_clbaddi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S4_clbaddi", [ImmArg<1>]>; def int_hexagon_F2_sffms : Hexagon_float_floatfloatfloat_Intrinsic<"HEXAGON_F2_sffms">; @@ -3754,7 +3775,7 @@ def int_hexagon_M2_mpy_acc_hh_s0 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_hh_s0">; def int_hexagon_S4_addi_asl_ri : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_asl_ri">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S4_addi_asl_ri", [ImmArg<0>, ImmArg<2>]>; def int_hexagon_M2_mpyd_nac_hh_s1 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s1">; @@ -3763,10 +3784,10 @@ def int_hexagon_M2_mpyd_nac_hh_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyd_nac_hh_s0">; def int_hexagon_S2_asr_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_nac">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S2_asr_i_r_nac", [ImmArg<2>]>; def int_hexagon_A4_cmpheqi : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpheqi">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_cmpheqi", [ImmArg<1>]>; def int_hexagon_S2_lsr_r_p_xor : Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_r_p_xor">; @@ -3781,7 +3802,7 @@ def int_hexagon_F2_conv_sf2ud_chop : Hexagon_i64_float_Intrinsic<"HEXAGON_F2_conv_sf2ud_chop">; def int_hexagon_C2_cmpgeui : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgeui">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C2_cmpgeui", [ImmArg<1>]>; def int_hexagon_M2_mpy_acc_sat_hh_s0 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_acc_sat_hh_s0">; @@ -3808,7 +3829,7 @@ def int_hexagon_M2_mpyud_nac_lh_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_mpyud_nac_lh_s0">; def int_hexagon_A4_round_ri_sat : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri_sat">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_round_ri_sat", [ImmArg<1>]>; def int_hexagon_M2_mpy_nac_hl_s0 : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mpy_nac_hl_s0">; @@ -3829,10 +3850,10 @@ def int_hexagon_M2_cmaci_s0 : Hexagon_i64_i64i32i32_Intrinsic<"HEXAGON_M2_cmaci_s0">; def int_hexagon_S2_setbit_i : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_setbit_i">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_setbit_i", [ImmArg<1>]>; def int_hexagon_S2_asl_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_or">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asl_i_p_or", [ImmArg<2>]>; def int_hexagon_A4_andn : Hexagon_i32_i32i32_Intrinsic<"HEXAGON_A4_andn">; @@ -3856,13 +3877,13 @@ def int_hexagon_M2_xor_xacc : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_xor_xacc">; def int_hexagon_A4_vcmpbgtui : -Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgtui">; +Hexagon_i32_i64i32_Intrinsic<"HEXAGON_A4_vcmpbgtui", [ImmArg<1>]>; def int_hexagon_A4_ornp : Hexagon_i64_i64i64_Intrinsic<"HEXAGON_A4_ornp">; def int_hexagon_A2_tfrpi : -Hexagon_i64_i32_Intrinsic<"HEXAGON_A2_tfrpi">; +Hexagon_i64_i32_Intrinsic<"HEXAGON_A2_tfrpi", [ImmArg<0>]>; def int_hexagon_C4_and_or : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_C4_and_or">; @@ -3886,16 +3907,16 @@ def int_hexagon_M2_vmpy2su_s0 : Hexagon_i64_i32i32_Intrinsic<"HEXAGON_M2_vmpy2su_s0">; def int_hexagon_S2_asr_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_acc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_asr_i_p_acc", [ImmArg<2>]>; def int_hexagon_C4_nbitsclri : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsclri">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_C4_nbitsclri", [ImmArg<1>]>; def int_hexagon_S2_lsr_i_vh : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vh">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S2_lsr_i_vh", [ImmArg<1>]>; def int_hexagon_S2_lsr_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_xacc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S2_lsr_i_p_xacc", [ImmArg<2>]>; // V55 Scalar Instructions. @@ -3905,40 +3926,40 @@ Hexagon_i64i32_i64i64i64_Intrinsic<"HEXAGON_A5_ACS">; // V60 Scalar Instructions. def int_hexagon_S6_rol_i_p_and : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_and">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_and", [ImmArg<2>]>; def int_hexagon_S6_rol_i_r_xacc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_xacc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_xacc", [ImmArg<2>]>; def int_hexagon_S6_rol_i_r_and : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_and">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_and", [ImmArg<2>]>; def int_hexagon_S6_rol_i_r_acc : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_acc">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_acc", [ImmArg<2>]>; def int_hexagon_S6_rol_i_p_xacc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_xacc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_xacc", [ImmArg<2>]>; def int_hexagon_S6_rol_i_p : -Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S6_rol_i_p">; +Hexagon_i64_i64i32_Intrinsic<"HEXAGON_S6_rol_i_p", [ImmArg<1>]>; def int_hexagon_S6_rol_i_p_nac : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_nac">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_nac", [ImmArg<2>]>; def int_hexagon_S6_rol_i_p_acc : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_acc">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_acc", [ImmArg<2>]>; def int_hexagon_S6_rol_i_r_or : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_or">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_or", [ImmArg<2>]>; def int_hexagon_S6_rol_i_r : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S6_rol_i_r">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S6_rol_i_r", [ImmArg<1>]>; def int_hexagon_S6_rol_i_r_nac : -Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_nac">; +Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_S6_rol_i_r_nac", [ImmArg<2>]>; def int_hexagon_S6_rol_i_p_or : -Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_or">; +Hexagon_i64_i64i64i32_Intrinsic<"HEXAGON_S6_rol_i_p_or", [ImmArg<2>]>; // V62 Scalar Instructions. @@ -3980,7 +4001,7 @@ def int_hexagon_M2_mnaci : Hexagon_i32_i32i32i32_Intrinsic<"HEXAGON_M2_mnaci">; def int_hexagon_S2_mask : -Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_mask">; +Hexagon_i32_i32i32_Intrinsic<"HEXAGON_S2_mask", [ImmArg<0>, ImmArg<1>]>; // V60 HVX Instructions. @@ -4021,10 +4042,10 @@ def int_hexagon_V6_vaddh_dv_128B : Hexagon_v64i32_v64i32v64i32_Intrinsic<"HEXAGON_V6_vaddh_dv_128B">; def int_hexagon_V6_vrmpybusi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi">; +Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi", [ImmArg<2>]>; def int_hexagon_V6_vrmpybusi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_128B">; +Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_128B", [ImmArg<2>]>; def int_hexagon_V6_vshufoh : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vshufoh">; @@ -4045,10 +4066,10 @@ def int_hexagon_V6_vdmpyhsuisat_128B : Hexagon_v32i32_v64i32i32_Intrinsic<"HEXAGON_V6_vdmpyhsuisat_128B">; def int_hexagon_V6_vrsadubi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc">; +Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc", [ImmArg<3>]>; def int_hexagon_V6_vrsadubi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc_128B">; +Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_acc_128B", [ImmArg<3>]>; def int_hexagon_V6_vnavgw : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vnavgw">; @@ -4915,10 +4936,10 @@ def int_hexagon_V6_vsubhsat_128B : Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubhsat_128B">; def int_hexagon_V6_vrmpyubi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc">; +Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc", [ImmArg<3>]>; def int_hexagon_V6_vrmpyubi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc_128B">; +Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_acc_128B", [ImmArg<3>]>; def int_hexagon_V6_vabsw : Hexagon_v16i32_v16i32_Intrinsic<"HEXAGON_V6_vabsw">; @@ -5095,10 +5116,10 @@ def int_hexagon_V6_vmpybv_acc_128B : Hexagon_v64i32_v64i32v32i32v32i32_Intrinsic<"HEXAGON_V6_vmpybv_acc_128B">; def int_hexagon_V6_vrsadubi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi">; +Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi", [ImmArg<2>]>; def int_hexagon_V6_vrsadubi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_128B">; +Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrsadubi_128B", [ImmArg<2>]>; def int_hexagon_V6_vdmpyhb_dv_acc : Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vdmpyhb_dv_acc">; @@ -5377,10 +5398,10 @@ def int_hexagon_V6_vaddbnq_128B : Hexagon_v32i32_v1024i1v32i32v32i32_Intrinsic<"HEXAGON_V6_vaddbnq_128B">; def int_hexagon_V6_vlalignbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlalignbi">; +Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlalignbi", [ImmArg<2>]>; def int_hexagon_V6_vlalignbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlalignbi_128B">; +Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlalignbi_128B", [ImmArg<2>]>; def int_hexagon_V6_vsatwh : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsatwh">; @@ -5443,10 +5464,10 @@ def int_hexagon_V6_veqh_and_128B : Hexagon_v1024i1_v1024i1v32i32v32i32_Intrinsic<"HEXAGON_V6_veqh_and_128B">; def int_hexagon_V6_valignbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_valignbi">; +Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_valignbi", [ImmArg<2>]>; def int_hexagon_V6_valignbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_valignbi_128B">; +Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_valignbi_128B", [ImmArg<2>]>; def int_hexagon_V6_vaddwsat : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddwsat">; @@ -5689,10 +5710,10 @@ def int_hexagon_V6_vsubh_128B : Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubh_128B">; def int_hexagon_V6_vrmpyubi : -Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi">; +Hexagon_v32i32_v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi", [ImmArg<2>]>; def int_hexagon_V6_vrmpyubi_128B : -Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_128B">; +Hexagon_v64i32_v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpyubi_128B", [ImmArg<2>]>; def int_hexagon_V6_vminw : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vminw">; @@ -5755,10 +5776,10 @@ def int_hexagon_V6_vsubuhw_128B : Hexagon_v64i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuhw_128B">; def int_hexagon_V6_vrmpybusi_acc : -Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc">; +Hexagon_v32i32_v32i32v32i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc", [ImmArg<3>]>; def int_hexagon_V6_vrmpybusi_acc_128B : -Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc_128B">; +Hexagon_v64i32_v64i32v64i32i32i32_Intrinsic<"HEXAGON_V6_vrmpybusi_acc_128B", [ImmArg<3>]>; def int_hexagon_V6_vasrw : Hexagon_v16i32_v16i32i32_Intrinsic<"HEXAGON_V6_vasrw">; @@ -5883,10 +5904,10 @@ def int_hexagon_V6_vlsrb_128B : Hexagon_v32i32_v32i32i32_Intrinsic<"HEXAGON_V6_vlsrb_128B">; def int_hexagon_V6_vlutvwhi : -Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi">; +Hexagon_v32i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi", [ImmArg<2>]>; def int_hexagon_V6_vlutvwhi_128B : -Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi_128B">; +Hexagon_v64i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwhi_128B", [ImmArg<2>]>; def int_hexagon_V6_vaddububb_sat : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vaddububb_sat">; @@ -5907,10 +5928,10 @@ def int_hexagon_V6_ldtp0_128B : Hexagon_v32i32_i32i32_Intrinsic<"HEXAGON_V6_ldtp0_128B">; def int_hexagon_V6_vlutvvb_oracci : -Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci">; +Hexagon_v16i32_v16i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci", [ImmArg<3>]>; def int_hexagon_V6_vlutvvb_oracci_128B : -Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci_128B">; +Hexagon_v32i32_v32i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvb_oracci_128B", [ImmArg<3>]>; def int_hexagon_V6_vsubuwsat_dv : Hexagon_v32i32_v32i32v32i32_Intrinsic<"HEXAGON_V6_vsubuwsat_dv">; @@ -6045,10 +6066,10 @@ def int_hexagon_V6_vasrwuhrndsat_128B : Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vasrwuhrndsat_128B">; def int_hexagon_V6_vlutvvbi : -Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi">; +Hexagon_v16i32_v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi", [ImmArg<2>]>; def int_hexagon_V6_vlutvvbi_128B : -Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi_128B">; +Hexagon_v32i32_v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvvbi_128B", [ImmArg<2>]>; def int_hexagon_V6_vsubuwsat : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubuwsat">; @@ -6141,10 +6162,10 @@ def int_hexagon_V6_ldcnp0_128B : Hexagon_v32i32_i32i32_Intrinsic<"HEXAGON_V6_ldcnp0_128B">; def int_hexagon_V6_vlutvwh_oracci : -Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci">; +Hexagon_v32i32_v32i32v16i32v16i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci", [ImmArg<3>]>; def int_hexagon_V6_vlutvwh_oracci_128B : -Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci_128B">; +Hexagon_v64i32_v64i32v32i32v32i32i32_Intrinsic<"HEXAGON_V6_vlutvwh_oracci_128B", [ImmArg<3>]>; def int_hexagon_V6_vsubbsat : Hexagon_v16i32_v16i32v16i32_Intrinsic<"HEXAGON_V6_vsubbsat">; diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index 421a79be4ebc..6393a9ca35d5 100644 --- a/include/llvm/IR/IntrinsicsMips.td +++ b/include/llvm/IR/IntrinsicsMips.td @@ -1,9 +1,8 @@ //===- IntrinsicsMips.td - Defines Mips intrinsics ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -235,9 +234,9 @@ def int_mips_extpdp: GCCBuiltin<"__builtin_mips_extpdp">, // Misc def int_mips_wrdsp: GCCBuiltin<"__builtin_mips_wrdsp">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<1>]>; def int_mips_rddsp: GCCBuiltin<"__builtin_mips_rddsp">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrReadMem]>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrReadMem, ImmArg<0>]>; def int_mips_insv: GCCBuiltin<"__builtin_mips_insv">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrReadMem]>; @@ -303,10 +302,10 @@ def int_mips_adduh_r_qb: GCCBuiltin<"__builtin_mips_adduh_r_qb">, def int_mips_append: GCCBuiltin<"__builtin_mips_append">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_balign: GCCBuiltin<"__builtin_mips_balign">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_cmpgdu_eq_qb: GCCBuiltin<"__builtin_mips_cmpgdu_eq_qb">, Intrinsic<[llvm_i32_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; @@ -356,14 +355,14 @@ def int_mips_precr_qb_ph: GCCBuiltin<"__builtin_mips_precr_qb_ph">, Intrinsic<[llvm_v4i8_ty], [llvm_v2i16_ty, llvm_v2i16_ty], []>; def int_mips_precr_sra_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_ph_w">, Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_precr_sra_r_ph_w: GCCBuiltin<"__builtin_mips_precr_sra_r_ph_w">, Intrinsic<[llvm_v2i16_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_prepend: GCCBuiltin<"__builtin_mips_prepend">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_shra_qb: GCCBuiltin<"__builtin_mips_shra_qb">, Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_i32_ty], [IntrNoMem]>; @@ -464,22 +463,22 @@ def int_mips_addv_d : GCCBuiltin<"__builtin_msa_addv_d">, def int_mips_addvi_b : GCCBuiltin<"__builtin_msa_addvi_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], - [Commutative, IntrNoMem]>; + [Commutative, IntrNoMem, ImmArg<1>]>; def int_mips_addvi_h : GCCBuiltin<"__builtin_msa_addvi_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], - [Commutative, IntrNoMem]>; + [Commutative, IntrNoMem, ImmArg<1>]>; def int_mips_addvi_w : GCCBuiltin<"__builtin_msa_addvi_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [Commutative, IntrNoMem]>; + [Commutative, IntrNoMem, ImmArg<1>]>; def int_mips_addvi_d : GCCBuiltin<"__builtin_msa_addvi_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], - [Commutative, IntrNoMem]>; + [Commutative, IntrNoMem, ImmArg<1>]>; def int_mips_and_v : GCCBuiltin<"__builtin_msa_and_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_mips_andi_b : GCCBuiltin<"__builtin_msa_andi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_asub_s_b : GCCBuiltin<"__builtin_msa_asub_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -561,13 +560,13 @@ def int_mips_bclr_d : GCCBuiltin<"__builtin_msa_bclr_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_bclri_b : GCCBuiltin<"__builtin_msa_bclri_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bclri_h : GCCBuiltin<"__builtin_msa_bclri_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bclri_w : GCCBuiltin<"__builtin_msa_bclri_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bclri_d : GCCBuiltin<"__builtin_msa_bclri_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_binsl_b : GCCBuiltin<"__builtin_msa_binsl_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], @@ -584,16 +583,16 @@ def int_mips_binsl_d : GCCBuiltin<"__builtin_msa_binsl_d">, def int_mips_binsli_b : GCCBuiltin<"__builtin_msa_binsli_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsli_h : GCCBuiltin<"__builtin_msa_binsli_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsli_w : GCCBuiltin<"__builtin_msa_binsli_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsli_d : GCCBuiltin<"__builtin_msa_binsli_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsr_b : GCCBuiltin<"__builtin_msa_binsr_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], @@ -610,16 +609,16 @@ def int_mips_binsr_d : GCCBuiltin<"__builtin_msa_binsr_d">, def int_mips_binsri_b : GCCBuiltin<"__builtin_msa_binsri_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsri_h : GCCBuiltin<"__builtin_msa_binsri_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsri_w : GCCBuiltin<"__builtin_msa_binsri_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_binsri_d : GCCBuiltin<"__builtin_msa_binsri_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], @@ -627,7 +626,7 @@ def int_mips_bmnz_v : GCCBuiltin<"__builtin_msa_bmnz_v">, def int_mips_bmnzi_b : GCCBuiltin<"__builtin_msa_bmnzi_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], @@ -635,7 +634,7 @@ def int_mips_bmz_v : GCCBuiltin<"__builtin_msa_bmz_v">, def int_mips_bmzi_b : GCCBuiltin<"__builtin_msa_bmzi_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_bneg_b : GCCBuiltin<"__builtin_msa_bneg_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -647,13 +646,13 @@ def int_mips_bneg_d : GCCBuiltin<"__builtin_msa_bneg_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_bnegi_b : GCCBuiltin<"__builtin_msa_bnegi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bnegi_h : GCCBuiltin<"__builtin_msa_bnegi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bnegi_w : GCCBuiltin<"__builtin_msa_bnegi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bnegi_d : GCCBuiltin<"__builtin_msa_bnegi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bnz_b : GCCBuiltin<"__builtin_msa_bnz_b">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -673,7 +672,7 @@ def int_mips_bsel_v : GCCBuiltin<"__builtin_msa_bsel_v">, def int_mips_bseli_b : GCCBuiltin<"__builtin_msa_bseli_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_bset_b : GCCBuiltin<"__builtin_msa_bset_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -685,13 +684,13 @@ def int_mips_bset_d : GCCBuiltin<"__builtin_msa_bset_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_bseti_b : GCCBuiltin<"__builtin_msa_bseti_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bseti_h : GCCBuiltin<"__builtin_msa_bseti_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bseti_w : GCCBuiltin<"__builtin_msa_bseti_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bseti_d : GCCBuiltin<"__builtin_msa_bseti_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_bz_b : GCCBuiltin<"__builtin_msa_bz_b">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -715,16 +714,16 @@ def int_mips_ceq_d : GCCBuiltin<"__builtin_msa_ceq_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_ceqi_b : GCCBuiltin<"__builtin_msa_ceqi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_ceqi_h : GCCBuiltin<"__builtin_msa_ceqi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_ceqi_w : GCCBuiltin<"__builtin_msa_ceqi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_ceqi_d : GCCBuiltin<"__builtin_msa_ceqi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_cfcmsa : GCCBuiltin<"__builtin_msa_cfcmsa">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg<0>]>; def int_mips_cle_s_b : GCCBuiltin<"__builtin_msa_cle_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -745,22 +744,22 @@ def int_mips_cle_u_d : GCCBuiltin<"__builtin_msa_cle_u_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_clei_s_b : GCCBuiltin<"__builtin_msa_clei_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_s_h : GCCBuiltin<"__builtin_msa_clei_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_s_w : GCCBuiltin<"__builtin_msa_clei_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_s_d : GCCBuiltin<"__builtin_msa_clei_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_u_b : GCCBuiltin<"__builtin_msa_clei_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_u_h : GCCBuiltin<"__builtin_msa_clei_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_u_w : GCCBuiltin<"__builtin_msa_clei_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clei_u_d : GCCBuiltin<"__builtin_msa_clei_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clt_s_b : GCCBuiltin<"__builtin_msa_clt_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -781,22 +780,22 @@ def int_mips_clt_u_d : GCCBuiltin<"__builtin_msa_clt_u_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_clti_s_b : GCCBuiltin<"__builtin_msa_clti_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_s_h : GCCBuiltin<"__builtin_msa_clti_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_s_w : GCCBuiltin<"__builtin_msa_clti_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_s_d : GCCBuiltin<"__builtin_msa_clti_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_u_b : GCCBuiltin<"__builtin_msa_clti_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_u_h : GCCBuiltin<"__builtin_msa_clti_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_u_w : GCCBuiltin<"__builtin_msa_clti_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_clti_u_d : GCCBuiltin<"__builtin_msa_clti_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_copy_s_b : GCCBuiltin<"__builtin_msa_copy_s_b">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; @@ -817,7 +816,7 @@ def int_mips_copy_u_d : GCCBuiltin<"__builtin_msa_copy_u_d">, Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_ctcmsa : GCCBuiltin<"__builtin_msa_ctcmsa">, - Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], []>; + Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [ImmArg<0>]>; def int_mips_div_s_b : GCCBuiltin<"__builtin_msa_div_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1245,41 +1244,41 @@ def int_mips_insert_d : GCCBuiltin<"__builtin_msa_insert_d">, def int_mips_insve_b : GCCBuiltin<"__builtin_msa_insve_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_mips_insve_h : GCCBuiltin<"__builtin_msa_insve_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_mips_insve_w : GCCBuiltin<"__builtin_msa_insve_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_mips_insve_d : GCCBuiltin<"__builtin_msa_insve_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_mips_ld_b : GCCBuiltin<"__builtin_msa_ld_b">, Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_mips_ld_h : GCCBuiltin<"__builtin_msa_ld_h">, Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_mips_ld_w : GCCBuiltin<"__builtin_msa_ld_w">, Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_mips_ld_d : GCCBuiltin<"__builtin_msa_ld_d">, Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_mips_ldi_b : GCCBuiltin<"__builtin_msa_ldi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_mips_ldi_h : GCCBuiltin<"__builtin_msa_ldi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_mips_ldi_w : GCCBuiltin<"__builtin_msa_ldi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; def int_mips_ldi_d : GCCBuiltin<"__builtin_msa_ldi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; // This instruction is part of the MSA spec but it does not share the // __builtin_msa prefix because it operates on the GPR registers. @@ -1342,22 +1341,22 @@ def int_mips_max_u_d : GCCBuiltin<"__builtin_msa_max_u_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_maxi_s_b : GCCBuiltin<"__builtin_msa_maxi_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_s_h : GCCBuiltin<"__builtin_msa_maxi_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_s_w : GCCBuiltin<"__builtin_msa_maxi_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_s_d : GCCBuiltin<"__builtin_msa_maxi_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_u_b : GCCBuiltin<"__builtin_msa_maxi_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_u_h : GCCBuiltin<"__builtin_msa_maxi_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_u_w : GCCBuiltin<"__builtin_msa_maxi_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_maxi_u_d : GCCBuiltin<"__builtin_msa_maxi_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_min_a_b : GCCBuiltin<"__builtin_msa_min_a_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1387,22 +1386,22 @@ def int_mips_min_u_d : GCCBuiltin<"__builtin_msa_min_u_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_mini_s_b : GCCBuiltin<"__builtin_msa_mini_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_s_h : GCCBuiltin<"__builtin_msa_mini_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_s_w : GCCBuiltin<"__builtin_msa_mini_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_s_d : GCCBuiltin<"__builtin_msa_mini_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_u_b : GCCBuiltin<"__builtin_msa_mini_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_u_h : GCCBuiltin<"__builtin_msa_mini_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_u_w : GCCBuiltin<"__builtin_msa_mini_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mini_u_d : GCCBuiltin<"__builtin_msa_mini_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_mod_s_b : GCCBuiltin<"__builtin_msa_mod_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1493,13 +1492,13 @@ def int_mips_nor_v : GCCBuiltin<"__builtin_msa_nor_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_mips_nori_b : GCCBuiltin<"__builtin_msa_nori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_or_v : GCCBuiltin<"__builtin_msa_or_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_mips_ori_b : GCCBuiltin<"__builtin_msa_ori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_pckev_b : GCCBuiltin<"__builtin_msa_pckev_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1529,29 +1528,29 @@ def int_mips_pcnt_d : GCCBuiltin<"__builtin_msa_pcnt_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; def int_mips_sat_s_b : GCCBuiltin<"__builtin_msa_sat_s_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_s_h : GCCBuiltin<"__builtin_msa_sat_s_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_s_w : GCCBuiltin<"__builtin_msa_sat_s_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_s_d : GCCBuiltin<"__builtin_msa_sat_s_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_u_b : GCCBuiltin<"__builtin_msa_sat_u_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_u_h : GCCBuiltin<"__builtin_msa_sat_u_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_u_w : GCCBuiltin<"__builtin_msa_sat_u_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sat_u_d : GCCBuiltin<"__builtin_msa_sat_u_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_shf_b : GCCBuiltin<"__builtin_msa_shf_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_shf_h : GCCBuiltin<"__builtin_msa_shf_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; @@ -1564,16 +1563,16 @@ def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1585,13 +1584,13 @@ def int_mips_sll_d : GCCBuiltin<"__builtin_msa_sll_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_slli_b : GCCBuiltin<"__builtin_msa_slli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_slli_h : GCCBuiltin<"__builtin_msa_slli_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_slli_w : GCCBuiltin<"__builtin_msa_slli_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_slli_d : GCCBuiltin<"__builtin_msa_slli_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_splat_b : GCCBuiltin<"__builtin_msa_splat_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; @@ -1603,13 +1602,13 @@ def int_mips_splat_d : GCCBuiltin<"__builtin_msa_splat_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_splati_b : GCCBuiltin<"__builtin_msa_splati_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_splati_h : GCCBuiltin<"__builtin_msa_splati_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_splati_w : GCCBuiltin<"__builtin_msa_splati_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_splati_d : GCCBuiltin<"__builtin_msa_splati_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_sra_b : GCCBuiltin<"__builtin_msa_sra_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1621,13 +1620,13 @@ def int_mips_sra_d : GCCBuiltin<"__builtin_msa_sra_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_srai_b : GCCBuiltin<"__builtin_msa_srai_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srai_h : GCCBuiltin<"__builtin_msa_srai_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srai_w : GCCBuiltin<"__builtin_msa_srai_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srai_d : GCCBuiltin<"__builtin_msa_srai_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srar_b : GCCBuiltin<"__builtin_msa_srar_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1639,13 +1638,13 @@ def int_mips_srar_d : GCCBuiltin<"__builtin_msa_srar_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_srari_b : GCCBuiltin<"__builtin_msa_srari_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srari_h : GCCBuiltin<"__builtin_msa_srari_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srari_w : GCCBuiltin<"__builtin_msa_srari_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srari_d : GCCBuiltin<"__builtin_msa_srari_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srl_b : GCCBuiltin<"__builtin_msa_srl_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1657,13 +1656,13 @@ def int_mips_srl_d : GCCBuiltin<"__builtin_msa_srl_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_srli_b : GCCBuiltin<"__builtin_msa_srli_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srli_h : GCCBuiltin<"__builtin_msa_srli_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srli_w : GCCBuiltin<"__builtin_msa_srli_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srli_d : GCCBuiltin<"__builtin_msa_srli_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srlr_b : GCCBuiltin<"__builtin_msa_srlr_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1675,26 +1674,26 @@ def int_mips_srlr_d : GCCBuiltin<"__builtin_msa_srlr_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_srlri_b : GCCBuiltin<"__builtin_msa_srlri_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srlri_h : GCCBuiltin<"__builtin_msa_srlri_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srlri_w : GCCBuiltin<"__builtin_msa_srlri_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_srlri_d : GCCBuiltin<"__builtin_msa_srlri_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_st_b : GCCBuiltin<"__builtin_msa_st_b">, Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, ImmArg<2>]>; def int_mips_st_h : GCCBuiltin<"__builtin_msa_st_h">, Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, ImmArg<2>]>; def int_mips_st_w : GCCBuiltin<"__builtin_msa_st_w">, Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, ImmArg<2>]>; def int_mips_st_d : GCCBuiltin<"__builtin_msa_st_d">, Intrinsic<[], [llvm_v2i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrArgMemOnly, ImmArg<2>]>; def int_mips_subs_s_b : GCCBuiltin<"__builtin_msa_subs_s_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -1742,13 +1741,13 @@ def int_mips_subv_d : GCCBuiltin<"__builtin_msa_subv_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; def int_mips_subvi_b : GCCBuiltin<"__builtin_msa_subvi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_subvi_h : GCCBuiltin<"__builtin_msa_subvi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_subvi_w : GCCBuiltin<"__builtin_msa_subvi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_subvi_d : GCCBuiltin<"__builtin_msa_subvi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_mips_vshf_b : GCCBuiltin<"__builtin_msa_vshf_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], @@ -1767,5 +1766,5 @@ def int_mips_xor_v : GCCBuiltin<"__builtin_msa_xor_v">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_mips_xori_b : GCCBuiltin<"__builtin_msa_xori_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; } diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index 7f694f68969e..dba7dd76c4ff 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -1,9 +1,8 @@ //===- IntrinsicsNVVM.td - Defines NVVM intrinsics ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -38,6 +37,245 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64* // MISC // +// Helper class for construction of n-element list<LLVMtype> [t,t,...,t] +class RepLLVMType<int N, LLVMType T> { + list<LLVMType> ret = !if(N, !listconcat(RepLLVMType<!add(N,-1), T>.ret, [T]), []); +} + +// Helper class that represents a 'fragment' of an NVPTX *MMA instruction. +// Geom: m<M>n<N>k<K>. E.g. m8n32k16 +// Frag: [abcd] +// PtxEltType: PTX type for the element. +class WMMA_REGS<string Geom, string Frag, string PtxEltType> { + string geom = Geom; + string frag = Frag; + string ptx_elt_type = PtxEltType; + string gft = Geom#":"#Frag#":"#ptx_elt_type; + string ft = frag#":"#ptx_elt_type; + list<LLVMType> regs = !cond( + // fp16 -> fp16/fp32 @ m16n16k16/m8n32k16/m32n8k16 + // All currently supported geometries use the same fragment format, + // so we only need to consider {fragment, type}. + !eq(ft,"a:f16") : RepLLVMType<8, llvm_v2f16_ty>.ret, + !eq(ft,"b:f16") : RepLLVMType<8, llvm_v2f16_ty>.ret, + !eq(ft,"c:f16") : RepLLVMType<4, llvm_v2f16_ty>.ret, + !eq(ft,"d:f16") : RepLLVMType<4, llvm_v2f16_ty>.ret, + !eq(ft,"c:f32") : RepLLVMType<8, llvm_float_ty>.ret, + !eq(ft,"d:f32") : RepLLVMType<8, llvm_float_ty>.ret, + + // u8/s8 -> s32 @ m16n16k16/m8n32k16/m32n8k16 + !eq(gft,"m16n16k16:a:u8") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m16n16k16:a:s8") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m16n16k16:b:u8") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m16n16k16:b:s8") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m16n16k16:c:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + !eq(gft,"m16n16k16:d:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + + !eq(gft,"m8n32k16:a:u8") : [llvm_i32_ty], + !eq(gft,"m8n32k16:a:s8") : [llvm_i32_ty], + !eq(gft,"m8n32k16:b:u8") : RepLLVMType<4, llvm_i32_ty>.ret, + !eq(gft,"m8n32k16:b:s8") : RepLLVMType<4, llvm_i32_ty>.ret, + !eq(gft,"m8n32k16:c:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + !eq(gft,"m8n32k16:d:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + + !eq(gft,"m32n8k16:a:u8") : RepLLVMType<4, llvm_i32_ty>.ret, + !eq(gft,"m32n8k16:a:s8") : RepLLVMType<4, llvm_i32_ty>.ret, + !eq(gft,"m32n8k16:b:u8") : [llvm_i32_ty], + !eq(gft,"m32n8k16:b:s8") : [llvm_i32_ty], + !eq(gft,"m32n8k16:c:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + !eq(gft,"m32n8k16:d:s32") : RepLLVMType<8, llvm_i32_ty>.ret, + + // u4/s4/b1 -> s32 @ m8n8k32 (u4/s4), m8n8k128(b1) + !eq(gft,"m8n8k128:a:b1") : [llvm_i32_ty], + !eq(gft,"m8n8k32:a:u4") : [llvm_i32_ty], + !eq(gft,"m8n8k32:a:s4") : [llvm_i32_ty], + !eq(gft,"m8n8k128:b:b1") : [llvm_i32_ty], + !eq(gft,"m8n8k32:b:u4") : [llvm_i32_ty], + !eq(gft,"m8n8k32:b:s4") : [llvm_i32_ty], + !eq(gft,"m8n8k128:c:s32") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m8n8k128:d:s32") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m8n8k32:c:s32") : RepLLVMType<2, llvm_i32_ty>.ret, + !eq(gft,"m8n8k32:d:s32") : RepLLVMType<2, llvm_i32_ty>.ret, + ); +} + +class WMMA_NAME_LDST<string Op, WMMA_REGS Frag, string Layout, int WithStride> { + string intr = "llvm.nvvm.wmma." + # Frag.geom + # "." # Op + # "." # Frag.frag + # "." # Layout + # !if(WithStride, ".stride", "") + # "." # Frag.ptx_elt_type + ; + // TODO(tra): record name should ideally use the same field order as the intrinsic. + // E.g. string record = !subst("llvm", "int", + // !subst(".", "_", llvm)); + string record = "int_nvvm_wmma_" + # Frag.geom + # "_" # Op + # "_" # Frag.frag + # "_" # Frag.ptx_elt_type + # "_" # Layout + # !if(WithStride, "_stride", ""); +} + +class MMA_SIGNATURE<WMMA_REGS A, WMMA_REGS B, WMMA_REGS C, WMMA_REGS D> { + list<WMMA_REGS> id_frags = !cond( + // int and sub-int ops are identified by input type. + !eq(A.ptx_elt_type, "s8") : [A], + !eq(A.ptx_elt_type, "u8") : [A], + !eq(A.ptx_elt_type, "s4") : [A], + !eq(A.ptx_elt_type, "u4") : [A], + !eq(A.ptx_elt_type, "b1") : [A], + // the rest are FP ops identified by accumulator & result type. + 1: [D, C] + ); + string ret = !foldl("", id_frags, a, b, !strconcat(a, ".", b.ptx_elt_type)); +} + +class WMMA_NAME_MMA<string ALayout, string BLayout, int Satfinite, + WMMA_REGS A, WMMA_REGS B, WMMA_REGS C, WMMA_REGS D> { + string signature = MMA_SIGNATURE<A, B, C, D>.ret; + string llvm = "llvm.nvvm.wmma." + # A.geom + # ".mma" + # "." # ALayout + # "." # BLayout + # signature + # !if(Satfinite, ".satfinite", ""); + + string record = !subst(".", "_", + !subst("llvm.", "int_", llvm)); +} + +// Generates list of 4-tuples of WMMA_REGS representing a valid MMA op. +// Geom: list of supported geometries. +// TypeN: PTX type of the corresponding fragment's element. +// TypeB and TypeD may be empty if it must match that of TypeA or TypeC. +class MMA_OPS<list<string> Geom, list<string> TypeA, list<string> TypeB, + list<string> TypeC, list<string> TypeD> { + list<list<WMMA_REGS>> ret = + !foldl([]<list<WMMA_REGS>>, Geom, t1, geom, !listconcat(t1, + !foldl([]<list<WMMA_REGS>>, TypeA, t2, type_a, !listconcat(t2, + !foldl([]<list<WMMA_REGS>>, !if(!size(TypeB), TypeB, [type_a]), t3, type_b, !listconcat(t3, + !foldl([]<list<WMMA_REGS>>, TypeC, t4, type_c, !listconcat(t4, + !foldl([]<list<WMMA_REGS>>, !if(!size(TypeC), TypeC, [type_c]), t5, type_d, !listconcat(t5, + [[WMMA_REGS<geom, "a", type_a>, + WMMA_REGS<geom, "b", type_b>, + WMMA_REGS<geom, "c", type_c>, + WMMA_REGS<geom, "d", type_d>]])))))))))); + // Debugging aid for readable representation of the list above. + list<list<string>> ops = !foreach(x, ret, [x[0].gft, x[1].gft, x[2].gft, x[3].gft]); +} + +class MMA_LDST_OPS<list<string> Geom, list<string> Frags, list<string> Types> { + list<WMMA_REGS> ret = + !foldl([]<WMMA_REGS>, Geom, t1, geom, !listconcat(t1, + !foldl([]<WMMA_REGS>, Frags, t2, frag, !listconcat(t2, + !foldl([]<WMMA_REGS>, Types, t3, type, !listconcat(t3, + [WMMA_REGS<geom, frag, type>])))))); + // Debugging aid for readable representation of the list above. + list<string> ops = !foreach(x, ret, x.gft); +} + + + +// Creates list of valid combinations of fragments. This is the master list that +// drives generation of corresponding intrinsics and instructions. +class NVVM_MMA_OPS<int _ = 0> { + list<list<WMMA_REGS>> fp_mma_ops = MMA_OPS< + ["m16n16k16", "m32n8k16", "m8n32k16"], + ["f16"], [], ["f16", "f32"], ["f16", "f32"]>.ret; + list<list<WMMA_REGS>> int_mma_ops = MMA_OPS< + ["m16n16k16", "m32n8k16", "m8n32k16"], + ["s8", "u8"], [], ["s32"], []>.ret; + list<list<WMMA_REGS>> subint_mma_ops = MMA_OPS< + ["m8n8k32"], + ["s4", "u4"], [], ["s32"], []>.ret; + list<list<WMMA_REGS>> bit_mma_ops = MMA_OPS< + ["m8n8k128"], + ["b1"], [], ["s32"], []>.ret; + list<list<WMMA_REGS>> all_mma_ops = !listconcat(fp_mma_ops, int_mma_ops, + subint_mma_ops, bit_mma_ops); + + list<WMMA_REGS> ldst_ab_ops = MMA_LDST_OPS< + ["m16n16k16", "m32n8k16", "m8n32k16"], + ["a", "b"], ["f16", "u8", "s8"]>.ret; + list<WMMA_REGS> ldst_cd_ops = MMA_LDST_OPS< + ["m16n16k16", "m32n8k16", "m8n32k16"], + ["c", "d"], ["f16", "f32", "s32"]>.ret; + list<WMMA_REGS> ldst_subint_ab_ops = MMA_LDST_OPS< + ["m8n8k32"], ["a", "b"], ["s4","u4"]>.ret; + list<WMMA_REGS> ldst_bit_ab_ops = MMA_LDST_OPS< + ["m8n8k128"], ["a", "b"], ["b1"]>.ret; + list<WMMA_REGS> ldst_subint_cd_ops = MMA_LDST_OPS< + ["m8n8k32", "m8n8k128"], ["c", "d"], ["s32"]>.ret; + list<WMMA_REGS> all_ldst_ops = !listconcat(ldst_ab_ops, ldst_cd_ops, + ldst_subint_ab_ops, + ldst_bit_ab_ops, + ldst_subint_cd_ops); + // Separate A/B/C fragments (loads) from D (stores). + list<WMMA_REGS> all_ld_ops = !foldl([]<WMMA_REGS>, all_ldst_ops, a, b, + !listconcat(a, !if(!eq(b.frag,"d"), [],[b]))); + list<WMMA_REGS> all_st_ops = !foldl([]<WMMA_REGS>, all_ldst_ops, a, b, + !listconcat(a, !if(!eq(b.frag,"d"), [b],[]))); +} + +def NVVM_MMA_OPS : NVVM_MMA_OPS; + +// Returns [1] if this combination of layout/satf is supported, [] otherwise. +// MMA ops must provide all parameters. Loads and stores -- only frags and layout_a. +// The class is used to prevent generation of records for the unsupported variants. +// E.g. +// foreach _ = NVVM_MMA_SUPPORTED<...>.ret in = +// def : FOO<>; // The record will only be defined for supported ops. +// +class NVVM_MMA_SUPPORTED<list<WMMA_REGS> frags, string layout_a, string layout_b="-", int satf=-1> { + // MMA ops check both layouts. + string mma = frags[0].ptx_elt_type + # ":" # layout_a + # ":" # layout_b; + // Load ops only need type/fragment/layout. + string ld = frags[0].ptx_elt_type + # ":" # frags[0].frag + # ":" # layout_a + ; + string ldf = frags[0].ptx_elt_type + # ":" # frags[0].frag + ; + string t = frags[0].ptx_elt_type; + list<int> ret = !cond( + // Sub-int MMA only supports fixed A/B layout. + // b1 does not support .satf. + !eq(mma#":"#satf, "b1:row:col:0") : [1], + !eq(mma, "s4:row:col") : [1], + !eq(mma, "u4:row:col") : [1], + !eq(mma, "s4:row:col") : [1], + !eq(mma, "u4:row:col") : [1], + // Sub-int load/stores have fixed layout for A and B. + !and(!eq(layout_b, "-"), // It's a Load or Store op + !or(!eq(ld, "b1:a:row"), + !eq(ld, "b1:b:col"), + !eq(ldf, "b1:c"), + !eq(ldf, "b1:d"), + !eq(ld, "s4:a:row"), + !eq(ld, "s4:b:col"), + !eq(ldf, "s4:c"), + !eq(ldf, "s4:d"), + !eq(ld, "u4:a:row"), + !eq(ld, "u4:b:col"), + !eq(ldf, "u4:c"), + !eq(ldf, "u4:d"))) : [1], + // All other sub-int ops are not supported. + !eq(t, "b1") : [], + !eq(t, "s4") : [], + !eq(t, "u4") : [], + // All other (non sub-int) are OK. + 1: [1] + ); +} + let TargetPrefix = "nvvm" in { def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], @@ -689,14 +927,6 @@ let TargetPrefix = "nvvm" in { [IntrNoMem]>; // Atomics not available as llvm intrinsics. - def int_nvvm_atomic_load_add_f32 : Intrinsic<[llvm_float_ty], - [LLVMAnyPointerType<llvm_float_ty>, llvm_float_ty], - [IntrArgMemOnly, NoCapture<0>]>; - // Atomic add of f64 requires sm_60. - def int_nvvm_atomic_load_add_f64 : Intrinsic<[llvm_double_ty], - [LLVMAnyPointerType<llvm_double_ty>, llvm_double_ty], - [IntrArgMemOnly, NoCapture<0>]>; - def int_nvvm_atomic_load_inc_32 : Intrinsic<[llvm_i32_ty], [LLVMAnyPointerType<llvm_i32_ty>, llvm_i32_ty], [IntrArgMemOnly, NoCapture<0>]>; @@ -3674,11 +3904,19 @@ multiclass PTXReadSRegIntrinsic_v4i32<string regname> { class PTXReadSRegIntrinsic_r32<string name> : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; - class PTXReadSRegIntrinsic_r64<string name> : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>, GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; +// Intrinsics to read registers with non-constant values. E.g. the values that +// do change over the kernel lifetime. Such reads should not be CSE'd. +class PTXReadNCSRegIntrinsic_r32<string name> + : Intrinsic<[llvm_i32_ty], [], [IntrInaccessibleMemOnly]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; +class PTXReadNCSRegIntrinsic_r64<string name> + : Intrinsic<[llvm_i64_ty], [], [IntrInaccessibleMemOnly]>, + GCCBuiltin<"__nvvm_read_ptx_sreg_" # name>; + defm int_nvvm_read_ptx_sreg_tid : PTXReadSRegIntrinsic_v4i32<"tid">; defm int_nvvm_read_ptx_sreg_ntid : PTXReadSRegIntrinsic_v4i32<"ntid">; @@ -3704,13 +3942,13 @@ def int_nvvm_read_ptx_sreg_lanemask_ge : def int_nvvm_read_ptx_sreg_lanemask_gt : PTXReadSRegIntrinsic_r32<"lanemask_gt">; -def int_nvvm_read_ptx_sreg_clock : PTXReadSRegIntrinsic_r32<"clock">; -def int_nvvm_read_ptx_sreg_clock64 : PTXReadSRegIntrinsic_r64<"clock64">; +def int_nvvm_read_ptx_sreg_clock : PTXReadNCSRegIntrinsic_r32<"clock">; +def int_nvvm_read_ptx_sreg_clock64 : PTXReadNCSRegIntrinsic_r64<"clock64">; -def int_nvvm_read_ptx_sreg_pm0 : PTXReadSRegIntrinsic_r32<"pm0">; -def int_nvvm_read_ptx_sreg_pm1 : PTXReadSRegIntrinsic_r32<"pm1">; -def int_nvvm_read_ptx_sreg_pm2 : PTXReadSRegIntrinsic_r32<"pm2">; -def int_nvvm_read_ptx_sreg_pm3 : PTXReadSRegIntrinsic_r32<"pm3">; +def int_nvvm_read_ptx_sreg_pm0 : PTXReadNCSRegIntrinsic_r32<"pm0">; +def int_nvvm_read_ptx_sreg_pm1 : PTXReadNCSRegIntrinsic_r32<"pm1">; +def int_nvvm_read_ptx_sreg_pm2 : PTXReadNCSRegIntrinsic_r32<"pm2">; +def int_nvvm_read_ptx_sreg_pm3 : PTXReadNCSRegIntrinsic_r32<"pm3">; def int_nvvm_read_ptx_sreg_warpsize : PTXReadSRegIntrinsic_r32<"warpsize">; @@ -3882,166 +4120,59 @@ def int_nvvm_match_all_sync_i64p : // // WMMA instructions // - // WMMA.LOAD -class NVVM_WMMA_LD_GALSTS<string Geometry, string Abc, string Layout, - string Type, LLVMType regty, int WithStride> - : Intrinsic<!if(!eq(Abc#Type,"cf16"), - [regty, regty, regty, regty], - [regty, regty, regty, regty, - regty, regty, regty, regty]), +class NVVM_WMMA_LD<WMMA_REGS Frag, string Layout, int WithStride> + : Intrinsic<Frag.regs, !if(WithStride, [llvm_anyptr_ty, llvm_i32_ty], [llvm_anyptr_ty]), [IntrReadMem, IntrArgMemOnly, ReadOnly<0>, NoCapture<0>], - "llvm.nvvm.wmma." - # Geometry - # ".load" - # "." # Abc - # "." # Layout - # !if(WithStride, ".stride", "") - # "." # Type>; - -multiclass NVVM_WMMA_LD_GALT<string Geometry, string Abc, string Layout, - string Type, LLVMType regty> { - def _stride: NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 1>; - def NAME : NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 0>; -} - -multiclass NVVM_WMMA_LD_GAT<string Geometry, string Abc, - string Type, LLVMType regty> { - defm _row: NVVM_WMMA_LD_GALT<Geometry, Abc, "row", Type, regty>; - defm _col: NVVM_WMMA_LD_GALT<Geometry, Abc, "col", Type, regty>; -} - -multiclass NVVM_WMMA_LD_G<string Geometry> { - defm _a_f16: NVVM_WMMA_LD_GAT<Geometry, "a", "f16", llvm_v2f16_ty>; - defm _b_f16: NVVM_WMMA_LD_GAT<Geometry, "b", "f16", llvm_v2f16_ty>; - defm _c_f16: NVVM_WMMA_LD_GAT<Geometry, "c", "f16", llvm_v2f16_ty>; - defm _c_f32: NVVM_WMMA_LD_GAT<Geometry, "c", "f32", llvm_float_ty>; -} - -multiclass NVVM_WMMA_LD { - defm _m32n8k16_load: NVVM_WMMA_LD_G<"m32n8k16">; - defm _m16n16k16_load: NVVM_WMMA_LD_G<"m16n16k16">; - defm _m8n32k16_load: NVVM_WMMA_LD_G<"m8n32k16">; -} - -defm int_nvvm_wmma: NVVM_WMMA_LD; + WMMA_NAME_LDST<"load", Frag, Layout, WithStride>.intr>; // WMMA.STORE.D -class NVVM_WMMA_STD_GLSTS<string Geometry, string Layout, - string Type, LLVMType regty, int WithStride, - // This is only used to create a typed empty array we - // need to pass to !if below. - list<LLVMType>Empty=[]> +class NVVM_WMMA_ST<WMMA_REGS Frag, string Layout, int WithStride> : Intrinsic<[], !listconcat( [llvm_anyptr_ty], - !if(!eq(Type,"f16"), - [regty, regty, regty, regty], - [regty, regty, regty, regty, - regty, regty, regty, regty]), - !if(WithStride, [llvm_i32_ty], Empty)), + Frag.regs, + !if(WithStride, [llvm_i32_ty], [])), [IntrWriteMem, IntrArgMemOnly, WriteOnly<0>, NoCapture<0>], - "llvm.nvvm.wmma." - # Geometry - # ".store.d" - # "." # Layout - # !if(WithStride, ".stride", "") - # "." # Type>; - -multiclass NVVM_WMMA_STD_GLT<string Geometry, string Layout, - string Type, LLVMType regty> { - def _stride: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 1>; - def NAME: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 0>; -} - -multiclass NVVM_WMMA_STD_GT<string Geometry, string Type, LLVMType regty> { - defm _row: NVVM_WMMA_STD_GLT<Geometry, "row", Type, regty>; - defm _col: NVVM_WMMA_STD_GLT<Geometry, "col", Type, regty>; -} -multiclass NVVM_WMMA_STD_G<string Geometry> { - defm _d_f16: NVVM_WMMA_STD_GT<Geometry, "f16", llvm_v2f16_ty>; - defm _d_f32: NVVM_WMMA_STD_GT<Geometry, "f32", llvm_float_ty>; -} - -multiclass NVVM_WMMA_STD { - defm _m32n8k16_store: NVVM_WMMA_STD_G<"m32n8k16">; - defm _m16n16k16_store: NVVM_WMMA_STD_G<"m16n16k16">; - defm _m8n32k16_store: NVVM_WMMA_STD_G<"m8n32k16">; + WMMA_NAME_LDST<"store", Frag, Layout, WithStride>.intr>; + +// Create all load/store variants +foreach layout = ["row", "col"] in { + foreach stride = [0, 1] in { + foreach frag = NVVM_MMA_OPS.all_ld_ops in + foreach _ = NVVM_MMA_SUPPORTED<[frag], layout>.ret in + def WMMA_NAME_LDST<"load", frag, layout, stride>.record + : NVVM_WMMA_LD<frag, layout, stride>; + foreach frag = NVVM_MMA_OPS.all_st_ops in + foreach _ = NVVM_MMA_SUPPORTED<[frag], layout>.ret in + def WMMA_NAME_LDST<"store", frag, layout, stride>.record + : NVVM_WMMA_ST<frag, layout, stride>; + } } -defm int_nvvm_wmma: NVVM_WMMA_STD; - // WMMA.MMA -class NVVM_WMMA_MMA_GABDCS<string Geometry, - string ALayout, string BLayout, - string DType, LLVMType d_regty, - string CType, LLVMType c_regty, - string Satfinite = ""> - : Intrinsic<!if(!eq(DType,"f16"), - [d_regty, d_regty, d_regty, d_regty], - [d_regty, d_regty, d_regty, d_regty, - d_regty, d_regty, d_regty, d_regty]), - !listconcat( - [// A - llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, - llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, - // B - llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, - llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty, llvm_v2f16_ty], - !if(!eq(CType,"f16"), - [c_regty, c_regty, c_regty, c_regty], - [c_regty, c_regty, c_regty, c_regty, - c_regty, c_regty, c_regty, c_regty])), +class NVVM_WMMA_MMA<string ALayout, string BLayout, int Satfinite, + WMMA_REGS A, WMMA_REGS B, + WMMA_REGS C, WMMA_REGS D> + : Intrinsic<D.regs, + !listconcat(A.regs, B.regs, C.regs), [IntrNoMem], - "llvm.nvvm.wmma." - # Geometry - # ".mma" - # "." # ALayout - # "." # BLayout - # "." # DType - # "." # CType - # Satfinite> { -} - -multiclass NVVM_WMMA_MMA_GABDC<string Geometry, string ALayout, string BLayout, - string DType, LLVMType d_regty, - string CType, LLVMType c_regty> { - def NAME : NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout, - DType, d_regty, CType, c_regty>; - def _satfinite: NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout, - DType, d_regty, CType, c_regty,".satfinite">; -} - -multiclass NVVM_WMMA_MMA_GABD<string Geometry, string ALayout, string BLayout, - string DType, LLVMType d_regty> { - defm _f16: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty, - "f16", llvm_v2f16_ty>; - defm _f32: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty, - "f32", llvm_float_ty>; -} - -multiclass NVVM_WMMA_MMA_GAB<string Geometry, string ALayout, string BLayout> { - defm _f16: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f16", llvm_v2f16_ty>; - defm _f32: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f32", llvm_float_ty>; -} - -multiclass NVVM_WMMA_MMA_GA<string Geometry, string ALayout> { - defm _col: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "col">; - defm _row: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "row">; -} - -multiclass NVVM_WMMA_MMA_G<string Geometry> { - defm _col: NVVM_WMMA_MMA_GA<Geometry, "col">; - defm _row: NVVM_WMMA_MMA_GA<Geometry, "row">; -} - -multiclass NVVM_WMMA_MMA { - defm _m32n8k16_mma : NVVM_WMMA_MMA_G<"m32n8k16">; - defm _m16n16k16_mma : NVVM_WMMA_MMA_G<"m16n16k16">; - defm _m8n32k16_mma : NVVM_WMMA_MMA_G<"m8n32k16">; -} - -defm int_nvvm_wmma : NVVM_WMMA_MMA; + WMMA_NAME_MMA<ALayout, BLayout, Satfinite, A, B, C, D>.llvm>; + +foreach layout_a = ["row", "col"] in { + foreach layout_b = ["row", "col"] in { + foreach satf = [0, 1] in { + foreach op = NVVM_MMA_OPS.all_mma_ops in { + foreach _ = NVVM_MMA_SUPPORTED<op, layout_a, layout_b, satf>.ret in { + def WMMA_NAME_MMA<layout_a, layout_b, satf, + op[0], op[1], op[2], op[3]>.record + : NVVM_WMMA_MMA<layout_a, layout_b, satf, + op[0], op[1], op[2], op[3]>; + } + } + } // satf + } // layout_b +} // layout_a } // let TargetPrefix = "nvvm" diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 62b2e8f77e7d..f87317445753 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -1,9 +1,8 @@ //===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,7 +18,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. def int_ppc_dcba : Intrinsic<[], [llvm_ptr_ty], []>; - def int_ppc_dcbf : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbf : GCCBuiltin<"__builtin_dcbf">, + Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], @@ -610,16 +610,16 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // FP <-> integer conversion. def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; @@ -716,11 +716,11 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_crypto_vshasigmad : GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>, ImmArg<2>]>; def int_ppc_altivec_crypto_vshasigmaw : GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>, ImmArg<2>]>; } def int_ppc_altivec_crypto_vcipher : PowerPC_Vec_DDD_Intrinsic<"crypto_vcipher">; @@ -915,10 +915,10 @@ def int_ppc_vsx_xvxsigsp : [llvm_v4f32_ty], [IntrNoMem]>; def int_ppc_vsx_xvtstdcdp : PowerPC_VSX_Intrinsic<"xvtstdcdp", [llvm_v2i64_ty], - [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_ppc_vsx_xvtstdcsp : PowerPC_VSX_Intrinsic<"xvtstdcsp", [llvm_v4i32_ty], - [llvm_v4f32_ty,llvm_i32_ty], [IntrNoMem]>; + [llvm_v4f32_ty,llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_ppc_vsx_xvcvhpsp : PowerPC_VSX_Intrinsic<"xvcvhpsp", [llvm_v4f32_ty], [llvm_v8i16_ty],[IntrNoMem]>; @@ -1113,9 +1113,9 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg<0>]>; def int_ppc_tend : GCCBuiltin<"__builtin_tend">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [ImmArg<0>]>; def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; @@ -1167,4 +1167,9 @@ def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">, Intrinsic<[llvm_i64_ty], [], []>; def int_ppc_cfence : Intrinsic<[], [llvm_anyint_ty], []>; + +// PowerPC set FPSCR Intrinsic Definitions. +def int_ppc_setrnd : GCCBuiltin<"__builtin_setrnd">, + Intrinsic<[llvm_double_ty], [llvm_i32_ty], []>; + } diff --git a/include/llvm/IR/IntrinsicsRISCV.td b/include/llvm/IR/IntrinsicsRISCV.td index 0ac7348b56db..60393189b830 100644 --- a/include/llvm/IR/IntrinsicsRISCV.td +++ b/include/llvm/IR/IntrinsicsRISCV.td @@ -1,9 +1,8 @@ //===- IntrinsicsRISCV.td - Defines RISCV intrinsics -------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,13 +18,13 @@ let TargetPrefix = "riscv" in { class MaskedAtomicRMW32Intrinsic : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture<0>]>; + [IntrArgMemOnly, NoCapture<0>, ImmArg<3>]>; class MaskedAtomicRMW32WithSextIntrinsic : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture<0>]>; + [IntrArgMemOnly, NoCapture<0>, ImmArg<4>]>; def int_riscv_masked_atomicrmw_xchg_i32 : MaskedAtomicRMW32Intrinsic; def int_riscv_masked_atomicrmw_add_i32 : MaskedAtomicRMW32Intrinsic; @@ -39,6 +38,31 @@ def int_riscv_masked_atomicrmw_umin_i32 : MaskedAtomicRMW32Intrinsic; def int_riscv_masked_cmpxchg_i32 : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture<0>]>; + [IntrArgMemOnly, NoCapture<0>, ImmArg<4>]>; + +class MaskedAtomicRMW64Intrinsic + : Intrinsic<[llvm_i64_ty], + [llvm_anyptr_ty, llvm_i64_ty, llvm_i64_ty, llvm_i64_ty], + [IntrArgMemOnly, NoCapture<0>, ImmArg<3>]>; + +class MaskedAtomicRMW64WithSextIntrinsic + : Intrinsic<[llvm_i64_ty], + [llvm_anyptr_ty, llvm_i64_ty, llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty], + [IntrArgMemOnly, NoCapture<0>, ImmArg<4>]>; + +def int_riscv_masked_atomicrmw_xchg_i64 : MaskedAtomicRMW64Intrinsic; +def int_riscv_masked_atomicrmw_add_i64 : MaskedAtomicRMW64Intrinsic; +def int_riscv_masked_atomicrmw_sub_i64 : MaskedAtomicRMW64Intrinsic; +def int_riscv_masked_atomicrmw_nand_i64 : MaskedAtomicRMW64Intrinsic; +def int_riscv_masked_atomicrmw_max_i64 : MaskedAtomicRMW64WithSextIntrinsic; +def int_riscv_masked_atomicrmw_min_i64 : MaskedAtomicRMW64WithSextIntrinsic; +def int_riscv_masked_atomicrmw_umax_i64 : MaskedAtomicRMW64Intrinsic; +def int_riscv_masked_atomicrmw_umin_i64 : MaskedAtomicRMW64Intrinsic; + +def int_riscv_masked_cmpxchg_i64 + : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty, llvm_i64_ty, llvm_i64_ty, + llvm_i64_ty, llvm_i64_ty], + [IntrArgMemOnly, NoCapture<0>, ImmArg<4>]>; } // TargetPrefix = "riscv" diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td index caa2ec209a31..40d6ba17eaf1 100644 --- a/include/llvm/IR/IntrinsicsSystemZ.td +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -1,9 +1,8 @@ //===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -39,7 +38,8 @@ class SystemZBinaryConvCC<LLVMType result, LLVMType arg> : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>; class SystemZBinaryConvIntCC<LLVMType result, LLVMType arg> - : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], [IntrNoMem]>; + : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; class SystemZBinaryCC<LLVMType type> : SystemZBinaryConvCC<type, type>; @@ -48,23 +48,28 @@ class SystemZTernaryConv<string name, LLVMType result, LLVMType arg> : GCCBuiltin<"__builtin_s390_" ## name>, Intrinsic<[result], [arg, arg, result], [IntrNoMem]>; +class SystemZTernaryConvCC<LLVMType result, LLVMType arg> + : Intrinsic<[result, llvm_i32_ty], [arg, arg, result], [IntrNoMem]>; + class SystemZTernary<string name, LLVMType type> : SystemZTernaryConv<name, type, type>; class SystemZTernaryInt<string name, LLVMType type> : GCCBuiltin<"__builtin_s390_" ## name>, - Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; class SystemZTernaryIntCC<LLVMType type> - : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], [IntrNoMem]>; + : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; class SystemZQuaternaryInt<string name, LLVMType type> : GCCBuiltin<"__builtin_s390_" ## name>, - Intrinsic<[type], [type, type, type, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[type], [type, type, type, llvm_i32_ty], + [IntrNoMem, ImmArg<3>]>; class SystemZQuaternaryIntCC<LLVMType type> : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; multiclass SystemZUnaryExtBHF<string name> { def b : SystemZUnaryConv<name##"b", llvm_v8i16_ty, llvm_v16i8_ty>; @@ -180,7 +185,8 @@ multiclass SystemZQuaternaryIntBHF<string name> { def f : SystemZQuaternaryInt<name##"f", llvm_v4i32_ty>; } -multiclass SystemZQuaternaryIntBHFG<string name> : SystemZQuaternaryIntBHF<name> { +multiclass SystemZQuaternaryIntBHFG<string name> : + SystemZQuaternaryIntBHF<name> { def g : SystemZQuaternaryInt<name##"g", llvm_v2i64_ty>; } @@ -232,11 +238,11 @@ let TargetPrefix = "s390" in { let TargetPrefix = "s390" in { def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">, Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">, Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">, Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], @@ -245,7 +251,7 @@ let TargetPrefix = "s390" in { def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">, Intrinsic<[llvm_v16i8_ty], @@ -311,7 +317,7 @@ let TargetPrefix = "s390" in { def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">; @@ -370,7 +376,7 @@ let TargetPrefix = "s390" in { def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>, ImmArg<2>]>; // Instructions from the Vector Enhancements Facility 1 def int_s390_vbperm : SystemZBinaryConv<"vbperm", llvm_v2i64_ty, @@ -379,20 +385,20 @@ let TargetPrefix = "s390" in { def int_s390_vmslg : GCCBuiltin<"__builtin_s390_vmslg">, Intrinsic<[llvm_v16i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v16i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_s390_vfmaxdb : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_s390_vfmindb : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_s390_vfmaxsb : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_s390_vfminsb : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_s390_vfcesbs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v4f32_ty>; def int_s390_vfchsbs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v4f32_ty>; @@ -402,7 +408,7 @@ let TargetPrefix = "s390" in { def int_s390_vfisb : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>, ImmArg<2>]>; // Instructions from the Vector Packed Decimal Facility def int_s390_vlrl : GCCBuiltin<"__builtin_s390_vlrl">, @@ -412,6 +418,24 @@ let TargetPrefix = "s390" in { def int_s390_vstrl : GCCBuiltin<"__builtin_s390_vstrl">, Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], [IntrArgMemOnly, IntrWriteMem]>; + + // Instructions from the Vector Enhancements Facility 2 + def int_s390_vsld : GCCBuiltin<"__builtin_s390_vsld">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; + + def int_s390_vsrd : GCCBuiltin<"__builtin_s390_vsrd">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; + + def int_s390_vstrsb : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v16i8_ty>; + def int_s390_vstrsh : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v8i16_ty>; + def int_s390_vstrsf : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v4i32_ty>; + def int_s390_vstrszb : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v16i8_ty>; + def int_s390_vstrszh : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v8i16_ty>; + def int_s390_vstrszf : SystemZTernaryConvCC<llvm_v16i8_ty, llvm_v4i32_ty>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td index b015650906e0..1b892727547d 100644 --- a/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/include/llvm/IR/IntrinsicsWebAssembly.td @@ -1,9 +1,8 @@ //===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -41,8 +40,8 @@ def int_wasm_trunc_saturate_unsigned : Intrinsic<[llvm_anyint_ty], // throw / rethrow def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], - [Throws, IntrNoReturn]>; -def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>; + [Throws, IntrNoReturn, ImmArg<0>]>; +def int_wasm_rethrow_in_catch : Intrinsic<[], [], [Throws, IntrNoReturn]>; // Since wasm does not use landingpad instructions, these instructions return // exception pointer and selector values until we lower them in WasmEHPrepare. @@ -50,17 +49,16 @@ def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], [IntrHasSideEffects]>; def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrHasSideEffects]>; - -// wasm.catch returns the pointer to the exception object caught by wasm 'catch' -// instruction. -def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], - [IntrHasSideEffects]>; +// This is the same as llvm.wasm.get.exception except that it does not take a +// token operand. This is only for instruction selection purpose. +def int_wasm_extract_exception : Intrinsic<[llvm_ptr_ty], [], + [IntrHasSideEffects]>; // WebAssembly EH must maintain the landingpads in the order assigned to them // by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is // used in order to give them the indices in WasmEHPrepare. def int_wasm_landingpad_index: Intrinsic<[], [llvm_token_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; // Returns LSDA address of the current function. def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; @@ -112,4 +110,27 @@ def int_wasm_alltrue : [llvm_anyvector_ty], [IntrNoMem, IntrSpeculatable]>; +//===----------------------------------------------------------------------===// +// Bulk memory intrinsics +//===----------------------------------------------------------------------===// + +def int_wasm_memory_init : + Intrinsic<[], + [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem, IntrInaccessibleMemOrArgMemOnly, WriteOnly<2>, + IntrHasSideEffects, ImmArg<0>, ImmArg<1>]>; +def int_wasm_data_drop : + Intrinsic<[], + [llvm_i32_ty], + [IntrNoDuplicate, IntrHasSideEffects, ImmArg<0>]>; + +//===----------------------------------------------------------------------===// +// Thread-local storage intrinsics +//===----------------------------------------------------------------------===// + +def int_wasm_tls_size : + Intrinsic<[llvm_anyint_ty], + [], + [IntrNoMem, IntrSpeculatable]>; + } // TargetPrefix = "wasm" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 8d8cc8e97678..236d312d7d78 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -1,9 +1,8 @@ //===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,7 +13,7 @@ //===----------------------------------------------------------------------===// // Interrupt traps let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_int : Intrinsic<[], [llvm_i8_ty]>; + def int_x86_int : Intrinsic<[], [llvm_i8_ty], [ImmArg<0>]>; } //===----------------------------------------------------------------------===// @@ -204,12 +203,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; // NOTE: This comparison intrinsic is not used by clang as long as the // distinction in signaling behaviour is not implemented. def int_x86_sse_cmp_ps : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -278,9 +277,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Control register. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_stmxcsr : - Intrinsic<[], [llvm_ptr_ty], []>; + Intrinsic<[], [llvm_ptr_ty], + [IntrWriteMem, IntrArgMemOnly, + // This prevents reordering with ldmxcsr + IntrHasSideEffects]>; def int_x86_sse_ldmxcsr : - Intrinsic<[], [llvm_ptr_ty], []>; + Intrinsic<[], [llvm_ptr_ty], + [IntrReadMem, IntrArgMemOnly, IntrHasSideEffects, + // FIXME: LDMXCSR does not actualy write to memory, + // but Fast and DAG Isel both use writing to memory + // as a proxy for having side effects. + IntrWriteMem]>; } // Misc. @@ -312,12 +319,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; // NOTE: This comparison intrinsic is not used by clang as long as the // distinction in signaling behaviour is not implemented. def int_x86_sse2_cmp_pd : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; @@ -367,6 +374,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem, Commutative]>; @@ -399,6 +412,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + // Oddly these don't require an immediate due to a gcc compatibility issue. def int_x86_sse2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -604,7 +618,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v16i8_ty], [IntrNoMem]>; def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; } // Sign ops @@ -650,16 +664,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_round_ss : GCCBuiltin<"__builtin_ia32_roundss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_sse41_round_ps : GCCBuiltin<"__builtin_ia32_roundps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_x86_sse41_round_sd : GCCBuiltin<"__builtin_ia32_roundsd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_sse41_round_pd : GCCBuiltin<"__builtin_ia32_roundpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; } // Vector min element @@ -722,20 +736,20 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_aesni_aeskeygenassist : GCCBuiltin<"__builtin_ia32_aeskeygenassist128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; } // PCLMUL instructions let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_pclmulqdq : GCCBuiltin<"__builtin_ia32_pclmulqdq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_pclmulqdq_256 : GCCBuiltin<"__builtin_ia32_pclmulqdq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_pclmulqdq_512 : GCCBuiltin<"__builtin_ia32_pclmulqdq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; } // Vector pack @@ -749,7 +763,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; } // Vector blend @@ -769,17 +783,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem, Commutative]>; + [IntrNoMem, Commutative, ImmArg<2>]>; def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem, Commutative]>; + [IntrNoMem, Commutative, ImmArg<2>]>; } // Vector sum of absolute differences let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty], - [IntrNoMem, Commutative]>; + [IntrNoMem, Commutative, ImmArg<2>]>; } // Test instruction with bitwise comparison. @@ -820,66 +834,66 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; } //===----------------------------------------------------------------------===// @@ -888,13 +902,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse4a_extrqi : GCCBuiltin<"__builtin_ia32_extrqi">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>, ImmArg<2>]>; def int_x86_sse4a_extrq : GCCBuiltin<"__builtin_ia32_extrq">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_x86_sse4a_insertqi : GCCBuiltin<"__builtin_ia32_insertqi">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; def int_x86_sse4a_insertq : GCCBuiltin<"__builtin_ia32_insertq">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; } @@ -931,10 +946,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_round_pd_256 : GCCBuiltin<"__builtin_ia32_roundpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; def int_x86_avx_round_ps_256 : GCCBuiltin<"__builtin_ia32_roundps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<1>]>; } // Horizontal ops @@ -1086,33 +1101,33 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v16qi">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8affineinvqb_256 : GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v32qi">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8affineinvqb_512 : GCCBuiltin<"__builtin_ia32_vgf2p8affineinvqb_v64qi">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8affineqb_128 : GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v16qi">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8affineqb_256 : GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v32qi">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8affineqb_512 : GCCBuiltin<"__builtin_ia32_vgf2p8affineqb_v64qi">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_vgf2p8mulb_128 : GCCBuiltin<"__builtin_ia32_vgf2p8mulb_v16qi">, @@ -1145,17 +1160,18 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem, Commutative]>; + llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem, Commutative, ImmArg<2>]>; } // Vector compare let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_cmp_pd_256 : Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx_cmp_ps_256 : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; } // Vector convert @@ -1222,30 +1238,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_fpclass_pd_128 : Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_fpclass_pd_256 : Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_fpclass_pd_512 : Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_fpclass_ps_128 : Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_fpclass_ps_256 : Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_fpclass_ps_512 : Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_fpclass_sd : GCCBuiltin<"__builtin_ia32_fpclasssd_mask">, Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_fpclass_ss : GCCBuiltin<"__builtin_ia32_fpclassss_mask">, Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; } // Vector extract sign mask @@ -1328,6 +1344,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb256">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, + llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, + llvm_v16i16_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; @@ -1360,6 +1382,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + // Oddly these don't require an immediate due to a gcc compatibility issue. def int_x86_avx2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -1392,6 +1415,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + // Oddly these don't require an immediate due to a gcc compatibility issue. def int_x86_avx512_psrai_q_128 : GCCBuiltin<"__builtin_ia32_psraqi128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; @@ -1427,6 +1451,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v2i64_ty], [IntrNoMem]>; + // Oddly these don't require an immediate due to a gcc compatibility issue. def int_x86_avx512_pslli_w_512 : GCCBuiltin<"__builtin_ia32_psllwi512">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; @@ -1677,71 +1702,73 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Gather ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; } // Misc. @@ -1753,7 +1780,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v32i8_ty], [IntrNoMem]>; def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i8_ty], [IntrNoMem, Commutative]>; + llvm_i8_ty], [IntrNoMem, Commutative, ImmArg<2>]>; } //===----------------------------------------------------------------------===// @@ -1763,32 +1790,32 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_vfmadd_pd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_vfmadd_ps_512 : Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; // TODO: Can we use 2 vfmadds+shufflevector? def int_x86_avx512_vfmaddsub_pd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_vfmaddsub_ps_512 : Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_vfmadd_f64 : Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_vfmadd_f32 : Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_vpmadd52h_uq_128 : GCCBuiltin<"__builtin_ia32_vpmadd52huq128">, @@ -1878,23 +1905,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xop_vpermil2pd : GCCBuiltin<"__builtin_ia32_vpermil2pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_xop_vpermil2pd_256 : GCCBuiltin<"__builtin_ia32_vpermil2pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_xop_vpermil2ps : GCCBuiltin<"__builtin_ia32_vpermil2ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_xop_vpermil2ps_256 : GCCBuiltin<"__builtin_ia32_vpermil2ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_xop_vfrcz_pd : GCCBuiltin<"__builtin_ia32_vfrczpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; @@ -1909,31 +1936,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xop_vfrcz_ps_256 : GCCBuiltin<"__builtin_ia32_vfrczps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_xop_vpcomb : GCCBuiltin<"__builtin_ia32_vpcomb">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomw : GCCBuiltin<"__builtin_ia32_vpcomw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomd : GCCBuiltin<"__builtin_ia32_vpcomd">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomq : GCCBuiltin<"__builtin_ia32_vpcomq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomub : GCCBuiltin<"__builtin_ia32_vpcomub">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomuw : GCCBuiltin<"__builtin_ia32_vpcomuw">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomud : GCCBuiltin<"__builtin_ia32_vpcomud">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vpcomuq : GCCBuiltin<"__builtin_ia32_vpcomuq">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_xop_vphaddbd : GCCBuiltin<"__builtin_ia32_vphaddbd">, Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; @@ -2261,6 +2263,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], [IntrNoMem]>; + // Oddly these don't require an immediate due to a gcc compatibility issue. def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; @@ -2398,15 +2401,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; } //===----------------------------------------------------------------------===// @@ -2527,13 +2530,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8f32_ty], [llvm_v8i16_ty], [IntrNoMem]>; def int_x86_vcvtps2ph_128 : GCCBuiltin<"__builtin_ia32_vcvtps2ph">, Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256">, Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_vcvtph2ps_256 : GCCBuiltin<"__builtin_ia32_vcvtph2ps256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8i16_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -2542,13 +2546,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512_mask">, Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty, - llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256_mask">, Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_vcvtps2ph_128 : GCCBuiltin<"__builtin_ia32_vcvtps2ph_mask">, Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; } //===----------------------------------------------------------------------===// @@ -2556,9 +2563,11 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_tbm_bextri_u32 : GCCBuiltin<"__builtin_ia32_bextri_u32">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_tbm_bextri_u64 : GCCBuiltin<"__builtin_ia32_bextri_u64">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem, ImmArg<1>]>; } //===----------------------------------------------------------------------===// @@ -2604,7 +2613,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xend : GCCBuiltin<"__builtin_ia32_xend">, Intrinsic<[], [], []>; def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">, - Intrinsic<[], [llvm_i8_ty], []>; + Intrinsic<[], [llvm_i8_ty], [ImmArg<0>]>; def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, Intrinsic<[llvm_i32_ty], [], []>; } @@ -2645,55 +2654,71 @@ let TargetPrefix = "x86" in { // Conversion ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_cvttss2si : GCCBuiltin<"__builtin_ia32_vcvttss2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttss2si64 : GCCBuiltin<"__builtin_ia32_vcvttss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttss2usi : GCCBuiltin<"__builtin_ia32_vcvttss2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_vcvttss2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss32">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss64">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cvttsd2si : GCCBuiltin<"__builtin_ia32_vcvttsd2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_vcvttsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttsd2usi : GCCBuiltin<"__builtin_ia32_vcvttsd2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvttsd2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_vcvtss2usi32 : GCCBuiltin<"__builtin_ia32_vcvtss2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtss2usi64 : GCCBuiltin<"__builtin_ia32_vcvtss2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtss2si32 : GCCBuiltin<"__builtin_ia32_vcvtss2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtss2si64 : GCCBuiltin<"__builtin_ia32_vcvtss2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtsd2usi32 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvtsd2usi64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtsd2si32 : GCCBuiltin<"__builtin_ia32_vcvtsd2si32">, - Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_vcvtsd2si64 : GCCBuiltin<"__builtin_ia32_vcvtsd2si64">, - Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_cvtsi2ss32 : GCCBuiltin<"__builtin_ia32_cvtsi2ss32">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cvtsi2ss64 : GCCBuiltin<"__builtin_ia32_cvtsi2ss64">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; } // Pack ops. @@ -2714,11 +2739,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_cvtdq2ps_512 : - GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + def int_x86_avx512_sitofp_round : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; + + def int_x86_avx512_uitofp_round : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_cvtpd2dq_128 : GCCBuiltin<"__builtin_ia32_cvtpd2dq128_mask">, @@ -2730,25 +2757,25 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">, Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtpd2ps_512 : GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtsd2ss_round : GCCBuiltin<"__builtin_ia32_cvtsd2ss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_cvtss2sd_round : GCCBuiltin<"__builtin_ia32_cvtss2sd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps_mask">, @@ -2772,7 +2799,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtpd2qq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtpd2udq_128 : GCCBuiltin<"__builtin_ia32_cvtpd2udq128_mask">, @@ -2790,7 +2817,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">, Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtpd2uqq_128 : GCCBuiltin<"__builtin_ia32_cvtpd2uqq128_mask">, @@ -2808,7 +2835,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtpd2uqq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtps2dq_128 : GCCBuiltin<"__builtin_ia32_cvtps2dq128_mask">, @@ -2826,13 +2853,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtps2pd_512 : GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f32_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtps2qq_128 : GCCBuiltin<"__builtin_ia32_cvtps2qq128_mask">, @@ -2850,7 +2877,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtps2qq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtps2udq_128 : GCCBuiltin<"__builtin_ia32_cvtps2udq128_mask">, @@ -2868,7 +2895,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtps2uqq_128 : GCCBuiltin<"__builtin_ia32_cvtps2uqq128_mask">, @@ -2886,13 +2913,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvtps2uqq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtqq2pd_512 : - GCCBuiltin<"__builtin_ia32_cvtqq2pd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtqq2ps_128 : GCCBuiltin<"__builtin_ia32_cvtqq2ps128_mask">, @@ -2900,18 +2921,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtqq2ps_256 : - GCCBuiltin<"__builtin_ia32_cvtqq2ps256_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtqq2ps_512 : - GCCBuiltin<"__builtin_ia32_cvtqq2ps512_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvttpd2dq_128 : GCCBuiltin<"__builtin_ia32_cvttpd2dq128_mask">, Intrinsic<[llvm_v4i32_ty], @@ -2922,7 +2931,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttpd2qq_128 : GCCBuiltin<"__builtin_ia32_cvttpd2qq128_mask">, @@ -2940,7 +2949,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttpd2qq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttpd2udq_128 : GCCBuiltin<"__builtin_ia32_cvttpd2udq128_mask">, @@ -2958,7 +2967,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">, Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttpd2uqq_128 : GCCBuiltin<"__builtin_ia32_cvttpd2uqq128_mask">, @@ -2976,13 +2985,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttpd2uqq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttps2dq_512 : GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttps2qq_128 : GCCBuiltin<"__builtin_ia32_cvttps2qq128_mask">, @@ -3000,7 +3009,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttps2qq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttps2udq_128 : GCCBuiltin<"__builtin_ia32_cvttps2udq128_mask">, @@ -3018,7 +3027,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvttps2uqq_128 : GCCBuiltin<"__builtin_ia32_cvttps2uqq128_mask">, @@ -3036,19 +3045,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_cvttps2uqq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtudq2ps_512 : - GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtuqq2pd_512 : - GCCBuiltin<"__builtin_ia32_cvtuqq2pd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_cvtuqq2ps_128 : GCCBuiltin<"__builtin_ia32_cvtuqq2ps128_mask">, @@ -3056,72 +3053,78 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtuqq2ps_256 : - GCCBuiltin<"__builtin_ia32_cvtuqq2ps256_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtuqq2ps_512 : - GCCBuiltin<"__builtin_ia32_cvtuqq2ps512_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_rndscale_pd_128 : GCCBuiltin<"__builtin_ia32_rndscalepd_128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_rndscale_pd_256 : GCCBuiltin<"__builtin_ia32_rndscalepd_256_mask">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_rndscale_ps_128 : GCCBuiltin<"__builtin_ia32_rndscaleps_128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_rndscale_ps_256 : GCCBuiltin<"__builtin_ia32_rndscaleps_256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_reduce_pd_128 : GCCBuiltin<"__builtin_ia32_reducepd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_reduce_pd_256 : GCCBuiltin<"__builtin_ia32_reducepd256_mask">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_reduce_pd_512 : GCCBuiltin<"__builtin_ia32_reducepd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_reduce_ps_128 : GCCBuiltin<"__builtin_ia32_reduceps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_reduce_ps_256 : GCCBuiltin<"__builtin_ia32_reduceps256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_reduce_ps_512 : GCCBuiltin<"__builtin_ia32_reduceps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_range_pd_128 : GCCBuiltin<"__builtin_ia32_rangepd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_range_pd_256 : GCCBuiltin<"__builtin_ia32_rangepd256_mask">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_range_pd_512 : GCCBuiltin<"__builtin_ia32_rangepd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, - llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<5>]>; def int_x86_avx512_mask_range_ps_128 : GCCBuiltin<"__builtin_ia32_rangeps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_range_ps_256 : GCCBuiltin<"__builtin_ia32_rangeps256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, - llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<5>]>; } // Vector load with broadcast @@ -3151,109 +3154,111 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_rndscale_sd : GCCBuiltin<"__builtin_ia32_rndscalesd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_range_ss : GCCBuiltin<"__builtin_ia32_rangess128_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_range_sd : GCCBuiltin<"__builtin_ia32_rangesd128_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_reduce_ss : GCCBuiltin<"__builtin_ia32_reducess_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_reduce_sd : GCCBuiltin<"__builtin_ia32_reducesd_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>, ImmArg<5>]>; def int_x86_avx512_mask_scalef_sd : GCCBuiltin<"__builtin_ia32_scalefsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_scalef_ss : GCCBuiltin<"__builtin_ia32_scalefss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_scalef_pd_128 : GCCBuiltin<"__builtin_ia32_scalefpd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3262,7 +3267,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v4f64_ty, llvm_i8_ty],[IntrNoMem]>; def int_x86_avx512_mask_scalef_pd_512 : GCCBuiltin<"__builtin_ia32_scalefpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_scalef_ps_128 : GCCBuiltin<"__builtin_ia32_scalefps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3271,99 +3277,104 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_scalef_ps_512 : GCCBuiltin<"__builtin_ia32_scalefps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_sqrt_ss : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_sqrt_sd : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_sqrt_pd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_sqrt_ps_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_fixupimm_pd_128 : GCCBuiltin<"__builtin_ia32_fixupimmpd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_maskz_fixupimm_pd_128 : GCCBuiltin<"__builtin_ia32_fixupimmpd128_maskz">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_fixupimm_pd_256 : GCCBuiltin<"__builtin_ia32_fixupimmpd256_mask">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_maskz_fixupimm_pd_256 : GCCBuiltin<"__builtin_ia32_fixupimmpd256_maskz">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_fixupimm_pd_512 : GCCBuiltin<"__builtin_ia32_fixupimmpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_maskz_fixupimm_pd_512 : GCCBuiltin<"__builtin_ia32_fixupimmpd512_maskz">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_mask_fixupimm_ps_128 : GCCBuiltin<"__builtin_ia32_fixupimmps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_maskz_fixupimm_ps_128 : GCCBuiltin<"__builtin_ia32_fixupimmps128_maskz">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_fixupimm_ps_256 : GCCBuiltin<"__builtin_ia32_fixupimmps256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_maskz_fixupimm_ps_256 : GCCBuiltin<"__builtin_ia32_fixupimmps256_maskz">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_fixupimm_ps_512 : GCCBuiltin<"__builtin_ia32_fixupimmps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_maskz_fixupimm_ps_512 : GCCBuiltin<"__builtin_ia32_fixupimmps512_maskz">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_mask_fixupimm_sd : GCCBuiltin<"__builtin_ia32_fixupimmsd_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_maskz_fixupimm_sd : GCCBuiltin<"__builtin_ia32_fixupimmsd_maskz">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_mask_fixupimm_ss : GCCBuiltin<"__builtin_ia32_fixupimmss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_maskz_fixupimm_ss : GCCBuiltin<"__builtin_ia32_fixupimmss_maskz">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>, ImmArg<5>]>; def int_x86_avx512_mask_getexp_pd_128 : GCCBuiltin<"__builtin_ia32_getexppd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3372,7 +3383,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_getexp_pd_512 : GCCBuiltin<"__builtin_ia32_getexppd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_getexp_ps_128 : GCCBuiltin<"__builtin_ia32_getexpps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3381,62 +3393,65 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_getexp_ps_512 : GCCBuiltin<"__builtin_ia32_getexpps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_mask_getexp_ss : GCCBuiltin<"__builtin_ia32_getexpss128_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_getexp_sd : GCCBuiltin<"__builtin_ia32_getexpsd128_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_mask_getmant_pd_128 : GCCBuiltin<"__builtin_ia32_getmantpd128_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,llvm_i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_getmant_pd_256 : GCCBuiltin<"__builtin_ia32_getmantpd256_mask">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,llvm_i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_getmant_pd_512 : GCCBuiltin<"__builtin_ia32_getmantpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty,llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty,llvm_i32_ty ], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_getmant_ps_128 : GCCBuiltin<"__builtin_ia32_getmantps128_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_getmant_ps_256 : GCCBuiltin<"__builtin_ia32_getmantps256_mask">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>]>; def int_x86_avx512_mask_getmant_ps_512 : GCCBuiltin<"__builtin_ia32_getmantps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty,llvm_i32_ty, llvm_v16f32_ty,llvm_i16_ty,llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<1>, ImmArg<4>]>; def int_x86_avx512_mask_getmant_ss : GCCBuiltin<"__builtin_ia32_getmantss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v4f32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>, ImmArg<5>]>; def int_x86_avx512_mask_getmant_sd : GCCBuiltin<"__builtin_ia32_getmantsd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, llvm_v2f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<2>, ImmArg<5>]>; def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, @@ -3491,41 +3506,41 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_rcp28_ps : GCCBuiltin<"__builtin_ia32_rcp28ps_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i16_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty, llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_rsqrt28_ps : GCCBuiltin<"__builtin_ia32_rsqrt28ps_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_rsqrt28_pd : GCCBuiltin<"__builtin_ia32_rsqrt28pd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd_round_mask">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<4>]>; def int_x86_avx512_psad_bw_512 : GCCBuiltin<"__builtin_ia32_psadbw512">, Intrinsic<[llvm_v8i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem, Commutative]>; @@ -3538,6 +3553,12 @@ let TargetPrefix = "x86" in { def int_x86_avx512_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_pavg_b_512 : GCCBuiltin<"__builtin_ia32_pavgb512">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty], + [IntrNoMem]>; + def int_x86_avx512_pavg_w_512 : GCCBuiltin<"__builtin_ia32_pavgw512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], + [IntrNoMem]>; def int_x86_avx512_pmaddw_d_512 : GCCBuiltin<"__builtin_ia32_pmaddwd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty], [IntrNoMem, Commutative]>; @@ -3548,582 +3569,553 @@ let TargetPrefix = "x86" in { def int_x86_avx512_dbpsadbw_128 : GCCBuiltin<"__builtin_ia32_dbpsadbw128">, Intrinsic<[llvm_v8i16_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_dbpsadbw_256 : GCCBuiltin<"__builtin_ia32_dbpsadbw256">, Intrinsic<[llvm_v16i16_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_dbpsadbw_512 : GCCBuiltin<"__builtin_ia32_dbpsadbw512">, Intrinsic<[llvm_v32i16_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty], [IntrNoMem]>; + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; } // Gather and Scatter ops let TargetPrefix = "x86" in { // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. - def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. + def int_x86_avx512_gather_dpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gathersiv16sf">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_dps_512 : Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8df">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_qpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16sf">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_qps_512 : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; - def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gathersiv8di">, + def int_x86_avx512_gather_dpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gathersiv16si">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_dpi_512 : Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8di">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_qpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16si">, + [IntrReadMem, ImmArg<4>]>; + def int_x86_avx512_gather_qpi_512 : Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div2_df : - GCCBuiltin<"__builtin_ia32_gather3div2df">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div2_di : - GCCBuiltin<"__builtin_ia32_gather3div2di">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div4_df : - GCCBuiltin<"__builtin_ia32_gather3div4df">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div4_di : - GCCBuiltin<"__builtin_ia32_gather3div4di">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div4_sf : - GCCBuiltin<"__builtin_ia32_gather3div4sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div4_si : - GCCBuiltin<"__builtin_ia32_gather3div4si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div8_sf : - GCCBuiltin<"__builtin_ia32_gather3div8sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3div8_si : - GCCBuiltin<"__builtin_ia32_gather3div8si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv2_df : - GCCBuiltin<"__builtin_ia32_gather3siv2df">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv2_di : - GCCBuiltin<"__builtin_ia32_gather3siv2di">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv4_df : - GCCBuiltin<"__builtin_ia32_gather3siv4df">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv4_di : - GCCBuiltin<"__builtin_ia32_gather3siv4di">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv4_sf : - GCCBuiltin<"__builtin_ia32_gather3siv4sf">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv4_si : - GCCBuiltin<"__builtin_ia32_gather3siv4si">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv8_sf : - GCCBuiltin<"__builtin_ia32_gather3siv8sf">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_gather3siv8_si : - GCCBuiltin<"__builtin_ia32_gather3siv8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; // scatter // NOTE: These are deprecated in favor of the versions that take a vXi1 mask. - def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scattersiv8df">, + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. + def int_x86_avx512_scatter_dpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scattersiv16sf">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_dps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8df">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_qpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16sf">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_qps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; - def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scattersiv8di">, + def int_x86_avx512_scatter_dpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scattersiv16si">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_dpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8di">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_qpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; - def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16si">, + [ImmArg<4>]>; + def int_x86_avx512_scatter_qpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv2_df : - GCCBuiltin<"__builtin_ia32_scatterdiv2df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv2_di : - GCCBuiltin<"__builtin_ia32_scatterdiv2di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv4_df : - GCCBuiltin<"__builtin_ia32_scatterdiv4df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv4_di : - GCCBuiltin<"__builtin_ia32_scatterdiv4di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv4_sf : - GCCBuiltin<"__builtin_ia32_scatterdiv4sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv4_si : - GCCBuiltin<"__builtin_ia32_scatterdiv4si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv8_sf : - GCCBuiltin<"__builtin_ia32_scatterdiv8sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scatterdiv8_si : - GCCBuiltin<"__builtin_ia32_scatterdiv8si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv2_df : - GCCBuiltin<"__builtin_ia32_scattersiv2df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv2_di : - GCCBuiltin<"__builtin_ia32_scattersiv2di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv4_df : - GCCBuiltin<"__builtin_ia32_scattersiv4df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv4_di : - GCCBuiltin<"__builtin_ia32_scattersiv4di">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv4_sf : - GCCBuiltin<"__builtin_ia32_scattersiv4sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv4_si : - GCCBuiltin<"__builtin_ia32_scattersiv4si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv8_sf : - GCCBuiltin<"__builtin_ia32_scattersiv8sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_scattersiv8_si : - GCCBuiltin<"__builtin_ia32_scattersiv8si">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; // gather prefetch + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_gatherpf_dps_512 : GCCBuiltin<"__builtin_ia32_gatherpfdps">, Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_gatherpf_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfqpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_gatherpf_qps_512 : GCCBuiltin<"__builtin_ia32_gatherpfqps">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; // scatter prefetch + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_scatterpf_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfdpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_scatterpf_dps_512 : GCCBuiltin<"__builtin_ia32_scatterpfdps">, Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_scatterpf_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfqpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; def int_x86_avx512_scatterpf_qps_512 : GCCBuiltin<"__builtin_ia32_scatterpfqps">, Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly]>; + llvm_i32_ty, llvm_i32_ty], [ImmArg<3>, ImmArg<4>]>; } // AVX512 gather/scatter intrinsics that use vXi1 masks. let TargetPrefix = "x86" in { + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_mask_gather_dpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_dps_512 : Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_qpd_512 : Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_qps_512 : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_dpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_dpi_512 : Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, llvm_v16i32_ty, llvm_v16i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_qpq_512 : Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather_qpi_512 : Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div2_df : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div2_di : Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div4_df : Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div4_di : Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div4_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div4_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div8_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3div8_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv2_df : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv2_di : Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv4_df : Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv4_di : Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv4_sf : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv4_si : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv8_sf : Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_gather3siv8_si : Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i1_ty, llvm_i32_ty], - [IntrReadMem, IntrArgMemOnly]>; + [IntrReadMem, ImmArg<4>]>; def int_x86_avx512_mask_scatter_dpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_dps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_qpd_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_qps_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; + // NOTE: These can't be ArgMemOnly because you can put the address completely + // in the index register. def int_x86_avx512_mask_scatter_dpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_dpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_qpq_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty,llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatter_qpi_512 : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv2_df : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv2_di : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv4_df : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv4_di : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv4_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv4_si : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv8_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scatterdiv8_si : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv2_df : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv2_di : Intrinsic<[], [llvm_ptr_ty, llvm_v2i1_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv4_df : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv4_di : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv4_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv4_si : Intrinsic<[], [llvm_ptr_ty, llvm_v4i1_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv8_sf : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; def int_x86_avx512_mask_scattersiv8_si : Intrinsic<[], [llvm_ptr_ty, llvm_v8i1_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [ImmArg<4>]>; } // AVX-512 conflict detection instruction // Instructions that count the number of leading zero bits let TargetPrefix = "x86" in { - def int_x86_avx512_mask_conflict_d_128 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_conflict_d_256 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_conflict_d_512 : - GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_conflict_q_128 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_conflict_q_256 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_conflict_q_512 : - GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_conflict_d_128 : + GCCBuiltin<"__builtin_ia32_vpconflictsi_128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_conflict_d_256 : + GCCBuiltin<"__builtin_ia32_vpconflictsi_256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_conflict_d_512 : + GCCBuiltin<"__builtin_ia32_vpconflictsi_512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], [IntrNoMem]>; + + def int_x86_avx512_conflict_q_128 : + GCCBuiltin<"__builtin_ia32_vpconflictdi_128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_conflict_q_256 : + GCCBuiltin<"__builtin_ia32_vpconflictdi_256">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_conflict_q_512 : + GCCBuiltin<"__builtin_ia32_vpconflictdi_512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], [IntrNoMem]>; } // Compares @@ -4131,164 +4123,26 @@ let TargetPrefix = "x86" in { // 512-bit def int_x86_avx512_vcomi_sd : GCCBuiltin<"__builtin_ia32_vcomisd">, Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, - llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; def int_x86_avx512_vcomi_ss : GCCBuiltin<"__builtin_ia32_vcomiss">, Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, - llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; } // Compress, Expand let TargetPrefix = "x86" in { - def int_x86_avx512_mask_compress_ps_512 : - GCCBuiltin<"__builtin_ia32_compresssf512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_pd_512 : - GCCBuiltin<"__builtin_ia32_compressdf512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_ps_256 : - GCCBuiltin<"__builtin_ia32_compresssf256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_pd_256 : - GCCBuiltin<"__builtin_ia32_compressdf256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_ps_128 : - GCCBuiltin<"__builtin_ia32_compresssf128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_pd_128 : - GCCBuiltin<"__builtin_ia32_compressdf128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_compress_d_512 : - GCCBuiltin<"__builtin_ia32_compresssi512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_q_512 : - GCCBuiltin<"__builtin_ia32_compressdi512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_d_256 : - GCCBuiltin<"__builtin_ia32_compresssi256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_q_256 : - GCCBuiltin<"__builtin_ia32_compressdi256_mask">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_d_128 : - GCCBuiltin<"__builtin_ia32_compresssi128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_q_128 : - GCCBuiltin<"__builtin_ia32_compressdi128_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_compress_b_512 : - GCCBuiltin<"__builtin_ia32_compressqi512_mask">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, - llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_w_512 : - GCCBuiltin<"__builtin_ia32_compresshi512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_b_256 : - GCCBuiltin<"__builtin_ia32_compressqi256_mask">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_w_256 : - GCCBuiltin<"__builtin_ia32_compresshi256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_b_128 : - GCCBuiltin<"__builtin_ia32_compressqi128_mask">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_w_128 : - GCCBuiltin<"__builtin_ia32_compresshi128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; - -// expand - def int_x86_avx512_mask_expand_ps_512 : - GCCBuiltin<"__builtin_ia32_expandsf512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_pd_512 : - GCCBuiltin<"__builtin_ia32_expanddf512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_ps_256 : - GCCBuiltin<"__builtin_ia32_expandsf256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_pd_256 : - GCCBuiltin<"__builtin_ia32_expanddf256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_ps_128 : - GCCBuiltin<"__builtin_ia32_expandsf128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_pd_128 : - GCCBuiltin<"__builtin_ia32_expanddf128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_expand_d_512 : - GCCBuiltin<"__builtin_ia32_expandsi512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_q_512 : - GCCBuiltin<"__builtin_ia32_expanddi512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_d_256 : - GCCBuiltin<"__builtin_ia32_expandsi256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_q_256 : - GCCBuiltin<"__builtin_ia32_expanddi256_mask">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_d_128 : - GCCBuiltin<"__builtin_ia32_expandsi128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_q_128 : - GCCBuiltin<"__builtin_ia32_expanddi128_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_expand_b_512 : - GCCBuiltin<"__builtin_ia32_expandqi512_mask">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, - llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_w_512 : - GCCBuiltin<"__builtin_ia32_expandhi512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_b_256 : - GCCBuiltin<"__builtin_ia32_expandqi256_mask">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_w_256 : - GCCBuiltin<"__builtin_ia32_expandhi256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_b_128 : - GCCBuiltin<"__builtin_ia32_expandqi128_mask">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_w_128 : - GCCBuiltin<"__builtin_ia32_expandhi128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [IntrNoMem]>; + def int_x86_avx512_mask_expand : + Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [IntrNoMem]>; } // truncate @@ -4502,10 +4356,6 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_256 : // FIXME: Replace with trunc+select. - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pmov_qd_mem_256 : GCCBuiltin<"__builtin_ia32_pmovqd256mem_mask">, Intrinsic<[], @@ -4531,10 +4381,6 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_512 : // FIXME: Replace with trunc+select. - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pmov_qd_mem_512 : GCCBuiltin<"__builtin_ia32_pmovqd512mem_mask">, Intrinsic<[], @@ -4768,10 +4614,6 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_256 : // FIXME: Replace with trunc+select. - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pmov_wb_mem_256 : GCCBuiltin<"__builtin_ia32_pmovwb256mem_mask">, Intrinsic<[], @@ -4797,10 +4639,6 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_512 : // FIXME: Replace with trunc+select. - Intrinsic<[llvm_v32i8_ty], - [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pmov_wb_mem_512 : GCCBuiltin<"__builtin_ia32_pmovwb512mem_mask">, Intrinsic<[], @@ -4834,36 +4672,64 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_pternlogd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_pternlog_d_256 : GCCBuiltin<"__builtin_ia32_pternlogd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_pternlog_d_512 : GCCBuiltin<"__builtin_ia32_pternlogd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_pternlog_q_128 : GCCBuiltin<"__builtin_ia32_pternlogq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_pternlog_q_256 : GCCBuiltin<"__builtin_ia32_pternlogq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<3>]>; def int_x86_avx512_pternlog_q_512 : GCCBuiltin<"__builtin_ia32_pternlogq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<3>]>; +} + +// vp2intersect +let TargetPrefix = "x86" in { + def int_x86_avx512_vp2intersect_q_512 : + Intrinsic<[llvm_v8i1_ty, llvm_v8i1_ty], + [llvm_v8i64_ty, llvm_v8i64_ty], + [IntrNoMem]>; + def int_x86_avx512_vp2intersect_q_256 : + Intrinsic<[llvm_v4i1_ty, llvm_v4i1_ty], + [llvm_v4i64_ty, llvm_v4i64_ty], + [IntrNoMem]>; + def int_x86_avx512_vp2intersect_q_128 : + Intrinsic<[llvm_v2i1_ty, llvm_v2i1_ty], + [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_avx512_vp2intersect_d_512 : + Intrinsic<[llvm_v16i1_ty, llvm_v16i1_ty], + [llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; + def int_x86_avx512_vp2intersect_d_256 : + Intrinsic<[llvm_v8i1_ty, llvm_v8i1_ty], + [llvm_v8i32_ty, llvm_v8i32_ty], + [IntrNoMem]>; + def int_x86_avx512_vp2intersect_d_128 : + Intrinsic<[llvm_v4i1_ty, llvm_v4i1_ty], + [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; } @@ -4873,31 +4739,35 @@ let TargetPrefix = "x86" in { // distinction in signaling behaviour is not implemented. def int_x86_avx512_cmp_ps_512 : Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; def int_x86_avx512_cmp_pd_512 : Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<3>]>; def int_x86_avx512_cmp_ps_256 : Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cmp_pd_256 : Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cmp_ps_128 : Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_cmp_pd_128 : Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem, ImmArg<2>]>; def int_x86_avx512_mask_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss_mask">, Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<4>]>; def int_x86_avx512_mask_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd_mask">, Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>, ImmArg<4>]>; } //===----------------------------------------------------------------------===// @@ -4905,7 +4775,7 @@ let TargetPrefix = "x86" in { let TargetPrefix = "x86" in { def int_x86_sha1rnds4 : GCCBuiltin<"__builtin_ia32_sha1rnds4">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; + [IntrNoMem, ImmArg<2>]>; def int_x86_sha1nexte : GCCBuiltin<"__builtin_ia32_sha1nexte">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; def int_x86_sha1msg1 : GCCBuiltin<"__builtin_ia32_sha1msg1">, @@ -5000,3 +4870,51 @@ let TargetPrefix = "x86" in { def int_x86_invpcid : GCCBuiltin<"__builtin_ia32_invpcid">, Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>; } + +let TargetPrefix = "x86" in { + def int_x86_avx512bf16_cvtne2ps2bf16_128: + GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_avx512bf16_cvtne2ps2bf16_256: + GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_256">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8f32_ty, llvm_v8f32_ty], + [IntrNoMem]>; + def int_x86_avx512bf16_cvtne2ps2bf16_512: + GCCBuiltin<"__builtin_ia32_cvtne2ps2bf16_512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty], + [IntrNoMem]>; + // Intrinsic must be masked due to it producing less than 128 bits of results. + def int_x86_avx512bf16_mask_cvtneps2bf16_128: + Intrinsic<[llvm_v8i16_ty], + [llvm_v4f32_ty, llvm_v8i16_ty, llvm_v4i1_ty], + [IntrNoMem]>; + def int_x86_avx512bf16_cvtneps2bf16_256: + GCCBuiltin<"__builtin_ia32_cvtneps2bf16_256">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx512bf16_cvtneps2bf16_512: + GCCBuiltin<"__builtin_ia32_cvtneps2bf16_512">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512bf16_dpbf16ps_128: + GCCBuiltin<"__builtin_ia32_dpbf16ps_128">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512bf16_dpbf16ps_256: + GCCBuiltin<"__builtin_ia32_dpbf16ps_256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512bf16_dpbf16ps_512: + GCCBuiltin<"__builtin_ia32_dpbf16ps_512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// ENQCMD - Enqueue Stores Instructions + +let TargetPrefix = "x86" in { + def int_x86_enqcmd : GCCBuiltin<"__builtin_ia32_enqcmd">, + Intrinsic<[llvm_i8_ty], [llvm_ptr_ty, llvm_ptr_ty], []>; + def int_x86_enqcmds : GCCBuiltin<"__builtin_ia32_enqcmds">, + Intrinsic<[llvm_i8_ty], [llvm_ptr_ty, llvm_ptr_ty], []>; +} diff --git a/include/llvm/IR/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td index b614e1ed6ec0..7fe8bdfd3bd0 100644 --- a/include/llvm/IR/IntrinsicsXCore.td +++ b/include/llvm/IR/IntrinsicsXCore.td @@ -1,9 +1,8 @@ //==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index bd7097b39a3e..c80504500418 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -1,9 +1,8 @@ //===- llvm/LLVMContext.h - Class for managing "global" state ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -36,12 +35,8 @@ template <typename T> class SmallVectorImpl; class SMDiagnostic; class StringRef; class Twine; - -namespace yaml { - -class Output; - -} // end namespace yaml +class RemarkStreamer; +class raw_ostream; namespace SyncScope { @@ -103,6 +98,8 @@ public: MD_callees = 23, // "callees" MD_irr_loop = 24, // "irr_loop" MD_access_group = 25, // "llvm.access.group" + MD_callback = 26, // "callback" + MD_preserve_access_index = 27, // "llvm.preserve.*.access.index" }; /// Known operand bundle tag IDs, which always have the same value. All @@ -246,16 +243,23 @@ public: /// included in optimization diagnostics. void setDiagnosticsHotnessThreshold(uint64_t Threshold); - /// Return the YAML file used by the backend to save optimization - /// diagnostics. If null, diagnostics are not saved in a file but only - /// emitted via the diagnostic handler. - yaml::Output *getDiagnosticsOutputFile(); - /// Set the diagnostics output file used for optimization diagnostics. + /// Return the streamer used by the backend to save remark diagnostics. If it + /// does not exist, diagnostics are not saved in a file but only emitted via + /// the diagnostic handler. + RemarkStreamer *getRemarkStreamer(); + const RemarkStreamer *getRemarkStreamer() const; + + /// Set the diagnostics output used for optimization diagnostics. + /// This filename may be embedded in a section for tools to find the + /// diagnostics whenever they're needed. + /// + /// If a remark streamer is already set, it will be replaced with + /// \p RemarkStreamer. /// - /// By default or if invoked with null, diagnostics are not saved in a file - /// but only emitted via the diagnostic handler. Even if an output file is - /// set, the handler is invoked for each diagnostic message. - void setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F); + /// By default, diagnostics are not saved in a file but only emitted via the + /// diagnostic handler. Even if an output file is set, the handler is invoked + /// for each diagnostic message. + void setRemarkStreamer(std::unique_ptr<RemarkStreamer> RemarkStreamer); /// Get the prefix that should be printed in front of a diagnostic of /// the given \p Severity diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index 5257a0eed488..d6bb79ab6019 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -1,9 +1,8 @@ //===- LegacyPassManager.h - Legacy Container for Passes --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index 51a2eb2a146d..72bc80fb5381 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -1,9 +1,8 @@ //===- LegacyPassManagers.h - Legacy Pass Infrastructure --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index 4cec08196408..30820e750350 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -1,9 +1,8 @@ //===- LegacyPassNameParser.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 174616c7ab1d..3a2b1bddf45d 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -1,9 +1,8 @@ //===---- llvm/MDBuilder.h - Builder for LLVM metadata ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -95,6 +94,17 @@ public: MDNode *createCallees(ArrayRef<Function *> Callees); //===------------------------------------------------------------------===// + // Callback metadata. + //===------------------------------------------------------------------===// + + /// Return metadata describing a callback (see llvm::AbstractCallSite). + MDNode *createCallbackEncoding(unsigned CalleeArgNo, ArrayRef<int> Arguments, + bool VarArgsArePassed); + + /// Merge the new callback encoding \p NewCB into \p ExistingCallbacks. + MDNode *mergeCallbackEncodings(MDNode *ExistingCallbacks, MDNode *NewCB); + + //===------------------------------------------------------------------===// // AA metadata. //===------------------------------------------------------------------===// diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h index 0261c00f524c..e4a05ab46a65 100644 --- a/include/llvm/IR/Mangler.h +++ b/include/llvm/IR/Mangler.h @@ -1,9 +1,8 @@ //===-- llvm/IR/Mangler.h - Self-contained name mangler ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 70a03f28b488..1df60cadac08 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -1,9 +1,8 @@ //===- llvm/IR/Metadata.def - Metadata definitions --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -114,6 +113,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity) HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacro) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIMacroFile) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICommonBlock) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index be82c4efc115..7ca2540181ba 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -1,9 +1,8 @@ //===- llvm/IR/Metadata.h - Metadata definitions ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 9ef35f1f73cd..f458680cfe15 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -1,9 +1,8 @@ //===- llvm/Module.h - C++ class to represent a VM module -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -29,6 +28,7 @@ #include "llvm/IR/GlobalIFunc.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/CodeGen.h" @@ -333,16 +333,18 @@ public: /// Look up the specified function in the module symbol table. Four /// possibilities: /// 1. If it does not exist, add a prototype for the function and return it. - /// 2. If it exists, and has a local linkage, the existing function is - /// renamed and a new one is inserted. - /// 3. Otherwise, if the existing function has the correct prototype, return + /// 2. Otherwise, if the existing function has the correct prototype, return /// the existing function. - /// 4. Finally, the function exists but has the wrong prototype: return the + /// 3. Finally, the function exists but has the wrong prototype: return the /// function with a constantexpr cast to the right prototype. - Constant *getOrInsertFunction(StringRef Name, FunctionType *T, - AttributeList AttributeList); + /// + /// In all cases, the returned value is a FunctionCallee wrapper around the + /// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or + /// the bitcast to the function. + FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, + AttributeList AttributeList); - Constant *getOrInsertFunction(StringRef Name, FunctionType *T); + FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T); /// Look up the specified function in the module symbol table. If it does not /// exist, add a prototype for the function and return it. This function @@ -350,11 +352,10 @@ public: /// or a ConstantExpr BitCast of that type if the named function has a /// different type. This version of the method takes a list of /// function arguments, which makes it easier for clients to use. - template<typename... ArgsTy> - Constant *getOrInsertFunction(StringRef Name, - AttributeList AttributeList, - Type *RetTy, ArgsTy... Args) - { + template <typename... ArgsTy> + FunctionCallee getOrInsertFunction(StringRef Name, + AttributeList AttributeList, Type *RetTy, + ArgsTy... Args) { SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...}; return getOrInsertFunction(Name, FunctionType::get(RetTy, ArgTys, false), @@ -362,15 +363,17 @@ public: } /// Same as above, but without the attributes. - template<typename... ArgsTy> - Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ArgsTy... Args) { + template <typename... ArgsTy> + FunctionCallee getOrInsertFunction(StringRef Name, Type *RetTy, + ArgsTy... Args) { return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...); } // Avoid an incorrect ordering that'd otherwise compile incorrectly. template <typename... ArgsTy> - Constant *getOrInsertFunction(StringRef Name, AttributeList AttributeList, - FunctionType *Invalid, ArgsTy... Args) = delete; + FunctionCallee + getOrInsertFunction(StringRef Name, AttributeList AttributeList, + FunctionType *Invalid, ArgsTy... Args) = delete; /// Look up the specified function in the module symbol table. If it does not /// exist, return null. @@ -866,10 +869,11 @@ public: /// @{ /// Attach profile summary metadata to this module. - void setProfileSummary(Metadata *M); + void setProfileSummary(Metadata *M, ProfileSummary::Kind Kind); - /// Returns profile summary metadata - Metadata *getProfileSummary(); + /// Returns profile summary metadata. When IsCS is true, use the context + /// sensitive profile summary. + Metadata *getProfileSummary(bool IsCS); /// @} /// Returns true if PLT should be avoided for RTLib calls. diff --git a/include/llvm/IR/ModuleSlotTracker.h b/include/llvm/IR/ModuleSlotTracker.h index eb26fba906ea..85f8ff938366 100644 --- a/include/llvm/IR/ModuleSlotTracker.h +++ b/include/llvm/IR/ModuleSlotTracker.h @@ -1,9 +1,8 @@ //===-- llvm/IR/ModuleSlotTracker.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index a1acee494475..aacf8cfc089f 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -1,9 +1,8 @@ //===- llvm/ModuleSummaryIndex.h - Module Summary Index ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -120,7 +119,7 @@ class GlobalValueSummary; using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>; -struct GlobalValueSummaryInfo { +struct LLVM_ALIGNAS(8) GlobalValueSummaryInfo { union NameOrGV { NameOrGV(bool HaveGVs) { if (HaveGVs) @@ -163,7 +162,8 @@ using GlobalValueSummaryMapTy = /// Struct that holds a reference to a particular GUID in a global value /// summary. struct ValueInfo { - PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 2, int> + enum Flags { HaveGV = 1, ReadOnly = 2, WriteOnly = 4 }; + PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 3, int> RefAndFlags; ValueInfo() = default; @@ -189,15 +189,42 @@ struct ValueInfo { : getRef()->second.U.Name; } - bool haveGVs() const { return RefAndFlags.getInt() & 0x1; } - bool isReadOnly() const { return RefAndFlags.getInt() & 0x2; } - void setReadOnly() { RefAndFlags.setInt(RefAndFlags.getInt() | 0x2); } + bool haveGVs() const { return RefAndFlags.getInt() & HaveGV; } + bool isReadOnly() const { + assert(isValidAccessSpecifier()); + return RefAndFlags.getInt() & ReadOnly; + } + bool isWriteOnly() const { + assert(isValidAccessSpecifier()); + return RefAndFlags.getInt() & WriteOnly; + } + unsigned getAccessSpecifier() const { + assert(isValidAccessSpecifier()); + return RefAndFlags.getInt() & (ReadOnly | WriteOnly); + } + bool isValidAccessSpecifier() const { + unsigned BadAccessMask = ReadOnly | WriteOnly; + return (RefAndFlags.getInt() & BadAccessMask) != BadAccessMask; + } + void setReadOnly() { + // We expect ro/wo attribute to set only once during + // ValueInfo lifetime. + assert(getAccessSpecifier() == 0); + RefAndFlags.setInt(RefAndFlags.getInt() | ReadOnly); + } + void setWriteOnly() { + assert(getAccessSpecifier() == 0); + RefAndFlags.setInt(RefAndFlags.getInt() | WriteOnly); + } const GlobalValueSummaryMapTy::value_type *getRef() const { return RefAndFlags.getPointer(); } bool isDSOLocal() const; + + /// Checks if all copies are eligible for auto-hiding (have flag set). + bool canAutoHide() const; }; inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) { @@ -280,11 +307,23 @@ public: /// within the same linkage unit. unsigned DSOLocal : 1; + /// In the per-module summary, indicates that the global value is + /// linkonce_odr and global unnamed addr (so eligible for auto-hiding + /// via hidden visibility). In the combined summary, indicates that the + /// prevailing linkonce_odr copy can be auto-hidden via hidden visibility + /// when it is upgraded to weak_odr in the backend. This is legal when + /// all copies are eligible for auto-hiding (i.e. all copies were + /// linkonce_odr global unnamed addr. If any copy is not (e.g. it was + /// originally weak_odr, we cannot auto-hide the prevailing copy as it + /// means the symbol was externally visible. + unsigned CanAutoHide : 1; + /// Convenience Constructors explicit GVFlags(GlobalValue::LinkageTypes Linkage, - bool NotEligibleToImport, bool Live, bool IsLocal) + bool NotEligibleToImport, bool Live, bool IsLocal, + bool CanAutoHide) : Linkage(Linkage), NotEligibleToImport(NotEligibleToImport), - Live(Live), DSOLocal(IsLocal) {} + Live(Live), DSOLocal(IsLocal), CanAutoHide(CanAutoHide) {} }; private: @@ -365,6 +404,10 @@ public: bool isDSOLocal() const { return Flags.DSOLocal; } + void setCanAutoHide(bool CanAutoHide) { Flags.CanAutoHide = CanAutoHide; } + + bool canAutoHide() const { return Flags.CanAutoHide; } + /// Flag that this global value cannot be imported. void setNotEligibleToImport() { Flags.NotEligibleToImport = true; } @@ -381,25 +424,35 @@ public: /// Alias summary information. class AliasSummary : public GlobalValueSummary { + ValueInfo AliaseeValueInfo; + + /// This is the Aliasee in the same module as alias (could get from VI, trades + /// memory for time). Note that this pointer may be null (and the value info + /// empty) when we have a distributed index where the alias is being imported + /// (as a copy of the aliasee), but the aliasee is not. GlobalValueSummary *AliaseeSummary; - // AliaseeGUID is only set and accessed when we are building a combined index - // via the BitcodeReader. - GlobalValue::GUID AliaseeGUID; public: AliasSummary(GVFlags Flags) : GlobalValueSummary(AliasKind, Flags, ArrayRef<ValueInfo>{}), - AliaseeSummary(nullptr), AliaseeGUID(0) {} + AliaseeSummary(nullptr) {} /// Check if this is an alias summary. static bool classof(const GlobalValueSummary *GVS) { return GVS->getSummaryKind() == AliasKind; } - void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; } - void setAliaseeGUID(GlobalValue::GUID GUID) { AliaseeGUID = GUID; } + void setAliasee(ValueInfo &AliaseeVI, GlobalValueSummary *Aliasee) { + AliaseeValueInfo = AliaseeVI; + AliaseeSummary = Aliasee; + } - bool hasAliasee() const { return !!AliaseeSummary; } + bool hasAliasee() const { + assert(!!AliaseeSummary == (AliaseeValueInfo && + !AliaseeValueInfo.getSummaryList().empty()) && + "Expect to have both aliasee summary and summary list or neither"); + return !!AliaseeSummary; + } const GlobalValueSummary &getAliasee() const { assert(AliaseeSummary && "Unexpected missing aliasee summary"); @@ -410,10 +463,13 @@ public: return const_cast<GlobalValueSummary &>( static_cast<const AliasSummary *>(this)->getAliasee()); } - bool hasAliaseeGUID() const { return AliaseeGUID != 0; } - const GlobalValue::GUID &getAliaseeGUID() const { - assert(AliaseeGUID && "Unexpected missing aliasee GUID"); - return AliaseeGUID; + ValueInfo getAliaseeVI() const { + assert(AliaseeValueInfo && "Unexpected missing aliasee"); + return AliaseeValueInfo; + } + GlobalValue::GUID getAliaseeGUID() const { + assert(AliaseeValueInfo && "Unexpected missing aliasee"); + return AliaseeValueInfo.getGUID(); } }; @@ -500,7 +556,8 @@ public: return FunctionSummary( FunctionSummary::GVFlags( GlobalValue::LinkageTypes::AvailableExternallyLinkage, - /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false), + /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false, + /*CanAutoHide=*/false), /*InsCount=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, std::vector<ValueInfo>(), std::move(Edges), std::vector<GlobalValue::GUID>(), @@ -552,8 +609,8 @@ public: std::move(TypeTestAssumeConstVCalls), std::move(TypeCheckedLoadConstVCalls)}); } - // Gets the number of immutable refs in RefEdgeList - unsigned immutableRefCount() const; + // Gets the number of readonly and writeonly refs in RefEdgeList + std::pair<unsigned, unsigned> specialRefCounts() const; /// Check if this is a function summary. static bool classof(const GlobalValueSummary *GVS) { @@ -666,18 +723,43 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> { } }; +/// The ValueInfo and offset for a function within a vtable definition +/// initializer array. +struct VirtFuncOffset { + VirtFuncOffset(ValueInfo VI, uint64_t Offset) + : FuncVI(VI), VTableOffset(Offset) {} + + ValueInfo FuncVI; + uint64_t VTableOffset; +}; +/// List of functions referenced by a particular vtable definition. +using VTableFuncList = std::vector<VirtFuncOffset>; + /// Global variable summary information to aid decisions and /// implementation of importing. /// -/// Global variable summary has extra flag, telling if it is -/// modified during the program run or not. This affects ThinLTO -/// internalization +/// Global variable summary has two extra flag, telling if it is +/// readonly or writeonly. Both readonly and writeonly variables +/// can be optimized in the backed: readonly variables can be +/// const-folded, while writeonly vars can be completely eliminated +/// together with corresponding stores. We let both things happen +/// by means of internalizing such variables after ThinLTO import. class GlobalVarSummary : public GlobalValueSummary { +private: + /// For vtable definitions this holds the list of functions and + /// their corresponding offsets within the initializer array. + std::unique_ptr<VTableFuncList> VTableFuncs; + public: struct GVarFlags { - GVarFlags(bool ReadOnly = false) : ReadOnly(ReadOnly) {} - - unsigned ReadOnly : 1; + GVarFlags(bool ReadOnly, bool WriteOnly) + : MaybeReadOnly(ReadOnly), MaybeWriteOnly(WriteOnly) {} + + // In permodule summaries both MaybeReadOnly and MaybeWriteOnly + // bits are set, because attribute propagation occurs later on + // thin link phase. + unsigned MaybeReadOnly : 1; + unsigned MaybeWriteOnly : 1; } VarFlags; GlobalVarSummary(GVFlags Flags, GVarFlags VarFlags, @@ -691,8 +773,21 @@ public: } GVarFlags varflags() const { return VarFlags; } - void setReadOnly(bool RO) { VarFlags.ReadOnly = RO; } - bool isReadOnly() const { return VarFlags.ReadOnly; } + void setReadOnly(bool RO) { VarFlags.MaybeReadOnly = RO; } + void setWriteOnly(bool WO) { VarFlags.MaybeWriteOnly = WO; } + bool maybeReadOnly() const { return VarFlags.MaybeReadOnly; } + bool maybeWriteOnly() const { return VarFlags.MaybeWriteOnly; } + + void setVTableFuncs(VTableFuncList Funcs) { + assert(!VTableFuncs); + VTableFuncs = llvm::make_unique<VTableFuncList>(std::move(Funcs)); + } + + ArrayRef<VirtFuncOffset> vTableFuncs() const { + if (VTableFuncs) + return *VTableFuncs; + return {}; + } }; struct TypeTestResolution { @@ -791,6 +886,29 @@ using GVSummaryMapTy = DenseMap<GlobalValue::GUID, GlobalValueSummary *>; using TypeIdSummaryMapTy = std::multimap<GlobalValue::GUID, std::pair<std::string, TypeIdSummary>>; +/// The following data structures summarize type metadata information. +/// For type metadata overview see https://llvm.org/docs/TypeMetadata.html. +/// Each type metadata includes both the type identifier and the offset of +/// the address point of the type (the address held by objects of that type +/// which may not be the beginning of the virtual table). Vtable definitions +/// are decorated with type metadata for the types they are compatible with. +/// +/// Holds information about vtable definitions decorated with type metadata: +/// the vtable definition value and its address point offset in a type +/// identifier metadata it is decorated (compatible) with. +struct TypeIdOffsetVtableInfo { + TypeIdOffsetVtableInfo(uint64_t Offset, ValueInfo VI) + : AddressPointOffset(Offset), VTableVI(VI) {} + + uint64_t AddressPointOffset; + ValueInfo VTableVI; +}; +/// List of vtable definitions decorated by a particular type identifier, +/// and their corresponding offsets in that type identifier's metadata. +/// Note that each type identifier may be compatible with multiple vtables, due +/// to inheritance, which is why this is a vector. +using TypeIdCompatibleVtableInfo = std::vector<TypeIdOffsetVtableInfo>; + /// Class to hold module path string table and global value map, /// and encapsulate methods for operating on them. class ModuleSummaryIndex { @@ -803,9 +921,15 @@ private: ModulePathStringTableTy ModulePathStringTable; /// Mapping from type identifier GUIDs to type identifier and its summary - /// information. + /// information. Produced by thin link. TypeIdSummaryMapTy TypeIdMap; + /// Mapping from type identifier to information about vtables decorated + /// with that type identifier's metadata. Produced by per module summary + /// analysis and consumed by thin link. For more information, see description + /// above where TypeIdCompatibleVtableInfo is defined. + std::map<std::string, TypeIdCompatibleVtableInfo> TypeIdCompatibleVtableMap; + /// Mapping from original ID to GUID. If original ID can map to multiple /// GUIDs, it will be mapped to 0. std::map<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap; @@ -1044,24 +1168,30 @@ public: OidGuidMap[OrigGUID] = ValueGUID; } - /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if + /// Find the summary for ValueInfo \p VI in module \p ModuleId, or nullptr if /// not found. - GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID, - StringRef ModuleId) const { - auto CalleeInfo = getValueInfo(ValueGUID); - if (!CalleeInfo) { - return nullptr; // This function does not have a summary - } + GlobalValueSummary *findSummaryInModule(ValueInfo VI, StringRef ModuleId) const { + auto SummaryList = VI.getSummaryList(); auto Summary = - llvm::find_if(CalleeInfo.getSummaryList(), + llvm::find_if(SummaryList, [&](const std::unique_ptr<GlobalValueSummary> &Summary) { return Summary->modulePath() == ModuleId; }); - if (Summary == CalleeInfo.getSummaryList().end()) + if (Summary == SummaryList.end()) return nullptr; return Summary->get(); } + /// Find the summary for global \p GUID in module \p ModuleId, or nullptr if + /// not found. + GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID, + StringRef ModuleId) const { + auto CalleeInfo = getValueInfo(ValueGUID); + if (!CalleeInfo) + return nullptr; // This function does not have a summary + return findSummaryInModule(CalleeInfo, ModuleId); + } + /// Returns the first GlobalValueSummary for \p GV, asserting that there /// is only one if \p PerModuleIndex. GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV, @@ -1163,6 +1293,29 @@ public: return nullptr; } + const std::map<std::string, TypeIdCompatibleVtableInfo> & + typeIdCompatibleVtableMap() const { + return TypeIdCompatibleVtableMap; + } + + /// Return an existing or new TypeIdCompatibleVtableMap entry for \p TypeId. + /// This accessor can mutate the map and therefore should not be used in + /// the ThinLTO backends. + TypeIdCompatibleVtableInfo & + getOrInsertTypeIdCompatibleVtableSummary(StringRef TypeId) { + return TypeIdCompatibleVtableMap[TypeId]; + } + + /// For the given \p TypeId, this returns the TypeIdCompatibleVtableMap + /// entry if present in the summary map. This may be used when importing. + Optional<TypeIdCompatibleVtableInfo> + getTypeIdCompatibleVtableSummary(StringRef TypeId) const { + auto I = TypeIdCompatibleVtableMap.find(TypeId); + if (I == TypeIdCompatibleVtableMap.end()) + return None; + return I->second; + } + /// Collect for the given module the list of functions it defines /// (GUID -> Summary). void collectDefinedFunctionsForModule(StringRef ModulePath, @@ -1170,8 +1323,16 @@ public: /// Collect for each module the list of Summaries it defines (GUID -> /// Summary). - void collectDefinedGVSummariesPerModule( - StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const; + template <class Map> + void + collectDefinedGVSummariesPerModule(Map &ModuleToDefinedGVSummaries) const { + for (auto &GlobalList : *this) { + auto GUID = GlobalList.first; + for (auto &Summary : GlobalList.second.SummaryList) { + ModuleToDefinedGVSummaries[Summary->modulePath()][GUID] = Summary.get(); + } + } + } /// Print to an output stream. void print(raw_ostream &OS, bool IsForDebug = false) const; @@ -1186,7 +1347,7 @@ public: void dumpSCCs(raw_ostream &OS); /// Analyze index and detect unmodified globals - void propagateConstants(const DenseSet<GlobalValue::GUID> &PreservedSymbols); + void propagateAttributes(const DenseSet<GlobalValue::GUID> &PreservedSymbols); }; /// GraphTraits definition to build SCC for the index diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h index a88ee26b51c3..26d9c43fabf1 100644 --- a/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -1,9 +1,8 @@ //===-- llvm/ModuleSummaryIndexYAML.h - YAML I/O for summary ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -137,7 +136,7 @@ template <> struct MappingTraits<TypeIdSummary> { struct FunctionSummaryYaml { unsigned Linkage; - bool NotEligibleToImport, Live, IsLocal; + bool NotEligibleToImport, Live, IsLocal, CanAutoHide; std::vector<uint64_t> Refs; std::vector<uint64_t> TypeTests; std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls, @@ -181,6 +180,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> { io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); io.mapOptional("Live", summary.Live); io.mapOptional("Local", summary.IsLocal); + io.mapOptional("CanAutoHide", summary.CanAutoHide); io.mapOptional("Refs", summary.Refs); io.mapOptional("TypeTests", summary.TypeTests); io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); @@ -223,7 +223,7 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>( GlobalValueSummary::GVFlags( static_cast<GlobalValue::LinkageTypes>(FSum.Linkage), - FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal), + FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal, FSum.CanAutoHide), /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, Refs, ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests), std::move(FSum.TypeTestAssumeVCalls), @@ -244,7 +244,8 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { FSum->flags().Linkage, static_cast<bool>(FSum->flags().NotEligibleToImport), static_cast<bool>(FSum->flags().Live), - static_cast<bool>(FSum->flags().DSOLocal), Refs, + static_cast<bool>(FSum->flags().DSOLocal), + static_cast<bool>(FSum->flags().CanAutoHide), Refs, FSum->type_tests(), FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index def07ffe2ff6..0e3c19f4947f 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -1,9 +1,8 @@ //===- NoFolder.h - Constant folding helper ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -204,6 +203,10 @@ public: return BinaryOperator::CreateNot(C); } + Instruction *CreateUnOp(Instruction::UnaryOps Opc, Constant *C) const { + return UnaryOperator::Create(Opc, C); + } + //===--------------------------------------------------------------------===// // Memory Instructions //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h index c618aff3df9a..979ad35019f8 100644 --- a/include/llvm/IR/OperandTraits.h +++ b/include/llvm/IR/OperandTraits.h @@ -1,9 +1,8 @@ //===-- llvm/OperandTraits.h - OperandTraits class definition ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 6b387bbcccb1..8199c65ca8a0 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -1,9 +1,8 @@ //===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -188,6 +187,12 @@ public: FastMathFlags() = default; + static FastMathFlags getFast() { + FastMathFlags FMF; + FMF.setFast(); + return FMF; + } + bool any() const { return Flags != 0; } bool none() const { return Flags == 0; } bool all() const { return Flags == ~0U; } @@ -380,6 +385,7 @@ public: case Instruction::ExtractElement: case Instruction::ShuffleVector: case Instruction::InsertElement: + case Instruction::PHI: return false; default: return V->getType()->isFPOrFPVectorTy(); diff --git a/include/llvm/IR/OptBisect.h b/include/llvm/IR/OptBisect.h index aa24c94c0130..1b2b0bd7acaa 100644 --- a/include/llvm/IR/OptBisect.h +++ b/include/llvm/IR/OptBisect.h @@ -1,9 +1,8 @@ //===- llvm/IR/OptBisect.h - LLVM Bisect support ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -20,12 +19,6 @@ namespace llvm { class Pass; -class Module; -class Function; -class BasicBlock; -class Region; -class Loop; -class CallGraphSCC; /// Extensions to this class implement mechanisms to disable passes and /// individual optimizations at compile time. @@ -33,12 +26,14 @@ class OptPassGate { public: virtual ~OptPassGate() = default; - virtual bool shouldRunPass(const Pass *P, const Module &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Function &U) {return true; } - virtual bool shouldRunPass(const Pass *P, const BasicBlock &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Region &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const Loop &U) { return true; } - virtual bool shouldRunPass(const Pass *P, const CallGraphSCC &U) { return true; } + /// IRDescription is a textual description of the IR unit the pass is running + /// over. + virtual bool shouldRunPass(const Pass *P, StringRef IRDescription) { + return true; + } + + /// isEnabled should return true before calling shouldRunPass + virtual bool isEnabled() const { return false; } }; /// This class implements a mechanism to disable passes and individual @@ -60,23 +55,19 @@ public: /// Checks the bisect limit to determine if the specified pass should run. /// - /// These functions immediately return true if bisection is disabled. If the - /// bisect limit is set to -1, the functions print a message describing + /// If the bisect limit is set to -1, the function prints a message describing /// the pass and the bisect number assigned to it and return true. Otherwise, - /// the functions print a message with the bisect number assigned to the + /// the function prints a message with the bisect number assigned to the /// pass and indicating whether or not the pass will be run and return true if /// the bisect limit has not yet been exceeded or false if it has. /// - /// Most passes should not call these routines directly. Instead, they are + /// Most passes should not call this routine directly. Instead, they are /// called through helper routines provided by the pass base classes. For /// instance, function passes should call FunctionPass::skipFunction(). - bool shouldRunPass(const Pass *P, const Module &U) override; - bool shouldRunPass(const Pass *P, const Function &U) override; - bool shouldRunPass(const Pass *P, const BasicBlock &U) override; - bool shouldRunPass(const Pass *P, const Region &U) override; - bool shouldRunPass(const Pass *P, const Loop &U) override; - bool shouldRunPass(const Pass *P, const CallGraphSCC &U) override; + bool shouldRunPass(const Pass *P, StringRef IRDescription) override; + /// isEnabled should return true before calling shouldRunPass + bool isEnabled() const override { return BisectEnabled; } private: bool checkPass(const StringRef PassName, const StringRef TargetDesc); diff --git a/include/llvm/IR/PassInstrumentation.h b/include/llvm/IR/PassInstrumentation.h index 08dac1c4a274..f8a1196871cf 100644 --- a/include/llvm/IR/PassInstrumentation.h +++ b/include/llvm/IR/PassInstrumentation.h @@ -1,9 +1,8 @@ //===- llvm/IR/PassInstrumentation.h ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 738a2242eea0..37fe2a5b01ad 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -1,9 +1,8 @@ //===- PassManager.h - Pass management infrastructure -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -287,6 +286,13 @@ public: PA.PreservedIDs.count(ID)); } + /// Return true if the checker's analysis was not abandoned, i.e. it was not + /// explicitly invalidated. Even if the analysis is not explicitly + /// preserved, if the analysis is known stateless, then it is preserved. + bool preservedWhenStateless() { + return !IsAbandoned; + } + /// Returns true if the checker's analysis was not abandoned and either /// - \p AnalysisSetT is explicitly preserved or /// - all analyses are preserved. diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h index 5ad68be62742..58198bf67b11 100644 --- a/include/llvm/IR/PassManagerInternal.h +++ b/include/llvm/IR/PassManagerInternal.h @@ -1,9 +1,8 @@ //===- PassManager internal APIs and implementation details -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/IR/PassTimingInfo.h b/include/llvm/IR/PassTimingInfo.h index e9945f997f43..b8d8f117f73d 100644 --- a/include/llvm/IR/PassTimingInfo.h +++ b/include/llvm/IR/PassTimingInfo.h @@ -1,9 +1,8 @@ //===- PassTimingInfo.h - pass execution timing -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -27,10 +26,12 @@ namespace llvm { class Pass; class PassInstrumentationCallbacks; +class raw_ostream; /// If -time-passes has been specified, report the timings immediately and then -/// reset the timers to zero. -void reportAndResetTimings(); +/// reset the timers to zero. By default it uses the stream created by +/// CreateInfoOutputFile(). +void reportAndResetTimings(raw_ostream *OutStream = nullptr); /// Request the timer for this legacy-pass-manager's pass instance. Timer *getPassTimer(Pass *); @@ -63,18 +64,18 @@ class TimePassesHandler { /// Stack of currently active timers. SmallVector<Timer *, 8> TimerStack; + /// Custom output stream to print timing information into. + /// By default (== nullptr) we emit time report into the stream created by + /// CreateInfoOutputFile(). + raw_ostream *OutStream = nullptr; + bool Enabled; public: TimePassesHandler(bool Enabled = TimePassesIsEnabled); /// Destructor handles the print action if it has not been handled before. - ~TimePassesHandler() { - // First destroying the timers from TimingData, which deploys all their - // collected data into the TG time group member, which later prints itself - // when being destroyed. - TimingData.clear(); - } + ~TimePassesHandler() { print(); } /// Prints out timing information and then resets the timers. void print(); @@ -85,6 +86,9 @@ public: void registerCallbacks(PassInstrumentationCallbacks &PIC); + /// Set a custom output stream for subsequent reporting. + void setOutStream(raw_ostream &OutStream); + private: /// Dumps information for running/triggered timers, useful for debugging LLVM_DUMP_METHOD void dump() const; diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 120fc253b908..0f03d7cc56b8 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -1,9 +1,8 @@ //===- PatternMatch.h - Match on the LLVM IR --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -419,6 +418,46 @@ inline cst_pred_ty<is_lowbit_mask> m_LowBitMask() { return cst_pred_ty<is_lowbit_mask>(); } +struct icmp_pred_with_threshold { + ICmpInst::Predicate Pred; + const APInt *Thr; + bool isValue(const APInt &C) { + switch (Pred) { + case ICmpInst::Predicate::ICMP_EQ: + return C.eq(*Thr); + case ICmpInst::Predicate::ICMP_NE: + return C.ne(*Thr); + case ICmpInst::Predicate::ICMP_UGT: + return C.ugt(*Thr); + case ICmpInst::Predicate::ICMP_UGE: + return C.uge(*Thr); + case ICmpInst::Predicate::ICMP_ULT: + return C.ult(*Thr); + case ICmpInst::Predicate::ICMP_ULE: + return C.ule(*Thr); + case ICmpInst::Predicate::ICMP_SGT: + return C.sgt(*Thr); + case ICmpInst::Predicate::ICMP_SGE: + return C.sge(*Thr); + case ICmpInst::Predicate::ICMP_SLT: + return C.slt(*Thr); + case ICmpInst::Predicate::ICMP_SLE: + return C.sle(*Thr); + default: + llvm_unreachable("Unhandled ICmp predicate"); + } + } +}; +/// Match an integer or vector with every element comparing 'pred' (eg/ne/...) +/// to Threshold. For vectors, this includes constants with undefined elements. +inline cst_pred_ty<icmp_pred_with_threshold> +m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) { + cst_pred_ty<icmp_pred_with_threshold> P; + P.Pred = Predicate; + P.Thr = &Threshold; + return P; +} + struct is_nan { bool isValue(const APFloat &C) { return C.isNaN(); } }; @@ -668,18 +707,26 @@ template <typename Op_t> struct FNeg_match { FNeg_match(const Op_t &Op) : X(Op) {} template <typename OpTy> bool match(OpTy *V) { auto *FPMO = dyn_cast<FPMathOperator>(V); - if (!FPMO || FPMO->getOpcode() != Instruction::FSub) - return false; - if (FPMO->hasNoSignedZeros()) { - // With 'nsz', any zero goes. - if (!cstfp_pred_ty<is_any_zero_fp>().match(FPMO->getOperand(0))) - return false; - } else { - // Without 'nsz', we need fsub -0.0, X exactly. - if (!cstfp_pred_ty<is_neg_zero_fp>().match(FPMO->getOperand(0))) - return false; + if (!FPMO) return false; + + if (FPMO->getOpcode() == Instruction::FNeg) + return X.match(FPMO->getOperand(0)); + + if (FPMO->getOpcode() == Instruction::FSub) { + if (FPMO->hasNoSignedZeros()) { + // With 'nsz', any zero goes. + if (!cstfp_pred_ty<is_any_zero_fp>().match(FPMO->getOperand(0))) + return false; + } else { + // Without 'nsz', we need fsub -0.0, X exactly. + if (!cstfp_pred_ty<is_neg_zero_fp>().match(FPMO->getOperand(0))) + return false; + } + + return X.match(FPMO->getOperand(1)); } - return X.match(FPMO->getOperand(1)); + + return false; } }; @@ -1464,6 +1511,20 @@ struct UAddWithOverflow_match { if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + // Match special-case for increment-by-1. + if (Pred == ICmpInst::ICMP_EQ) { + // (a + 1) == 0 + // (1 + a) == 0 + if (AddExpr.match(ICmpLHS) && m_ZeroInt().match(ICmpRHS) && + (m_One().match(AddLHS) || m_One().match(AddRHS))) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); + // 0 == (a + 1) + // 0 == (1 + a) + if (m_ZeroInt().match(ICmpLHS) && AddExpr.match(ICmpRHS) && + (m_One().match(AddLHS) || m_One().match(AddRHS))) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + } + return false; } }; diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 81f535311431..cc835277910b 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -1,9 +1,8 @@ //===- PredIteratorCache.h - pred_iterator Cache ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/ProfileSummary.h b/include/llvm/IR/ProfileSummary.h index e38663770a13..78635ec4386c 100644 --- a/include/llvm/IR/ProfileSummary.h +++ b/include/llvm/IR/ProfileSummary.h @@ -1,9 +1,8 @@ //===- ProfileSummary.h - Profile summary data structure. -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,11 +42,10 @@ using SummaryEntryVector = std::vector<ProfileSummaryEntry>; class ProfileSummary { public: - enum Kind { PSK_Instr, PSK_Sample }; + enum Kind { PSK_Instr, PSK_CSInstr, PSK_Sample }; private: const Kind PSK; - static const char *KindStr[2]; SummaryEntryVector DetailedSummary; uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount; uint32_t NumCounts, NumFunctions; diff --git a/include/llvm/IR/RemarkStreamer.h b/include/llvm/IR/RemarkStreamer.h new file mode 100644 index 000000000000..f34cc660b2fb --- /dev/null +++ b/include/llvm/IR/RemarkStreamer.h @@ -0,0 +1,96 @@ +//===- llvm/IR/RemarkStreamer.h - Remark Streamer ---------------*- 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 main interface for outputting remarks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_REMARKSTREAMER_H +#define LLVM_IR_REMARKSTREAMER_H + +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Remarks/RemarkSerializer.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +#include <vector> + +namespace llvm { +/// Streamer for remarks. +class RemarkStreamer { + /// The filename that the remark diagnostics are emitted to. + const std::string Filename; + /// The regex used to filter remarks based on the passes that emit them. + Optional<Regex> PassFilter; + /// The object used to serialize the remarks to a specific format. + std::unique_ptr<remarks::Serializer> Serializer; + + /// Convert diagnostics into remark objects. + /// The lifetime of the members of the result is bound to the lifetime of + /// the LLVM diagnostics. + remarks::Remark toRemark(const DiagnosticInfoOptimizationBase &Diag); + +public: + RemarkStreamer(StringRef Filename, + std::unique_ptr<remarks::Serializer> Serializer); + /// Return the filename that the remark diagnostics are emitted to. + StringRef getFilename() const { return Filename; } + /// Return stream that the remark diagnostics are emitted to. + raw_ostream &getStream() { return Serializer->OS; } + /// Return the serializer used for this stream. + remarks::Serializer &getSerializer() { return *Serializer; } + /// Set a pass filter based on a regex \p Filter. + /// Returns an error if the regex is invalid. + Error setFilter(StringRef Filter); + /// Emit a diagnostic through the streamer. + void emit(const DiagnosticInfoOptimizationBase &Diag); +}; + +template <typename ThisError> +struct RemarkSetupErrorInfo : public ErrorInfo<ThisError> { + std::string Msg; + std::error_code EC; + + RemarkSetupErrorInfo(Error E) { + handleAllErrors(std::move(E), [&](const ErrorInfoBase &EIB) { + Msg = EIB.message(); + EC = EIB.convertToErrorCode(); + }); + } + + void log(raw_ostream &OS) const override { OS << Msg; } + std::error_code convertToErrorCode() const override { return EC; } +}; + +struct RemarkSetupFileError : RemarkSetupErrorInfo<RemarkSetupFileError> { + static char ID; + using RemarkSetupErrorInfo<RemarkSetupFileError>::RemarkSetupErrorInfo; +}; + +struct RemarkSetupPatternError : RemarkSetupErrorInfo<RemarkSetupPatternError> { + static char ID; + using RemarkSetupErrorInfo<RemarkSetupPatternError>::RemarkSetupErrorInfo; +}; + +struct RemarkSetupFormatError : RemarkSetupErrorInfo<RemarkSetupFormatError> { + static char ID; + using RemarkSetupErrorInfo<RemarkSetupFormatError>::RemarkSetupErrorInfo; +}; + +/// Setup optimization remarks. +Expected<std::unique_ptr<ToolOutputFile>> +setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, + StringRef RemarksPasses, StringRef RemarksFormat, + bool RemarksWithHotness, + unsigned RemarksHotnessThreshold = 0); + +} // end namespace llvm + +#endif // LLVM_IR_REMARKSTREAMER_H diff --git a/include/llvm/IR/RuntimeLibcalls.def b/include/llvm/IR/RuntimeLibcalls.def index 89005120cdc1..f6c74d497b18 100644 --- a/include/llvm/IR/RuntimeLibcalls.def +++ b/include/llvm/IR/RuntimeLibcalls.def @@ -1,9 +1,8 @@ //===-- llvm/RuntimeLibcalls.def - File that describes libcalls -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -255,6 +254,26 @@ HANDLE_LIBCALL(FMAX_F64, "fmax") HANDLE_LIBCALL(FMAX_F80, "fmaxl") HANDLE_LIBCALL(FMAX_F128, "fmaxl") HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl") +HANDLE_LIBCALL(LROUND_F32, "lroundf") +HANDLE_LIBCALL(LROUND_F64, "lround") +HANDLE_LIBCALL(LROUND_F80, "lroundl") +HANDLE_LIBCALL(LROUND_F128, "lroundl") +HANDLE_LIBCALL(LROUND_PPCF128, "lroundl") +HANDLE_LIBCALL(LLROUND_F32, "llroundf") +HANDLE_LIBCALL(LLROUND_F64, "llround") +HANDLE_LIBCALL(LLROUND_F80, "llroundl") +HANDLE_LIBCALL(LLROUND_F128, "llroundl") +HANDLE_LIBCALL(LLROUND_PPCF128, "llroundl") +HANDLE_LIBCALL(LRINT_F32, "lrintf") +HANDLE_LIBCALL(LRINT_F64, "lrint") +HANDLE_LIBCALL(LRINT_F80, "lrintl") +HANDLE_LIBCALL(LRINT_F128, "lrintl") +HANDLE_LIBCALL(LRINT_PPCF128, "lrintl") +HANDLE_LIBCALL(LLRINT_F32, "llrintf") +HANDLE_LIBCALL(LLRINT_F64, "llrint") +HANDLE_LIBCALL(LLRINT_F80, "llrintl") +HANDLE_LIBCALL(LLRINT_F128, "llrintl") +HANDLE_LIBCALL(LLRINT_PPCF128, "llrintl") // Conversion HANDLE_LIBCALL(FPEXT_F32_PPCF128, "__gcc_stoq") @@ -530,6 +549,9 @@ HANDLE_LIBCALL(STACKPROTECTOR_CHECK_FAIL, "__stack_chk_fail") // Deoptimization HANDLE_LIBCALL(DEOPTIMIZE, "__llvm_deoptimize") +// Return address +HANDLE_LIBCALL(RETURN_ADDRESS, nullptr) + HANDLE_LIBCALL(UNKNOWN_LIBCALL, nullptr) #undef HANDLE_LIBCALL diff --git a/include/llvm/IR/SafepointIRVerifier.h b/include/llvm/IR/SafepointIRVerifier.h index 092050d1d207..ec5527954adc 100644 --- a/include/llvm/IR/SafepointIRVerifier.h +++ b/include/llvm/IR/SafepointIRVerifier.h @@ -1,9 +1,8 @@ //===- SafepointIRVerifier.h - Checks for GC relocation problems *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,8 @@ #ifndef LLVM_IR_SAFEPOINT_IR_VERIFIER #define LLVM_IR_SAFEPOINT_IR_VERIFIER +#include "llvm/IR/PassManager.h" + namespace llvm { class Function; @@ -30,6 +31,16 @@ void verifySafepointIR(Function &F); /// Create an instance of the safepoint verifier pass which can be added to /// a pass pipeline to check for relocation bugs. FunctionPass *createSafepointIRVerifierPass(); + +/// Create an instance of the safepoint verifier pass which can be added to +/// a pass pipeline to check for relocation bugs. +class SafepointIRVerifierPass : public PassInfoMixin<SafepointIRVerifierPass> { + +public: + explicit SafepointIRVerifierPass() {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; } #endif // LLVM_IR_SAFEPOINT_IR_VERIFIER diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index 8908e1b0d090..89f130bc3351 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -1,14 +1,13 @@ //===- llvm/IR/Statepoint.h - gc.statepoint utilities -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 utility functions and a wrapper class analogous to -// CallSite for accessing the fields of gc.statepoint, gc.relocate, +// CallBase for accessing the fields of gc.statepoint, gc.relocate, // gc.result intrinsics; and some general utilities helpful when dealing with // gc.statepoint. // @@ -21,7 +20,6 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -57,42 +55,36 @@ enum class StatepointFlags { class GCRelocateInst; class GCResultInst; -bool isStatepoint(ImmutableCallSite CS); +bool isStatepoint(const CallBase *Call); bool isStatepoint(const Value *V); bool isStatepoint(const Value &V); -bool isGCRelocate(ImmutableCallSite CS); +bool isGCRelocate(const CallBase *Call); bool isGCRelocate(const Value *V); -bool isGCResult(ImmutableCallSite CS); +bool isGCResult(const CallBase *Call); bool isGCResult(const Value *V); -/// Analogous to CallSiteBase, this provides most of the actual +/// A wrapper around a GC intrinsic call, this provides most of the actual /// functionality for Statepoint and ImmutableStatepoint. It is /// templatized to allow easily specializing of const and non-const -/// concrete subtypes. This is structured analogous to CallSite -/// rather than the IntrinsicInst.h helpers since we need to support -/// invokable statepoints. +/// concrete subtypes. template <typename FunTy, typename InstructionTy, typename ValueTy, - typename CallSiteTy> + typename CallBaseTy> class StatepointBase { - CallSiteTy StatepointCS; + CallBaseTy *StatepointCall; protected: explicit StatepointBase(InstructionTy *I) { - if (isStatepoint(I)) { - StatepointCS = CallSiteTy(I); - assert(StatepointCS && "isStatepoint implies CallSite"); - } + StatepointCall = isStatepoint(I) ? cast<CallBaseTy>(I) : nullptr; } - explicit StatepointBase(CallSiteTy CS) { - if (isStatepoint(CS)) - StatepointCS = CS; + explicit StatepointBase(CallBaseTy *Call) { + StatepointCall = isStatepoint(Call) ? Call : nullptr; } public: - using arg_iterator = typename CallSiteTy::arg_iterator; + using arg_iterator = typename CallBaseTy::const_op_iterator; enum { IDPos = 0, @@ -107,30 +99,30 @@ public: void *operator new(size_t s) = delete; explicit operator bool() const { - // We do not assign non-statepoint CallSites to StatepointCS. - return (bool)StatepointCS; + // We do not assign non-statepoint call instructions to StatepointCall. + return (bool)StatepointCall; } - /// Return the underlying CallSite. - CallSiteTy getCallSite() const { + /// Return the underlying call instruction. + CallBaseTy *getCall() const { assert(*this && "check validity first!"); - return StatepointCS; + return StatepointCall; } uint64_t getFlags() const { - return cast<ConstantInt>(getCallSite().getArgument(FlagsPos)) + return cast<ConstantInt>(getCall()->getArgOperand(FlagsPos)) ->getZExtValue(); } /// Return the ID associated with this statepoint. uint64_t getID() const { - const Value *IDVal = getCallSite().getArgument(IDPos); + const Value *IDVal = getCall()->getArgOperand(IDPos); return cast<ConstantInt>(IDVal)->getZExtValue(); } /// Return the number of patchable bytes associated with this statepoint. uint32_t getNumPatchBytes() const { - const Value *NumPatchBytesVal = getCallSite().getArgument(NumPatchBytesPos); + const Value *NumPatchBytesVal = getCall()->getArgOperand(NumPatchBytesPos); uint64_t NumPatchBytes = cast<ConstantInt>(NumPatchBytesVal)->getZExtValue(); assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); @@ -139,12 +131,11 @@ public: /// Return the value actually being called or invoked. ValueTy *getCalledValue() const { - return getCallSite().getArgument(CalledFunctionPos); + return getCall()->getArgOperand(CalledFunctionPos); } - InstructionTy *getInstruction() const { - return getCallSite().getInstruction(); - } + // FIXME: Migrate users of this to `getCall` and remove it. + InstructionTy *getInstruction() const { return getCall(); } /// Return the function being called if this is a direct call, otherwise /// return null (if it's an indirect call). @@ -153,12 +144,12 @@ public: } /// Return the caller function for this statepoint. - FunTy *getCaller() const { return getCallSite().getCaller(); } + FunTy *getCaller() const { return getCall()->getCaller(); } /// Determine if the statepoint cannot unwind. bool doesNotThrow() const { Function *F = getCalledFunction(); - return getCallSite().doesNotThrow() || (F ? F->doesNotThrow() : false); + return getCall()->doesNotThrow() || (F ? F->doesNotThrow() : false); } /// Return the type of the value returned by the call underlying the @@ -171,18 +162,18 @@ public: /// Number of arguments to be passed to the actual callee. int getNumCallArgs() const { - const Value *NumCallArgsVal = getCallSite().getArgument(NumCallArgsPos); + const Value *NumCallArgsVal = getCall()->getArgOperand(NumCallArgsPos); return cast<ConstantInt>(NumCallArgsVal)->getZExtValue(); } size_t arg_size() const { return getNumCallArgs(); } - typename CallSiteTy::arg_iterator arg_begin() const { - assert(CallArgsBeginPos <= (int)getCallSite().arg_size()); - return getCallSite().arg_begin() + CallArgsBeginPos; + arg_iterator arg_begin() const { + assert(CallArgsBeginPos <= (int)getCall()->arg_size()); + return getCall()->arg_begin() + CallArgsBeginPos; } - typename CallSiteTy::arg_iterator arg_end() const { + arg_iterator arg_end() const { auto I = arg_begin() + arg_size(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -199,8 +190,8 @@ public: /// Return true if the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { Function *F = getCalledFunction(); - return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) || - (F ? F->getAttributes().hasAttribute(i, A) : false); + return getCall()->paramHasAttr(i + CallArgsBeginPos, A) || + (F ? F->getAttributes().hasAttribute(i, A) : false); } /// Number of GC transition args. @@ -208,14 +199,14 @@ public: const Value *NumGCTransitionArgs = *arg_end(); return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator gc_transition_args_begin() const { + arg_iterator gc_transition_args_begin() const { auto I = arg_end() + 1; - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } - typename CallSiteTy::arg_iterator gc_transition_args_end() const { + arg_iterator gc_transition_args_end() const { auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -231,14 +222,14 @@ public: return cast<ConstantInt>(NumVMSArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator deopt_begin() const { + arg_iterator deopt_begin() const { auto I = gc_transition_args_end() + 1; - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } - typename CallSiteTy::arg_iterator deopt_end() const { + arg_iterator deopt_end() const { auto I = deopt_begin() + getNumTotalVMSArgs(); - assert((getCallSite().arg_end() - I) >= 0); + assert((getCall()->arg_end() - I) >= 0); return I; } @@ -247,15 +238,11 @@ public: return make_range(deopt_begin(), deopt_end()); } - typename CallSiteTy::arg_iterator gc_args_begin() const { - return deopt_end(); - } - typename CallSiteTy::arg_iterator gc_args_end() const { - return getCallSite().arg_end(); - } + arg_iterator gc_args_begin() const { return deopt_end(); } + arg_iterator gc_args_end() const { return getCall()->arg_end(); } unsigned gcArgsStartIdx() const { - return gc_args_begin() - getInstruction()->op_begin(); + return gc_args_begin() - getCall()->op_begin(); } /// range adapter for gc arguments @@ -304,25 +291,24 @@ public: /// to a gc.statepoint. class ImmutableStatepoint : public StatepointBase<const Function, const Instruction, const Value, - ImmutableCallSite> { - using Base = - StatepointBase<const Function, const Instruction, const Value, - ImmutableCallSite>; + const CallBase> { + using Base = StatepointBase<const Function, const Instruction, const Value, + const CallBase>; public: explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} - explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} + explicit ImmutableStatepoint(const CallBase *Call) : Base(Call) {} }; /// A specialization of it's base class for read-write access /// to a gc.statepoint. class Statepoint - : public StatepointBase<Function, Instruction, Value, CallSite> { - using Base = StatepointBase<Function, Instruction, Value, CallSite>; + : public StatepointBase<Function, Instruction, Value, CallBase> { + using Base = StatepointBase<Function, Instruction, Value, CallBase>; public: explicit Statepoint(Instruction *I) : Base(I) {} - explicit Statepoint(CallSite CS) : Base(CS) {} + explicit Statepoint(CallBase *Call) : Base(Call) {} }; /// Common base class for representing values projected from a statepoint. @@ -347,14 +333,14 @@ public: } /// The statepoint with which this gc.relocate is associated. - const Instruction *getStatepoint() const { + const CallBase *getStatepoint() const { const Value *Token = getArgOperand(0); // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. if (!isa<LandingPadInst>(Token)) { assert(isStatepoint(Token)); - return cast<Instruction>(Token); + return cast<CallBase>(Token); } // This relocate is on exceptional path of an invoke statepoint @@ -366,7 +352,7 @@ public: "safepoint block should be well formed"); assert(isStatepoint(InvokeBB->getTerminator())); - return InvokeBB->getTerminator(); + return cast<CallBase>(InvokeBB->getTerminator()); } }; @@ -395,13 +381,11 @@ public: } Value *getBasePtr() const { - ImmutableCallSite CS(getStatepoint()); - return *(CS.arg_begin() + getBasePtrIndex()); + return *(getStatepoint()->arg_begin() + getBasePtrIndex()); } Value *getDerivedPtr() const { - ImmutableCallSite CS(getStatepoint()); - return *(CS.arg_begin() + getDerivedPtrIndex()); + return *(getStatepoint()->arg_begin() + getDerivedPtrIndex()); } }; @@ -418,28 +402,25 @@ public: }; template <typename FunTy, typename InstructionTy, typename ValueTy, - typename CallSiteTy> + typename CallBaseTy> std::vector<const GCRelocateInst *> -StatepointBase<FunTy, InstructionTy, ValueTy, CallSiteTy>::getRelocates() +StatepointBase<FunTy, InstructionTy, ValueTy, CallBaseTy>::getRelocates() const { - std::vector<const GCRelocateInst *> Result; - CallSiteTy StatepointCS = getCallSite(); - // Search for relocated pointers. Note that working backwards from the // gc_relocates ensures that we only get pairs which are actually relocated // and used after the statepoint. - for (const User *U : getInstruction()->users()) + for (const User *U : StatepointCall->users()) if (auto *Relocate = dyn_cast<GCRelocateInst>(U)) Result.push_back(Relocate); - if (!StatepointCS.isInvoke()) + auto *StatepointInvoke = dyn_cast<InvokeInst>(StatepointCall); + if (!StatepointInvoke) return Result; // We need to scan thorough exceptional relocations if it is invoke statepoint - LandingPadInst *LandingPad = - cast<InvokeInst>(getInstruction())->getLandingPadInst(); + LandingPadInst *LandingPad = StatepointInvoke->getLandingPadInst(); // Search for gc relocates that are attached to this landingpad. for (const User *LandingPadUser : LandingPad->users()) { diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h index 87ce902c2811..5b793e5dbf28 100644 --- a/include/llvm/IR/SymbolTableListTraits.h +++ b/include/llvm/IR/SymbolTableListTraits.h @@ -1,9 +1,8 @@ //===- llvm/SymbolTableListTraits.h - Traits for iplist ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h index 084efada221f..d7377398b91b 100644 --- a/include/llvm/IR/TrackingMDRef.h +++ b/include/llvm/IR/TrackingMDRef.h @@ -1,9 +1,8 @@ //===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 9c1f99d1b3a2..f2aa49030aaa 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -1,9 +1,8 @@ //===- llvm/Type.h - Classes for handling data types ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -367,6 +366,7 @@ public: return ContainedTys[0]; } + inline bool getVectorIsScalable() const; inline unsigned getVectorNumElements() const; Type *getVectorElementType() const { assert(getTypeID() == VectorTyID); @@ -467,28 +467,6 @@ template <> struct isa_impl<PointerType, Type> { } }; -//===----------------------------------------------------------------------===// -// Provide specializations of GraphTraits to be able to treat a type as a -// graph of sub types. - -template <> struct GraphTraits<Type *> { - using NodeRef = Type *; - using ChildIteratorType = Type::subtype_iterator; - - static NodeRef getEntryNode(Type *T) { return T; } - static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); } -}; - -template <> struct GraphTraits<const Type*> { - using NodeRef = const Type *; - using ChildIteratorType = Type::subtype_iterator; - - static NodeRef getEntryNode(NodeRef T) { return T; } - static ChildIteratorType child_begin(NodeRef N) { return N->subtype_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->subtype_end(); } -}; - // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef) diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index c050c388d398..a83f85ea84c3 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -1,9 +1,8 @@ //===- llvm/IR/TypeFinder.h - Class to find used struct types ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 25c44e0871a9..034ca2c8ac23 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -1,9 +1,8 @@ //===- llvm/Use.h - Definition of the Use class -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -140,7 +139,7 @@ private: const Use *getImpliedUser() const LLVM_READONLY; Value *Val = nullptr; - Use *Next; + Use *Next = nullptr; PointerIntPair<Use **, 2, PrevPtrTag, PrevPointerTraits> Prev; void setPrev(Use **NewPrev) { Prev.setPointer(NewPrev); } diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index b6bb0f19a0aa..a1f313e269b2 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -1,9 +1,8 @@ //===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index aea31467f2fa..19d87c5c621d 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -1,9 +1,8 @@ //===- llvm/User.h - User class definition ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def index e2ddba0aa159..aaf1651979a9 100644 --- a/include/llvm/IR/Value.def +++ b/include/llvm/IR/Value.def @@ -1,9 +1,8 @@ //===-------- llvm/IR/Value.def - File that describes Values ---v-*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 4f3a45c684fc..b2d8e7ac4741 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -1,9 +1,8 @@ //===- llvm/Value.h - Definition of the Value class -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -494,7 +493,7 @@ public: /// swifterror attribute. bool isSwiftError() const; - /// Strip off pointer casts, all-zero GEPs, and aliases. + /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. @@ -504,6 +503,17 @@ public: static_cast<const Value *>(this)->stripPointerCasts()); } + /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases + /// but ensures the representation of the result stays the same. + /// + /// Returns the original uncasted value with the same representation. If this + /// is called on a non-pointer value, it returns 'this'. + const Value *stripPointerCastsSameRepresentation() const; + Value *stripPointerCastsSameRepresentation() { + return const_cast<Value *>(static_cast<const Value *>(this) + ->stripPointerCastsSameRepresentation()); + } + /// Strip off pointer casts, all-zero GEPs, aliases and invariant group /// info. /// @@ -536,19 +546,48 @@ public: static_cast<const Value *>(this)->stripInBoundsConstantOffsets()); } - /// Accumulate offsets from \a stripInBoundsConstantOffsets(). - /// - /// Stores the resulting constant offset stripped into the APInt provided. - /// The provided APInt will be extended or truncated as needed to be the - /// correct bitwidth for an offset of this pointer type. - /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Accumulate the constant offset this value has compared to a base pointer. + /// Only 'getelementptr' instructions (GEPs) with constant indices are + /// accumulated but other instructions, e.g., casts, are stripped away as + /// well. The accumulated constant offset is added to \p Offset and the base + /// pointer is returned. + /// + /// The APInt \p Offset has to have a bit-width equal to the IntPtr type for + /// the address space of 'this' pointer value, e.g., use + /// DataLayout::getIndexTypeSizeInBits(Ty). + /// + /// If \p AllowNonInbounds is true, constant offsets in GEPs are stripped and + /// accumulated even if the GEP is not "inbounds". + /// + /// If this is called on a non-pointer value, it returns 'this' and the + /// \p Offset is not modified. + /// + /// Note that this function will never return a nullptr. It will also never + /// manipulate the \p Offset in a way that would not match the difference + /// between the underlying value and the returned one. Thus, if no constant + /// offset was found, the returned value is the underlying one and \p Offset + /// is unchanged. + const Value *stripAndAccumulateConstantOffsets(const DataLayout &DL, + APInt &Offset, + bool AllowNonInbounds) const; + Value *stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, + bool AllowNonInbounds) { + return const_cast<Value *>( + static_cast<const Value *>(this)->stripAndAccumulateConstantOffsets( + DL, Offset, AllowNonInbounds)); + } + + /// This is a wrapper around stripAndAccumulateConstantOffsets with the + /// in-bounds requirement set to false. const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, - APInt &Offset) const; + APInt &Offset) const { + return stripAndAccumulateConstantOffsets(DL, Offset, + /* AllowNonInbounds */ false); + } Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, APInt &Offset) { - return const_cast<Value *>(static_cast<const Value *>(this) - ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset)); + return stripAndAccumulateConstantOffsets(DL, Offset, + /* AllowNonInbounds */ false); } /// Strip off pointer casts and inbounds GEPs. diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index d94472ce1be1..1135d796f7ed 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -1,9 +1,8 @@ //===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -309,15 +308,6 @@ struct DenseMapInfo<AssertingVH<T>> { } }; -template <typename T> -struct isPodLike<AssertingVH<T>> { -#ifdef NDEBUG - static const bool value = true; -#else - static const bool value = false; -#endif -}; - /// Value handle that tracks a Value across RAUW. /// /// TrackingVH is designed for situations where a client needs to hold a handle @@ -549,14 +539,6 @@ template <typename T> struct DenseMapInfo<PoisoningVH<T>> { } }; -template <typename T> struct isPodLike<PoisoningVH<T>> { -#ifdef NDEBUG - static const bool value = true; -#else - static const bool value = false; -#endif -}; - } // end namespace llvm #endif // LLVM_IR_VALUEHANDLE_H diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index e7e33918a613..6a79b1d387f3 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -1,9 +1,8 @@ //===- ValueMap.h - Safe map from Values to data ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h index 012e717c7470..105ea73857af 100644 --- a/include/llvm/IR/ValueSymbolTable.h +++ b/include/llvm/IR/ValueSymbolTable.h @@ -1,9 +1,8 @@ //===- llvm/ValueSymbolTable.h - Implement a Value Symtab -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 7255132e1e65..62c33c8325eb 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -1,9 +1,8 @@ //===- Verifier.h - LLVM IR Verifier ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index bedde8954fbb..05171300b602 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -1,9 +1,8 @@ //===---- llvm/IRReader/IRReader.h - Reader for LLVM IR files ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,11 +20,22 @@ namespace llvm { class StringRef; +class MemoryBuffer; class MemoryBufferRef; class Module; class SMDiagnostic; class LLVMContext; +/// If the given MemoryBuffer holds a bitcode image, return a Module +/// for it which does lazy deserialization of function bodies. Otherwise, +/// attempt to parse it as LLVM Assembly and return a fully populated +/// Module. The ShouldLazyLoadMetadata flag is passed down to the bitcode +/// reader to optionally enable lazy metadata loading. This takes ownership +/// of \p Buffer. +std::unique_ptr<Module> getLazyIRModule(std::unique_ptr<MemoryBuffer> Buffer, + SMDiagnostic &Err, LLVMContext &Context, + bool ShouldLazyLoadMetadata = false); + /// If the given file holds a bitcode image, return a Module /// for it which does lazy deserialization of function bodies. Otherwise, /// attempt to parse it as LLVM Assembly and return a fully populated diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 037c0dbb56ec..164d0be2855a 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -1,9 +1,8 @@ //===- llvm/InitializePasses.h - Initialize All Passes ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -65,8 +64,9 @@ void initializeAAEvalLegacyPassPass(PassRegistry&); void initializeAAResultsWrapperPassPass(PassRegistry&); void initializeADCELegacyPassPass(PassRegistry&); void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); -void initializeAddressSanitizerModulePass(PassRegistry&); -void initializeAddressSanitizerPass(PassRegistry&); +void initializeModuleAddressSanitizerLegacyPassPass(PassRegistry &); +void initializeASanGlobalsMetadataWrapperPassPass(PassRegistry &); +void initializeAddressSanitizerLegacyPassPass(PassRegistry &); void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlignmentFromAssumptionsPass(PassRegistry&); @@ -74,6 +74,7 @@ void initializeAlwaysInlinerLegacyPassPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); void initializeAssumptionCacheTrackerPass(PassRegistry&); void initializeAtomicExpandPass(PassRegistry&); +void initializeAttributorLegacyPassPass(PassRegistry&); void initializeBDCELegacyPassPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAAWrapperPassPass(PassRegistry&); @@ -134,16 +135,15 @@ void initializeEarlyIfConverterPass(PassRegistry&); void initializeEarlyMachineLICMPass(PassRegistry&); void initializeEarlyTailDuplicatePass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); -void initializeEfficiencySanitizerPass(PassRegistry&); void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&); void initializeEntryExitInstrumenterPass(PassRegistry&); -void initializeExpandISelPseudosPass(PassRegistry&); void initializeExpandMemCmpPassPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeExpandReductionsPass(PassRegistry&); void initializeMakeGuardsExplicitLegacyPassPass(PassRegistry&); void initializeExternalAAWrapperPassPass(PassRegistry&); void initializeFEntryInserterPass(PassRegistry&); +void initializeFinalizeISelPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeFloat2IntLegacyPassPass(PassRegistry&); @@ -163,8 +163,9 @@ void initializeGlobalOptLegacyPassPass(PassRegistry&); void initializeGlobalSplitPass(PassRegistry&); void initializeGlobalsAAWrapperPassPass(PassRegistry&); void initializeGuardWideningLegacyPassPass(PassRegistry&); +void initializeHardwareLoopsPass(PassRegistry&); void initializeHotColdSplittingLegacyPassPass(PassRegistry&); -void initializeHWAddressSanitizerPass(PassRegistry&); +void initializeHWAddressSanitizerLegacyPassPass(PassRegistry &); void initializeIPCPPass(PassRegistry&); void initializeIPSCCPLegacyPassPass(PassRegistry&); void initializeIRCELegacyPassPass(PassRegistry&); @@ -181,6 +182,7 @@ void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInstSimplifyLegacyPassPass(PassRegistry &); void initializeInstrProfilingLegacyPassPass(PassRegistry&); +void initializeInstrOrderFileLegacyPassPass(PassRegistry&); void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstructionSelectPass(PassRegistry&); void initializeInterleavedAccessPass(PassRegistry&); @@ -219,6 +221,7 @@ void initializeLoopDeletionLegacyPassPass(PassRegistry&); void initializeLoopDistributeLegacyPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); void initializeLoopGuardWideningLegacyPassPass(PassRegistry&); +void initializeLoopFuseLegacyPass(PassRegistry&); void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&); void initializeLoopInfoWrapperPassPass(PassRegistry&); void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&); @@ -241,6 +244,7 @@ void initializeLowerAtomicLegacyPassPass(PassRegistry&); void initializeLowerEmuTLSPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); +void initializeLowerWidenableConditionLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokeLegacyPassPass(PassRegistry&); void initializeLowerSwitchPass(PassRegistry&); @@ -277,7 +281,7 @@ void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&); void initializeMemorySSAWrapperPassPass(PassRegistry&); void initializeMemorySanitizerLegacyPassPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); -void initializeMergeICmpsPass(PassRegistry&); +void initializeMergeICmpsLegacyPassPass(PassRegistry &); void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&); void initializeMetaRenamerPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); @@ -298,6 +302,7 @@ void initializePEIPass(PassRegistry&); void initializePGOIndirectCallPromotionLegacyPassPass(PassRegistry&); void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&); void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&); +void initializePGOInstrumentationGenCreateVarLegacyPassPass(PassRegistry&); void initializePGOMemOPSizeOptLegacyPassPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); void initializePartialInlinerLegacyPassPass(PassRegistry&); diff --git a/include/llvm/LTO/Caching.h b/include/llvm/LTO/Caching.h index 7201ab31f5b0..4c4a708d24e9 100644 --- a/include/llvm/LTO/Caching.h +++ b/include/llvm/LTO/Caching.h @@ -1,9 +1,8 @@ //===- Caching.h - LLVM Link Time Optimizer Configuration -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,8 +24,8 @@ namespace lto { /// (e.g. in a cache). /// /// Buffer callbacks must be thread safe. -typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)> - AddBufferFn; +using AddBufferFn = + std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)>; /// Create a local file system cache which uses the given cache directory and /// file callback. This function also creates the cache directory if it does not diff --git a/include/llvm/LTO/Config.h b/include/llvm/LTO/Config.h index 7058602c3ee2..fb107e3fbe02 100644 --- a/include/llvm/LTO/Config.h +++ b/include/llvm/LTO/Config.h @@ -1,9 +1,8 @@ //===-Config.h - LLVM Link Time Optimizer Configuration -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -56,6 +55,9 @@ struct Config { /// Disable entirely the optimizer, including importing for ThinLTO bool CodeGenOnly = false; + /// Run PGO context sensitive IR instrumentation. + bool RunCSIRInstr = false; + /// If this field is set, the set of passes run in the middle-end optimizer /// will be the one specified by the string. Only works with the new pass /// manager as the old one doesn't have this ability. @@ -74,6 +76,9 @@ struct Config { /// with this triple. std::string DefaultTriple; + /// Context Sensitive PGO profile path. + std::string CSIRProfile; + /// Sample PGO profile path. std::string SampleProfile; @@ -83,17 +88,29 @@ struct Config { /// The directory to store .dwo files. std::string DwoDir; + /// The name for the split debug info file used for the DW_AT_[GNU_]dwo_name + /// attribute in the skeleton CU. This should generally only be used when + /// running an individual backend directly via thinBackend(), as otherwise + /// all objects would use the same .dwo file. Not used as output path. + std::string SplitDwarfFile; + /// The path to write a .dwo file to. This should generally only be used when /// running an individual backend directly via thinBackend(), as otherwise - /// all .dwo files will be written to the same path. - std::string DwoPath; + /// all .dwo files will be written to the same path. Not used in skeleton CU. + std::string SplitDwarfOutput; /// Optimization remarks file path. std::string RemarksFilename = ""; + /// Optimization remarks pass filter. + std::string RemarksPasses = ""; + /// Whether to emit optimization remarks with hotness informations. bool RemarksWithHotness = false; + /// The format used for serializing remarks (default: YAML). + std::string RemarksFormat = ""; + /// Whether to emit the pass manager debuggging informations. bool DebugPassManager = false; @@ -133,7 +150,7 @@ struct Config { /// /// Note that in out-of-process backend scenarios, none of the hooks will be /// called for ThinLTO tasks. - typedef std::function<bool(unsigned Task, const Module &)> ModuleHookFn; + using ModuleHookFn = std::function<bool(unsigned Task, const Module &)>; /// This module hook is called after linking (regular LTO) or loading /// (ThinLTO) the module, before modifying it. @@ -166,8 +183,8 @@ struct Config { /// /// It is called regardless of whether the backend is in-process, although it /// is not called from individual backend processes. - typedef std::function<bool(const ModuleSummaryIndex &Index)> - CombinedIndexHookFn; + using CombinedIndexHookFn = + std::function<bool(const ModuleSummaryIndex &Index)>; CombinedIndexHookFn CombinedIndexHook; /// This is a convenience function that configures this Config object to write diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h index 534d9b6f3f2a..ca0a8b64523a 100644 --- a/include/llvm/LTO/LTO.h +++ b/include/llvm/LTO/LTO.h @@ -1,9 +1,8 @@ //===-LTO.h - LLVM Link Time Optimizer ------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,6 +20,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/IR/RemarkStreamer.h" #include "llvm/LTO/Config.h" #include "llvm/Linker/IRMover.h" #include "llvm/Object/IRSymtab.h" @@ -51,7 +51,8 @@ void thinLTOResolvePrevailingInIndex( function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing, function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)> - recordNewLinkage); + recordNewLinkage, + const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); /// Update the linkages in the given \p Index to mark exported values /// as external and non-exported values as internal. The ThinLTO backends @@ -84,8 +85,13 @@ std::string getThinLTOOutputFile(const std::string &Path, /// Setup optimization remarks. Expected<std::unique_ptr<ToolOutputFile>> -setupOptimizationRemarks(LLVMContext &Context, StringRef LTORemarksFilename, - bool LTOPassRemarksWithHotness, int Count = -1); +setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, + StringRef RemarksPasses, StringRef RemarksFormat, + bool RemarksWithHotness, int Count = -1); + +/// Setups the output file for saving statistics. +Expected<std::unique_ptr<ToolOutputFile>> +setupStatsFile(StringRef StatsFilename); class LTO; struct SymbolResolution; @@ -110,6 +116,7 @@ private: std::vector<std::pair<size_t, size_t>> ModuleSymIndices; StringRef TargetTriple, SourceFileName, COFFLinkerOpts; + std::vector<StringRef> DependentLibraries; std::vector<StringRef> ComdatTable; public: @@ -131,6 +138,7 @@ public: using irsymtab::Symbol::isWeak; using irsymtab::Symbol::isIndirect; using irsymtab::Symbol::getName; + using irsymtab::Symbol::getIRName; using irsymtab::Symbol::getVisibility; using irsymtab::Symbol::canBeOmittedFromSymbolTable; using irsymtab::Symbol::isTLS; @@ -140,6 +148,7 @@ public: using irsymtab::Symbol::getCOFFWeakExternalFallback; using irsymtab::Symbol::getSectionName; using irsymtab::Symbol::isExecutable; + using irsymtab::Symbol::isUsed; }; /// A range over the symbols in this InputFile. @@ -148,6 +157,9 @@ public: /// Returns linker options specified in the input file. StringRef getCOFFLinkerOpts() const { return COFFLinkerOpts; } + /// Returns dependent library specifiers from the input file. + ArrayRef<StringRef> getDependentLibraries() const { return DependentLibraries; } + /// Returns the path to the InputFile. StringRef getName() const; @@ -160,6 +172,9 @@ public: // Returns a table with all the comdats used by this file. ArrayRef<StringRef> getComdatTable() const { return ComdatTable; } + // Returns the only BitcodeModule from InputFile. + BitcodeModule &getSingleBitcodeModule(); + private: ArrayRef<Symbol> module_symbols(unsigned I) const { const auto &Indices = ModuleSymIndices[I]; @@ -183,8 +198,8 @@ public: /// the fly. /// /// Stream callbacks must be thread safe. -typedef std::function<std::unique_ptr<NativeObjectStream>(unsigned Task)> - AddStreamFn; +using AddStreamFn = + std::function<std::unique_ptr<NativeObjectStream>(unsigned Task)>; /// This is the type of a native object cache. To request an item from the /// cache, pass a unique string as the Key. For hits, the cached file will be @@ -198,17 +213,16 @@ typedef std::function<std::unique_ptr<NativeObjectStream>(unsigned Task)> /// /// if (AddStreamFn AddStream = Cache(Task, Key)) /// ProduceContent(AddStream); -typedef std::function<AddStreamFn(unsigned Task, StringRef Key)> - NativeObjectCache; +using NativeObjectCache = + std::function<AddStreamFn(unsigned Task, StringRef Key)>; /// A ThinBackend defines what happens after the thin-link phase during ThinLTO. /// The details of this type definition aren't important; clients can only /// create a ThinBackend using one of the create*ThinBackend() functions below. -typedef std::function<std::unique_ptr<ThinBackendProc>( +using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>( Config &C, ModuleSummaryIndex &CombinedIndex, StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, - AddStreamFn AddStream, NativeObjectCache Cache)> - ThinBackend; + AddStreamFn AddStream, NativeObjectCache Cache)>; /// This ThinBackend runs the individual backend jobs in-process. ThinBackend createInProcessThinBackend(unsigned ParallelismLevel); @@ -397,7 +411,10 @@ private: const SymbolResolution *&ResI, const SymbolResolution *ResE); Error runRegularLTO(AddStreamFn AddStream); - Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache); + Error runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, + const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); + + Error checkPartiallySplit(); mutable bool CalledGetMaxTasks = false; diff --git a/include/llvm/LTO/LTOBackend.h b/include/llvm/LTO/LTOBackend.h index d4743f6940ff..4ff8a1993d49 100644 --- a/include/llvm/LTO/LTOBackend.h +++ b/include/llvm/LTO/LTOBackend.h @@ -1,9 +1,8 @@ //===-LTOBackend.h - LLVM Link Time Optimizer Backend ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/LTO/SummaryBasedOptimizations.h b/include/llvm/LTO/SummaryBasedOptimizations.h index ad3a8e7dc77b..6697c821a5ea 100644 --- a/include/llvm/LTO/SummaryBasedOptimizations.h +++ b/include/llvm/LTO/SummaryBasedOptimizations.h @@ -1,9 +1,8 @@ //=- llvm/LTO/SummaryBasedOptimizations.h -Link time optimizations-*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/LTO/legacy/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h index 8f23b7cb4574..d3cb4c8b79a0 100644 --- a/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -1,9 +1,8 @@ //===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -242,6 +241,7 @@ private: TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile; std::unique_ptr<ToolOutputFile> DiagnosticOutputFile; bool Freestanding = false; + std::unique_ptr<ToolOutputFile> StatsFile = nullptr; }; } #endif diff --git a/include/llvm/LTO/legacy/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h index 017e223ed8a6..84b9b8c02942 100644 --- a/include/llvm/LTO/legacy/LTOModule.h +++ b/include/llvm/LTO/legacy/LTOModule.h @@ -1,9 +1,8 @@ //===-LTOModule.h - LLVM Link Time Optimizer ------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/IR/Module.h" +#include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Target/TargetMachine.h" @@ -48,6 +48,8 @@ private: std::string LinkerOpts; + std::string DependentLibraries; + std::unique_ptr<Module> Mod; MemoryBufferRef MBRef; ModuleSymbolTable SymTab; @@ -156,9 +158,17 @@ public: const std::vector<StringRef> &getAsmUndefinedRefs() { return _asm_undefines; } + static lto::InputFile *createInputFile(const void *buffer, size_t buffer_size, + const char *path, std::string &out_error); + + static size_t getDependentLibraryCount(lto::InputFile *input); + + static const char *getDependentLibrary(lto::InputFile *input, size_t index, size_t *size); + private: /// Parse metadata from the module // FIXME: it only parses "llvm.linker.options" metadata at the moment + // FIXME: can't access metadata in lazily loaded modules void parseMetadata(); /// Parse the symbols from the module and model-level ASM and add them to diff --git a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h index d4c69a1ce260..210a2ce00bdf 100644 --- a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -1,9 +1,8 @@ //===-ThinLTOCodeGenerator.h - LLVM Link Time Optimizer -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,6 +19,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/LTO/LTO.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/MemoryBuffer.h" @@ -32,23 +32,6 @@ class StringRef; class LLVMContext; class TargetMachine; -/// Wrapper around MemoryBufferRef, owning the identifier -class ThinLTOBuffer { - std::string OwnedIdentifier; - StringRef Buffer; - -public: - ThinLTOBuffer(StringRef Buffer, StringRef Identifier) - : OwnedIdentifier(Identifier), Buffer(Buffer) {} - - MemoryBufferRef getMemBuffer() const { - return MemoryBufferRef(Buffer, - {OwnedIdentifier.c_str(), OwnedIdentifier.size()}); - } - StringRef getBuffer() const { return Buffer; } - StringRef getBufferIdentifier() const { return OwnedIdentifier; } -}; - /// Helper to gather options relevant to the target machine creation struct TargetMachineBuilder { Triple TheTriple; @@ -268,37 +251,49 @@ public: * and additionally resolve weak and linkonce symbols. * Index is updated to reflect linkage changes from weak resolution. */ - void promote(Module &Module, ModuleSummaryIndex &Index); + void promote(Module &Module, ModuleSummaryIndex &Index, + const lto::InputFile &File); /** * Compute and emit the imported files for module at \p ModulePath. */ void emitImports(Module &Module, StringRef OutputName, - ModuleSummaryIndex &Index); + ModuleSummaryIndex &Index, + const lto::InputFile &File); /** * Perform cross-module importing for the module identified by * ModuleIdentifier. */ - void crossModuleImport(Module &Module, ModuleSummaryIndex &Index); + void crossModuleImport(Module &Module, ModuleSummaryIndex &Index, + const lto::InputFile &File); /** * Compute the list of summaries needed for importing into module. */ void gatherImportedSummariesForModule( Module &Module, ModuleSummaryIndex &Index, - std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); + std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex, + const lto::InputFile &File); /** * Perform internalization. Index is updated to reflect linkage changes. */ - void internalize(Module &Module, ModuleSummaryIndex &Index); + void internalize(Module &Module, ModuleSummaryIndex &Index, + const lto::InputFile &File); /** * Perform post-importing ThinLTO optimizations. */ void optimize(Module &Module); + /** + * Write temporary object file to SavedObjectDirectoryPath, write symlink + * to Cache directory if needed. Returns the path to the generated file in + * SavedObjectsDirectoryPath. + */ + std::string writeGeneratedObject(int count, StringRef CacheEntryPath, + const MemoryBuffer &OutputBuffer); /**@}*/ private: @@ -314,7 +309,7 @@ private: /// Vector holding the input buffers containing the bitcode modules to /// process. - std::vector<ThinLTOBuffer> Modules; + std::vector<std::unique_ptr<lto::InputFile>> Modules; /// Set of symbols that need to be preserved outside of the set of bitcode /// files. diff --git a/include/llvm/LTO/legacy/UpdateCompilerUsed.h b/include/llvm/LTO/legacy/UpdateCompilerUsed.h index 4be0027e97d7..af9d62b4af30 100644 --- a/include/llvm/LTO/legacy/UpdateCompilerUsed.h +++ b/include/llvm/LTO/legacy/UpdateCompilerUsed.h @@ -1,9 +1,8 @@ //==------ UpdateCompilerUsed.h - LLVM Link Time Optimizer Utility --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h index 68995d0633ad..0beaf1bb23a9 100644 --- a/include/llvm/LineEditor/LineEditor.h +++ b/include/llvm/LineEditor/LineEditor.h @@ -1,9 +1,8 @@ //===-- llvm/LineEditor/LineEditor.h - line editor --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/LinkAllIR.h b/include/llvm/LinkAllIR.h index 4f4af7187be4..4b0aabeee701 100644 --- a/include/llvm/LinkAllIR.h +++ b/include/llvm/LinkAllIR.h @@ -1,9 +1,8 @@ //===----- LinkAllIR.h - Reference All VMCore Code --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 0851c2f8d265..675d179eb22a 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -1,9 +1,8 @@ //===- llvm/LinkAllPasses.h ------------ Reference All Passes ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -42,6 +41,7 @@ #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" +#include "llvm/Transforms/IPO/Attributor.h" #include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Instrumentation.h" @@ -103,6 +103,7 @@ namespace { (void) llvm::createGCOVProfilerPass(); (void) llvm::createPGOInstrumentationGenLegacyPass(); (void) llvm::createPGOInstrumentationUseLegacyPass(); + (void) llvm::createPGOInstrumentationGenCreateVarLegacyPass(); (void) llvm::createPGOIndirectCallPromotionLegacyPass(); (void) llvm::createPGOMemOPSizeOptLegacyPass(); (void) llvm::createInstrProfilingLegacyPass(); @@ -188,10 +189,11 @@ namespace { (void) llvm::createPostDomTree(); (void) llvm::createInstructionNamerPass(); (void) llvm::createMetaRenamerPass(); + (void) llvm::createAttributorLegacyPass(); (void) llvm::createPostOrderFunctionAttrsLegacyPass(); (void) llvm::createReversePostOrderFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); - (void) llvm::createMergeICmpsPass(); + (void) llvm::createMergeICmpsLegacyPass(); (void) llvm::createExpandMemCmpPass(); std::string buf; llvm::raw_string_ostream os(buf); @@ -221,6 +223,7 @@ namespace { (void) llvm::createEliminateAvailableExternallyPass(); (void) llvm::createScalarizeMaskedMemIntrinPass(); (void) llvm::createWarnMissedTransformationsPass(); + (void) llvm::createHardwareLoopsPass(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolutionWrapperPass(); diff --git a/include/llvm/Linker/IRMover.h b/include/llvm/Linker/IRMover.h index 235ada47cef4..e5df83f01fe3 100644 --- a/include/llvm/Linker/IRMover.h +++ b/include/llvm/Linker/IRMover.h @@ -1,9 +1,8 @@ //===- IRMover.h ------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 7776c720ec53..c9b1d42b3903 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -1,9 +1,8 @@ //===- Linker.h - Module Linker Interface -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index ef33250204ec..2fe5ce252c94 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -1,9 +1,8 @@ -//===- ConstantPool.h - Keep track of assembler-generated ------*- C++ -*-===// +//===- ConstantPools.h - Keep track of assembler-generated ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/LaneBitmask.h b/include/llvm/MC/LaneBitmask.h index 8c0b4ecb8fd4..d5f69287a265 100644 --- a/include/llvm/MC/LaneBitmask.h +++ b/include/llvm/MC/LaneBitmask.h @@ -1,9 +1,8 @@ //===- llvm/MC/LaneBitmask.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 07835c21fced..1f3ad6c1e547 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmBackend.h - MC Asm Backend ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -88,6 +87,22 @@ public: return false; } + /// Hook to check if extra nop bytes must be inserted for alignment directive. + /// For some targets this may be necessary in order to support linker + /// relaxation. The number of bytes to insert are returned in Size. + virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF, + unsigned &Size) { + return false; + } + + /// Hook which indicates if the target requires a fixup to be generated when + /// handling an align directive in an executable section + virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm, + const MCAsmLayout &Layout, + MCAlignFragment &AF) { + return false; + } + /// Apply the \p Value for given \p Fixup into the provided data fragment, at /// the offset specified by the fixup and following the fixup kind as /// appropriate. Errors (such as an out of range fixup value) should be diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 120fb8fa7492..971e9354da8c 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCAsmInfo.h - Asm info --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,16 +17,17 @@ #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCTargetOptions.h" #include <vector> namespace llvm { class MCContext; +class MCCFIInstruction; class MCExpr; class MCSection; class MCStreamer; +class MCSubtargetInfo; class MCSymbol; namespace WinEH { @@ -474,7 +474,13 @@ public: bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } bool hasCOFFAssociativeComdats() const { return HasCOFFAssociativeComdats; } bool hasCOFFComdatConstants() const { return HasCOFFComdatConstants; } - unsigned getMaxInstLength() const { return MaxInstLength; } + + /// Returns the maximum possible encoded instruction size in bytes. If \p STI + /// is null, this should be the maximum size for any subtarget. + virtual unsigned getMaxInstLength(const MCSubtargetInfo *STI = nullptr) const { + return MaxInstLength; + } + unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } const char *getSeparatorString() const { return SeparatorString; } @@ -492,7 +498,7 @@ public: StringRef getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { - return LinkerPrivateGlobalPrefix[0] != '\0'; + return !LinkerPrivateGlobalPrefix.empty(); } StringRef getLinkerPrivateGlobalPrefix() const { @@ -598,9 +604,7 @@ public: return SupportsExtendedDwarfLocDirective; } - void addInitialFrameState(const MCCFIInstruction &Inst) { - InitialFrameState.push_back(Inst); - } + void addInitialFrameState(const MCCFIInstruction &Inst); const std::vector<MCCFIInstruction> &getInitialFrameState() const { return InitialFrameState; diff --git a/include/llvm/MC/MCAsmInfoCOFF.h b/include/llvm/MC/MCAsmInfoCOFF.h index 01c8ae49a6fc..1dfb4750af66 100644 --- a/include/llvm/MC/MCAsmInfoCOFF.h +++ b/include/llvm/MC/MCAsmInfoCOFF.h @@ -1,9 +1,8 @@ //===- MCAsmInfoCOFF.h - COFF asm properties --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index a533d604a89e..c889ce99cebe 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -1,9 +1,8 @@ //===- MCAsmInfoDarwin.h - Darwin asm properties ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index f113afc9885e..aa2e5873e2c6 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmInfoELF.h - ELF Asm info --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAsmInfoWasm.h b/include/llvm/MC/MCAsmInfoWasm.h index 71c6ee28df70..3afc610b8b07 100644 --- a/include/llvm/MC/MCAsmInfoWasm.h +++ b/include/llvm/MC/MCAsmInfoWasm.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCAsmInfoWasm.h - Wasm Asm info -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAsmInfoXCOFF.h b/include/llvm/MC/MCAsmInfoXCOFF.h new file mode 100644 index 000000000000..2a72ba7398a7 --- /dev/null +++ b/include/llvm/MC/MCAsmInfoXCOFF.h @@ -0,0 +1,25 @@ +//===- MCAsmInfoXCOFF.h - XCOFF asm properties ----------------- *- 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_MC_MCASMINFOXCOFF_H +#define LLVM_MC_MCASMINFOXCOFF_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + +class MCAsmInfoXCOFF : public MCAsmInfo { + virtual void anchor(); + +protected: + MCAsmInfoXCOFF(); +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCASMINFOXCOFF_H diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index b711db319302..45ac96f0b81e 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -1,9 +1,8 @@ //===- MCAsmLayout.h - Assembly Layout Object -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAsmMacro.h b/include/llvm/MC/MCAsmMacro.h index 135fa4f2e33d..364d3b5f3666 100644 --- a/include/llvm/MC/MCAsmMacro.h +++ b/include/llvm/MC/MCAsmMacro.h @@ -1,9 +1,8 @@ //===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 986c6e17548f..4543018901a4 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -1,9 +1,8 @@ //===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index f1b0b784a2df..04b4367ada7b 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCCodeEmitter.h - Instruction Encoding -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCCodePadder.h b/include/llvm/MC/MCCodePadder.h index 4dde6bf59272..f7b1a2113a9a 100644 --- a/include/llvm/MC/MCCodePadder.h +++ b/include/llvm/MC/MCCodePadder.h @@ -1,9 +1,8 @@ -//===- llvm/MC/CodePadder.h - MC Code Padder --------------------*- C++ -*-===// +//===- llvm/MC/MCCodePadder.h - MC Code Padder ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCCodeView.h b/include/llvm/MC/MCCodeView.h index cef03a409f95..2126354cded6 100644 --- a/include/llvm/MC/MCCodeView.h +++ b/include/llvm/MC/MCCodeView.h @@ -1,9 +1,8 @@ //===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 3b8ac8b79e21..5c2124cc0d15 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -1,9 +1,8 @@ //===- MCContext.h - Machine Code Context -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -19,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/BinaryFormat/XCOFF.h" #include "llvm/MC/MCAsmMacro.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -50,6 +50,7 @@ namespace llvm { class MCSectionELF; class MCSectionMachO; class MCSectionWasm; + class MCSectionXCOFF; class MCStreamer; class MCSymbol; class MCSymbolELF; @@ -92,6 +93,7 @@ namespace llvm { SpecificBumpPtrAllocator<MCSectionELF> ELFAllocator; SpecificBumpPtrAllocator<MCSectionMachO> MachOAllocator; SpecificBumpPtrAllocator<MCSectionWasm> WasmAllocator; + SpecificBumpPtrAllocator<MCSectionXCOFF> XCOFFAllocator; /// Bindings of names to symbols. SymbolTable Symbols; @@ -247,10 +249,25 @@ namespace llvm { } }; + struct XCOFFSectionKey { + std::string SectionName; + XCOFF::StorageMappingClass MappingClass; + + XCOFFSectionKey(StringRef SectionName, + XCOFF::StorageMappingClass MappingClass) + : SectionName(SectionName), MappingClass(MappingClass) {} + + bool operator<(const XCOFFSectionKey &Other) const { + return std::tie(SectionName, MappingClass) < + std::tie(Other.SectionName, Other.MappingClass); + } + }; + StringMap<MCSectionMachO *> MachOUniquingMap; std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap; std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap; std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap; + std::map<XCOFFSectionKey, MCSectionXCOFF *> XCOFFUniquingMap; StringMap<bool> RelSecNames; SpecificBumpPtrAllocator<MCSubtargetInfo> MCSubtargetAllocator; @@ -441,8 +458,6 @@ namespace llvm { SectionKind Kind, const char *BeginSymName = nullptr); - MCSectionCOFF *getCOFFSection(StringRef Section); - /// Gets or creates a section equivalent to Sec that is associated with the /// section containing KeySym. For example, to create a debug info section /// associated with an inline function, pass the normal debug info section @@ -473,6 +488,11 @@ namespace llvm { const MCSymbolWasm *Group, unsigned UniqueID, const char *BeginSymName); + MCSectionXCOFF *getXCOFFSection(StringRef Section, + XCOFF::StorageMappingClass MappingClass, + SectionKind K, + const char *BeginSymName = nullptr); + // Create and save a copy of STI and return a reference to the copy. MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); @@ -489,12 +509,6 @@ namespace llvm { /// Set the compilation directory for DW_AT_comp_dir void setCompilationDir(StringRef S) { CompilationDir = S.str(); } - /// Get the debug prefix map. - const std::map<const std::string, const std::string> & - getDebugPrefixMap() const { - return DebugPrefixMap; - } - /// Add an entry to the debug prefix map. void addDebugPrefixMapEntry(const std::string &From, const std::string &To); @@ -512,7 +526,7 @@ namespace llvm { /// Creates an entry in the dwarf file and directory tables. Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber, - MD5::MD5Result *Checksum, + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); @@ -539,13 +553,6 @@ namespace llvm { return getMCDwarfLineTable(CUID).getMCDwarfDirs(); } - bool hasMCLineSections() const { - for (const auto &Table : MCDwarfLineTablesCUMap) - if (!Table.second.getMCDwarfFiles().empty() || Table.second.getLabel()) - return true; - return false; - } - unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; } void setDwarfCompileUnitID(unsigned CUIndex) { @@ -555,7 +562,8 @@ namespace llvm { /// Specifies the "root" file and directory of the compilation unit. /// These are "file 0" and "directory 0" in DWARF v5. void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir, - StringRef Filename, MD5::MD5Result *Checksum, + StringRef Filename, + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source) { getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum, Source); @@ -595,6 +603,10 @@ namespace llvm { GenDwarfFileNumber = FileNumber; } + /// Specifies information about the "root file" for assembler clients + /// (e.g., llvm-mc). Assumes compilation dir etc. have been set up. + void setGenDwarfRootFile(StringRef FileName, StringRef Buffer); + const SetVector<MCSection *> &getGenDwarfSectionSyms() { return SectionsForRanges; } diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 8c74b169135b..4029264c2026 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -1,9 +1,8 @@ //===- MCDirectives.h - Enums for directives on various targets -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,6 +19,7 @@ enum MCSymbolAttr { MCSA_Invalid = 0, ///< Not a valid directive. // Various directives in alphabetical order. + MCSA_Cold, ///< .cold (MachO) MCSA_ELF_TypeFunction, ///< .type _foo, STT_FUNC # aka @function MCSA_ELF_TypeIndFunction, ///< .type _foo, STT_GNU_IFUNC MCSA_ELF_TypeObject, ///< .type _foo, STT_OBJECT # aka @object diff --git a/include/llvm/MC/MCDisassembler/MCDisassembler.h b/include/llvm/MC/MCDisassembler/MCDisassembler.h index 7f09c05ccf2a..268f3ccad889 100644 --- a/include/llvm/MC/MCDisassembler/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler/MCDisassembler.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCDisassembler.h - Disassembler interface --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -17,6 +16,7 @@ namespace llvm { template <typename T> class ArrayRef; +class StringRef; class MCContext; class MCInst; class MCSubtargetInfo; @@ -80,6 +80,23 @@ public: raw_ostream &VStream, raw_ostream &CStream) const = 0; + /// May parse any prelude that precedes instructions after the start of a + /// symbol. Needed for some targets, e.g. WebAssembly. + /// + /// \param Name - The name of the symbol. + /// \param Size - The number of bytes consumed. + /// \param Address - The address, in the memory space of region, of the first + /// byte of the symbol. + /// \param Bytes - A reference to the actual bytes at the symbol location. + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the bytes are valid, + /// MCDisassembler::Fail if the bytes were invalid. + virtual DecodeStatus onSymbolStart(StringRef Name, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const; + private: MCContext &Ctx; diff --git a/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h b/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h index df909a0dccd3..ffac5ee5cb1f 100644 --- a/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h +++ b/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCExternalSymbolizer.h - ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCDisassembler/MCRelocationInfo.h b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h index 6030ae660d38..efc59da19335 100644 --- a/include/llvm/MC/MCDisassembler/MCRelocationInfo.h +++ b/include/llvm/MC/MCDisassembler/MCRelocationInfo.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCRelocationInfo.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCDisassembler/MCSymbolizer.h b/include/llvm/MC/MCDisassembler/MCSymbolizer.h index 0bfa569474ec..b7ca83a5f16c 100644 --- a/include/llvm/MC/MCDisassembler/MCSymbolizer.h +++ b/include/llvm/MC/MCDisassembler/MCSymbolizer.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCSymbolizer.h - MCSymbolizer class --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 7b96e9aaca89..1a37aafd0654 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -1,9 +1,8 @@ //===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -42,11 +41,14 @@ class raw_ostream; class SMLoc; class SourceMgr; -/// Instances of this class represent the name of the dwarf -/// .file directive and its associated dwarf file number in the MC file, -/// and MCDwarfFile's are created and uniqued by the MCContext class where -/// the file number for each is its index into the vector of DwarfFiles (note -/// index 0 is not used and not a valid dwarf file number). +/// Instances of this class represent the name of the dwarf .file directive and +/// its associated dwarf file number in the MC file. MCDwarfFile's are created +/// and uniqued by the MCContext class. In Dwarf 4 file numbers start from 1; +/// i.e. the entry with file number 1 is the first element in the vector of +/// DwarfFiles and there is no MCDwarfFile with file number 0. In Dwarf 5 file +/// numbers start from 0, with the MCDwarfFile with file number 0 being the +/// primary source file, and file numbers correspond to their index in the +/// vector. struct MCDwarfFile { // The base name of the file without its directory path. std::string Name; @@ -56,7 +58,7 @@ struct MCDwarfFile { /// The MD5 checksum, if there is one. Non-owning pointer to data allocated /// in MCContext. - MD5::MD5Result *Checksum = nullptr; + Optional<MD5::MD5Result> Checksum; /// The source code of the file. Non-owning reference to data allocated in /// MCContext. @@ -224,8 +226,9 @@ public: MCDwarfLineTableHeader() = default; Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, - MD5::MD5Result *Checksum, - Optional<StringRef> &Source, + Optional<MD5::MD5Result> Checksum, + Optional<StringRef> Source, + uint16_t DwarfVersion, unsigned FileNumber = 0); std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, @@ -246,32 +249,50 @@ public: return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); } + void setRootFile(StringRef Directory, StringRef FileName, + Optional<MD5::MD5Result> Checksum, + Optional<StringRef> Source) { + CompilationDir = Directory; + RootFile.Name = FileName; + RootFile.DirIndex = 0; + RootFile.Checksum = Checksum; + RootFile.Source = Source; + trackMD5Usage(Checksum.hasValue()); + HasSource = Source.hasValue(); + } + + void resetFileTable() { + MCDwarfDirs.clear(); + MCDwarfFiles.clear(); + RootFile.Name.clear(); + resetMD5Usage(); + HasSource = false; + } + private: void emitV2FileDirTables(MCStreamer *MCOS) const; - void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr, - StringRef CtxCompilationDir) const; + void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr) const; }; class MCDwarfDwoLineTable { MCDwarfLineTableHeader Header; + bool HasSplitLineTable = false; public: void maybeSetRootFile(StringRef Directory, StringRef FileName, - MD5::MD5Result *Checksum, Optional<StringRef> Source) { + Optional<MD5::MD5Result> Checksum, + Optional<StringRef> Source) { if (!Header.RootFile.Name.empty()) return; - Header.CompilationDir = Directory; - Header.RootFile.Name = FileName; - Header.RootFile.DirIndex = 0; - Header.RootFile.Checksum = Checksum; - Header.RootFile.Source = Source; - Header.trackMD5Usage(Checksum); - Header.HasSource = Source.hasValue(); + Header.setRootFile(Directory, FileName, Checksum, Source); } unsigned getFile(StringRef Directory, StringRef FileName, - MD5::MD5Result *Checksum, Optional<StringRef> Source) { - return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source)); + Optional<MD5::MD5Result> Checksum, uint16_t DwarfVersion, + Optional<StringRef> Source) { + HasSplitLineTable = true; + return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source, + DwarfVersion)); } void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, @@ -291,36 +312,34 @@ public: Optional<MCDwarfLineStr> &LineStr) const; Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, - MD5::MD5Result *Checksum, + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, + uint16_t DwarfVersion, unsigned FileNumber = 0); unsigned getFile(StringRef &Directory, StringRef &FileName, - MD5::MD5Result *Checksum, Optional<StringRef> &Source, - unsigned FileNumber = 0) { + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, + uint16_t DwarfVersion, unsigned FileNumber = 0) { return cantFail(tryGetFile(Directory, FileName, Checksum, Source, - FileNumber)); + DwarfVersion, FileNumber)); } void setRootFile(StringRef Directory, StringRef FileName, - MD5::MD5Result *Checksum, Optional<StringRef> Source) { + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source) { Header.CompilationDir = Directory; Header.RootFile.Name = FileName; Header.RootFile.DirIndex = 0; Header.RootFile.Checksum = Checksum; Header.RootFile.Source = Source; - Header.trackMD5Usage(Checksum); + Header.trackMD5Usage(Checksum.hasValue()); Header.HasSource = Source.hasValue(); } - void resetRootFile() { - assert(Header.MCDwarfFiles.empty()); - Header.RootFile.Name.clear(); - Header.resetMD5Usage(); - Header.HasSource = false; - } + void resetFileTable() { Header.resetFileTable(); } bool hasRootFile() const { return !Header.RootFile.Name.empty(); } + const MCDwarfFile &getRootFile() const { return Header.RootFile; } + // Report whether MD5 usage has been consistent (all-or-none). bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index f226d6a45a5a..2d441fdeee28 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -54,13 +53,14 @@ struct ELFRelocationEntry { class MCELFObjectTargetWriter : public MCObjectTargetWriter { const uint8_t OSABI; + const uint8_t ABIVersion; const uint16_t EMachine; const unsigned HasRelocationAddend : 1; const unsigned Is64Bit : 1; protected: MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, uint16_t EMachine_, - bool HasRelocationAddend); + bool HasRelocationAddend_, uint8_t ABIVersion_ = 0); public: virtual ~MCELFObjectTargetWriter() = default; @@ -98,6 +98,7 @@ public: /// \name Accessors /// @{ uint8_t getOSABI() const { return OSABI; } + uint8_t getABIVersion() const { return ABIVersion; } uint16_t getEMachine() const { return EMachine; } bool hasRelocationAddend() const { return HasRelocationAddend; } bool is64Bit() const { return Is64Bit; } diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 3797079661e4..8838d53d75b5 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -1,9 +1,8 @@ //===- MCELFStreamer.h - MCStreamer ELF Object File Interface ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 8cb6b86fd672..fb23c0114c76 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -1,9 +1,8 @@ //===- MCExpr.h - Assembly Level Expressions --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -135,15 +134,21 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { //// Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; + bool PrintInHex = false; - explicit MCConstantExpr(int64_t Value) + MCConstantExpr(int64_t Value) : MCExpr(MCExpr::Constant, SMLoc()), Value(Value) {} + MCConstantExpr(int64_t Value, bool PrintInHex) + : MCExpr(MCExpr::Constant, SMLoc()), Value(Value), + PrintInHex(PrintInHex) {} + public: /// \name Construction /// @{ - static const MCConstantExpr *create(int64_t Value, MCContext &Ctx); + static const MCConstantExpr *create(int64_t Value, MCContext &Ctx, + bool PrintInHex = false); /// @} /// \name Accessors @@ -151,6 +156,8 @@ public: int64_t getValue() const { return Value; } + bool useHexFormat() const { return PrintInHex; } + /// @} static bool classof(const MCExpr *E) { @@ -285,16 +292,17 @@ public: VK_Hexagon_IE, VK_Hexagon_IE_GOT, - VK_WebAssembly_FUNCTION, // Function table index, rather than virtual addr - VK_WebAssembly_GLOBAL, // Global object index - VK_WebAssembly_TYPEINDEX,// Type table index - VK_WebAssembly_EVENT, // Event index + VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature) + VK_WASM_MBREL, // Memory address relative to memory base + VK_WASM_TBREL, // Table index relative to table bare VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi VK_AMDGPU_REL32_LO, // symbol@rel32@lo VK_AMDGPU_REL32_HI, // symbol@rel32@hi VK_AMDGPU_REL64, // symbol@rel64 + VK_AMDGPU_ABS32_LO, // symbol@abs32@lo + VK_AMDGPU_ABS32_HI, // symbol@abs32@hi VK_TPREL, VK_DTPREL diff --git a/include/llvm/MC/MCFixedLenDisassembler.h b/include/llvm/MC/MCFixedLenDisassembler.h index ad34d9494bb9..218ae0d13189 100644 --- a/include/llvm/MC/MCFixedLenDisassembler.h +++ b/include/llvm/MC/MCFixedLenDisassembler.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // Fixed length disassembler decoder state machine driver. diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index 5f301eafc556..accffb7f2247 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -21,7 +20,8 @@ class MCExpr; /// Extensible enumeration to represent the type of a fixup. enum MCFixupKind { - FK_Data_1 = 0, ///< A one-byte fixup. + FK_NONE = 0, ///< A no-op fixup. + FK_Data_1, ///< A one-byte fixup. FK_Data_2, ///< A two-byte fixup. FK_Data_4, ///< A four-byte fixup. FK_Data_8, ///< A eight-byte fixup. diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h index 483abb39403f..0ea34866db6a 100644 --- a/include/llvm/MC/MCFixupKindInfo.h +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCFixupKindInfo.h - Fixup Descriptors -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h index c999c9fc4f17..aadf2ce725ea 100644 --- a/include/llvm/MC/MCFragment.h +++ b/include/llvm/MC/MCFragment.h @@ -1,9 +1,8 @@ //===- MCFragment.h - Fragment type hierarchy -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index d501b686bb2e..8df8096bba94 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCInst.h - MCInst class --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -154,8 +153,6 @@ public: bool evaluateAsConstantImm(int64_t &Imm) const; }; -template <> struct isPodLike<MCOperand> { static const bool value = true; }; - /// Instances of this class represent a single low-level machine /// instruction. class MCInst { @@ -190,6 +187,7 @@ public: void clear() { Operands.clear(); } void erase(iterator I) { Operands.erase(I); } + void erase(iterator First, iterator Last) { Operands.erase(First, Last); } size_t size() const { return Operands.size(); } iterator begin() { return Operands.begin(); } const_iterator begin() const { return Operands.begin(); } diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h index c5c4f481e7df..0c8e01fdc412 100644 --- a/include/llvm/MC/MCInstBuilder.h +++ b/include/llvm/MC/MCInstBuilder.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCInstBuilder.h - Simplify creation of MCInsts --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index df221e1db0e7..6bbc4bc2903b 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -1,9 +1,8 @@ //===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -65,6 +64,10 @@ public: virtual ~MCInstPrinter(); + /// Customize the printer according to a command line option. + /// @return true if the option is recognized and applied. + virtual bool applyTargetSpecificCLOption(StringRef Opt) { return false; } + /// Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index 200f10f7d64b..dfefd7e72777 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 61e7d09afbcb..0aa586dfc901 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCInstrDesc.h - Instruction Descriptors -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -135,6 +134,7 @@ enum Flag { FoldableAsLoad, MayLoad, MayStore, + MayRaiseFPException, Predicable, NotDuplicable, UnmodeledSideEffects, @@ -404,6 +404,11 @@ public: /// may not actually modify anything, for example. bool mayStore() const { return Flags & (1ULL << MCID::MayStore); } + /// Return true if this instruction may raise a floating-point exception. + bool mayRaiseFPException() const { + return Flags & (1ULL << MCID::MayRaiseFPException); + } + /// Return true if this instruction has side /// effects that are not modeled by other flags. This does not return true /// for instructions whose effects are captured by: diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 18da87cf8929..874b1e46795b 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCInstrInfo.h - Target Instruction Info ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index fe81376e0db7..485aa663272e 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCInstrItineraries.h - Scheduling ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index aaf70691fc01..0b8afac8f754 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -1,9 +1,8 @@ //===- MCLabel.h - Machine Code Directional Local Labels --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index f0fd07f43cf3..f2a1364ad884 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -1,10 +1,9 @@ //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===// // // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 22fbeb72a4ec..278aebee99ac 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCMachObjectWriter.h - Mach Object Writer --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index f8142ccd8ac5..abc87bf27748 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCObjectFileInfo.h - Object File Info -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -160,6 +159,9 @@ protected: /// FaultMap section. MCSection *FaultMapSection; + /// Remarks section. + MCSection *RemarksSection; + /// EH frame section. /// /// It is initialized on demand so it can be overwritten (with uniquing). @@ -315,6 +317,7 @@ public: MCSection *getStackMapSection() const { return StackMapSection; } MCSection *getFaultMapSection() const { return FaultMapSection; } + MCSection *getRemarksSection() const { return RemarksSection; } MCSection *getStackSizesSection(const MCSection &TextSec) const; @@ -381,7 +384,7 @@ public: return EHFrameSection; } - enum Environment { IsMachO, IsELF, IsCOFF, IsWasm }; + enum Environment { IsMachO, IsELF, IsCOFF, IsWasm, IsXCOFF }; Environment getObjectFileType() const { return Env; } bool isPositionIndependent() const { return PositionIndependent; } @@ -397,6 +400,7 @@ private: void initELFMCObjectFileInfo(const Triple &T, bool Large); void initCOFFMCObjectFileInfo(const Triple &T); void initWasmMCObjectFileInfo(const Triple &T); + void initXCOFFMCObjectFileInfo(const Triple &T); MCSection *getDwarfComdatSection(const char *Name, uint64_t Hash) const; public: diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 892909656c15..8affca49490f 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -1,9 +1,8 @@ //===- MCObjectStreamer.h - MCStreamer Object File Interface ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -116,8 +115,7 @@ public: void EmitSLEB128Value(const MCExpr *Value) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; - void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - bool = false) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; /// Emit an instruction to a special fragment, because this instruction /// can change its size during relaxation. diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 8bae2bf20083..2547b2b7c9c1 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCObjectWriter.h - Object File Writer Interface --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/AsmCond.h b/include/llvm/MC/MCParser/AsmCond.h index a6e0fbd7f337..ea2155010081 100644 --- a/include/llvm/MC/MCParser/AsmCond.h +++ b/include/llvm/MC/MCParser/AsmCond.h @@ -1,9 +1,8 @@ //===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 2e9b8dfa3b26..b7294493b2f8 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -1,9 +1,8 @@ //===- AsmLexer.h - Lexer for Assembly Files --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index ea13d1cdc09f..e89abeaac94c 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index b80289878e6e..da5653ee71d3 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -130,9 +129,6 @@ protected: // Can only create subclasses. /// Flag tracking whether any errors have been encountered. bool HadError = false; - /// Enable print [latency:throughput] in output file. - bool EnablePrintSchedInfo = false; - bool ShowParsedOperands = false; public: @@ -166,9 +162,6 @@ public: bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - void setEnablePrintSchedInfo(bool Value) { EnablePrintSchedInfo = Value; } - bool shouldPrintSchedInfo() const { return EnablePrintSchedInfo; } - /// Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 1a132bceddc5..5d2afe81a54b 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/MCAsmParserUtils.h b/include/llvm/MC/MCParser/MCAsmParserUtils.h index 84173bb9cb8e..d692da7402fe 100644 --- a/include/llvm/MC/MCParser/MCAsmParserUtils.h +++ b/include/llvm/MC/MCParser/MCAsmParserUtils.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 4af76ac2a858..2b6e2aa48b8f 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCParsedAsmOperand.h - Asm Parser Operand --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCParser/MCTargetAsmParser.h b/include/llvm/MC/MCParser/MCTargetAsmParser.h index ccf13a6a4fb4..849dbd57f1aa 100644 --- a/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCTargetAsmParser.h - Target Assembly Parser -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -17,6 +16,7 @@ #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/SMLoc.h" #include <cstdint> #include <memory> @@ -203,7 +203,7 @@ public: // The instruction encoding is not valid because it requires some target // features that are not currently enabled. MissingFeatures has a bit set for // each feature that the encoding needs but which is not enabled. - static NearMissInfo getMissedFeature(uint64_t MissingFeatures) { + static NearMissInfo getMissedFeature(const FeatureBitset &MissingFeatures) { NearMissInfo Result; Result.Kind = NearMissFeature; Result.Features = MissingFeatures; @@ -255,7 +255,7 @@ public: // Feature flags required by the instruction, that the current target does // not have. - uint64_t getFeatures() const { + const FeatureBitset& getFeatures() const { assert(Kind == NearMissFeature); return Features; } @@ -305,7 +305,7 @@ private: }; union { - uint64_t Features; + FeatureBitset Features; unsigned PredicateError; MissedOpInfo MissedOperand; TooFewOperandsInfo TooFewOperands; @@ -335,7 +335,7 @@ protected: // Can only create subclasses. MCSubtargetInfo ©STI(); /// AvailableFeatures - The current set of available features. - uint64_t AvailableFeatures = 0; + FeatureBitset AvailableFeatures; /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm = false; @@ -360,8 +360,12 @@ public: const MCSubtargetInfo &getSTI() const; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } + const FeatureBitset& getAvailableFeatures() const { + return AvailableFeatures; + } + void setAvailableFeatures(const FeatureBitset& Value) { + AvailableFeatures = Value; + } bool isParsingInlineAsm () { return ParsingInlineAsm; } void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } @@ -380,9 +384,6 @@ public: virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; - /// Sets frame register corresponding to the current MachineFunction. - virtual void SetFrameRegister(unsigned RegNo) {} - /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 8d8c677c77ea..92d39c3fcfb7 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -1,9 +1,8 @@ //===- MC/MCRegisterInfo.h - Target Register Description --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 689ac73cbdd1..df3248ee6e86 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCSchedule.h - Scheduling -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -15,6 +14,7 @@ #ifndef LLVM_MC_MCSCHEDULE_H #define LLVM_MC_MCSCHEDULE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/DataTypes.h" @@ -370,6 +370,11 @@ struct MCSchedModel { getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, const MCInst &Inst) const; + /// Returns the maximum forwarding delay for register reads dependent on + /// writes of scheduling class WriteResourceIdx. + static unsigned getForwardingDelayCycles(ArrayRef<MCReadAdvanceEntry> Entries, + unsigned WriteResourceIdx = 0); + /// Returns the default initialized model. static const MCSchedModel &GetDefaultSchedModel() { return Default; } static const MCSchedModel Default; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index eb210b4e9dfa..6fad1ec2069c 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -1,9 +1,8 @@ //===- MCSection.h - Machine Code Sections ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -38,7 +37,7 @@ template <> struct ilist_alloc_traits<MCFragment> { /// current translation unit. The MCContext class uniques and creates these. class MCSection { public: - enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm }; + enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm, SV_XCOFF }; /// Express the state of bundle locked groups while emitting code. enum BundleLockStateType { diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 24b9f8898ebb..8be95e0f1de5 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -1,9 +1,8 @@ //===- MCSectionCOFF.h - COFF Machine Code Sections -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -63,8 +62,6 @@ private: } public: - ~MCSectionCOFF(); - /// Decides whether a '.section' directive should be printed before the /// section name bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 00c289c6bd6e..fe6b2d7afc79 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -1,9 +1,8 @@ //===- MCSectionELF.h - ELF Machine Code Sections ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -64,8 +63,6 @@ private: void setSectionName(StringRef Name) { SectionName = Name; } public: - ~MCSectionELF(); - /// Decides whether a '.section' directive should be printed before the /// section name bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index 89db09cbdbdc..2c73661fb1fd 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -1,9 +1,8 @@ //===- MCSectionMachO.h - MachO Machine Code Sections -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCSectionWasm.h b/include/llvm/MC/MCSectionWasm.h index ab4cd7b007ec..2941a40f3b8c 100644 --- a/include/llvm/MC/MCSectionWasm.h +++ b/include/llvm/MC/MCSectionWasm.h @@ -1,9 +1,8 @@ //===- MCSectionWasm.h - Wasm Machine Code Sections -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -43,20 +42,19 @@ class MCSectionWasm final : public MCSection { // segment uint32_t SegmentIndex = 0; + // Whether this data segment is passive + bool IsPassive = false; + friend class MCContext; MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin) : MCSection(SV_Wasm, K, Begin), SectionName(Section), UniqueID(UniqueID), Group(group) {} - void setSectionName(StringRef Name) { SectionName = Name; } - public: - ~MCSectionWasm(); - /// Decides whether a '.section' directive should be printed before the /// section name - bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + bool shouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } const MCSymbolWasm *getGroup() const { return Group; } @@ -68,7 +66,8 @@ public: bool isVirtualSection() const override; bool isWasmData() const { - return Kind.isGlobalWriteableData() || Kind.isReadOnly(); + return Kind.isGlobalWriteableData() || Kind.isReadOnly() || + Kind.isThreadLocal(); } bool isUnique() const { return UniqueID != ~0U; } @@ -80,6 +79,14 @@ public: uint32_t getSegmentIndex() const { return SegmentIndex; } void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; } + bool getPassive() const { + assert(isWasmData()); + return IsPassive; + } + void setPassive(bool V = true) { + assert(isWasmData()); + IsPassive = V; + } static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; } }; diff --git a/include/llvm/MC/MCSectionXCOFF.h b/include/llvm/MC/MCSectionXCOFF.h new file mode 100644 index 000000000000..2a3f391fd3e2 --- /dev/null +++ b/include/llvm/MC/MCSectionXCOFF.h @@ -0,0 +1,56 @@ +//===- MCSectionXCOFF.h - XCOFF Machine Code Sections -----------*- 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 MCSectionXCOFF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONXCOFF_H +#define LLVM_MC_MCSECTIONXCOFF_H + +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/MC/MCSection.h" + +namespace llvm { + +class MCSymbol; + +// This class represents an XCOFF `Control Section`, more commonly referred to +// as a csect. A csect represents the smallest possible unit of data/code which +// will be relocated as a single block. +class MCSectionXCOFF final : public MCSection { + friend class MCContext; + + StringRef Name; + XCOFF::StorageMappingClass MappingClass; + + MCSectionXCOFF(StringRef Section, XCOFF::StorageMappingClass SMC, + SectionKind K, MCSymbol *Begin) + : MCSection(SV_XCOFF, K, Begin), Name(Section), MappingClass(SMC) {} + +public: + ~MCSectionXCOFF(); + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_XCOFF; + } + + StringRef getSectionName() const { return Name; } + XCOFF::StorageMappingClass getMappingClass() const { return MappingClass; } + + void PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, + raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index f613d3a1943f..731e7515448c 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -1,9 +1,8 @@ //===- MCStreamer.h - High-level Streaming Machine Code Output --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -20,7 +19,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCDirectives.h" -#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWinEH.h" @@ -44,6 +42,7 @@ class MCAsmBackend; class MCCodeEmitter; struct MCCodePaddingContext; class MCContext; +struct MCDwarfFrameInfo; class MCExpr; class MCInst; class MCInstPrinter; @@ -267,10 +266,8 @@ public: /// closed. Otherwise, issue an error and return null. WinEH::FrameInfo *EnsureValidWinFrameInfo(SMLoc Loc); - unsigned getNumFrameInfos() { return DwarfFrameInfos.size(); } - ArrayRef<MCDwarfFrameInfo> getDwarfFrameInfos() const { - return DwarfFrameInfos; - } + unsigned getNumFrameInfos(); + ArrayRef<MCDwarfFrameInfo> getDwarfFrameInfos() const; bool hasUnfinishedDwarfFrameInfo(); @@ -629,13 +626,20 @@ public: /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); + /// Special case of EmitValue that avoids the client having to pass + /// in a MCExpr for constant integers & prints in Hex format for certain + /// modes. + virtual void EmitIntValueInHex(uint64_t Value, unsigned Size) { + EmitIntValue(Value, Size); + } + virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); /// Special case of EmitULEB128Value that avoids the client having to /// pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value); + void EmitULEB128IntValue(uint64_t Value, unsigned PadTo = 0); /// Special case of EmitSLEB128Value that avoids the client having to /// pass in a MCExpr for constant integers. @@ -782,7 +786,7 @@ public: /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, - MD5::MD5Result *Checksum = nullptr, + Optional<MD5::MD5Result> Checksum = None, Optional<StringRef> Source = None, unsigned CUID = 0) { return cantFail( @@ -797,12 +801,12 @@ public: /// '.file 4 "dir/foo.c" md5 "..." source "..."' assembler directive. virtual Expected<unsigned> tryEmitDwarfFileDirective( unsigned FileNo, StringRef Directory, StringRef Filename, - MD5::MD5Result *Checksum = nullptr, Optional<StringRef> Source = None, + Optional<MD5::MD5Result> Checksum = None, Optional<StringRef> Source = None, unsigned CUID = 0); /// Specify the "root" file of the compilation, using the ".file 0" extension. virtual void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, - MD5::MD5Result *Checksum, + Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID = 0); @@ -953,9 +957,7 @@ public: virtual void EmitAddrsigSym(const MCSymbol *Sym) {} /// Emit the given \p Instruction into the current section. - /// PrintSchedInfo == true then schedul comment should be added to output - virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, - bool PrintSchedInfo = false); + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// Set the bundle alignment mode from now on in the section. /// The argument is the power of 2 to which the alignment is set. The diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index b3ce523d9c0c..9490a6ecedad 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCSubtargetInfo.h - Subtarget Information --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -30,6 +29,45 @@ namespace llvm { class MCInst; //===----------------------------------------------------------------------===// + +/// Used to provide key value pairs for feature and CPU bit flags. +struct SubtargetFeatureKV { + const char *Key; ///< K-V key string + const char *Desc; ///< Help descriptor + unsigned Value; ///< K-V integer value + FeatureBitArray Implies; ///< K-V bit mask + + /// Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; + } + + /// Compare routine for std::is_sorted. + bool operator<(const SubtargetFeatureKV &Other) const { + return StringRef(Key) < StringRef(Other.Key); + } +}; + +//===----------------------------------------------------------------------===// + +/// Used to provide key value pairs for feature and CPU bit flags. +struct SubtargetSubTypeKV { + const char *Key; ///< K-V key string + FeatureBitArray Implies; ///< K-V bit mask + const MCSchedModel *SchedModel; + + /// Compare routine for std::lower_bound + bool operator<(StringRef S) const { + return StringRef(Key) < S; + } + + /// Compare routine for std::is_sorted. + bool operator<(const SubtargetSubTypeKV &Other) const { + return StringRef(Key) < StringRef(Other.Key); + } +}; + +//===----------------------------------------------------------------------===// /// /// Generic base class for all target subtargets. /// @@ -37,10 +75,9 @@ class MCSubtargetInfo { Triple TargetTriple; std::string CPU; // CPU being targeted. ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list - ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions + ArrayRef<SubtargetSubTypeKV> ProcDesc; // Processor descriptions // Scheduler machine model - const SubtargetInfoKV *ProcSchedModels; const MCWriteProcResEntry *WriteProcResTable; const MCWriteLatencyEntry *WriteLatencyTable; const MCReadAdvanceEntry *ReadAdvanceTable; @@ -55,8 +92,7 @@ public: MCSubtargetInfo(const MCSubtargetInfo &) = default; MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF, - ArrayRef<SubtargetFeatureKV> PD, - const SubtargetInfoKV *ProcSched, + ArrayRef<SubtargetSubTypeKV> PD, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, const unsigned *OC, const unsigned *FP); @@ -105,6 +141,10 @@ public: /// all feature bits implied by the flag. FeatureBitset ApplyFeatureFlag(StringRef FS); + /// Set/clear additional feature bits, including all other bits they imply. + FeatureBitset SetFeatureBitsTransitively(const FeatureBitset& FB); + FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB); + /// Check whether the subtarget features are enabled/disabled as per /// the provided string, ignoring all other features. bool checkFeatures(StringRef FS) const; @@ -153,6 +193,16 @@ public: return 0; } + /// Return the set of ReadAdvance entries declared by the scheduling class + /// descriptor in input. + ArrayRef<MCReadAdvanceEntry> + getReadAdvanceEntries(const MCSchedClassDesc &SC) const { + if (!SC.NumReadAdvanceEntries) + return ArrayRef<MCReadAdvanceEntry>(); + return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx], + SC.NumReadAdvanceEntries); + } + /// Get scheduling itinerary of a CPU. InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; @@ -171,11 +221,6 @@ public: auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU); return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; } - - /// Returns string representation of scheduler comment - virtual std::string getSchedInfoStr(MCInst const &MCI) const { - return {}; - } }; } // end namespace llvm diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 4681a1be60c4..189484deac7e 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -1,9 +1,8 @@ //===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -49,6 +48,7 @@ protected: SymbolKindELF, SymbolKindMachO, SymbolKindWasm, + SymbolKindXCOFF, }; /// A symbol can contain an Offset, or Value, or be Common, but never more @@ -58,6 +58,7 @@ protected: SymContentsOffset, SymContentsVariable, SymContentsCommon, + SymContentsTargetCommon, // Index stores the section index }; // Special sentinal value for the absolute pseudo fragment. @@ -108,7 +109,7 @@ protected: /// This is actually a Contents enumerator, but is unsigned to avoid sign /// extension and achieve better bitpacking with MSVC. - unsigned SymbolContents : 2; + unsigned SymbolContents : 3; /// The alignment of the symbol, if it is 'common', or -1. /// @@ -286,6 +287,8 @@ public: bool isWasm() const { return Kind == SymbolKindWasm; } + bool isXCOFF() const { return Kind == SymbolKindXCOFF; } + /// @} /// \name Variable Symbols /// @{ @@ -342,10 +345,11 @@ public: /// /// \param Size - The size of the symbol. /// \param Align - The alignment of the symbol. - void setCommon(uint64_t Size, unsigned Align) { + /// \param Target - Is the symbol a target-specific common-like symbol. + void setCommon(uint64_t Size, unsigned Align, bool Target = false) { assert(getOffset() == 0); CommonSize = Size; - SymbolContents = SymContentsCommon; + SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; assert((!Align || isPowerOf2_32(Align)) && "Alignment must be a power of 2"); @@ -365,20 +369,28 @@ public: /// /// \param Size - The size of the symbol. /// \param Align - The alignment of the symbol. + /// \param Target - Is the symbol a target-specific common-like symbol. /// \return True if symbol was already declared as a different type - bool declareCommon(uint64_t Size, unsigned Align) { + bool declareCommon(uint64_t Size, unsigned Align, bool Target = false) { assert(isCommon() || getOffset() == 0); if(isCommon()) { - if(CommonSize != Size || getCommonAlignment() != Align) - return true; + if (CommonSize != Size || getCommonAlignment() != Align || + isTargetCommon() != Target) + return true; } else - setCommon(Size, Align); + setCommon(Size, Align, Target); return false; } /// Is this a 'common' symbol. bool isCommon() const { - return SymbolContents == SymContentsCommon; + return SymbolContents == SymContentsCommon || + SymbolContents == SymContentsTargetCommon; + } + + /// Is this a target-specific common-like symbol. + bool isTargetCommon() const { + return SymbolContents == SymContentsTargetCommon; } MCFragment *getFragment(bool SetUsed = true) const { diff --git a/include/llvm/MC/MCSymbolCOFF.h b/include/llvm/MC/MCSymbolCOFF.h index 7918c353dc15..94087ce871ae 100644 --- a/include/llvm/MC/MCSymbolCOFF.h +++ b/include/llvm/MC/MCSymbolCOFF.h @@ -1,9 +1,8 @@ //===- MCSymbolCOFF.h - ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCSymbolELF.h b/include/llvm/MC/MCSymbolELF.h index bbcd22e8e7db..34e5c4344aff 100644 --- a/include/llvm/MC/MCSymbolELF.h +++ b/include/llvm/MC/MCSymbolELF.h @@ -1,9 +1,8 @@ //===- MCSymbolELF.h - -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_MC_MCSYMBOLELF_H diff --git a/include/llvm/MC/MCSymbolMachO.h b/include/llvm/MC/MCSymbolMachO.h index 6125c2050976..8f9ff56470a7 100644 --- a/include/llvm/MC/MCSymbolMachO.h +++ b/include/llvm/MC/MCSymbolMachO.h @@ -1,9 +1,8 @@ //===- MCSymbolMachO.h - ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_MC_MCSYMBOLMACHO_H @@ -35,6 +34,7 @@ class MCSymbolMachO : public MCSymbol { SF_WeakDefinition = 0x0080, SF_SymbolResolver = 0x0100, SF_AltEntry = 0x0200, + SF_Cold = 0x0400, // Common alignment SF_CommonAlignmentMask = 0xF0FF, @@ -98,6 +98,10 @@ public: return getFlags() & SF_AltEntry; } + void setCold() const { modifyFlags(SF_Cold, SF_Cold); } + + bool isCold() const { return getFlags() & SF_Cold; } + void setDesc(unsigned Value) const { assert(Value == (Value & SF_DescFlagsMask) && "Invalid .desc value!"); diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h index 8e66dc881d0f..c50cd0ee4709 100644 --- a/include/llvm/MC/MCSymbolWasm.h +++ b/include/llvm/MC/MCSymbolWasm.h @@ -1,9 +1,8 @@ //===- MCSymbolWasm.h - ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_MC_MCSYMBOLWASM_H @@ -19,7 +18,9 @@ class MCSymbolWasm : public MCSymbol { bool IsWeak = false; bool IsHidden = false; bool IsComdat = false; - std::string ModuleName; + mutable bool IsUsedInGOT = false; + Optional<std::string> ImportModule; + Optional<std::string> ImportName; wasm::WasmSignature *Signature = nullptr; Optional<wasm::WasmGlobalType> GlobalType; Optional<wasm::WasmEventType> EventType; @@ -32,7 +33,7 @@ public: // Use a module name of "env" for now, for compatibility with existing tools. // This is temporary, and may change, as the ABI is not yet stable. MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary) - : MCSymbol(SymbolKindWasm, Name, isTemporary), ModuleName("env") {} + : MCSymbol(SymbolKindWasm, Name, isTemporary) {} static bool classof(const MCSymbol *S) { return S->isWasm(); } const MCExpr *getSize() const { return SymbolSize; } @@ -46,6 +47,13 @@ public: wasm::WasmSymbolType getType() const { return Type; } void setType(wasm::WasmSymbolType type) { Type = type; } + bool isExported() const { + return getFlags() & wasm::WASM_SYMBOL_EXPORTED; + } + void setExported() const { + modifyFlags(wasm::WASM_SYMBOL_EXPORTED, wasm::WASM_SYMBOL_EXPORTED); + } + bool isWeak() const { return IsWeak; } void setWeak(bool isWeak) { IsWeak = isWeak; } @@ -55,8 +63,24 @@ public: bool isComdat() const { return IsComdat; } void setComdat(bool isComdat) { IsComdat = isComdat; } - const StringRef getModuleName() const { return ModuleName; } - void setModuleName(StringRef Name) { ModuleName = Name; } + const StringRef getImportModule() const { + if (ImportModule.hasValue()) { + return ImportModule.getValue(); + } + return "env"; + } + void setImportModule(StringRef Name) { ImportModule = Name; } + + const StringRef getImportName() const { + if (ImportName.hasValue()) { + return ImportName.getValue(); + } + return getName(); + } + void setImportName(StringRef Name) { ImportName = Name; } + + void setUsedInGOT() const { IsUsedInGOT = true; } + bool isUsedInGOT() const { return IsUsedInGOT; } const wasm::WasmSignature *getSignature() const { return Signature; } void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; } diff --git a/include/llvm/MC/MCSymbolXCOFF.h b/include/llvm/MC/MCSymbolXCOFF.h new file mode 100644 index 000000000000..0a1fe1475138 --- /dev/null +++ b/include/llvm/MC/MCSymbolXCOFF.h @@ -0,0 +1,26 @@ +//===- MCSymbolXCOFF.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_MC_MCSYMBOLXCOFF_H +#define LLVM_MC_MCSYMBOLXCOFF_H + +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/MC/MCSymbol.h" + +namespace llvm { + +class MCSymbolXCOFF : public MCSymbol { +public: + MCSymbolXCOFF(const StringMapEntry<bool> *Name, bool isTemporary) + : MCSymbol(SymbolKindXCOFF, Name, isTemporary) {} + + static bool classof(const MCSymbol *S) { return S->isXCOFF(); } +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOLXCOFF_H diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index f5d330fbeb22..f184620ff047 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -1,9 +1,8 @@ //===- MCTargetOptions.h - MC Target Options --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -16,18 +15,18 @@ namespace llvm { enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - WinEH, /// Windows Exception Handling - Wasm, /// WebAssembly Exception Handling + None, ///< No exception support + DwarfCFI, ///< DWARF-like instruction based exceptions + SjLj, ///< setjmp/longjmp based exceptions + ARM, ///< ARM EHABI + WinEH, ///< Windows Exception Handling + Wasm, ///< WebAssembly Exception Handling }; enum class DebugCompressionType { - None, /// No compression - GNU, /// zlib-gnu style compression - Z, /// zlib style complession + None, ///< No compression + GNU, ///< zlib-gnu style compression + Z, ///< zlib style complession }; class StringRef; @@ -39,9 +38,6 @@ public: AsmInstrumentationAddress }; - /// Enables AddressSanitizer instrumentation at machine level. - bool SanitizeAddress : 1; - bool MCRelaxAll : 1; bool MCNoExecStack : 1; bool MCFatalWarnings : 1; diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.inc b/include/llvm/MC/MCTargetOptionsCommandFlags.inc index 5172fa44511f..9f1177f470b9 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.inc +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.inc @@ -1,9 +1,8 @@ //===-- MCTargetOptionsCommandFlags.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,15 +18,6 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; -static cl::opt<MCTargetOptions::AsmInstrumentation> AsmInstrumentation( - "asm-instrumentation", cl::desc("Instrumentation of inline assembly and " - "assembly source files"), - cl::init(MCTargetOptions::AsmInstrumentationNone), - cl::values(clEnumValN(MCTargetOptions::AsmInstrumentationNone, "none", - "no instrumentation at all"), - clEnumValN(MCTargetOptions::AsmInstrumentationAddress, "address", - "instrument instructions with memory arguments"))); - static cl::opt<bool> RelaxAll("mc-relax-all", cl::desc("When used with filetype=obj, " "relax all fixups in the emitted object file")); @@ -63,8 +53,6 @@ ABIName("target-abi", cl::Hidden, static MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; - Options.SanitizeAddress = - (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); Options.MCRelaxAll = RelaxAll; Options.MCIncrementalLinkerCompatible = IncrementalLinkerCompatible; Options.MCPIECopyRelocations = PIECopyRelocations; diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index 11f5082ed3f4..0be7ce7055c5 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h index 6b788cfe96b9..4adbca28f116 100644 --- a/include/llvm/MC/MCWasmObjectWriter.h +++ b/include/llvm/MC/MCWasmObjectWriter.h @@ -1,9 +1,8 @@ //===-- llvm/MC/MCWasmObjectWriter.h - Wasm Object Writer -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCWasmStreamer.h b/include/llvm/MC/MCWasmStreamer.h index 01e6a4379287..2d7f2b9975c9 100644 --- a/include/llvm/MC/MCWasmStreamer.h +++ b/include/llvm/MC/MCWasmStreamer.h @@ -1,9 +1,8 @@ //===- MCWasmStreamer.h - MCStreamer Wasm Object File Interface -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h index 1a9f6f403d7c..60ec06e61b7c 100644 --- a/include/llvm/MC/MCWin64EH.h +++ b/include/llvm/MC/MCWin64EH.h @@ -1,9 +1,8 @@ //===- MCWin64EH.h - Machine Code Win64 EH support --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index c1d35ea1f6ba..3fe124fd7f1c 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -1,9 +1,8 @@ //===- llvm/MC/MCWinCOFFObjectWriter.h - Win COFF Object Writer -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 0049d04b4b3f..c1c1ec56cb48 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -1,9 +1,8 @@ //===- MCWinCOFFStreamer.h - COFF Object File Interface ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 98ef0367a11d..b1c28c0ecae7 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -1,9 +1,8 @@ //===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/MCXCOFFObjectWriter.h b/include/llvm/MC/MCXCOFFObjectWriter.h new file mode 100644 index 000000000000..fe4087f70614 --- /dev/null +++ b/include/llvm/MC/MCXCOFFObjectWriter.h @@ -0,0 +1,41 @@ +//===-- llvm/MC/MCXCOFFObjectWriter.h - XCOFF Object Writer ---------------===// +// +// 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_MC_MCXCOFFOBJECTWRITER_H +#define LLVM_MC_MCXCOFFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" + +namespace llvm { + +class raw_pwrite_stream; + +class MCXCOFFObjectTargetWriter : public MCObjectTargetWriter { +protected: + MCXCOFFObjectTargetWriter(bool Is64Bit); + +public: + ~MCXCOFFObjectTargetWriter() override; + + Triple::ObjectFormatType getFormat() const override { return Triple::XCOFF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::XCOFF; + } + bool is64Bit() const { return Is64Bit; } + +private: + bool Is64Bit; +}; + +std::unique_ptr<MCObjectWriter> +createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, + raw_pwrite_stream &OS); + +} // end namespace llvm + +#endif // LLVM_MC_MCXCOFFOBJECTWRITER_H diff --git a/include/llvm/MC/MCXCOFFStreamer.h b/include/llvm/MC/MCXCOFFStreamer.h new file mode 100644 index 000000000000..159ae4818749 --- /dev/null +++ b/include/llvm/MC/MCXCOFFStreamer.h @@ -0,0 +1,33 @@ +//===- MCXCOFFObjectStreamer.h - MCStreamer XCOFF Object File 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCXCOFFSTREAMER_H +#define LLVM_MC_MCXCOFFSTREAMER_H + +#include "llvm/MC/MCObjectStreamer.h" + +namespace llvm { + +class MCXCOFFStreamer : public MCObjectStreamer { +public: + MCXCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter); + + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; +}; + +} // end namespace llvm + +#endif // LLVM_MC_MCXCOFFSTREAMER_H diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index 91ed661ebeab..5872540e6104 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -1,9 +1,8 @@ //===- llvm/MC/MachineLocation.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 MachineLocation class is used to represent a simple location in a machine diff --git a/include/llvm/MC/SectionKind.h b/include/llvm/MC/SectionKind.h index 66eb9ec56d14..0342c4cfbbde 100644 --- a/include/llvm/MC/SectionKind.h +++ b/include/llvm/MC/SectionKind.h @@ -1,9 +1,8 @@ //===-- llvm/MC/SectionKind.h - Classification of sections ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h index 265260fcee4d..c83eca4e512d 100644 --- a/include/llvm/MC/StringTableBuilder.h +++ b/include/llvm/MC/StringTableBuilder.h @@ -1,9 +1,8 @@ //===- StringTableBuilder.h - String table building utility -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 76c7dd560800..fc9565ceafad 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -1,9 +1,8 @@ //===- llvm/MC/SubtargetFeature.h - CPU characteristics ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #define LLVM_MC_SUBTARGETFEATURE_H #include "llvm/ADT/StringRef.h" +#include <array> #include <bitset> #include <initializer_list> #include <string> @@ -26,11 +26,12 @@ namespace llvm { -template <typename T> class ArrayRef; class raw_ostream; class Triple; -const unsigned MAX_SUBTARGET_FEATURES = 192; +const unsigned MAX_SUBTARGET_WORDS = 3; +const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64; + /// Container class for subtarget features. /// This is convenient because std::bitset does not have a constructor /// with an initializer list of set bits. @@ -45,38 +46,34 @@ public: for (auto I : Init) set(I); } -}; - -//===----------------------------------------------------------------------===// - -/// Used to provide key value pairs for feature and CPU bit flags. -struct SubtargetFeatureKV { - const char *Key; ///< K-V key string - const char *Desc; ///< Help descriptor - FeatureBitset Value; ///< K-V integer value - FeatureBitset Implies; ///< K-V bit mask - /// Compare routine for std::lower_bound - bool operator<(StringRef S) const { - return StringRef(Key) < S; - } - - /// Compare routine for std::is_sorted. - bool operator<(const SubtargetFeatureKV &Other) const { - return StringRef(Key) < StringRef(Other.Key); + bool operator < (const FeatureBitset &Other) const { + for (unsigned I = 0, E = size(); I != E; ++I) { + bool LHS = test(I), RHS = Other.test(I); + if (LHS != RHS) + return LHS < RHS; + } + return false; } }; -//===----------------------------------------------------------------------===// +/// Class used to store the subtarget bits in the tables created by tablegen. +/// The std::initializer_list constructor of FeatureBitset can't be done at +/// compile time and requires a static constructor to run at startup. +class FeatureBitArray { + std::array<uint64_t, MAX_SUBTARGET_WORDS> Bits; + +public: + constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) + : Bits(B) {} -/// Used to provide key value pairs for CPU and arbitrary pointers. -struct SubtargetInfoKV { - const char *Key; ///< K-V key string - const void *Value; ///< K-V pointer value + FeatureBitset getAsBitset() const { + FeatureBitset Result; - /// Compare routine for std::lower_bound - bool operator<(StringRef S) const { - return StringRef(Key) < S; + for (unsigned i = 0, e = Bits.size(); i != e; ++i) + Result |= FeatureBitset(Bits[i]) << (64 * i); + + return Result; } }; @@ -102,19 +99,6 @@ public: /// Adds Features. void AddFeature(StringRef String, bool Enable = true); - /// Toggles a feature and update the feature bits. - static void ToggleFeature(FeatureBitset &Bits, StringRef String, - ArrayRef<SubtargetFeatureKV> FeatureTable); - - /// Applies the feature flag and update the feature bits. - static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, - ArrayRef<SubtargetFeatureKV> FeatureTable); - - /// Returns feature bits of a CPU. - FeatureBitset getFeatureBits(StringRef CPU, - ArrayRef<SubtargetFeatureKV> CPUTable, - ArrayRef<SubtargetFeatureKV> FeatureTable); - /// Returns the vector of individual subtarget features. const std::vector<std::string> &getFeatures() const { return Features; } @@ -126,6 +110,32 @@ public: /// Adds the default features for the specified target triple. void getDefaultSubtargetFeatures(const Triple& Triple); + + /// Determine if a feature has a flag; '+' or '-' + static bool hasFlag(StringRef Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' or '-' flag + return Ch == '+' || Ch =='-'; + } + + /// Return string stripped of flag. + static std::string StripFlag(StringRef Feature) { + return hasFlag(Feature) ? Feature.substr(1) : Feature; + } + + /// Return true if enable flag; '+'. + static inline bool isEnabled(StringRef Feature) { + assert(!Feature.empty() && "Empty string"); + // Get first character + char Ch = Feature[0]; + // Check if first character is '+' for enabled + return Ch == '+'; + } + + /// Splits a string of comma separated items in to a vector of strings. + static void Split(std::vector<std::string> &V, StringRef S); }; } // end namespace llvm diff --git a/include/llvm/MCA/Context.h b/include/llvm/MCA/Context.h index 6b2bee0fdc42..503d780d4947 100644 --- a/include/llvm/MCA/Context.h +++ b/include/llvm/MCA/Context.h @@ -1,9 +1,8 @@ //===---------------------------- Context.h ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -32,15 +31,21 @@ namespace mca { /// This is a convenience struct to hold the parameters necessary for creating /// the pre-built "default" out-of-order pipeline. struct PipelineOptions { - PipelineOptions(unsigned DW, unsigned RFS, unsigned LQS, unsigned SQS, - bool NoAlias) - : DispatchWidth(DW), RegisterFileSize(RFS), LoadQueueSize(LQS), - StoreQueueSize(SQS), AssumeNoAlias(NoAlias) {} + PipelineOptions(unsigned UOPQSize, unsigned DecThr, unsigned DW, unsigned RFS, + unsigned LQS, unsigned SQS, bool NoAlias, + bool ShouldEnableBottleneckAnalysis = false) + : MicroOpQueueSize(UOPQSize), DecodersThroughput(DecThr), + DispatchWidth(DW), RegisterFileSize(RFS), LoadQueueSize(LQS), + StoreQueueSize(SQS), AssumeNoAlias(NoAlias), + EnableBottleneckAnalysis(ShouldEnableBottleneckAnalysis) {} + unsigned MicroOpQueueSize; + unsigned DecodersThroughput; // Instructions per cycle. unsigned DispatchWidth; unsigned RegisterFileSize; unsigned LoadQueueSize; unsigned StoreQueueSize; bool AssumeNoAlias; + bool EnableBottleneckAnalysis; }; class Context { diff --git a/include/llvm/MCA/HWEventListener.h b/include/llvm/MCA/HWEventListener.h index 3b32b2cd6577..e11d06de2b2e 100644 --- a/include/llvm/MCA/HWEventListener.h +++ b/include/llvm/MCA/HWEventListener.h @@ -1,9 +1,8 @@ //===----------------------- HWEventListener.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -40,6 +39,7 @@ public: // Events generated by the Retire Control Unit. Retired, // Events generated by the Scheduler. + Pending, Ready, Issued, Executed, @@ -126,6 +126,35 @@ public: const InstRef &IR; }; +// A HWPressureEvent describes an increase in backend pressure caused by +// the presence of data dependencies or unavailability of pipeline resources. +class HWPressureEvent { +public: + enum GenericReason { + INVALID = 0, + // Scheduler was unable to issue all the ready instructions because some + // pipeline resources were unavailable. + RESOURCES, + // Instructions could not be issued because of register data dependencies. + REGISTER_DEPS, + // Instructions could not be issued because of memory dependencies. + MEMORY_DEPS + }; + + HWPressureEvent(GenericReason reason, ArrayRef<InstRef> Insts, + uint64_t Mask = 0) + : Reason(reason), AffectedInstructions(Insts), ResourceMask(Mask) {} + + // Reason for this increase in backend pressure. + GenericReason Reason; + + // Instructions affected (i.e. delayed) by this increase in backend pressure. + ArrayRef<InstRef> AffectedInstructions; + + // A mask of unavailable processor resources. + const uint64_t ResourceMask; +}; + class HWEventListener { public: // Generic events generated by the pipeline. @@ -134,6 +163,7 @@ public: virtual void onEvent(const HWInstructionEvent &Event) {} virtual void onEvent(const HWStallEvent &Event) {} + virtual void onEvent(const HWPressureEvent &Event) {} using ResourceRef = std::pair<uint64_t, uint64_t>; virtual void onResourceAvailable(const ResourceRef &RRef) {} diff --git a/include/llvm/MCA/HardwareUnits/HardwareUnit.h b/include/llvm/MCA/HardwareUnits/HardwareUnit.h index 104a2009f219..f6e178bcff10 100644 --- a/include/llvm/MCA/HardwareUnits/HardwareUnit.h +++ b/include/llvm/MCA/HardwareUnits/HardwareUnit.h @@ -1,9 +1,8 @@ //===-------------------------- HardwareUnit.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/HardwareUnits/LSUnit.h b/include/llvm/MCA/HardwareUnits/LSUnit.h index e217fc50f780..ae9a49c64855 100644 --- a/include/llvm/MCA/HardwareUnits/LSUnit.h +++ b/include/llvm/MCA/HardwareUnits/LSUnit.h @@ -1,9 +1,8 @@ //===------------------------- LSUnit.h --------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -16,21 +15,298 @@ #ifndef LLVM_MCA_LSUNIT_H #define LLVM_MCA_LSUNIT_H -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSchedule.h" #include "llvm/MCA/HardwareUnits/HardwareUnit.h" +#include "llvm/MCA/Instruction.h" namespace llvm { namespace mca { -class InstRef; class Scheduler; -/// A Load/Store Unit implementing a load and store queues. +/// A node of a memory dependency graph. A MemoryGroup describes a set of +/// instructions with same memory dependencies. /// -/// This class implements a load queue and a store queue to emulate the -/// out-of-order execution of memory operations. -/// Each load (or store) consumes an entry in the load (or store) queue. +/// By construction, instructions of a MemoryGroup don't depend on each other. +/// At dispatch stage, instructions are mapped by the LSUnit to MemoryGroups. +/// A Memory group identifier is then stored as a "token" in field +/// Instruction::LSUTokenID of each dispatched instructions. That token is used +/// internally by the LSUnit to track memory dependencies. +class MemoryGroup { + unsigned NumPredecessors; + unsigned NumExecutingPredecessors; + unsigned NumExecutedPredecessors; + + unsigned NumInstructions; + unsigned NumExecuting; + unsigned NumExecuted; + SmallVector<MemoryGroup *, 4> Succ; + + CriticalDependency CriticalPredecessor; + InstRef CriticalMemoryInstruction; + + MemoryGroup(const MemoryGroup &) = delete; + MemoryGroup &operator=(const MemoryGroup &) = delete; + +public: + MemoryGroup() + : NumPredecessors(0), NumExecutingPredecessors(0), + NumExecutedPredecessors(0), NumInstructions(0), NumExecuting(0), + NumExecuted(0), CriticalPredecessor(), CriticalMemoryInstruction() {} + MemoryGroup(MemoryGroup &&) = default; + + ArrayRef<MemoryGroup *> getSuccessors() const { return Succ; } + unsigned getNumSuccessors() const { return Succ.size(); } + unsigned getNumPredecessors() const { return NumPredecessors; } + unsigned getNumExecutingPredecessors() const { + return NumExecutingPredecessors; + } + unsigned getNumExecutedPredecessors() const { + return NumExecutedPredecessors; + } + unsigned getNumInstructions() const { return NumInstructions; } + unsigned getNumExecuting() const { return NumExecuting; } + unsigned getNumExecuted() const { return NumExecuted; } + + const InstRef &getCriticalMemoryInstruction() const { + return CriticalMemoryInstruction; + } + const CriticalDependency &getCriticalPredecessor() const { + return CriticalPredecessor; + } + + void addSuccessor(MemoryGroup *Group) { + Group->NumPredecessors++; + assert(!isExecuted() && "Should have been removed!"); + if (isExecuting()) + Group->onGroupIssued(CriticalMemoryInstruction); + Succ.emplace_back(Group); + } + + bool isWaiting() const { + return NumPredecessors > + (NumExecutingPredecessors + NumExecutedPredecessors); + } + bool isPending() const { + return NumExecutingPredecessors && + ((NumExecutedPredecessors + NumExecutingPredecessors) == + NumPredecessors); + } + bool isReady() const { return NumExecutedPredecessors == NumPredecessors; } + bool isExecuting() const { + return NumExecuting && (NumExecuting == (NumInstructions - NumExecuted)); + } + bool isExecuted() const { return NumInstructions == NumExecuted; } + + void onGroupIssued(const InstRef &IR) { + assert(!isReady() && "Unexpected group-start event!"); + NumExecutingPredecessors++; + + unsigned Cycles = IR.getInstruction()->getCyclesLeft(); + if (CriticalPredecessor.Cycles < Cycles) { + CriticalPredecessor.IID = IR.getSourceIndex(); + CriticalPredecessor.Cycles = Cycles; + } + } + + void onGroupExecuted() { + assert(!isReady() && "Inconsistent state found!"); + NumExecutingPredecessors--; + NumExecutedPredecessors++; + } + + void onInstructionIssued(const InstRef &IR) { + assert(!isExecuting() && "Invalid internal state!"); + ++NumExecuting; + + // update the CriticalMemDep. + const Instruction &IS = *IR.getInstruction(); + if ((bool)CriticalMemoryInstruction) { + const Instruction &OtherIS = *CriticalMemoryInstruction.getInstruction(); + if (OtherIS.getCyclesLeft() < IS.getCyclesLeft()) + CriticalMemoryInstruction = IR; + } else { + CriticalMemoryInstruction = IR; + } + + if (!isExecuting()) + return; + + // Notify successors that this group started execution. + for (MemoryGroup *MG : Succ) + MG->onGroupIssued(CriticalMemoryInstruction); + } + + void onInstructionExecuted() { + assert(isReady() && !isExecuted() && "Invalid internal state!"); + --NumExecuting; + ++NumExecuted; + + if (!isExecuted()) + return; + + // Notify successors that this group has finished execution. + for (MemoryGroup *MG : Succ) + MG->onGroupExecuted(); + } + + void addInstruction() { + assert(!getNumSuccessors() && "Cannot add instructions to this group!"); + ++NumInstructions; + } + + void cycleEvent() { + if (isWaiting() && CriticalPredecessor.Cycles) + CriticalPredecessor.Cycles--; + } +}; + +/// Abstract base interface for LS (load/store) units in llvm-mca. +class LSUnitBase : public HardwareUnit { + /// Load queue size. + /// + /// A value of zero for this field means that the load queue is unbounded. + /// Processor models can declare the size of a load queue via tablegen (see + /// the definition of tablegen class LoadQueue in + /// llvm/Target/TargetSchedule.td). + unsigned LQSize; + + /// Load queue size. + /// + /// A value of zero for this field means that the store queue is unbounded. + /// Processor models can declare the size of a store queue via tablegen (see + /// the definition of tablegen class StoreQueue in + /// llvm/Target/TargetSchedule.td). + unsigned SQSize; + + unsigned UsedLQEntries; + unsigned UsedSQEntries; + + /// True if loads don't alias with stores. + /// + /// By default, the LS unit assumes that loads and stores don't alias with + /// eachother. If this field is set to false, then loads are always assumed to + /// alias with stores. + const bool NoAlias; + + /// Used to map group identifiers to MemoryGroups. + DenseMap<unsigned, std::unique_ptr<MemoryGroup>> Groups; + unsigned NextGroupID; + +public: + LSUnitBase(const MCSchedModel &SM, unsigned LoadQueueSize, + unsigned StoreQueueSize, bool AssumeNoAlias); + + virtual ~LSUnitBase(); + + /// Returns the total number of entries in the load queue. + unsigned getLoadQueueSize() const { return LQSize; } + + /// Returns the total number of entries in the store queue. + unsigned getStoreQueueSize() const { return SQSize; } + + unsigned getUsedLQEntries() const { return UsedLQEntries; } + unsigned getUsedSQEntries() const { return UsedSQEntries; } + unsigned assignLQSlot() { return UsedLQEntries++; } + unsigned assignSQSlot() { return UsedSQEntries++; } + + bool assumeNoAlias() const { return NoAlias; } + + enum Status { + LSU_AVAILABLE = 0, + LSU_LQUEUE_FULL, // Load Queue unavailable + LSU_SQUEUE_FULL // Store Queue unavailable + }; + + /// This method checks the availability of the load/store buffers. + /// + /// Returns LSU_AVAILABLE if there are enough load/store queue entries to + /// accomodate instruction IR. By default, LSU_AVAILABLE is returned if IR is + /// not a memory operation. + virtual Status isAvailable(const InstRef &IR) const = 0; + + /// Allocates LS resources for instruction IR. + /// + /// This method assumes that a previous call to `isAvailable(IR)` succeeded + /// with a LSUnitBase::Status value of LSU_AVAILABLE. + /// Returns the GroupID associated with this instruction. That value will be + /// used to set the LSUTokenID field in class Instruction. + virtual unsigned dispatch(const InstRef &IR) = 0; + + bool isSQEmpty() const { return !UsedSQEntries; } + bool isLQEmpty() const { return !UsedLQEntries; } + bool isSQFull() const { return SQSize && SQSize == UsedSQEntries; } + bool isLQFull() const { return LQSize && LQSize == UsedLQEntries; } + + bool isValidGroupID(unsigned Index) const { + return Index && (Groups.find(Index) != Groups.end()); + } + + /// Check if a peviously dispatched instruction IR is now ready for execution. + bool isReady(const InstRef &IR) const { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + const MemoryGroup &Group = getGroup(GroupID); + return Group.isReady(); + } + + /// Check if instruction IR only depends on memory instructions that are + /// currently executing. + bool isPending(const InstRef &IR) const { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + const MemoryGroup &Group = getGroup(GroupID); + return Group.isPending(); + } + + /// Check if instruction IR is still waiting on memory operations, and the + /// wait time is still unknown. + bool isWaiting(const InstRef &IR) const { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + const MemoryGroup &Group = getGroup(GroupID); + return Group.isWaiting(); + } + + bool hasDependentUsers(const InstRef &IR) const { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + const MemoryGroup &Group = getGroup(GroupID); + return !Group.isExecuted() && Group.getNumSuccessors(); + } + + const MemoryGroup &getGroup(unsigned Index) const { + assert(isValidGroupID(Index) && "Group doesn't exist!"); + return *Groups.find(Index)->second; + } + + MemoryGroup &getGroup(unsigned Index) { + assert(isValidGroupID(Index) && "Group doesn't exist!"); + return *Groups.find(Index)->second; + } + + unsigned createMemoryGroup() { + Groups.insert( + std::make_pair(NextGroupID, llvm::make_unique<MemoryGroup>())); + return NextGroupID++; + } + + // Instruction executed event handlers. + virtual void onInstructionExecuted(const InstRef &IR); + + virtual void onInstructionIssued(const InstRef &IR) { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + Groups[GroupID]->onInstructionIssued(IR); + } + + virtual void cycleEvent(); + +#ifndef NDEBUG + void dump() const; +#endif +}; + +/// Default Load/Store Unit (LS Unit) for simulated processors. +/// +/// Each load (or store) consumes one entry in the load (or store) queue. /// /// Rules are: /// 1) A younger load is allowed to pass an older load only if there are no @@ -89,26 +365,7 @@ class Scheduler; /// A load/store barrier is "executed" when it becomes the oldest entry in /// the load/store queue(s). That also means, all the older loads/stores have /// already been executed. -class LSUnit : public HardwareUnit { - // Load queue size. - // LQ_Size == 0 means that there are infinite slots in the load queue. - unsigned LQ_Size; - - // Store queue size. - // SQ_Size == 0 means that there are infinite slots in the store queue. - unsigned SQ_Size; - - // If true, loads will never alias with stores. This is the default. - bool NoAlias; - - // When a `MayLoad` instruction is dispatched to the schedulers for execution, - // the LSUnit reserves an entry in the `LoadQueue` for it. - // - // LoadQueue keeps track of all the loads that are in-flight. A load - // instruction is eventually removed from the LoadQueue when it reaches - // completion stage. That means, a load leaves the queue whe it is 'executed', - // and its value can be forwarded on the data path to outside units. - // +class LSUnit : public LSUnitBase { // This class doesn't know about the latency of a load instruction. So, it // conservatively/pessimistically assumes that the latency of a load opcode // matches the instruction latency. @@ -139,66 +396,50 @@ class LSUnit : public HardwareUnit { // alternative approaches that let instructions specify the number of // load/store queue entries which they consume at dispatch stage (See // PR39830). - SmallSet<unsigned, 16> LoadQueue; - SmallSet<unsigned, 16> StoreQueue; - - void assignLQSlot(unsigned Index); - void assignSQSlot(unsigned Index); - bool isReadyNoAlias(unsigned Index) const; - + // // An instruction that both 'mayStore' and 'HasUnmodeledSideEffects' is // conservatively treated as a store barrier. It forces older store to be // executed before newer stores are issued. - SmallSet<unsigned, 8> StoreBarriers; - + // // An instruction that both 'MayLoad' and 'HasUnmodeledSideEffects' is // conservatively treated as a load barrier. It forces older loads to execute // before newer loads are issued. - SmallSet<unsigned, 8> LoadBarriers; - - bool isSQEmpty() const { return StoreQueue.empty(); } - bool isLQEmpty() const { return LoadQueue.empty(); } - bool isSQFull() const { return SQ_Size != 0 && StoreQueue.size() == SQ_Size; } - bool isLQFull() const { return LQ_Size != 0 && LoadQueue.size() == LQ_Size; } + unsigned CurrentLoadGroupID; + unsigned CurrentLoadBarrierGroupID; + unsigned CurrentStoreGroupID; public: - LSUnit(const MCSchedModel &SM, unsigned LQ = 0, unsigned SQ = 0, - bool AssumeNoAlias = false); + LSUnit(const MCSchedModel &SM) + : LSUnit(SM, /* LQSize */ 0, /* SQSize */ 0, /* NoAlias */ false) {} + LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ) + : LSUnit(SM, LQ, SQ, /* NoAlias */ false) {} + LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ, bool AssumeNoAlias) + : LSUnitBase(SM, LQ, SQ, AssumeNoAlias), CurrentLoadGroupID(0), + CurrentLoadBarrierGroupID(0), CurrentStoreGroupID(0) {} -#ifndef NDEBUG - void dump() const; -#endif + /// Returns LSU_AVAILABLE if there are enough load/store queue entries to + /// accomodate instruction IR. + Status isAvailable(const InstRef &IR) const override; - enum Status { LSU_AVAILABLE = 0, LSU_LQUEUE_FULL, LSU_SQUEUE_FULL }; + /// Allocates LS resources for instruction IR. + /// + /// This method assumes that a previous call to `isAvailable(IR)` succeeded + /// returning LSU_AVAILABLE. + /// + /// Rules are: + /// By default, rules are: + /// 1. A store may not pass a previous store. + /// 2. A load may not pass a previous store unless flag 'NoAlias' is set. + /// 3. A load may pass a previous load. + /// 4. A store may not pass a previous load (regardless of flag 'NoAlias'). + /// 5. A load has to wait until an older load barrier is fully executed. + /// 6. A store has to wait until an older store barrier is fully executed. + unsigned dispatch(const InstRef &IR) override; - // Returns LSU_AVAILABLE if there are enough load/store queue entries to serve - // IR. It also returns LSU_AVAILABLE if IR is not a memory operation. - Status isAvailable(const InstRef &IR) const; - - // Allocates load/store queue resources for IR. - // - // This method assumes that a previous call to `isAvailable(IR)` returned - // LSU_AVAILABLE, and that IR is a memory operation. - void dispatch(const InstRef &IR); - - // By default, rules are: - // 1. A store may not pass a previous store. - // 2. A load may not pass a previous store unless flag 'NoAlias' is set. - // 3. A load may pass a previous load. - // 4. A store may not pass a previous load (regardless of flag 'NoAlias'). - // 5. A load has to wait until an older load barrier is fully executed. - // 6. A store has to wait until an older store barrier is fully executed. - virtual bool isReady(const InstRef &IR) const; - - // Load and store instructions are tracked by their corresponding queues from - // dispatch until the "instruction executed" event. - // Only when a load instruction reaches the 'Executed' stage, its value - // becomes available to the users. At that point, the load no longer needs to - // be tracked by the load queue. // FIXME: For simplicity, we optimistically assume a similar behavior for // store instructions. In practice, store operations don't tend to leave the // store queue until they reach the 'Retired' stage (See PR39830). - void onInstructionExecuted(const InstRef &IR); + void onInstructionExecuted(const InstRef &IR) override; }; } // namespace mca diff --git a/include/llvm/MCA/HardwareUnits/RegisterFile.h b/include/llvm/MCA/HardwareUnits/RegisterFile.h index c23ab0389234..36506327bd29 100644 --- a/include/llvm/MCA/HardwareUnits/RegisterFile.h +++ b/include/llvm/MCA/HardwareUnits/RegisterFile.h @@ -1,9 +1,8 @@ //===--------------------- RegisterFile.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -21,6 +20,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSchedule.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MCA/HardwareUnits/HardwareUnit.h" #include "llvm/Support/Error.h" @@ -196,7 +196,7 @@ public: // Collect writes that are in a data dependency with RS, and update RS // internal state. - void addRegisterRead(ReadState &RS, SmallVectorImpl<WriteRef> &Writes) const; + void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const; // Removes write \param WS from the register mappings. // Physical registers may be released to reflect this update. diff --git a/include/llvm/MCA/HardwareUnits/ResourceManager.h b/include/llvm/MCA/HardwareUnits/ResourceManager.h index 549a46c247fe..2f91185516fb 100644 --- a/include/llvm/MCA/HardwareUnits/ResourceManager.h +++ b/include/llvm/MCA/HardwareUnits/ResourceManager.h @@ -1,9 +1,8 @@ //===--------------------- ResourceManager.h --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -335,13 +334,26 @@ class ResourceManager { // Used to quickly identify groups that own a particular resource unit. std::vector<uint64_t> Resource2Groups; - // A table to map processor resource IDs to processor resource masks. + // A table that maps processor resource IDs to processor resource masks. SmallVector<uint64_t, 8> ProcResID2Mask; + // A table that maps resource indices to actual processor resource IDs in the + // scheduling model. + SmallVector<unsigned, 8> ResIndex2ProcResID; + // Keeps track of which resources are busy, and how many cycles are left // before those become usable again. SmallDenseMap<ResourceRef, unsigned> BusyResources; + // Set of processor resource units available on the target. + uint64_t ProcResUnitMask; + + // Set of processor resource units that are available during this cycle. + uint64_t AvailableProcResUnits; + + // Set of processor resource groups that are currently reserved. + uint64_t ReservedResourceGroups; + // Returns the actual resource unit that will be used. ResourceRef selectPipe(uint64_t ResourceID); @@ -389,7 +401,14 @@ public: // Release a previously reserved processor resource. void releaseResource(uint64_t ResourceID); - bool canBeIssued(const InstrDesc &Desc) const; + // Returns a zero mask if resources requested by Desc are all available during + // this cycle. It returns a non-zero mask value only if there are unavailable + // processor resources; each bit set in the mask represents a busy processor + // resource unit or a reserved processor resource group. + uint64_t checkAvailability(const InstrDesc &Desc) const; + + uint64_t getProcResUnitMask() const { return ProcResUnitMask; } + uint64_t getAvailableProcResUnits() const { return AvailableProcResUnits; } void issueInstruction( const InstrDesc &Desc, diff --git a/include/llvm/MCA/HardwareUnits/RetireControlUnit.h b/include/llvm/MCA/HardwareUnits/RetireControlUnit.h index 71360e984ade..06290141739e 100644 --- a/include/llvm/MCA/HardwareUnits/RetireControlUnit.h +++ b/include/llvm/MCA/HardwareUnits/RetireControlUnit.h @@ -1,9 +1,8 @@ //===---------------------- RetireControlUnit.h -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/HardwareUnits/Scheduler.h b/include/llvm/MCA/HardwareUnits/Scheduler.h index 351ea4827df9..27beb842dfd2 100644 --- a/include/llvm/MCA/HardwareUnits/Scheduler.h +++ b/include/llvm/MCA/HardwareUnits/Scheduler.h @@ -1,9 +1,8 @@ //===--------------------- Scheduler.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -68,22 +67,6 @@ public: /// resources. This class is also responsible for tracking the progress of /// instructions from the dispatch stage, until the write-back stage. /// -/// An instruction dispatched to the Scheduler is initially placed into either -/// the 'WaitSet' or the 'ReadySet' depending on the availability of the input -/// operands. -/// -/// An instruction is moved from the WaitSet to the ReadySet when register -/// operands become available, and all memory dependencies are met. -/// Instructions that are moved from the WaitSet to the ReadySet transition -/// in state from 'IS_AVAILABLE' to 'IS_READY'. -/// -/// On every cycle, the Scheduler checks if it can promote instructions from the -/// WaitSet to the ReadySet. -/// -/// An Instruction is moved from the ReadySet the `IssuedSet` when it is issued -/// to a (one or more) pipeline(s). This event also causes an instruction state -/// transition (i.e. from state IS_READY, to state IS_EXECUTING). An Instruction -/// leaves the IssuedSet when it reaches the write-back stage. class Scheduler : public HardwareUnit { LSUnit &LSU; @@ -93,10 +76,58 @@ class Scheduler : public HardwareUnit { // Hardware resources that are managed by this scheduler. std::unique_ptr<ResourceManager> Resources; + // Instructions dispatched to the Scheduler are internally classified based on + // the instruction stage (see Instruction::InstrStage). + // + // An Instruction dispatched to the Scheduler is added to the WaitSet if not + // all its register operands are available, and at least one latency is + // unknown. By construction, the WaitSet only contains instructions that are + // in the IS_DISPATCHED stage. + // + // An Instruction transitions from the WaitSet to the PendingSet if the + // instruction is not ready yet, but the latency of every register read is + // known. Instructions in the PendingSet can only be in the IS_PENDING or + // IS_READY stage. Only IS_READY instructions that are waiting on memory + // dependencies can be added to the PendingSet. + // + // Instructions in the PendingSet are immediately dominated only by + // instructions that have already been issued to the underlying pipelines. In + // the presence of bottlenecks caused by data dependencies, the PendingSet can + // be inspected to identify problematic data dependencies between + // instructions. + // + // An instruction is moved to the ReadySet when all register operands become + // available, and all memory dependencies are met. Instructions that are + // moved from the PendingSet to the ReadySet must transition to the 'IS_READY' + // stage. + // + // On every cycle, the Scheduler checks if it can promote instructions from the + // PendingSet to the ReadySet. + // + // An Instruction is moved from the ReadySet to the `IssuedSet` when it starts + // exection. This event also causes an instruction state transition (i.e. from + // state IS_READY, to state IS_EXECUTING). An Instruction leaves the IssuedSet + // only when it reaches the write-back stage. std::vector<InstRef> WaitSet; + std::vector<InstRef> PendingSet; std::vector<InstRef> ReadySet; std::vector<InstRef> IssuedSet; + // A mask of busy resource units. It defaults to the empty set (i.e. a zero + // mask), and it is cleared at the beginning of every cycle. + // It is updated every time the scheduler fails to issue an instruction from + // the ready set due to unavailable pipeline resources. + // Each bit of the mask represents an unavailable resource. + uint64_t BusyResourceUnits; + + // Counts the number of instructions in the pending set that were dispatched + // during this cycle. + unsigned NumDispatchedToThePendingSet; + + // True if the previous pipeline Stage was unable to dispatch a full group of + // opcodes because scheduler buffers (or LS queues) were unavailable. + bool HadTokenStall; + /// Verify the given selection strategy and set the Strategy member /// accordingly. If no strategy is provided, the DefaultSchedulerStrategy is /// used. @@ -112,9 +143,15 @@ class Scheduler : public HardwareUnit { // vector 'Executed'. void updateIssuedSet(SmallVectorImpl<InstRef> &Executed); - // Try to promote instructions from WaitSet to ReadySet. + // Try to promote instructions from the PendingSet to the ReadySet. // Add promoted instructions to the 'Ready' vector in input. - void promoteToReadySet(SmallVectorImpl<InstRef> &Ready); + // Returns true if at least one instruction was promoted. + bool promoteToReadySet(SmallVectorImpl<InstRef> &Ready); + + // Try to promote instructions from the WaitSet to the PendingSet. + // Add promoted instructions to the 'Pending' vector in input. + // Returns true if at least one instruction was promoted. + bool promoteToPendingSet(SmallVectorImpl<InstRef> &Pending); public: Scheduler(const MCSchedModel &Model, LSUnit &Lsu) @@ -127,7 +164,8 @@ public: Scheduler(std::unique_ptr<ResourceManager> RM, LSUnit &Lsu, std::unique_ptr<SchedulerStrategy> SelectStrategy) - : LSU(Lsu), Resources(std::move(RM)) { + : LSU(Lsu), Resources(std::move(RM)), BusyResourceUnits(0), + NumDispatchedToThePendingSet(0), HadTokenStall(false) { initializeStrategy(std::move(SelectStrategy)); } @@ -140,15 +178,12 @@ public: SC_DISPATCH_GROUP_STALL, }; - /// Check if the instruction in 'IR' can be dispatched and returns an answer - /// in the form of a Status value. + /// Check if the instruction in 'IR' can be dispatched during this cycle. + /// Return SC_AVAILABLE if both scheduler and LS resources are available. /// - /// The DispatchStage is responsible for querying the Scheduler before - /// dispatching new instructions. This routine is used for performing such - /// a query. If the instruction 'IR' can be dispatched, then true is - /// returned, otherwise false is returned with Event set to the stall type. - /// Internally, it also checks if the load/store unit is available. - Status isAvailable(const InstRef &IR) const; + /// This method is also responsible for setting field HadTokenStall if + /// IR cannot be dispatched to the Scheduler due to unavailable resources. + Status isAvailable(const InstRef &IR); /// Reserves buffer and LSUnit queue resources that are necessary to issue /// this instruction. @@ -156,11 +191,11 @@ public: /// Returns true if instruction IR is ready to be issued to the underlying /// pipelines. Note that this operation cannot fail; it assumes that a /// previous call to method `isAvailable(IR)` returned `SC_AVAILABLE`. - void dispatch(const InstRef &IR); - - /// Returns true if IR is ready to be executed by the underlying pipelines. - /// This method assumes that IR has been previously dispatched. - bool isReady(const InstRef &IR) const; + /// + /// If IR is a memory operation, then the Scheduler queries the LS unit to + /// obtain a LS token. An LS token is used internally to track memory + /// dependencies. + bool dispatch(InstRef &IR); /// Issue an instruction and populates a vector of used pipeline resources, /// and a vector of instructions that transitioned to the ready state as a @@ -168,6 +203,7 @@ public: void issueInstruction( InstRef &IR, SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Used, + SmallVectorImpl<InstRef> &Pending, SmallVectorImpl<InstRef> &Ready); /// Returns true if IR has to be issued immediately, or if IR is a zero @@ -181,9 +217,15 @@ public: /// have changed in state, and that are now available to new instructions. /// Instructions executed are added to vector Executed, while vector Ready is /// populated with instructions that have become ready in this new cycle. + /// Vector Pending is popluated by instructions that have transitioned through + /// the pending stat during this cycle. The Pending and Ready sets may not be + /// disjoint. An instruction is allowed to transition from the WAIT state to + /// the READY state (going through the PENDING state) within a single cycle. + /// That means, instructions may appear in both the Pending and Ready set. void cycleEvent(SmallVectorImpl<ResourceRef> &Freed, - SmallVectorImpl<InstRef> &Ready, - SmallVectorImpl<InstRef> &Executed); + SmallVectorImpl<InstRef> &Executed, + SmallVectorImpl<InstRef> &Pending, + SmallVectorImpl<InstRef> &Ready); /// Convert a resource mask into a valid llvm processor resource identifier. unsigned getResourceID(uint64_t Mask) const { @@ -195,6 +237,26 @@ public: /// resources are not available. InstRef select(); + bool isReadySetEmpty() const { return ReadySet.empty(); } + bool isWaitSetEmpty() const { return WaitSet.empty(); } + + /// This method is called by the ExecuteStage at the end of each cycle to + /// identify bottlenecks caused by data dependencies. Vector RegDeps is + /// populated by instructions that were not issued because of unsolved + /// register dependencies. Vector MemDeps is populated by instructions that + /// were not issued because of unsolved memory dependencies. + void analyzeDataDependencies(SmallVectorImpl<InstRef> &RegDeps, + SmallVectorImpl<InstRef> &MemDeps); + + /// Returns a mask of busy resources, and populates vector Insts with + /// instructions that could not be issued to the underlying pipelines because + /// not all pipeline resources were available. + uint64_t analyzeResourcePressure(SmallVectorImpl<InstRef> &Insts); + + // Returns true if the dispatch logic couldn't dispatch a full group due to + // unavailable scheduler and/or LS resources. + bool hadTokenStall() const { return HadTokenStall; } + #ifndef NDEBUG // Update the ready queues. void dump() const; diff --git a/include/llvm/MCA/InstrBuilder.h b/include/llvm/MCA/InstrBuilder.h index 5f998db5e4ce..690016354f7a 100644 --- a/include/llvm/MCA/InstrBuilder.h +++ b/include/llvm/MCA/InstrBuilder.h @@ -1,9 +1,8 @@ //===--------------------- InstrBuilder.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Instruction.h b/include/llvm/MCA/Instruction.h index b91610c64d85..d4d3f22797f7 100644 --- a/include/llvm/MCA/Instruction.h +++ b/include/llvm/MCA/Instruction.h @@ -1,9 +1,8 @@ //===--------------------- Instruction.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -81,6 +80,15 @@ struct ReadDescriptor { class ReadState; +/// A critical data dependency descriptor. +/// +/// Field RegID is set to the invalid register for memory dependencies. +struct CriticalDependency { + unsigned IID; + unsigned RegID; + unsigned Cycles; +}; + /// Tracks uses of a register definition (e.g. register write). /// /// Each implicit/explicit register write is associated with an instance of @@ -124,9 +132,11 @@ class WriteState { // A partial write that is in a false dependency with this write. WriteState *PartialWrite; - unsigned DependentWriteCyclesLeft; + // Critical register dependency for this write. + CriticalDependency CRD; + // A list of dependent reads. Users is a set of dependent // reads. A dependent read is added to the set only if CyclesLeft // is "unknown". As soon as CyclesLeft is 'known', each user in the set @@ -141,7 +151,7 @@ public: : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), - DependentWriteCyclesLeft(0) {} + DependentWriteCyclesLeft(0), CRD() {} WriteState(const WriteState &Other) = default; WriteState &operator=(const WriteState &Other) = default; @@ -151,13 +161,21 @@ public: unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } unsigned getLatency() const { return WD->Latency; } - - void addUser(ReadState *Use, int ReadAdvance); - void addUser(WriteState *Use); - unsigned getDependentWriteCyclesLeft() const { return DependentWriteCyclesLeft; } + const WriteState *getDependentWrite() const { return DependentWrite; } + const CriticalDependency &getCriticalRegDep() const { return CRD; } + + // This method adds Use to the set of data dependent reads. IID is the + // instruction identifier associated with this write. ReadAdvance is the + // number of cycles to subtract from the latency of this data dependency. + // Use is in a RAW dependency with this write. + void addUser(unsigned IID, ReadState *Use, int ReadAdvance); + + // Use is a younger register write that is in a false dependency with this + // write. IID is the instruction identifier associated with this write. + void addUser(unsigned IID, WriteState *Use); unsigned getNumUsers() const { unsigned NumUsers = Users.size(); @@ -169,17 +187,20 @@ public: bool clearsSuperRegisters() const { return ClearsSuperRegs; } bool isWriteZero() const { return WritesZero; } bool isEliminated() const { return IsEliminated; } - bool isExecuted() const { - return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0; + + bool isReady() const { + if (DependentWrite) + return false; + unsigned CyclesLeft = getDependentWriteCyclesLeft(); + return !CyclesLeft || CyclesLeft < getLatency(); } - const WriteState *getDependentWrite() const { return DependentWrite; } - void setDependentWrite(WriteState *Other) { DependentWrite = Other; } - void writeStartEvent(unsigned Cycles) { - DependentWriteCyclesLeft = Cycles; - DependentWrite = nullptr; + bool isExecuted() const { + return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0; } + void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } + void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles); void setWriteZero() { WritesZero = true; } void setEliminated() { assert(Users.empty() && "Write is in an inconsistent state."); @@ -191,7 +212,7 @@ public: // On every cycle, update CyclesLeft and notify dependent users. void cycleEvent(); - void onInstructionIssued(); + void onInstructionIssued(unsigned IID); #ifndef NDEBUG void dump() const; @@ -221,6 +242,8 @@ class ReadState { // dependent writes (i.e. field DependentWrite) is zero, this value is // propagated to field CyclesLeft. unsigned TotalCycles; + // Longest register dependency. + CriticalDependency CRD; // This field is set to true only if there are no dependent writes, and // there are no `CyclesLeft' to wait. bool IsReady; @@ -232,14 +255,16 @@ class ReadState { public: ReadState(const ReadDescriptor &Desc, unsigned RegID) : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), - CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true), + CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true), IsZero(false), IndependentFromDef(false) {} const ReadDescriptor &getDescriptor() const { return *RD; } unsigned getSchedClass() const { return RD->SchedClassID; } unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } + const CriticalDependency &getCriticalRegDep() const { return CRD; } + bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } bool isReady() const { return IsReady; } bool isImplicitRead() const { return RD->isImplicitRead(); } @@ -247,7 +272,7 @@ public: void setIndependentFromDef() { IndependentFromDef = true; } void cycleEvent(); - void writeStartEvent(unsigned Cycles); + void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles); void setDependentWrites(unsigned Writes) { DependentWrites = Writes; IsReady = !Writes; @@ -330,9 +355,16 @@ struct InstrDesc { // A list of buffered resources consumed by this instruction. SmallVector<uint64_t, 4> Buffers; + unsigned UsedProcResUnits; + unsigned UsedProcResGroups; + unsigned MaxLatency; // Number of MicroOps for this instruction. unsigned NumMicroOps; + // SchedClassID used to construct this InstrDesc. + // This information is currently used by views to do fast queries on the + // subtarget when computing the reciprocal throughput. + unsigned SchedClassID; bool MayLoad; bool MayStore; @@ -398,6 +430,7 @@ public: // Returns true if this instruction is a candidate for move elimination. bool isOptimizableMove() const { return IsOptimizableMove; } void setOptimizableMove() { IsOptimizableMove = true; } + bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; } }; /// An instruction propagated through the simulated instruction pipeline. @@ -406,12 +439,13 @@ public: /// that are sent to the various components of the simulated hardware pipeline. class Instruction : public InstructionBase { enum InstrStage { - IS_INVALID, // Instruction in an invalid state. - IS_AVAILABLE, // Instruction dispatched but operands are not ready. - IS_READY, // Instruction dispatched and operands ready. - IS_EXECUTING, // Instruction issued. - IS_EXECUTED, // Instruction executed. Values are written back. - IS_RETIRED // Instruction retired. + IS_INVALID, // Instruction in an invalid state. + IS_DISPATCHED, // Instruction dispatched but operands are not ready. + IS_PENDING, // Instruction is not ready, but operand latency is known. + IS_READY, // Instruction dispatched and operands ready. + IS_EXECUTING, // Instruction issued. + IS_EXECUTED, // Instruction executed. Values are written back. + IS_RETIRED // Instruction retired. }; // The current instruction stage. @@ -424,12 +458,34 @@ class Instruction : public InstructionBase { // Retire Unit token ID for this instruction. unsigned RCUTokenID; + // LS token ID for this instruction. + // This field is set to the invalid null token if this is not a memory + // operation. + unsigned LSUTokenID; + + // Critical register dependency. + CriticalDependency CriticalRegDep; + + // Critical memory dependency. + CriticalDependency CriticalMemDep; + + // A bitmask of busy processor resource units. + // This field is set to zero only if execution is not delayed during this + // cycle because of unavailable pipeline resources. + uint64_t CriticalResourceMask; + + // True if this instruction has been optimized at register renaming stage. + bool IsEliminated; + public: Instruction(const InstrDesc &D) : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), - RCUTokenID(0) {} + RCUTokenID(0), LSUTokenID(0), CriticalRegDep(), CriticalMemDep(), + CriticalResourceMask(0), IsEliminated(false) {} unsigned getRCUTokenID() const { return RCUTokenID; } + unsigned getLSUTokenID() const { return LSUTokenID; } + void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; } int getCyclesLeft() const { return CyclesLeft; } // Transition to the dispatch stage, and assign a RCUToken to this @@ -438,37 +494,48 @@ public: void dispatch(unsigned RCUTokenID); // Instruction issued. Transition to the IS_EXECUTING state, and update - // all the definitions. - void execute(); - - // Force a transition from the IS_AVAILABLE state to the IS_READY state if - // input operands are all ready. State transitions normally occur at the - // beginning of a new cycle (see method cycleEvent()). However, the scheduler - // may decide to promote instructions from the wait queue to the ready queue - // as the result of another issue event. This method is called every time the - // instruction might have changed in state. + // all the register definitions. + void execute(unsigned IID); + + // Force a transition from the IS_DISPATCHED state to the IS_READY or + // IS_PENDING state. State transitions normally occur either at the beginning + // of a new cycle (see method cycleEvent()), or as a result of another issue + // event. This method is called every time the instruction might have changed + // in state. It internally delegates to method updateDispatched() and + // updateWaiting(). void update(); + bool updateDispatched(); + bool updatePending(); - bool isDispatched() const { return Stage == IS_AVAILABLE; } + bool isDispatched() const { return Stage == IS_DISPATCHED; } + bool isPending() const { return Stage == IS_PENDING; } bool isReady() const { return Stage == IS_READY; } bool isExecuting() const { return Stage == IS_EXECUTING; } bool isExecuted() const { return Stage == IS_EXECUTED; } bool isRetired() const { return Stage == IS_RETIRED; } + bool isEliminated() const { return IsEliminated; } - bool isEliminated() const { - return isReady() && getDefs().size() && - all_of(getDefs(), - [](const WriteState &W) { return W.isEliminated(); }); - } - - // Forces a transition from state IS_AVAILABLE to state IS_EXECUTED. + // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED. void forceExecuted(); + void setEliminated() { IsEliminated = true; } void retire() { assert(isExecuted() && "Instruction is in an invalid state!"); Stage = IS_RETIRED; } + const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; } + const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; } + const CriticalDependency &computeCriticalRegDep(); + void setCriticalMemDep(const CriticalDependency &MemDep) { + CriticalMemDep = MemDep; + } + + uint64_t getCriticalResourceMask() const { return CriticalResourceMask; } + void setCriticalResourceMask(uint64_t ResourceMask) { + CriticalResourceMask = ResourceMask; + } + void cycleEvent(); }; @@ -483,13 +550,17 @@ public: InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {} bool operator==(const InstRef &Other) const { return Data == Other.Data; } + bool operator!=(const InstRef &Other) const { return Data != Other.Data; } + bool operator<(const InstRef &Other) const { + return Data.first < Other.Data.first; + } unsigned getSourceIndex() const { return Data.first; } Instruction *getInstruction() { return Data.second; } const Instruction *getInstruction() const { return Data.second; } /// Returns true if this references a valid instruction. - operator bool() const { return Data.second != nullptr; } + explicit operator bool() const { return Data.second != nullptr; } /// Invalidate this reference. void invalidate() { Data.second = nullptr; } @@ -537,7 +608,7 @@ public: return !WS || WS->isExecuted(); } - bool isValid() const { return Data.first != INVALID_IID && Data.second; } + bool isValid() const { return Data.second && Data.first != INVALID_IID; } bool operator==(const WriteRef &Other) const { return Data == Other.Data; } #ifndef NDEBUG diff --git a/include/llvm/MCA/Pipeline.h b/include/llvm/MCA/Pipeline.h index acd256060bdd..935033f67f8b 100644 --- a/include/llvm/MCA/Pipeline.h +++ b/include/llvm/MCA/Pipeline.h @@ -1,9 +1,8 @@ //===--------------------- Pipeline.h ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/SourceMgr.h b/include/llvm/MCA/SourceMgr.h index 5e0ca6419f5d..dbe31db1b1dd 100644 --- a/include/llvm/MCA/SourceMgr.h +++ b/include/llvm/MCA/SourceMgr.h @@ -1,9 +1,8 @@ //===--------------------- SourceMgr.h --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Stages/DispatchStage.h b/include/llvm/MCA/Stages/DispatchStage.h index f015cd7522eb..d80ededeaca1 100644 --- a/include/llvm/MCA/Stages/DispatchStage.h +++ b/include/llvm/MCA/Stages/DispatchStage.h @@ -1,9 +1,8 @@ //===----------------------- DispatchStage.h --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -62,8 +61,6 @@ class DispatchStage final : public Stage { bool canDispatch(const InstRef &IR) const; Error dispatch(InstRef IR); - void updateRAWDependencies(ReadState &RS, const MCSubtargetInfo &STI); - void notifyInstructionDispatched(const InstRef &IR, ArrayRef<unsigned> UsedPhysRegs, unsigned uOps) const; @@ -71,9 +68,7 @@ class DispatchStage final : public Stage { public: DispatchStage(const MCSubtargetInfo &Subtarget, const MCRegisterInfo &MRI, unsigned MaxDispatchWidth, RetireControlUnit &R, - RegisterFile &F) - : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth), - CarryOver(0U), CarriedOver(), STI(Subtarget), RCU(R), PRF(F) {} + RegisterFile &F); bool isAvailable(const InstRef &IR) const override; diff --git a/include/llvm/MCA/Stages/EntryStage.h b/include/llvm/MCA/Stages/EntryStage.h index cd9a65b8cc2b..59a2daff886e 100644 --- a/include/llvm/MCA/Stages/EntryStage.h +++ b/include/llvm/MCA/Stages/EntryStage.h @@ -1,9 +1,8 @@ //===---------------------- EntryStage.h ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Stages/ExecuteStage.h b/include/llvm/MCA/Stages/ExecuteStage.h index 8cb287e06d9f..03737e0220eb 100644 --- a/include/llvm/MCA/Stages/ExecuteStage.h +++ b/include/llvm/MCA/Stages/ExecuteStage.h @@ -1,9 +1,8 @@ //===---------------------- ExecuteStage.h ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -29,6 +28,12 @@ namespace mca { class ExecuteStage final : public Stage { Scheduler &HWS; + unsigned NumDispatchedOpcodes; + unsigned NumIssuedOpcodes; + + // True if this stage should notify listeners of HWPressureEvents. + bool EnablePressureEvents; + Error issueInstruction(InstRef &IR); // Called at the beginning of each cycle to issue already dispatched @@ -42,7 +47,10 @@ class ExecuteStage final : public Stage { ExecuteStage &operator=(const ExecuteStage &Other) = delete; public: - ExecuteStage(Scheduler &S) : Stage(), HWS(S) {} + ExecuteStage(Scheduler &S) : ExecuteStage(S, false) {} + ExecuteStage(Scheduler &S, bool ShouldPerformBottleneckAnalysis) + : Stage(), HWS(S), NumDispatchedOpcodes(0), NumIssuedOpcodes(0), + EnablePressureEvents(ShouldPerformBottleneckAnalysis) {} // This stage works under the assumption that the Pipeline will eventually // execute a retire stage. We don't need to check if pipelines and/or @@ -61,12 +69,14 @@ public: // Instructions that transitioned to the 'Executed' state are automatically // moved to the next stage (i.e. RetireStage). Error cycleStart() override; + Error cycleEnd() override; Error execute(InstRef &IR) override; void notifyInstructionIssued( const InstRef &IR, MutableArrayRef<std::pair<ResourceRef, ResourceCycles>> Used) const; void notifyInstructionExecuted(const InstRef &IR) const; + void notifyInstructionPending(const InstRef &IR) const; void notifyInstructionReady(const InstRef &IR) const; void notifyResourceAvailable(const ResourceRef &RR) const; diff --git a/include/llvm/MCA/Stages/InstructionTables.h b/include/llvm/MCA/Stages/InstructionTables.h index 34e338f0ce6b..4b463c9b51c1 100644 --- a/include/llvm/MCA/Stages/InstructionTables.h +++ b/include/llvm/MCA/Stages/InstructionTables.h @@ -1,9 +1,8 @@ //===--------------------- InstructionTables.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Stages/MicroOpQueueStage.h b/include/llvm/MCA/Stages/MicroOpQueueStage.h new file mode 100644 index 000000000000..50a5ef87b2d2 --- /dev/null +++ b/include/llvm/MCA/Stages/MicroOpQueueStage.h @@ -0,0 +1,88 @@ +//===---------------------- MicroOpQueueStage.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 a stage that implements a queue of micro opcodes. +/// It can be used to simulate a hardware micro-op queue that serves opcodes to +/// the out of order backend. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MCA_MICRO_OP_QUEUE_STAGE_H +#define LLVM_MCA_MICRO_OP_QUEUE_STAGE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/MCA/Stages/Stage.h" + +namespace llvm { +namespace mca { + +/// A stage that simulates a queue of instruction opcodes. +class MicroOpQueueStage : public Stage { + SmallVector<InstRef, 8> Buffer; + unsigned NextAvailableSlotIdx; + unsigned CurrentInstructionSlotIdx; + + // Limits the number of instructions that can be written to this buffer every + // cycle. A value of zero means that there is no limit to the instruction + // throughput in input. + const unsigned MaxIPC; + unsigned CurrentIPC; + + // Number of entries that are available during this cycle. + unsigned AvailableEntries; + + // True if instructions dispatched to this stage don't need to wait for the + // next cycle before moving to the next stage. + // False if this buffer acts as a one cycle delay in the execution pipeline. + bool IsZeroLatencyStage; + + MicroOpQueueStage(const MicroOpQueueStage &Other) = delete; + MicroOpQueueStage &operator=(const MicroOpQueueStage &Other) = delete; + + // By default, an instruction consumes a number of buffer entries equal to its + // number of micro opcodes (see field `InstrDesc::NumMicroOpcodes`). The + // number of entries consumed by an instruction is normalized to the + // minimum value between NumMicroOpcodes and the buffer size. This is to avoid + // problems with (microcoded) instructions that generate a number of micro + // opcodes than doesn't fit in the buffer. + unsigned getNormalizedOpcodes(const InstRef &IR) const { + unsigned NormalizedOpcodes = + std::min(static_cast<unsigned>(Buffer.size()), + IR.getInstruction()->getDesc().NumMicroOps); + return NormalizedOpcodes ? NormalizedOpcodes : 1U; + } + + Error moveInstructions(); + +public: + MicroOpQueueStage(unsigned Size, unsigned IPC = 0, + bool ZeroLatencyStage = true); + + bool isAvailable(const InstRef &IR) const override { + if (MaxIPC && CurrentIPC == MaxIPC) + return false; + unsigned NormalizedOpcodes = getNormalizedOpcodes(IR); + if (NormalizedOpcodes > AvailableEntries) + return false; + return true; + } + + bool hasWorkToComplete() const override { + return AvailableEntries != Buffer.size(); + } + + Error execute(InstRef &IR) override; + Error cycleStart() override; + Error cycleEnd() override; +}; + +} // namespace mca +} // namespace llvm + +#endif // LLVM_MCA_MICRO_OP_QUEUE_STAGE_H diff --git a/include/llvm/MCA/Stages/RetireStage.h b/include/llvm/MCA/Stages/RetireStage.h index 2051ce5c86ad..08c216ac7bf4 100644 --- a/include/llvm/MCA/Stages/RetireStage.h +++ b/include/llvm/MCA/Stages/RetireStage.h @@ -1,9 +1,8 @@ //===---------------------- RetireStage.h -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Stages/Stage.h b/include/llvm/MCA/Stages/Stage.h index fc7ab569bb0f..46b242caa6cf 100644 --- a/include/llvm/MCA/Stages/Stage.h +++ b/include/llvm/MCA/Stages/Stage.h @@ -1,9 +1,8 @@ //===---------------------- Stage.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/MCA/Support.h b/include/llvm/MCA/Support.h index 7b0c5bf3a486..1da097c90922 100644 --- a/include/llvm/MCA/Support.h +++ b/include/llvm/MCA/Support.h @@ -1,9 +1,8 @@ //===--------------------- Support.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -61,24 +60,13 @@ public: return (Denominator == 1) ? Numerator : (double)Numerator / Denominator; } + unsigned getNumerator() const { return Numerator; } + unsigned getDenominator() const { return Denominator; } + // Add the components of RHS to this instance. Instead of calculating // the final value here, we keep track of the numerator and denominator // separately, to reduce floating point error. - ResourceCycles &operator+=(const ResourceCycles &RHS) { - if (Denominator == RHS.Denominator) - Numerator += RHS.Numerator; - else { - // Create a common denominator for LHS and RHS by calculating the least - // common multiple from the GCD. - unsigned GCD = GreatestCommonDivisor64(Denominator, RHS.Denominator); - unsigned LCM = (Denominator * RHS.Denominator) / GCD; - unsigned LHSNumerator = Numerator * (LCM / Denominator); - unsigned RHSNumerator = RHS.Numerator * (LCM / RHS.Denominator); - Numerator = LHSNumerator + RHSNumerator; - Denominator = LCM; - } - return *this; - } + ResourceCycles &operator+=(const ResourceCycles &RHS); }; /// Populates vector Masks with processor resource masks. @@ -106,6 +94,13 @@ public: void computeProcResourceMasks(const MCSchedModel &SM, MutableArrayRef<uint64_t> Masks); +// Returns the index of the highest bit set. For resource masks, the position of +// the highest bit set can be used to construct a resource mask identifier. +inline unsigned getResourceStateIndex(uint64_t Mask) { + assert(Mask && "Processor Resource Mask cannot be zero!"); + return (std::numeric_limits<uint64_t>::digits - countLeadingZeros(Mask)) - 1; +} + /// Compute the reciprocal block throughput from a set of processor resource /// cycles. The reciprocal block throughput is computed as the MAX between: /// - NumMicroOps / DispatchWidth diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 9ef1e4875191..c40278a4f923 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -1,9 +1,8 @@ //===- Archive.h - ar archive file format -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -16,6 +15,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/fallible_iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Support/Chrono.h" @@ -143,44 +143,38 @@ public: getAsBinary(LLVMContext *Context = nullptr) const; }; - class child_iterator { + class ChildFallibleIterator { Child C; - Error *E = nullptr; public: - child_iterator() : C(Child(nullptr, nullptr, nullptr)) {} - child_iterator(const Child &C, Error *E) : C(C), E(E) {} + ChildFallibleIterator() : C(Child(nullptr, nullptr, nullptr)) {} + ChildFallibleIterator(const Child &C) : C(C) {} const Child *operator->() const { return &C; } const Child &operator*() const { return C; } - bool operator==(const child_iterator &other) const { + bool operator==(const ChildFallibleIterator &other) const { // Ignore errors here: If an error occurred during increment then getNext // will have been set to child_end(), and the following comparison should // do the right thing. return C == other.C; } - bool operator!=(const child_iterator &other) const { + bool operator!=(const ChildFallibleIterator &other) const { return !(*this == other); } - // Code in loops with child_iterators must check for errors on each loop - // iteration. And if there is an error break out of the loop. - child_iterator &operator++() { // Preincrement - assert(E && "Can't increment iterator with no Error attached"); - ErrorAsOutParameter ErrAsOutParam(E); - if (auto ChildOrErr = C.getNext()) - C = *ChildOrErr; - else { - C = C.getParent()->child_end().C; - *E = ChildOrErr.takeError(); - E = nullptr; - } - return *this; + Error inc() { + auto NextChild = C.getNext(); + if (!NextChild) + return NextChild.takeError(); + C = std::move(*NextChild); + return Error::success(); } }; + using child_iterator = fallible_iterator<ChildFallibleIterator>; + class Symbol { const Archive *Parent; uint32_t SymbolIndex; diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 495b943d04c0..9e6daf2da36e 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -1,9 +1,8 @@ //===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -27,7 +26,6 @@ struct NewArchiveMember { sys::TimePoint<std::chrono::seconds> ModTime; unsigned UID = 0, GID = 0, Perms = 0644; - bool IsNew = false; NewArchiveMember() = default; NewArchiveMember(MemoryBufferRef BufRef); @@ -38,6 +36,8 @@ struct NewArchiveMember { bool Deterministic); }; +Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To); + Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 99745e24b8c8..3c3e977baff4 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -1,9 +1,8 @@ //===- Binary.h - A generic binary file -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #ifndef LLVM_OBJECT_BINARY_H #define LLVM_OBJECT_BINARY_H +#include "llvm-c/Types.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/Error.h" #include "llvm/Support/Error.h" @@ -42,7 +42,9 @@ protected: ID_Archive, ID_MachOUniversalBinary, ID_COFFImportFile, - ID_IR, // LLVM IR + ID_IR, // LLVM IR + + ID_Minidump, ID_WinRes, // Windows resource (.res) file. @@ -50,6 +52,9 @@ protected: ID_StartObjects, ID_COFF, + ID_XCOFF32, // AIX XCOFF 32-bit + ID_XCOFF64, // AIX XCOFF 64-bit + ID_ELF32L, // ELF 32-bit, little endian ID_ELF32B, // ELF 32-bit, big endian ID_ELF64L, // ELF 64-bit, little endian @@ -118,6 +123,8 @@ public: return TypeID == ID_COFF; } + bool isXCOFF() const { return TypeID == ID_XCOFF32 || TypeID == ID_XCOFF64; } + bool isWasm() const { return TypeID == ID_Wasm; } bool isCOFFImportFile() const { @@ -128,6 +135,8 @@ public: return TypeID == ID_IR; } + bool isMinidump() const { return TypeID == ID_Minidump; } + bool isLittleEndian() const { return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || TypeID == ID_MachO32B || TypeID == ID_MachO64B); @@ -156,6 +165,9 @@ public: } }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef) + /// Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index b753d261a0fc..c53cbc46c747 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -1,9 +1,8 @@ //===- COFF.h - COFF object file implementation -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -898,13 +897,12 @@ protected: Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; - std::error_code getSectionName(DataRefImpl Sec, - StringRef &Res) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; - std::error_code getSectionContents(DataRefImpl Sec, - StringRef &Res) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; @@ -1034,10 +1032,10 @@ public: ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; - std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; + Expected<StringRef> getSectionName(const coff_section *Sec) const; uint64_t getSectionSize(const coff_section *Sec) const; - std::error_code getSectionContents(const coff_section *Sec, - ArrayRef<uint8_t> &Res) const; + Error getSectionContents(const coff_section *Sec, + ArrayRef<uint8_t> &Res) const; uint64_t getImageBase() const; std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h index 0a4556ad8884..5aa836411118 100644 --- a/include/llvm/Object/COFFImportFile.h +++ b/include/llvm/Object/COFFImportFile.h @@ -1,9 +1,8 @@ //===- COFFImportFile.h - COFF short import file implementation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -37,12 +36,11 @@ public: void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } - std::error_code printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const override { + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override { if (Symb.p == 0) OS << "__imp_"; OS << StringRef(Data.getBufferStart() + sizeof(coff_import_header)); - return std::error_code(); + return Error::success(); } uint32_t getSymbolFlags(DataRefImpl Symb) const override { @@ -71,9 +69,21 @@ private: }; struct COFFShortExport { + /// The name of the export as specified in the .def file or on the command + /// line, i.e. "foo" in "/EXPORT:foo", and "bar" in "/EXPORT:foo=bar". This + /// may lack mangling, such as underscore prefixing and stdcall suffixing. std::string Name; + + /// The external, exported name. Only non-empty when export renaming is in + /// effect, i.e. "foo" in "/EXPORT:foo=bar". std::string ExtName; + + /// The real, mangled symbol name from the object file. Given + /// "/export:foo=bar", this could be "_bar@8" if bar is stdcall. std::string SymbolName; + + /// Creates a weak alias. This is the name of the weak aliasee. In a .def + /// file, this is "baz" in "EXPORTS\nfoo = bar == baz". std::string AliasTarget; uint16_t Ordinal = 0; diff --git a/include/llvm/Object/COFFModuleDefinition.h b/include/llvm/Object/COFFModuleDefinition.h index be139a2833b0..ab52259fea1a 100644 --- a/include/llvm/Object/COFFModuleDefinition.h +++ b/include/llvm/Object/COFFModuleDefinition.h @@ -1,9 +1,8 @@ //===--- COFFModuleDefinition.h ---------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Object/CVDebugRecord.h b/include/llvm/Object/CVDebugRecord.h index faad72c0df29..d41c7391f701 100644 --- a/include/llvm/Object/CVDebugRecord.h +++ b/include/llvm/Object/CVDebugRecord.h @@ -1,9 +1,8 @@ //===- CVDebugRecord.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Object/Decompressor.h b/include/llvm/Object/Decompressor.h index 2a77d2ffbf68..cc918481b308 100644 --- a/include/llvm/Object/Decompressor.h +++ b/include/llvm/Object/Decompressor.h @@ -1,9 +1,8 @@ //===-- Decompressor.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===/ diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index bcdc190cc7dc..cf8e4529bad9 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -1,9 +1,8 @@ //===- ELF.h - ELF object file implementation -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -45,10 +44,26 @@ getElfArchType(StringRef Object) { (uint8_t)Object[ELF::EI_DATA]); } -static inline Error createError(StringRef Err) { +static inline Error createError(const Twine &Err) { return make_error<StringError>(Err, object_error::parse_failed); } +template <class ELFT> class ELFFile; + +template <class ELFT> +std::string getSecIndexForError(const ELFFile<ELFT> *Obj, + const typename ELFT::Shdr *Sec) { + auto TableOrErr = Obj->sections(); + if (TableOrErr) + return "[index " + std::to_string(Sec - &TableOrErr->front()) + "]"; + // To make this helper be more convenient for error reporting purposes we + // drop the error. But really it should never be triggered. Before this point, + // our code should have called 'sections()' and reported a proper error on + // failure. + llvm::consumeError(TableOrErr.takeError()); + return "[unknown index]"; +} + template <class ELFT> class ELFFile { public: @@ -80,9 +95,7 @@ public: using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr_Range = typename ELFT::PhdrRange; - const uint8_t *base() const { - return reinterpret_cast<const uint8_t *>(Buf.data()); - } + const uint8_t *base() const { return Buf.bytes_begin(); } size_t getBufSize() const { return Buf.size(); } @@ -115,8 +128,8 @@ public: SmallVectorImpl<char> &Result) const; uint32_t getRelativeRelocationType() const; - const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const; - const char *getDynamicTagAsString(uint64_t Type) const; + std::string getDynamicTagAsString(unsigned Arch, uint64_t Type) const; + std::string getDynamicTagAsString(uint64_t Type) const; /// Get the symbol for a given relocation. Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, @@ -165,11 +178,16 @@ public: /// Iterate over program header table. Expected<Elf_Phdr_Range> program_headers() const { if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) - return createError("invalid e_phentsize"); + return createError("invalid e_phentsize: " + + Twine(getHeader()->e_phentsize)); if (getHeader()->e_phoff + (getHeader()->e_phnum * getHeader()->e_phentsize) > getBufSize()) - return createError("program headers longer than binary"); + return createError("program headers are longer than binary of size " + + Twine(getBufSize()) + ": e_phoff = 0x" + + Twine::utohexstr(getHeader()->e_phoff) + + ", e_phnum = " + Twine(getHeader()->e_phnum) + + ", e_phentsize = " + Twine(getHeader()->e_phentsize)); auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff); return makeArrayRef(Begin, Begin + getHeader()->e_phnum); @@ -183,12 +201,12 @@ public: /// \param Err [out] an error to support fallible iteration, which should /// be checked after iteration ends. Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { - if (Phdr.p_type != ELF::PT_NOTE) { - Err = createError("attempt to iterate notes of non-note program header"); - return Elf_Note_Iterator(Err); - } + assert(Phdr.p_type == ELF::PT_NOTE && "Phdr is not of type PT_NOTE"); + ErrorAsOutParameter ErrAsOutParam(&Err); if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { - Err = createError("invalid program header offset/size"); + Err = createError("PT_NOTE header has invalid offset (0x" + + Twine::utohexstr(Phdr.p_offset) + ") or size (0x" + + Twine::utohexstr(Phdr.p_filesz) + ")"); return Elf_Note_Iterator(Err); } return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); @@ -202,12 +220,13 @@ public: /// \param Err [out] an error to support fallible iteration, which should /// be checked after iteration ends. Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { - if (Shdr.sh_type != ELF::SHT_NOTE) { - Err = createError("attempt to iterate notes of non-note section"); - return Elf_Note_Iterator(Err); - } + assert(Shdr.sh_type == ELF::SHT_NOTE && "Shdr is not of type SHT_NOTE"); + ErrorAsOutParameter ErrAsOutParam(&Err); if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { - Err = createError("invalid section offset/size"); + Err = createError("SHT_NOTE section " + getSecIndexForError(this, &Shdr) + + " has invalid offset (0x" + + Twine::utohexstr(Shdr.sh_offset) + ") or size (0x" + + Twine::utohexstr(Shdr.sh_size) + ")"); return Elf_Note_Iterator(Err); } return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); @@ -274,7 +293,7 @@ template <class ELFT> inline Expected<const typename ELFT::Shdr *> getSection(typename ELFT::ShdrRange Sections, uint32_t Index) { if (Index >= Sections.size()) - return createError("invalid section index"); + return createError("invalid section index: " + Twine(Index)); return &Sections[Index]; } @@ -286,7 +305,10 @@ getExtendedSymbolTableIndex(const typename ELFT::Sym *Sym, assert(Sym->st_shndx == ELF::SHN_XINDEX); unsigned Index = Sym - FirstSym; if (Index >= ShndxTable.size()) - return createError("index past the end of the symbol table"); + return createError( + "extended symbol index (" + Twine(Index) + + ") is past the end of the SHT_SYMTAB_SHNDX section of size " + + Twine(ShndxTable.size())); // The size of the table was checked in getSHNDXTable. return ShndxTable[Index]; @@ -333,20 +355,18 @@ ELFFile<ELFT>::getSection(const Elf_Sym *Sym, Elf_Sym_Range Symbols, } template <class ELFT> -inline Expected<const typename ELFT::Sym *> -getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) { - if (Index >= Symbols.size()) - return createError("invalid symbol index"); - return &Symbols[Index]; -} - -template <class ELFT> Expected<const typename ELFT::Sym *> ELFFile<ELFT>::getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { - auto SymtabOrErr = symbols(Sec); - if (!SymtabOrErr) - return SymtabOrErr.takeError(); - return object::getSymbol<ELFT>(*SymtabOrErr, Index); + auto SymsOrErr = symbols(Sec); + if (!SymsOrErr) + return SymsOrErr.takeError(); + + Elf_Sym_Range Symbols = *SymsOrErr; + if (Index >= Symbols.size()) + return createError("unable to get symbol from section " + + getSecIndexForError(this, Sec) + + ": invalid symbol index (" + Twine(Index) + ")"); + return &Symbols[Index]; } template <class ELFT> @@ -354,18 +374,26 @@ template <typename T> Expected<ArrayRef<T>> ELFFile<ELFT>::getSectionContentsAsArray(const Elf_Shdr *Sec) const { if (Sec->sh_entsize != sizeof(T) && sizeof(T) != 1) - return createError("invalid sh_entsize"); + return createError("section " + getSecIndexForError(this, Sec) + + " has an invalid sh_entsize: " + Twine(Sec->sh_entsize)); uintX_t Offset = Sec->sh_offset; uintX_t Size = Sec->sh_size; if (Size % sizeof(T)) - return createError("size is not a multiple of sh_entsize"); + return createError("section " + getSecIndexForError(this, Sec) + + " has an invalid sh_size (" + Twine(Size) + + ") which is not a multiple of its sh_entsize (" + + Twine(Sec->sh_entsize) + ")"); if ((std::numeric_limits<uintX_t>::max() - Offset < Size) || Offset + Size > Buf.size()) - return createError("invalid section offset"); + return createError("section " + getSecIndexForError(this, Sec) + + " has a sh_offset (0x" + Twine::utohexstr(Offset) + + ") + sh_size (0x" + Twine(Size) + + ") that cannot be represented"); if (Offset % alignof(T)) + // TODO: this error is untested. return createError("unaligned data"); const T *Start = reinterpret_cast<const T *>(base() + Offset); @@ -438,8 +466,10 @@ ELFFile<ELFT>::getSectionStringTable(Elf_Shdr_Range Sections) const { if (!Index) // no section string table. return ""; + // TODO: Test a case when the sh_link of the section with index 0 is broken. if (Index >= Sections.size()) - return createError("invalid section index"); + return createError("section header string table index " + Twine(Index) + + " does not exist"); return getStringTable(&Sections[Index]); } @@ -448,7 +478,9 @@ template <class ELFT> ELFFile<ELFT>::ELFFile(StringRef Object) : Buf(Object) {} template <class ELFT> Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRef Object) { if (sizeof(Elf_Ehdr) > Object.size()) - return createError("Invalid buffer"); + return createError("invalid buffer: the size (" + Twine(Object.size()) + + ") is smaller than an ELF header (" + + Twine(sizeof(Elf_Ehdr)) + ")"); return ELFFile(Object); } @@ -459,16 +491,18 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { return ArrayRef<Elf_Shdr>(); if (getHeader()->e_shentsize != sizeof(Elf_Shdr)) - return createError( - "invalid section header entry size (e_shentsize) in ELF header"); + return createError("invalid e_shentsize in ELF header: " + + Twine(getHeader()->e_shentsize)); const uint64_t FileSize = Buf.size(); - if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) - return createError("section header table goes past the end of the file"); + return createError( + "section header table goes past the end of the file: e_shoff = 0x" + + Twine::utohexstr(SectionTableOffset)); // Invalid address alignment of section headers if (SectionTableOffset & (alignof(Elf_Shdr) - 1)) + // TODO: this error is untested. return createError("invalid alignment of section headers"); const Elf_Shdr *First = @@ -479,6 +513,7 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { NumSections = First->sh_size; if (NumSections > UINT64_MAX / sizeof(Elf_Shdr)) + // TODO: this error is untested. return createError("section table goes past the end of file"); const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr); @@ -505,10 +540,14 @@ template <typename T> Expected<const T *> ELFFile<ELFT>::getEntry(const Elf_Shdr *Section, uint32_t Entry) const { if (sizeof(T) != Section->sh_entsize) + // TODO: this error is untested. return createError("invalid sh_entsize"); size_t Pos = Section->sh_offset + Entry * sizeof(T); if (Pos + sizeof(T) > Buf.size()) - return createError("invalid section offset"); + return createError("unable to access section " + + getSecIndexForError(this, Section) + " data at 0x" + + Twine::utohexstr(Pos) + + ": offset goes past the end of file"); return reinterpret_cast<const T *>(base() + Pos); } @@ -534,6 +573,7 @@ ELFFile<ELFT>::getSection(const StringRef SectionName) const { if (*SecNameOrErr == SectionName) return &Sec; } + // TODO: this error is untested. return createError("invalid section name"); } @@ -541,15 +581,24 @@ template <class ELFT> Expected<StringRef> ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { if (Section->sh_type != ELF::SHT_STRTAB) - return createError("invalid sh_type for string table, expected SHT_STRTAB"); + return createError("invalid sh_type for string table section " + + getSecIndexForError(this, Section) + + ": expected SHT_STRTAB, but got " + + object::getELFSectionTypeName(getHeader()->e_machine, + Section->sh_type)); auto V = getSectionContentsAsArray<char>(Section); if (!V) return V.takeError(); ArrayRef<char> Data = *V; if (Data.empty()) + // TODO: this error is untested. return createError("empty string table"); if (Data.back() != '\0') - return createError("string table non-null terminated"); + return createError(object::getELFSectionTypeName(getHeader()->e_machine, + Section->sh_type) + + " string table section " + + getSecIndexForError(this, Section) + + " is non-null terminated"); return StringRef(Data.begin(), Data.size()); } @@ -577,9 +626,13 @@ ELFFile<ELFT>::getSHNDXTable(const Elf_Shdr &Section, const Elf_Shdr &SymTable = **SymTableOrErr; if (SymTable.sh_type != ELF::SHT_SYMTAB && SymTable.sh_type != ELF::SHT_DYNSYM) + // TODO: this error is untested. return createError("invalid sh_type"); if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym))) - return createError("invalid section contents size"); + return createError("SHT_SYMTAB_SHNDX section has sh_size (" + + Twine(SymTable.sh_size) + + ") which is not equal to the number of symbols (" + + Twine(V.size()) + ")"); return V; } @@ -598,6 +651,7 @@ ELFFile<ELFT>::getStringTableForSymtab(const Elf_Shdr &Sec, Elf_Shdr_Range Sections) const { if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) + // TODO: this error is untested. return createError( "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM"); auto SectionOrErr = object::getSection<ELFT>(Sections, Sec.sh_link); @@ -625,7 +679,11 @@ Expected<StringRef> ELFFile<ELFT>::getSectionName(const Elf_Shdr *Section, if (Offset == 0) return StringRef(); if (Offset >= DotShstrtab.size()) - return createError("invalid string offset"); + return createError("a section " + getSecIndexForError(this, Section) + + " has an invalid sh_name (0x" + + Twine::utohexstr(Offset) + + ") offset which goes past the end of the " + "section name string table"); return StringRef(DotShstrtab.data() + Offset); } diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 0f620681cd99..86c015efd704 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -1,9 +1,8 @@ //===- ELFObjectFile.h - ELF object file implementation ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -42,6 +41,9 @@ namespace llvm { namespace object { +constexpr int NumElfSymbolTypes = 8; +extern const llvm::EnumEntry<unsigned> ElfSymbolTypes[NumElfSymbolTypes]; + class elf_symbol_iterator; class ELFObjectFileBase : public ObjectFile { @@ -52,8 +54,8 @@ class ELFObjectFileBase : public ObjectFile { protected: ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); - virtual uint16_t getEMachine() const = 0; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; @@ -62,6 +64,7 @@ protected: virtual uint64_t getSectionOffset(DataRefImpl Sec) const = 0; virtual Expected<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0; + virtual Error getBuildAttributes(ARMAttributeParser &Attributes) const = 0; public: using elf_symbol_iterator_range = iterator_range<elf_symbol_iterator>; @@ -87,6 +90,8 @@ public: virtual uint16_t getEType() const = 0; + virtual uint16_t getEMachine() const = 0; + std::vector<std::pair<DataRefImpl, uint64_t>> getPltAddresses() const; }; @@ -142,6 +147,10 @@ public: return getObject()->getSymbolSize(getRawDataRefImpl()); } + uint8_t getBinding() const { + return getObject()->getSymbolBinding(getRawDataRefImpl()); + } + uint8_t getOther() const { return getObject()->getSymbolOther(getRawDataRefImpl()); } @@ -149,6 +158,16 @@ public: uint8_t getELFType() const { return getObject()->getSymbolELFType(getRawDataRefImpl()); } + + StringRef getELFTypeName() const { + uint8_t Type = getELFType(); + for (auto &EE : ElfSymbolTypes) { + if (EE.Value == Type) { + return EE.AltName; + } + } + return ""; + } }; class elf_symbol_iterator : public symbol_iterator { @@ -239,6 +258,7 @@ protected: uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; + uint8_t getSymbolBinding(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; @@ -247,13 +267,12 @@ protected: Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; - std::error_code getSectionName(DataRefImpl Sec, - StringRef &Res) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; - std::error_code getSectionContents(DataRefImpl Sec, - StringRef &Res) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; @@ -341,6 +360,28 @@ protected: (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED)); } + Error getBuildAttributes(ARMAttributeParser &Attributes) const override { + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return SectionsOrErr.takeError(); + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) { + auto ErrorOrContents = EF.getSectionContents(&Sec); + if (!ErrorOrContents) + return ErrorOrContents.takeError(); + + auto Contents = ErrorOrContents.get(); + if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1) + return Error::success(); + + Attributes.Parse(Contents, ELFT::TargetEndianness == support::little); + break; + } + } + return Error::success(); + } + // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. @@ -382,28 +423,6 @@ public: unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; } - std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override { - auto SectionsOrErr = EF.sections(); - if (!SectionsOrErr) - return errorToErrorCode(SectionsOrErr.takeError()); - - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES) { - auto ErrorOrContents = EF.getSectionContents(&Sec); - if (!ErrorOrContents) - return errorToErrorCode(ErrorOrContents.takeError()); - - auto Contents = ErrorOrContents.get(); - if (Contents[0] != ARMBuildAttrs::Format_Version || Contents.size() == 1) - return std::error_code(); - - Attributes.Parse(Contents, ELFT::TargetEndianness == support::little); - break; - } - } - return std::error_code(); - } - const ELFFile<ELFT> *getELFFile() const { return &EF; } bool isDyldType() const { return isDyldELFObject; } @@ -441,7 +460,16 @@ Expected<StringRef> ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Sym) const { auto SymStrTabOrErr = EF.getStringTable(StringTableSec); if (!SymStrTabOrErr) return SymStrTabOrErr.takeError(); - return ESym->getName(*SymStrTabOrErr); + Expected<StringRef> Name = ESym->getName(*SymStrTabOrErr); + + // If the symbol name is empty use the section name. + if ((!Name || Name->empty()) && ESym->getType() == ELF::STT_SECTION) { + StringRef SecName; + Expected<section_iterator> Sec = getSymbolSection(Sym); + if (Sec && !(*Sec)->getName(SecName)) + return SecName; + } + return Name; } template <class ELFT> @@ -533,6 +561,11 @@ uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const { } template <class ELFT> +uint8_t ELFObjectFile<ELFT>::getSymbolBinding(DataRefImpl Symb) const { + return getSymbol(Symb)->getBinding(); +} + +template <class ELFT> uint8_t ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb) const { return getSymbol(Symb)->st_other; } @@ -654,13 +687,8 @@ void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - auto Name = EF.getSectionName(&*getSection(Sec)); - if (!Name) - return errorToErrorCode(Name.takeError()); - Result = *Name; - return std::error_code(); +Expected<StringRef> ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec) const { + return EF.getSectionName(&*getSection(Sec)); } template <class ELFT> @@ -685,16 +713,15 @@ uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const { } template <class ELFT> -std::error_code -ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +Expected<ArrayRef<uint8_t>> +ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec) const { const Elf_Shdr *EShdr = getSection(Sec); if (std::error_code EC = checkOffset(getMemoryBufferRef(), (uintptr_t)base() + EShdr->sh_offset, EShdr->sh_size)) - return EC; - Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); - return std::error_code(); + return errorCodeToError(EC); + return makeArrayRef((const uint8_t *)base() + EShdr->sh_offset, + EShdr->sh_size); } template <class ELFT> @@ -750,7 +777,7 @@ ELFObjectFile<ELFT>::dynamic_relocation_sections() const { } } for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (is_contained(Offsets, Sec.sh_offset)) + if (is_contained(Offsets, Sec.sh_addr)) Res.emplace_back(toDRI(&Sec), this); } return Res; @@ -925,15 +952,13 @@ ELFObjectFile<ELFT>::create(MemoryBufferRef Object) { for (const Elf_Shdr &Sec : *SectionsOrErr) { switch (Sec.sh_type) { case ELF::SHT_DYNSYM: { - if (DotDynSymSec) - return createError("More than one dynamic symbol table!"); - DotDynSymSec = &Sec; + if (!DotDynSymSec) + DotDynSymSec = &Sec; break; } case ELF::SHT_SYMTAB: { - if (DotSymtabSec) - return createError("More than one static symbol table!"); - DotSymtabSec = &Sec; + if (!DotSymtabSec) + DotSymtabSec = &Sec; break; } case ELF::SHT_SYMTAB_SHNDX: { @@ -967,7 +992,9 @@ ELFObjectFile<ELFT>::ELFObjectFile(ELFObjectFile<ELFT> &&Other) template <class ELFT> basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin() const { - DataRefImpl Sym = toDRI(DotSymtabSec, 0); + DataRefImpl Sym = + toDRI(DotSymtabSec, + DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); return basic_symbol_iterator(SymbolRef(Sym, this)); } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index ec3c8e7bae46..5552208b1f8a 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -1,9 +1,8 @@ //===- ELFTypes.h - Endian specific types for ELF ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -593,9 +592,9 @@ class Elf_Note_Impl { template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl; +public: Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {} -public: /// Get the note's name, excluding the terminating null byte. StringRef getName() const { if (!Nhdr.n_namesz) diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index a15f8b9236eb..b7bbf06fc86d 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -1,9 +1,8 @@ //===- Error.h - system_error extensions for Object -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 993359b766a1..08b92f1bae50 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -1,9 +1,8 @@ //===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -38,8 +37,7 @@ class IRObjectFile : public SymbolicFile { public: ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; - std::error_code printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const override; + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; basic_symbol_iterator symbol_end() const override; diff --git a/include/llvm/Object/IRSymtab.h b/include/llvm/Object/IRSymtab.h index 5f6a024cd132..0bbfc932493c 100644 --- a/include/llvm/Object/IRSymtab.h +++ b/include/llvm/Object/IRSymtab.h @@ -1,9 +1,8 @@ //===- IRSymtab.h - data definitions for IR symbol tables -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -126,12 +125,13 @@ struct Uncommon { Str SectionName; }; + struct Header { /// Version number of the symtab format. This number should be incremented /// when the format changes, but it does not need to be incremented if a /// change to LLVM would cause it to create a different symbol table. Word Version; - enum { kCurrentVersion = 1 }; + enum { kCurrentVersion = 2 }; /// The producer's version string (LLVM_VERSION_STRING " " LLVM_REVISION). /// Consumers should rebuild the symbol table from IR if the producer's @@ -148,6 +148,9 @@ struct Header { /// COFF-specific: linker directives. Str COFFLinkerOpts; + + /// Dependent Library Specifiers + Range<Str> DependentLibraries; }; } // end namespace storage @@ -232,6 +235,7 @@ class Reader { ArrayRef<storage::Comdat> Comdats; ArrayRef<storage::Symbol> Symbols; ArrayRef<storage::Uncommon> Uncommons; + ArrayRef<storage::Str> DependentLibraries; StringRef str(storage::Str S) const { return S.get(Strtab); } @@ -252,6 +256,7 @@ public: Comdats = range(header().Comdats); Symbols = range(header().Symbols); Uncommons = range(header().Uncommons); + DependentLibraries = range(header().DependentLibraries); } using symbol_range = iterator_range<object::content_iterator<SymbolRef>>; @@ -284,6 +289,16 @@ public: /// COFF-specific: returns linker options specified in the input file. StringRef getCOFFLinkerOpts() const { return str(header().COFFLinkerOpts); } + + /// Returns dependent library specifiers + std::vector<StringRef> getDependentLibraries() const { + std::vector<StringRef> Specifiers; + Specifiers.reserve(DependentLibraries.size()); + for (auto S : DependentLibraries) { + Specifiers.push_back(str(S)); + } + return Specifiers; + } }; /// Ephemeral symbols produced by Reader::symbols() and diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index c2f4f4062934..ca9512f21706 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -1,9 +1,8 @@ //===- MachO.h - MachO object file implementation ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -134,11 +133,9 @@ public: BindRebaseSegInfo(const MachOObjectFile *Obj); // Used to check a Mach-O Bind or Rebase entry for errors when iterating. - const char *checkSegAndOffset(int32_t SegIndex, uint64_t SegOffset, - bool endInvalid); - const char *checkCountAndSkip(uint32_t Count, uint32_t Skip, - uint8_t PointerSize, int32_t SegIndex, - uint64_t SegOffset); + const char* checkSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, + uint8_t PointerSize, uint32_t Count=1, + uint32_t Skip=0); // Used with valid SegIndex/SegOffset values from checked entries. StringRef segmentName(int32_t SegIndex); StringRef sectionName(int32_t SegIndex, uint64_t SegOffset); @@ -296,13 +293,12 @@ public: unsigned getSectionID(SectionRef Sec) const; void moveSectionNext(DataRefImpl &Sec) const override; - std::error_code getSectionName(DataRefImpl Sec, - StringRef &Res) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; - std::error_code getSectionContents(DataRefImpl Sec, - StringRef &Res) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; Expected<SectionRef> getSection(unsigned SectionIndex) const; Expected<SectionRef> getSection(StringRef SectionName) const; @@ -413,36 +409,32 @@ public: bool is64, MachOBindEntry::Kind); - /// For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to - /// validate a MachOBindEntry. - const char *BindEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset, - bool endInvalid) const { - return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset, - endInvalid); - } - /// For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for - /// the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode. - const char *BindEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip, - uint8_t PointerSize, int32_t SegIndex, - uint64_t SegOffset) const { - return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize, - SegIndex, SegOffset); + // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists + // that fully contains a pointer at that location. Multiple fixups in a bind + // (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can + // be tested via the Count and Skip parameters. + // + // This is used by MachOBindEntry::moveNext() to validate a MachOBindEntry. + const char *BindEntryCheckSegAndOffsets(int32_t SegIndex, uint64_t SegOffset, + uint8_t PointerSize, uint32_t Count=1, + uint32_t Skip=0) const { + return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, + PointerSize, Count, Skip); } - /// For use with a SegIndex,SegOffset pair in MachORebaseEntry::moveNext() to - /// validate a MachORebaseEntry. - const char *RebaseEntryCheckSegAndOffset(int32_t SegIndex, uint64_t SegOffset, - bool endInvalid) const { - return BindRebaseSectionTable->checkSegAndOffset(SegIndex, SegOffset, - endInvalid); - } - /// For use in MachORebaseEntry::moveNext() to validate a MachORebaseEntry for - /// the REBASE_OPCODE_DO_*_TIMES* opcodes. - const char *RebaseEntryCheckCountAndSkip(uint32_t Count, uint32_t Skip, - uint8_t PointerSize, int32_t SegIndex, - uint64_t SegOffset) const { - return BindRebaseSectionTable->checkCountAndSkip(Count, Skip, PointerSize, - SegIndex, SegOffset); + // Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists + // that fully contains a pointer at that location. Multiple fixups in a rebase + // (such as with the REBASE_OPCODE_DO_*_TIMES* opcodes) can be tested via the + // Count and Skip parameters. + // + // This is used by MachORebaseEntry::moveNext() to validate a MachORebaseEntry + const char *RebaseEntryCheckSegAndOffsets(int32_t SegIndex, + uint64_t SegOffset, + uint8_t PointerSize, + uint32_t Count=1, + uint32_t Skip=0) const { + return BindRebaseSectionTable->checkSegAndOffsets(SegIndex, SegOffset, + PointerSize, Count, Skip); } /// For use with the SegIndex of a checked Mach-O Bind or Rebase entry to @@ -579,6 +571,7 @@ public: const char **McpuDefault = nullptr, const char **ArchFlag = nullptr); static bool isValidArch(StringRef ArchFlag); + static ArrayRef<StringRef> getValidArchs(); static Triple getHostArch(); bool isRelocatableObject() const override; @@ -616,6 +609,7 @@ public: case MachO::PLATFORM_TVOS: return "tvos"; case MachO::PLATFORM_WATCHOS: return "watchos"; case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; + case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 9e70b0bc30c0..5bf724f2c8b2 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -1,9 +1,8 @@ //===- MachOUniversal.h - Mach-O universal binaries -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Object/Minidump.h b/include/llvm/Object/Minidump.h new file mode 100644 index 000000000000..470008d552e7 --- /dev/null +++ b/include/llvm/Object/Minidump.h @@ -0,0 +1,165 @@ +//===- Minidump.h - Minidump object file 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MINIDUMP_H +#define LLVM_OBJECT_MINIDUMP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/BinaryFormat/Minidump.h" +#include "llvm/Object/Binary.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace object { + +/// A class providing access to the contents of a minidump file. +class MinidumpFile : public Binary { +public: + /// Construct a new MinidumpFile object from the given memory buffer. Returns + /// an error if this file cannot be identified as a minidump file, or if its + /// contents are badly corrupted (i.e. we cannot read the stream directory). + static Expected<std::unique_ptr<MinidumpFile>> create(MemoryBufferRef Source); + + static bool classof(const Binary *B) { return B->isMinidump(); } + + /// Returns the contents of the minidump header. + const minidump::Header &header() const { return Header; } + + /// Returns the list of streams (stream directory entries) in this file. + ArrayRef<minidump::Directory> streams() const { return Streams; } + + /// Returns the raw contents of the stream given by the directory entry. + ArrayRef<uint8_t> getRawStream(const minidump::Directory &Stream) const { + return getData().slice(Stream.Location.RVA, Stream.Location.DataSize); + } + + /// Returns the raw contents of the stream of the given type, or None if the + /// file does not contain a stream of this type. + Optional<ArrayRef<uint8_t>> getRawStream(minidump::StreamType Type) const; + + /// Returns the raw contents of an object given by the LocationDescriptor. An + /// error is returned if the descriptor points outside of the minidump file. + Expected<ArrayRef<uint8_t>> + getRawData(minidump::LocationDescriptor Desc) const { + return getDataSlice(getData(), Desc.RVA, Desc.DataSize); + } + + /// Returns the minidump string at the given offset. An error is returned if + /// we fail to parse the string, or the string is invalid UTF16. + Expected<std::string> getString(size_t Offset) const; + + /// Returns the contents of the SystemInfo stream, cast to the appropriate + /// type. An error is returned if the file does not contain this stream, or + /// the stream is smaller than the size of the SystemInfo structure. The + /// internal consistency of the stream is not checked in any way. + Expected<const minidump::SystemInfo &> getSystemInfo() const { + return getStream<minidump::SystemInfo>(minidump::StreamType::SystemInfo); + } + + /// Returns the module list embedded in the ModuleList stream. An error is + /// returned if the file does not contain this stream, or if the stream is + /// not large enough to contain the number of modules declared in the stream + /// header. The consistency of the Module entries themselves is not checked in + /// any way. + Expected<ArrayRef<minidump::Module>> getModuleList() const { + return getListStream<minidump::Module>(minidump::StreamType::ModuleList); + } + + /// Returns the thread list embedded in the ThreadList stream. An error is + /// returned if the file does not contain this stream, or if the stream is + /// not large enough to contain the number of threads declared in the stream + /// header. The consistency of the Thread entries themselves is not checked in + /// any way. + Expected<ArrayRef<minidump::Thread>> getThreadList() const { + return getListStream<minidump::Thread>(minidump::StreamType::ThreadList); + } + + /// Returns the list of memory ranges embedded in the MemoryList stream. An + /// error is returned if the file does not contain this stream, or if the + /// stream is not large enough to contain the number of memory descriptors + /// declared in the stream header. The consistency of the MemoryDescriptor + /// entries themselves is not checked in any way. + Expected<ArrayRef<minidump::MemoryDescriptor>> getMemoryList() const { + return getListStream<minidump::MemoryDescriptor>( + minidump::StreamType::MemoryList); + } + +private: + static Error createError(StringRef Str) { + return make_error<GenericBinaryError>(Str, object_error::parse_failed); + } + + static Error createEOFError() { + return make_error<GenericBinaryError>("Unexpected EOF", + object_error::unexpected_eof); + } + + /// Return a slice of the given data array, with bounds checking. + static Expected<ArrayRef<uint8_t>> getDataSlice(ArrayRef<uint8_t> Data, + size_t Offset, size_t Size); + + /// Return the slice of the given data array as an array of objects of the + /// given type. The function checks that the input array is large enough to + /// contain the correct number of objects of the given type. + template <typename T> + static Expected<ArrayRef<T>> getDataSliceAs(ArrayRef<uint8_t> Data, + size_t Offset, size_t Count); + + MinidumpFile(MemoryBufferRef Source, const minidump::Header &Header, + ArrayRef<minidump::Directory> Streams, + DenseMap<minidump::StreamType, std::size_t> StreamMap) + : Binary(ID_Minidump, Source), Header(Header), Streams(Streams), + StreamMap(std::move(StreamMap)) {} + + ArrayRef<uint8_t> getData() const { + return arrayRefFromStringRef(Data.getBuffer()); + } + + /// Return the stream of the given type, cast to the appropriate type. Checks + /// that the stream is large enough to hold an object of this type. + template <typename T> + Expected<const T &> getStream(minidump::StreamType Stream) const; + + /// Return the contents of a stream which contains a list of fixed-size items, + /// prefixed by the list size. + template <typename T> + Expected<ArrayRef<T>> getListStream(minidump::StreamType Stream) const; + + const minidump::Header &Header; + ArrayRef<minidump::Directory> Streams; + DenseMap<minidump::StreamType, std::size_t> StreamMap; +}; + +template <typename T> +Expected<const T &> MinidumpFile::getStream(minidump::StreamType Stream) const { + if (auto OptionalStream = getRawStream(Stream)) { + if (OptionalStream->size() >= sizeof(T)) + return *reinterpret_cast<const T *>(OptionalStream->data()); + return createEOFError(); + } + return createError("No such stream"); +} + +template <typename T> +Expected<ArrayRef<T>> MinidumpFile::getDataSliceAs(ArrayRef<uint8_t> Data, + size_t Offset, + size_t Count) { + // Check for overflow. + if (Count > std::numeric_limits<size_t>::max() / sizeof(T)) + return createEOFError(); + auto ExpectedArray = getDataSlice(Data, Offset, sizeof(T) * Count); + if (!ExpectedArray) + return ExpectedArray.takeError(); + return ArrayRef<T>(reinterpret_cast<const T *>(ExpectedArray->data()), Count); +} + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_MINIDUMP_H diff --git a/include/llvm/Object/ModuleSymbolTable.h b/include/llvm/Object/ModuleSymbolTable.h index c3cbc27998e5..4c582fbcda81 100644 --- a/include/llvm/Object/ModuleSymbolTable.h +++ b/include/llvm/Object/ModuleSymbolTable.h @@ -1,9 +1,8 @@ //===- ModuleSymbolTable.h - symbol table for in-memory IR ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 036c99cb6baf..483a3486bd72 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -1,9 +1,8 @@ //===- ObjectFile.h - File format independent object file -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -14,6 +13,7 @@ #ifndef LLVM_OBJECT_OBJECTFILE_H #define LLVM_OBJECT_OBJECTFILE_H +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" @@ -98,7 +98,7 @@ public: uint64_t getAddress() const; uint64_t getIndex() const; uint64_t getSize() const; - std::error_code getContents(StringRef &Result) const; + Expected<StringRef> getContents() const; /// Get the alignment of this section as the actual value (not log 2). uint64_t getAlignment() const; @@ -136,6 +136,30 @@ public: const ObjectFile *getObject() const; }; +struct SectionedAddress { + // TODO: constructors could be removed when C++14 would be adopted. + SectionedAddress() {} + SectionedAddress(uint64_t Addr, uint64_t SectIdx) + : Address(Addr), SectionIndex(SectIdx) {} + + const static uint64_t UndefSection = UINT64_MAX; + + uint64_t Address = 0; + uint64_t SectionIndex = UndefSection; +}; + +inline bool operator<(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) < + std::tie(RHS.SectionIndex, RHS.Address); +} + +inline bool operator==(const SectionedAddress &LHS, + const SectionedAddress &RHS) { + return std::tie(LHS.SectionIndex, LHS.Address) == + std::tie(RHS.SectionIndex, RHS.Address); +} + /// This is a value type class that represents a single symbol in the list of /// symbols in the object file. class SymbolRef : public BasicSymbolRef { @@ -220,7 +244,7 @@ protected: friend class SymbolRef; virtual Expected<StringRef> getSymbolName(DataRefImpl Symb) const = 0; - std::error_code printSymbolName(raw_ostream &OS, + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; virtual Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; @@ -234,13 +258,12 @@ protected: friend class SectionRef; virtual void moveSectionNext(DataRefImpl &Sec) const = 0; - virtual std::error_code getSectionName(DataRefImpl Sec, - StringRef &Res) const = 0; + virtual Expected<StringRef> getSectionName(DataRefImpl Sec) const = 0; virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0; virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; - virtual std::error_code getSectionContents(DataRefImpl Sec, - StringRef &Res) const = 0; + virtual Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const = 0; virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; virtual bool isSectionCompressed(DataRefImpl Sec) const = 0; virtual bool isSectionText(DataRefImpl Sec) const = 0; @@ -308,11 +331,6 @@ public: /// Create a triple from the data in this object file. Triple makeTriple() const; - virtual std::error_code - getBuildAttributes(ARMAttributeParser &Attributes) const { - return std::error_code(); - } - /// Maps a debug section name to a standard DWARF section name. virtual StringRef mapDebugSectionName(StringRef Name) const { return Name; } @@ -341,6 +359,9 @@ public: createCOFFObjectFile(MemoryBufferRef Object); static Expected<std::unique_ptr<ObjectFile>> + createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); + + static Expected<std::unique_ptr<ObjectFile>> createELFObjectFile(MemoryBufferRef Object); static Expected<std::unique_ptr<MachOObjectFile>> @@ -396,14 +417,16 @@ inline SectionRef::SectionRef(DataRefImpl SectionP, , OwningObject(Owner) {} inline bool SectionRef::operator==(const SectionRef &Other) const { - return SectionPimpl == Other.SectionPimpl; + return OwningObject == Other.OwningObject && + SectionPimpl == Other.SectionPimpl; } inline bool SectionRef::operator!=(const SectionRef &Other) const { - return SectionPimpl != Other.SectionPimpl; + return !(*this == Other); } inline bool SectionRef::operator<(const SectionRef &Other) const { + assert(OwningObject == Other.OwningObject); return SectionPimpl < Other.SectionPimpl; } @@ -412,7 +435,11 @@ inline void SectionRef::moveNext() { } inline std::error_code SectionRef::getName(StringRef &Result) const { - return OwningObject->getSectionName(SectionPimpl, Result); + Expected<StringRef> NameOrErr = OwningObject->getSectionName(SectionPimpl); + if (!NameOrErr) + return errorToErrorCode(NameOrErr.takeError()); + Result = *NameOrErr; + return std::error_code(); } inline uint64_t SectionRef::getAddress() const { @@ -427,8 +454,12 @@ inline uint64_t SectionRef::getSize() const { return OwningObject->getSectionSize(SectionPimpl); } -inline std::error_code SectionRef::getContents(StringRef &Result) const { - return OwningObject->getSectionContents(SectionPimpl, Result); +inline Expected<StringRef> SectionRef::getContents() const { + Expected<ArrayRef<uint8_t>> Res = + OwningObject->getSectionContents(SectionPimpl); + if (!Res) + return Res.takeError(); + return StringRef(reinterpret_cast<const char *>(Res->data()), Res->size()); } inline uint64_t SectionRef::getAlignment() const { @@ -531,6 +562,25 @@ inline const ObjectFile *RelocationRef::getObject() const { } // end namespace object +template <> struct DenseMapInfo<object::SectionRef> { + static bool isEqual(const object::SectionRef &A, + const object::SectionRef &B) { + return A == B; + } + static object::SectionRef getEmptyKey() { + return object::SectionRef({}, nullptr); + } + static object::SectionRef getTombstoneKey() { + object::DataRefImpl TS; + TS.p = (uintptr_t)-1; + return object::SectionRef(TS, nullptr); + } + static unsigned getHashValue(const object::SectionRef &Sec) { + object::DataRefImpl Raw = Sec.getRawDataRefImpl(); + return hash_combine(Raw.p, Raw.d.a, Raw.d.b); + } +}; + } // end namespace llvm #endif // LLVM_OBJECT_OBJECTFILE_H diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h deleted file mode 100644 index 9a978de2e599..000000000000 --- a/include/llvm/Object/RelocVisitor.h +++ /dev/null @@ -1,351 +0,0 @@ -//===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides a wrapper around all the different types of relocations -// in different file formats, such that a client can handle them in a unified -// manner by only implementing a minimal number of functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_RELOCVISITOR_H -#define LLVM_OBJECT_RELOCVISITOR_H - -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/ELF.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Object/COFF.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/Wasm.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include <cstdint> -#include <system_error> - -namespace llvm { -namespace object { - -/// Base class for object file relocation visitors. -class RelocVisitor { -public: - explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} - - // TODO: Should handle multiple applied relocations via either passing in the - // previously computed value or just count paired relocations as a single - // visit. - uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) { - if (isa<ELFObjectFileBase>(ObjToVisit)) - return visitELF(Rel, R, Value); - if (isa<COFFObjectFile>(ObjToVisit)) - return visitCOFF(Rel, R, Value); - if (isa<MachOObjectFile>(ObjToVisit)) - return visitMachO(Rel, R, Value); - if (isa<WasmObjectFile>(ObjToVisit)) - return visitWasm(Rel, R, Value); - - HasError = true; - return 0; - } - - bool error() { return HasError; } - -private: - const ObjectFile &ObjToVisit; - bool HasError = false; - - uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file - switch (ObjToVisit.getArch()) { - case Triple::x86_64: - return visitX86_64(Rel, R, Value); - case Triple::aarch64: - case Triple::aarch64_be: - return visitAarch64(Rel, R, Value); - case Triple::bpfel: - case Triple::bpfeb: - return visitBpf(Rel, R, Value); - case Triple::mips64el: - case Triple::mips64: - return visitMips64(Rel, R, Value); - case Triple::ppc64le: - case Triple::ppc64: - return visitPPC64(Rel, R, Value); - case Triple::systemz: - return visitSystemz(Rel, R, Value); - case Triple::sparcv9: - return visitSparc64(Rel, R, Value); - case Triple::amdgcn: - return visitAmdgpu(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - // 32-bit object file - assert(ObjToVisit.getBytesInAddress() == 4 && - "Invalid word size in object file"); - - switch (ObjToVisit.getArch()) { - case Triple::x86: - return visitX86(Rel, R, Value); - case Triple::ppc: - return visitPPC32(Rel, R, Value); - case Triple::arm: - case Triple::armeb: - return visitARM(Rel, R, Value); - case Triple::lanai: - return visitLanai(Rel, R, Value); - case Triple::mipsel: - case Triple::mips: - return visitMips32(Rel, R, Value); - case Triple::sparc: - return visitSparc32(Rel, R, Value); - case Triple::hexagon: - return visitHexagon(Rel, R, Value); - default: - HasError = true; - return 0; - } - } - - int64_t getELFAddend(RelocationRef R) { - Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); - handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { - report_fatal_error(EI.message()); - }); - return *AddendOrErr; - } - - uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_X86_64_NONE: - return 0; - case ELF::R_X86_64_64: - case ELF::R_X86_64_DTPOFF32: - case ELF::R_X86_64_DTPOFF64: - return Value + getELFAddend(R); - case ELF::R_X86_64_PC32: - return Value + getELFAddend(R) - R.getOffset(); - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - } - HasError = true; - return 0; - } - - uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_AARCH64_ABS32: { - int64_t Res = Value + getELFAddend(R); - if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; - return static_cast<uint32_t>(Res); - } - case ELF::R_AARCH64_ABS64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_BPF_64_32: - return Value & 0xFFFFFFFF; - case ELF::R_BPF_64_64: - return Value; - } - HasError = true; - return 0; - } - - uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_MIPS_32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_MIPS_64: - return Value + getELFAddend(R); - case ELF::R_MIPS_TLS_DTPREL64: - return Value + getELFAddend(R) - 0x8000; - } - HasError = true; - return 0; - } - - uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_PPC64_ADDR32: - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - case ELF::R_PPC64_ADDR64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_390_32: { - int64_t Res = Value + getELFAddend(R); - if (Res < INT32_MIN || Res > UINT32_MAX) - HasError = true; - return static_cast<uint32_t>(Res); - } - case ELF::R_390_64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_SPARC_32: - case ELF::R_SPARC_64: - case ELF::R_SPARC_UA32: - case ELF::R_SPARC_UA64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_AMDGPU_ABS32: - case ELF::R_AMDGPU_ABS64: - return Value + getELFAddend(R); - } - HasError = true; - return 0; - } - - uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (Rel) { - case ELF::R_386_NONE: - return 0; - case ELF::R_386_32: - return Value; - case ELF::R_386_PC32: - return Value - R.getOffset(); - } - HasError = true; - return 0; - } - - uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_PPC_ADDR32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_ARM_ABS32) { - if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX) - HasError = true; - return static_cast<uint32_t>(Value); - } - HasError = true; - return 0; - } - - uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_LANAI_32) - return (Value + getELFAddend(R)) & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) { - // FIXME: Take in account implicit addends to get correct results. - if (Rel == ELF::R_MIPS_32) - return Value & 0xFFFFFFFF; - if (Rel == ELF::R_MIPS_TLS_DTPREL32) - return Value & 0xFFFFFFFF; - HasError = true; - return 0; - } - - uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) - return Value + getELFAddend(R); - HasError = true; - return 0; - } - - uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (Rel == ELF::R_HEX_32) - return Value + getELFAddend(R); - HasError = true; - return 0; - } - - uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) { - switch (ObjToVisit.getArch()) { - case Triple::x86: - switch (Rel) { - case COFF::IMAGE_REL_I386_SECREL: - case COFF::IMAGE_REL_I386_DIR32: - return static_cast<uint32_t>(Value); - } - break; - case Triple::x86_64: - switch (Rel) { - case COFF::IMAGE_REL_AMD64_SECREL: - return static_cast<uint32_t>(Value); - case COFF::IMAGE_REL_AMD64_ADDR64: - return Value; - } - break; - default: - break; - } - HasError = true; - return 0; - } - - uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::x86_64 && - Rel == MachO::X86_64_RELOC_UNSIGNED) - return Value; - HasError = true; - return 0; - } - - uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) { - if (ObjToVisit.getArch() == Triple::wasm32) { - switch (Rel) { - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: - case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: - case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: - case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: - case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB: - // For wasm section, its offset at 0 -- ignoring Value - return 0; - } - } - HasError = true; - return 0; - } -}; - -} // end namespace object -} // end namespace llvm - -#endif // LLVM_OBJECT_RELOCVISITOR_H diff --git a/include/llvm/Object/RelocationResolver.h b/include/llvm/Object/RelocationResolver.h new file mode 100644 index 000000000000..1246dcc5ec73 --- /dev/null +++ b/include/llvm/Object/RelocationResolver.h @@ -0,0 +1,42 @@ +//===- RelocVisitor.h - Visitor for object file relocations -----*- 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 a wrapper around all the different types of relocations +// in different file formats, such that a client can handle them in a unified +// manner by only implementing a minimal number of functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RELOCVISITOR_H +#define LLVM_OBJECT_RELOCVISITOR_H + +#include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstdint> +#include <system_error> + +namespace llvm { +namespace object { + +using RelocationResolver = uint64_t (*)(RelocationRef R, uint64_t S, uint64_t A); + +std::pair<bool (*)(uint64_t), RelocationResolver> +getRelocationResolver(const ObjectFile &Obj); + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_RELOCVISITOR_H diff --git a/include/llvm/Object/StackMapParser.h b/include/llvm/Object/StackMapParser.h index 557db5afa825..ed44efbf80b9 100644 --- a/include/llvm/Object/StackMapParser.h +++ b/include/llvm/Object/StackMapParser.h @@ -1,9 +1,8 @@ //===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,8 +19,9 @@ namespace llvm { +/// A parser for the latest stackmap format. At the moment, latest=V2. template <support::endianness Endianness> -class StackMapV2Parser { +class StackMapParser { public: template <typename AccessorT> class AccessorIterator { @@ -50,7 +50,7 @@ public: /// Accessor for function records. class FunctionAccessor { - friend class StackMapV2Parser; + friend class StackMapParser; public: /// Get the function address. @@ -82,7 +82,7 @@ public: /// Accessor for constants. class ConstantAccessor { - friend class StackMapV2Parser; + friend class StackMapParser; public: /// Return the value of this constant. @@ -106,7 +106,7 @@ public: /// Accessor for location records. class LocationAccessor { - friend class StackMapV2Parser; + friend class StackMapParser; friend class RecordAccessor; public: @@ -115,6 +115,12 @@ public: return LocationKind(P[KindOffset]); } + /// Get the Size for this location. + unsigned getSizeInBytes() const { + return read<uint16_t>(P + SizeOffset); + + } + /// Get the Dwarf register number for this location. uint16_t getDwarfRegNum() const { return read<uint16_t>(P + DwarfRegNumOffset); @@ -149,16 +155,17 @@ public: } static const int KindOffset = 0; - static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t); - static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t); - static const int LocationAccessorSize = sizeof(uint64_t); + static const int SizeOffset = KindOffset + sizeof(uint16_t); + static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t); + static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t); + static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t); const uint8_t *P; }; /// Accessor for stackmap live-out fields. class LiveOutAccessor { - friend class StackMapV2Parser; + friend class StackMapParser; friend class RecordAccessor; public: @@ -189,7 +196,7 @@ public: /// Accessor for stackmap records. class RecordAccessor { - friend class StackMapV2Parser; + friend class StackMapParser; public: using location_iterator = AccessorIterator<LocationAccessor>; @@ -264,8 +271,9 @@ public: RecordAccessor(const uint8_t *P) : P(P) {} unsigned getNumLiveOutsOffset() const { - return LocationListOffset + LocationSize * getNumLocations() + - sizeof(uint16_t); + unsigned LocOffset = + ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7; + return LocOffset + sizeof(uint16_t); } unsigned getSizeInBytes() const { @@ -285,7 +293,7 @@ public: InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); static const unsigned LocationListOffset = NumLocationsOffset + sizeof(uint16_t); - static const unsigned LocationSize = sizeof(uint64_t); + static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t); static const unsigned LiveOutSize = sizeof(uint32_t); const uint8_t *P; @@ -293,12 +301,12 @@ public: /// Construct a parser for a version-2 stackmap. StackMap data will be read /// from the given array. - StackMapV2Parser(ArrayRef<uint8_t> StackMapSection) + StackMapParser(ArrayRef<uint8_t> StackMapSection) : StackMapSection(StackMapSection) { ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; - assert(StackMapSection[0] == 2 && - "StackMapV2Parser can only parse version 2 stackmaps"); + assert(StackMapSection[0] == 3 && + "StackMapParser can only parse version 3 stackmaps"); unsigned CurrentRecordOffset = ConstantsListOffset + getNumConstants() * ConstantSize; @@ -314,8 +322,8 @@ public: using constant_iterator = AccessorIterator<ConstantAccessor>; using record_iterator = AccessorIterator<RecordAccessor>; - /// Get the version number of this stackmap. (Always returns 2). - unsigned getVersion() const { return 2; } + /// Get the version number of this stackmap. (Always returns 3). + unsigned getVersion() const { return 3; } /// Get the number of functions in the stack map. uint32_t getNumFunctions() const { diff --git a/include/llvm/Object/SymbolSize.h b/include/llvm/Object/SymbolSize.h index 1a1dc8752943..085623e35907 100644 --- a/include/llvm/Object/SymbolSize.h +++ b/include/llvm/Object/SymbolSize.h @@ -1,9 +1,8 @@ //===- SymbolSize.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 5b9549bc3449..1398fa134c81 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -1,9 +1,8 @@ //===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -127,7 +126,7 @@ public: void moveNext(); - std::error_code printName(raw_ostream &OS) const; + Error printName(raw_ostream &OS) const; /// Get symbol flags (bitwise OR of SymbolRef::Flags) uint32_t getFlags() const; @@ -146,8 +145,7 @@ public: // virtual interface. virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; - virtual std::error_code printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const = 0; + virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; @@ -194,7 +192,7 @@ inline void BasicSymbolRef::moveNext() { return OwningObject->moveSymbolNext(SymbolPimpl); } -inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const { +inline Error BasicSymbolRef::printName(raw_ostream &OS) const { return OwningObject->printSymbolName(OS, SymbolPimpl); } diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h index ed857652a048..e130ea32ed21 100644 --- a/include/llvm/Object/Wasm.h +++ b/include/llvm/Object/Wasm.h @@ -1,9 +1,8 @@ -//===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===// +//===- Wasm.h - Wasm object file implementation -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -130,6 +129,10 @@ public: static bool classof(const Binary *v) { return v->isWasm(); } const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; } + const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; } + ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const { + return TargetFeatures; + } ArrayRef<wasm::WasmSignature> types() const { return Signatures; } ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; } ArrayRef<wasm::WasmImport> imports() const { return Imports; } @@ -149,7 +152,6 @@ public: uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } uint32_t getNumImportedEvents() const { return NumImportedEvents; } - void moveSymbolNext(DataRefImpl &Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; @@ -169,13 +171,12 @@ public: // Overrides from SectionRef. void moveSectionNext(DataRefImpl &Sec) const override; - std::error_code getSectionName(DataRefImpl Sec, - StringRef &Res) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; uint64_t getSectionAddress(DataRefImpl Sec) const override; uint64_t getSectionIndex(DataRefImpl Sec) const override; uint64_t getSectionSize(DataRefImpl Sec) const override; - std::error_code getSectionContents(DataRefImpl Sec, - StringRef &Res) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; @@ -222,13 +223,13 @@ private: bool isValidDataSymbol(uint32_t Index) const; bool isValidSectionSymbol(uint32_t Index) const; wasm::WasmFunction &getDefinedFunction(uint32_t Index); + const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const; wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); wasm::WasmEvent &getDefinedEvent(uint32_t Index); const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; - const uint8_t *getPtr(size_t Offset) const; Error parseSection(WasmSection &Sec); Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx); @@ -245,6 +246,7 @@ private: Error parseElemSection(ReadContext &Ctx); Error parseCodeSection(ReadContext &Ctx); Error parseDataSection(ReadContext &Ctx); + Error parseDataCountSection(ReadContext &Ctx); // Custom section types Error parseDylinkSection(ReadContext &Ctx); @@ -252,11 +254,15 @@ private: Error parseLinkingSection(ReadContext &Ctx); Error parseLinkingSectionSymtab(ReadContext &Ctx); Error parseLinkingSectionComdat(ReadContext &Ctx); + Error parseProducersSection(ReadContext &Ctx); + Error parseTargetFeaturesSection(ReadContext &Ctx); Error parseRelocSection(StringRef Name, ReadContext &Ctx); wasm::WasmObjectHeader Header; std::vector<WasmSection> Sections; wasm::WasmDylinkInfo DylinkInfo; + wasm::WasmProducerInfo ProducerInfo; + std::vector<wasm::WasmFeatureEntry> TargetFeatures; std::vector<wasm::WasmSignature> Signatures; std::vector<uint32_t> FunctionTypes; std::vector<wasm::WasmTable> Tables; @@ -267,6 +273,7 @@ private: std::vector<wasm::WasmExport> Exports; std::vector<wasm::WasmElemSegment> ElemSegments; std::vector<WasmSegment> DataSegments; + llvm::Optional<size_t> DataCount; std::vector<wasm::WasmFunction> Functions; std::vector<WasmSymbol> Symbols; std::vector<wasm::WasmFunctionName> DebugNames; @@ -287,40 +294,51 @@ class WasmSectionOrderChecker { public: // We define orders for all core wasm sections and known custom sections. enum : int { + // Sentinel, must be zero + WASM_SEC_ORDER_NONE = 0, + // Core sections - // The order of standard sections is precisely given by the spec. - WASM_SEC_ORDER_TYPE = 1, - WASM_SEC_ORDER_IMPORT = 2, - WASM_SEC_ORDER_FUNCTION = 3, - WASM_SEC_ORDER_TABLE = 4, - WASM_SEC_ORDER_MEMORY = 5, - WASM_SEC_ORDER_GLOBAL = 6, - WASM_SEC_ORDER_EVENT = 7, - WASM_SEC_ORDER_EXPORT = 8, - WASM_SEC_ORDER_START = 9, - WASM_SEC_ORDER_ELEM = 10, - WASM_SEC_ORDER_DATACOUNT = 11, - WASM_SEC_ORDER_CODE = 12, - WASM_SEC_ORDER_DATA = 13, + WASM_SEC_ORDER_TYPE, + WASM_SEC_ORDER_IMPORT, + WASM_SEC_ORDER_FUNCTION, + WASM_SEC_ORDER_TABLE, + WASM_SEC_ORDER_MEMORY, + WASM_SEC_ORDER_GLOBAL, + WASM_SEC_ORDER_EVENT, + WASM_SEC_ORDER_EXPORT, + WASM_SEC_ORDER_START, + WASM_SEC_ORDER_ELEM, + WASM_SEC_ORDER_DATACOUNT, + WASM_SEC_ORDER_CODE, + WASM_SEC_ORDER_DATA, // Custom sections // "dylink" should be the very first section in the module - WASM_SEC_ORDER_DYLINK = 0, + WASM_SEC_ORDER_DYLINK, // "linking" section requires DATA section in order to validate data symbols - WASM_SEC_ORDER_LINKING = 100, + WASM_SEC_ORDER_LINKING, // Must come after "linking" section in order to validate reloc indexes. - WASM_SEC_ORDER_RELOC = 101, + WASM_SEC_ORDER_RELOC, // "name" section must appear after DATA. Comes after "linking" to allow // symbol table to set default function name. - WASM_SEC_ORDER_NAME = 102, + WASM_SEC_ORDER_NAME, // "producers" section must appear after "name" section. - WASM_SEC_ORDER_PRODUCERS = 103 + WASM_SEC_ORDER_PRODUCERS, + // "target_features" section must appear after producers section + WASM_SEC_ORDER_TARGET_FEATURES, + + // Must be last + WASM_NUM_SEC_ORDERS + }; + // Sections that may or may not be present, but cannot be predecessors + static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS]; + bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = ""); private: - int LastOrder = -1; // Lastly seen known section's order + bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already // Returns -1 for unknown sections. int getSectionOrder(unsigned ID, StringRef CustomSectionName = ""); diff --git a/include/llvm/Object/WasmTraits.h b/include/llvm/Object/WasmTraits.h index 049d72f79e41..3eee8e71b187 100644 --- a/include/llvm/Object/WasmTraits.h +++ b/include/llvm/Object/WasmTraits.h @@ -1,9 +1,8 @@ //===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Object/WindowsMachineFlag.h b/include/llvm/Object/WindowsMachineFlag.h new file mode 100644 index 000000000000..acc6afc0329c --- /dev/null +++ b/include/llvm/Object/WindowsMachineFlag.h @@ -0,0 +1,33 @@ +//===- WindowsMachineFlag.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 +// +//===----------------------------------------------------------------------===// +// +// Functions for implementing the /machine: flag. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H +#define LLVM_TOOLDRIVERS_MACHINEFLAG_MACHINEFLAG_H + +namespace llvm { + +class StringRef; +namespace COFF { +enum MachineTypes : unsigned; +} + +// Returns a user-readable string for ARMNT, ARM64, AMD64, I386. +// Other MachineTypes values must not be passed in. +StringRef machineToStr(COFF::MachineTypes MT); + +// Maps /machine: arguments to a MachineTypes value. +// Only returns ARMNT, ARM64, AMD64, I386, or IMAGE_FILE_MACHINE_UNKNOWN. +COFF::MachineTypes getMachineType(StringRef S); + +} + +#endif diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h index a077c82871bf..356dcb03abba 100644 --- a/include/llvm/Object/WindowsResource.h +++ b/include/llvm/Object/WindowsResource.h @@ -1,9 +1,8 @@ //===-- WindowsResource.h ---------------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// // @@ -38,11 +37,14 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" -#include "llvm/Support/ScopedPrinter.h" #include <map> namespace llvm { + +class raw_ostream; +class ScopedPrinter; + namespace object { class WindowsResource; @@ -118,6 +120,7 @@ private: const WindowsResource *Owner); BinaryStreamReader Reader; + const WindowsResource *Owner; bool IsStringType; ArrayRef<UTF16> Type; uint16_t TypeID; @@ -149,7 +152,7 @@ class WindowsResourceParser { public: class TreeNode; WindowsResourceParser(); - Error parse(WindowsResource *WR); + Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates); void printTree(raw_ostream &OS) const; const TreeNode &getTree() const { return Root; } const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } @@ -185,21 +188,25 @@ public: static std::unique_ptr<TreeNode> createIDNode(); static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, uint16_t MinorVersion, - uint32_t Characteristics); + uint32_t Characteristics, + uint32_t Origin); explicit TreeNode(bool IsStringNode); TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, - uint32_t Characteristics); + uint32_t Characteristics, uint32_t Origin); - void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString, - bool &IsNewNameString); + bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin, + bool &IsNewTypeString, bool &IsNewNameString, + TreeNode *&Result); TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString); TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString); - TreeNode &addLanguageNode(const ResourceEntryRef &Entry); - TreeNode &addChild(uint32_t ID, bool IsDataNode = false, - uint16_t MajorVersion = 0, uint16_t MinorVersion = 0, - uint32_t Characteristics = 0); - TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString); + bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin, + TreeNode *&Result); + bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion, + uint32_t Characteristics, uint32_t Origin, + TreeNode *&Result); + TreeNode &addIDChild(uint32_t ID); + TreeNode &addNameChild(ArrayRef<UTF16> NameRef, bool &IsNewString); bool IsDataNode = false; uint32_t StringIndex; @@ -209,18 +216,26 @@ public: uint16_t MajorVersion = 0; uint16_t MinorVersion = 0; uint32_t Characteristics = 0; + + // The .res file that defined this TreeNode, for diagnostics. + // Index into InputFilenames. + uint32_t Origin; }; private: TreeNode Root; std::vector<std::vector<uint8_t>> Data; std::vector<std::vector<UTF16>> StringTable; + + std::vector<std::string> InputFilenames; }; Expected<std::unique_ptr<MemoryBuffer>> writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, - const WindowsResourceParser &Parser); + const WindowsResourceParser &Parser, + uint32_t TimeDateStamp); +void printResourceTypeName(uint16_t TypeID, raw_ostream &OS); } // namespace object } // namespace llvm diff --git a/include/llvm/Object/XCOFFObjectFile.h b/include/llvm/Object/XCOFFObjectFile.h new file mode 100644 index 000000000000..cdee7129a2ab --- /dev/null +++ b/include/llvm/Object/XCOFFObjectFile.h @@ -0,0 +1,268 @@ +//===- XCOFFObjectFile.h - XCOFF object file 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 declares the XCOFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_XCOFFOBJECTFILE_H +#define LLVM_OBJECT_XCOFFOBJECTFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include <cassert> +#include <cstdint> +#include <memory> +#include <system_error> + +namespace llvm { +namespace object { + +struct XCOFFFileHeader32 { + support::ubig16_t Magic; + support::ubig16_t NumberOfSections; + + // Unix time value, value of 0 indicates no timestamp. + // Negative values are reserved. + support::big32_t TimeStamp; + + support::ubig32_t SymbolTableOffset; // File offset to symbol table. + support::big32_t NumberOfSymTableEntries; + support::ubig16_t AuxHeaderSize; + support::ubig16_t Flags; +}; + +struct XCOFFFileHeader64 { + support::ubig16_t Magic; + support::ubig16_t NumberOfSections; + + // Unix time value, value of 0 indicates no timestamp. + // Negative values are reserved. + support::big32_t TimeStamp; + + support::ubig64_t SymbolTableOffset; // File offset to symbol table. + support::ubig16_t AuxHeaderSize; + support::ubig16_t Flags; + support::ubig32_t NumberOfSymTableEntries; +}; + +struct XCOFFSectionHeader32 { + char Name[XCOFF::SectionNameSize]; + support::ubig32_t PhysicalAddress; + support::ubig32_t VirtualAddress; + support::ubig32_t SectionSize; + support::ubig32_t FileOffsetToRawData; + support::ubig32_t FileOffsetToRelocationInfo; + support::ubig32_t FileOffsetToLineNumberInfo; + support::ubig16_t NumberOfRelocations; + support::ubig16_t NumberOfLineNumbers; + support::big32_t Flags; + + StringRef getName() const; +}; + +struct XCOFFSectionHeader64 { + char Name[XCOFF::SectionNameSize]; + support::ubig64_t PhysicalAddress; + support::ubig64_t VirtualAddress; + support::ubig64_t SectionSize; + support::big64_t FileOffsetToRawData; + support::big64_t FileOffsetToRelocationInfo; + support::big64_t FileOffsetToLineNumberInfo; + support::ubig32_t NumberOfRelocations; + support::ubig32_t NumberOfLineNumbers; + support::big32_t Flags; + char Padding[4]; + + StringRef getName() const; +}; + +struct XCOFFSymbolEntry { + enum { NAME_IN_STR_TBL_MAGIC = 0x0 }; + typedef struct { + support::big32_t Magic; // Zero indicates name in string table. + support::ubig32_t Offset; + } NameInStrTblType; + + typedef struct { + uint8_t LanguageId; + uint8_t CpuTypeId; + } CFileLanguageIdAndTypeIdType; + + union { + char SymbolName[XCOFF::SymbolNameSize]; + NameInStrTblType NameInStrTbl; + }; + + support::ubig32_t Value; // Symbol value; storage class-dependent. + support::big16_t SectionNumber; + + union { + support::ubig16_t SymbolType; + CFileLanguageIdAndTypeIdType CFileLanguageIdAndTypeId; + }; + + XCOFF::StorageClass StorageClass; + uint8_t NumberOfAuxEntries; +}; + +struct XCOFFStringTable { + uint32_t Size; + const char *Data; +}; + +class XCOFFObjectFile : public ObjectFile { +private: + const void *FileHeader = nullptr; + const void *SectionHeaderTable = nullptr; + + const XCOFFSymbolEntry *SymbolTblPtr = nullptr; + XCOFFStringTable StringTable = {0, nullptr}; + + const XCOFFFileHeader32 *fileHeader32() const; + const XCOFFFileHeader64 *fileHeader64() const; + + const XCOFFSectionHeader32 *sectionHeaderTable32() const; + const XCOFFSectionHeader64 *sectionHeaderTable64() const; + + size_t getFileHeaderSize() const; + size_t getSectionHeaderSize() const; + + const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; + const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; + void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; + uintptr_t getSectionHeaderTableAddress() const; + + // This returns a pointer to the start of the storage for the name field of + // the 32-bit or 64-bit SectionHeader struct. This string is *not* necessarily + // null-terminated. + const char *getSectionNameInternal(DataRefImpl Sec) const; + + int32_t getSectionFlags(DataRefImpl Sec) const; + + static bool isReservedSectionNumber(int16_t SectionNumber); + Expected<DataRefImpl> getSectionByNum(int16_t Num) const; + + // Constructor and "create" factory function. The constructor is only a thin + // wrapper around the base constructor. The "create" function fills out the + // XCOFF-specific information and performs the error checking along the way. + XCOFFObjectFile(unsigned Type, MemoryBufferRef Object); + static Expected<std::unique_ptr<XCOFFObjectFile>> create(unsigned Type, + MemoryBufferRef MBR); + + // Helper for parsing the StringTable. Returns an 'Error' if parsing failed + // and an XCOFFStringTable if parsing succeeded. + static Expected<XCOFFStringTable> parseStringTable(const XCOFFObjectFile *Obj, + uint64_t Offset); + + // Make a friend so it can call the private 'create' function. + friend Expected<std::unique_ptr<ObjectFile>> + ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object, unsigned FileType); + +public: + // Interface inherited from base classes. + void moveSymbolNext(DataRefImpl &Symb) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + basic_symbol_iterator symbol_begin() const override; + basic_symbol_iterator symbol_end() const override; + + Expected<StringRef> getSymbolName(DataRefImpl Symb) const override; + Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override; + Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected<StringRef> getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected<ArrayRef<uint8_t>> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + + bool isSectionVirtual(DataRefImpl Sec) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + section_iterator section_begin() const override; + section_iterator section_end() const override; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + Triple::ArchType getArch() const override; + SubtargetFeatures getFeatures() const override; + Expected<uint64_t> getStartAddress() const override; + bool isRelocatableObject() const override; + + // Below here is the non-inherited interface. + bool is64Bit() const; + + const XCOFFSymbolEntry *getPointerToSymbolTable() const { + assert(!is64Bit() && "Symbol table handling not supported yet."); + return SymbolTblPtr; + } + + Expected<StringRef> + getSymbolSectionName(const XCOFFSymbolEntry *SymEntPtr) const; + + const XCOFFSymbolEntry *toSymbolEntry(DataRefImpl Ref) const; + + // File header related interfaces. + uint16_t getMagic() const; + uint16_t getNumberOfSections() const; + int32_t getTimeStamp() const; + + // Symbol table offset and entry count are handled differently between + // XCOFF32 and XCOFF64. + uint32_t getSymbolTableOffset32() const; + uint64_t getSymbolTableOffset64() const; + + // Note that this value is signed and might return a negative value. Negative + // values are reserved for future use. + int32_t getRawNumberOfSymbolTableEntries32() const; + + // The sanitized value appropriate to use as an index into the symbol table. + uint32_t getLogicalNumberOfSymbolTableEntries32() const; + + uint32_t getNumberOfSymbolTableEntries64() const; + + uint16_t getOptionalHeaderSize() const; + uint16_t getFlags() const; + + // Section header table related interfaces. + ArrayRef<XCOFFSectionHeader32> sections32() const; + ArrayRef<XCOFFSectionHeader64> sections64() const; +}; // XCOFFObjectFile + +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_XCOFFOBJECTFILE_H diff --git a/include/llvm/ObjectYAML/COFFYAML.h b/include/llvm/ObjectYAML/COFFYAML.h index 253c627dd683..eec5af928f6d 100644 --- a/include/llvm/ObjectYAML/COFFYAML.h +++ b/include/llvm/ObjectYAML/COFFYAML.h @@ -1,9 +1,8 @@ //===- COFFYAML.h - COFF YAMLIO implementation ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h index d620008e22d2..9cbacb88b518 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h @@ -1,9 +1,8 @@ //=- CodeViewYAMLDebugSections.h - CodeView YAMLIO debug sections -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h b/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h index 791193c78f19..7c05c9eea05e 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLSymbols.h @@ -1,9 +1,8 @@ //===- CodeViewYAMLSymbols.h - CodeView YAMLIO Symbol implementation ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h b/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h index 344966fe6891..d6cec8d310eb 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h @@ -1,9 +1,8 @@ //==- CodeViewYAMLTypeHashing.h - CodeView YAMLIO Type hashing ----*- C++-*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h index 1b1306df4f53..04b5e0ba3aa1 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h @@ -1,9 +1,8 @@ //==- CodeViewYAMLTypes.h - CodeView YAMLIO Type implementation --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ObjectYAML/DWARFEmitter.h b/include/llvm/ObjectYAML/DWARFEmitter.h index ce3227421930..2ccc876d5023 100644 --- a/include/llvm/ObjectYAML/DWARFEmitter.h +++ b/include/llvm/ObjectYAML/DWARFEmitter.h @@ -1,9 +1,8 @@ //===--- DWARFEmitter.h - ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/ObjectYAML/DWARFYAML.h b/include/llvm/ObjectYAML/DWARFYAML.h index 705c88778945..78d736c3ef05 100644 --- a/include/llvm/ObjectYAML/DWARFYAML.h +++ b/include/llvm/ObjectYAML/DWARFYAML.h @@ -1,9 +1,8 @@ //===- DWARFYAML.h - DWARF YAMLIO implementation ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/ObjectYAML/ELFYAML.h b/include/llvm/ObjectYAML/ELFYAML.h index f2b0c35521f0..f4212516f486 100644 --- a/include/llvm/ObjectYAML/ELFYAML.h +++ b/include/llvm/ObjectYAML/ELFYAML.h @@ -1,9 +1,8 @@ //===- ELFYAML.h - ELF YAMLIO implementation --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -44,6 +43,8 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) +// Just use 64, since it can hold 32-bit values too. +LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_DYNTAG) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_PF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) @@ -51,6 +52,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_SHN) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STB) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) @@ -73,6 +75,11 @@ struct FileHeader { ELF_EM Machine; ELF_EF Flags; llvm::yaml::Hex64 Entry; + + Optional<llvm::yaml::Hex16> SHEntSize; + Optional<llvm::yaml::Hex16> SHOffset; + Optional<llvm::yaml::Hex16> SHNum; + Optional<llvm::yaml::Hex16> SHStrNdx; }; struct SectionName { @@ -85,53 +92,81 @@ struct ProgramHeader { llvm::yaml::Hex64 VAddr; llvm::yaml::Hex64 PAddr; Optional<llvm::yaml::Hex64> Align; + Optional<llvm::yaml::Hex64> FileSize; + Optional<llvm::yaml::Hex64> MemSize; + Optional<llvm::yaml::Hex64> Offset; std::vector<SectionName> Sections; }; struct Symbol { StringRef Name; + Optional<uint32_t> NameIndex; ELF_STT Type; StringRef Section; Optional<ELF_SHN> Index; + ELF_STB Binding; llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Size; uint8_t Other; }; -struct LocalGlobalWeakSymbols { - std::vector<Symbol> Local; - std::vector<Symbol> Global; - std::vector<Symbol> Weak; -}; - struct SectionOrType { StringRef sectionNameOrType; }; +struct DynamicEntry { + ELF_DYNTAG Tag; + llvm::yaml::Hex64 Val; +}; + struct Section { enum class SectionKind { + Dynamic, Group, RawContent, Relocation, NoBits, + Verdef, + Verneed, + Symver, MipsABIFlags }; SectionKind Kind; StringRef Name; ELF_SHT Type; - ELF_SHF Flags; + Optional<ELF_SHF> Flags; llvm::yaml::Hex64 Address; StringRef Link; - StringRef Info; llvm::yaml::Hex64 AddressAlign; Optional<llvm::yaml::Hex64> EntSize; + // This can be used to override the sh_offset field. It does not place the + // section data at the offset specified. Useful for creating invalid objects. + Optional<llvm::yaml::Hex64> ShOffset; + + // This can be used to override the sh_size field. It does not affect the + // content written. + Optional<llvm::yaml::Hex64> ShSize; + Section(SectionKind Kind) : Kind(Kind) {} virtual ~Section(); }; + +struct DynamicSection : Section { + std::vector<DynamicEntry> Entries; + Optional<yaml::BinaryRef> Content; + + DynamicSection() : Section(SectionKind::Dynamic) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Dynamic; + } +}; + struct RawContentSection : Section { - yaml::BinaryRef Content; - llvm::yaml::Hex64 Size; + Optional<yaml::BinaryRef> Content; + Optional<llvm::yaml::Hex64> Size; + Optional<llvm::yaml::Hex64> Info; RawContentSection() : Section(SectionKind::RawContent) {} @@ -150,10 +185,64 @@ struct NoBitsSection : Section { } }; +struct VernauxEntry { + uint32_t Hash; + uint16_t Flags; + uint16_t Other; + StringRef Name; +}; + +struct VerneedEntry { + uint16_t Version; + StringRef File; + std::vector<VernauxEntry> AuxV; +}; + +struct VerneedSection : Section { + std::vector<VerneedEntry> VerneedV; + llvm::yaml::Hex64 Info; + + VerneedSection() : Section(SectionKind::Verneed) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Verneed; + } +}; + +struct SymverSection : Section { + std::vector<uint16_t> Entries; + + SymverSection() : Section(SectionKind::Symver) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Symver; + } +}; + +struct VerdefEntry { + uint16_t Version; + uint16_t Flags; + uint16_t VersionNdx; + uint32_t Hash; + std::vector<StringRef> VerNames; +}; + +struct VerdefSection : Section { + std::vector<VerdefEntry> Entries; + llvm::yaml::Hex64 Info; + + VerdefSection() : Section(SectionKind::Verdef) {} + + static bool classof(const Section *S) { + return S->Kind == SectionKind::Verdef; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. std::vector<SectionOrType> Members; + StringRef Signature; /* Info */ Group() : Section(SectionKind::Group) {} @@ -171,6 +260,7 @@ struct Relocation { struct RelocationSection : Section { std::vector<Relocation> Relocations; + StringRef RelocatableSec; /* Info */ RelocationSection() : Section(SectionKind::Relocation) {} @@ -208,16 +298,20 @@ struct Object { // cleaner and nicer if we read them from the YAML as a separate // top-level key, which automatically ensures that invariants like there // being a single SHT_SYMTAB section are upheld. - LocalGlobalWeakSymbols Symbols; - LocalGlobalWeakSymbols DynamicSymbols; + std::vector<Symbol> Symbols; + std::vector<Symbol> DynamicSymbols; }; } // end namespace ELFYAML } // end namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::DynamicEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::ProgramHeader) LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerdefEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VernauxEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::VerneedEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionOrType) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::SectionName) @@ -277,6 +371,10 @@ template <> struct ScalarEnumerationTraits<ELFYAML::ELF_SHN> { static void enumeration(IO &IO, ELFYAML::ELF_SHN &Value); }; +template <> struct ScalarEnumerationTraits<ELFYAML::ELF_STB> { + static void enumeration(IO &IO, ELFYAML::ELF_STB &Value); +}; + template <> struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); @@ -298,6 +396,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { }; template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_DYNTAG> { + static void enumeration(IO &IO, ELFYAML::ELF_DYNTAG &Value); +}; + +template <> struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> { static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); }; @@ -347,9 +450,20 @@ struct MappingTraits<ELFYAML::Symbol> { static StringRef validate(IO &IO, ELFYAML::Symbol &Symbol); }; -template <> -struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> { - static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); +template <> struct MappingTraits<ELFYAML::DynamicEntry> { + static void mapping(IO &IO, ELFYAML::DynamicEntry &Rel); +}; + +template <> struct MappingTraits<ELFYAML::VerdefEntry> { + static void mapping(IO &IO, ELFYAML::VerdefEntry &E); +}; + +template <> struct MappingTraits<ELFYAML::VerneedEntry> { + static void mapping(IO &IO, ELFYAML::VerneedEntry &E); +}; + +template <> struct MappingTraits<ELFYAML::VernauxEntry> { + static void mapping(IO &IO, ELFYAML::VernauxEntry &E); }; template <> struct MappingTraits<ELFYAML::Relocation> { diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h index cec4f86185f0..d7e1c033f43b 100644 --- a/include/llvm/ObjectYAML/MachOYAML.h +++ b/include/llvm/ObjectYAML/MachOYAML.h @@ -1,9 +1,8 @@ //===- MachOYAML.h - Mach-O YAMLIO implementation ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/ObjectYAML/MinidumpYAML.h b/include/llvm/ObjectYAML/MinidumpYAML.h new file mode 100644 index 000000000000..39fdd62e017b --- /dev/null +++ b/include/llvm/ObjectYAML/MinidumpYAML.h @@ -0,0 +1,239 @@ +//===- MinidumpYAML.h - Minidump YAMLIO 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECTYAML_MINIDUMPYAML_H +#define LLVM_OBJECTYAML_MINIDUMPYAML_H + +#include "llvm/BinaryFormat/Minidump.h" +#include "llvm/Object/Minidump.h" +#include "llvm/ObjectYAML/YAML.h" +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace MinidumpYAML { + +/// The base class for all minidump streams. The "Type" of the stream +/// corresponds to the Stream Type field in the minidump file. The "Kind" field +/// specifies how are we going to treat it. For highly specialized streams (e.g. +/// SystemInfo), there is a 1:1 mapping between Types and Kinds, but in general +/// one stream Kind can be used to represent multiple stream Types (e.g. any +/// unrecognised stream Type will be handled via RawContentStream). The mapping +/// from Types to Kinds is fixed and given by the static getKind function. +struct Stream { + enum class StreamKind { + MemoryList, + ModuleList, + RawContent, + SystemInfo, + TextContent, + ThreadList, + }; + + Stream(StreamKind Kind, minidump::StreamType Type) : Kind(Kind), Type(Type) {} + virtual ~Stream(); // anchor + + const StreamKind Kind; + const minidump::StreamType Type; + + /// Get the stream Kind used for representing streams of a given Type. + static StreamKind getKind(minidump::StreamType Type); + + /// Create an empty stream of the given Type. + static std::unique_ptr<Stream> create(minidump::StreamType Type); + + /// Create a stream from the given stream directory entry. + static Expected<std::unique_ptr<Stream>> + create(const minidump::Directory &StreamDesc, + const object::MinidumpFile &File); +}; + +namespace detail { +/// A stream representing a list of abstract entries in a minidump stream. Its +/// instantiations can be used to represent the ModuleList stream and other +/// streams with a similar structure. +template <typename EntryT> struct ListStream : public Stream { + using entry_type = EntryT; + + std::vector<entry_type> Entries; + + explicit ListStream(std::vector<entry_type> Entries = {}) + : Stream(EntryT::Kind, EntryT::Type), Entries(std::move(Entries)) {} + + static bool classof(const Stream *S) { return S->Kind == EntryT::Kind; } +}; + +/// A structure containing all data belonging to a single minidump module. +struct ParsedModule { + static constexpr Stream::StreamKind Kind = Stream::StreamKind::ModuleList; + static constexpr minidump::StreamType Type = minidump::StreamType::ModuleList; + + minidump::Module Entry; + std::string Name; + yaml::BinaryRef CvRecord; + yaml::BinaryRef MiscRecord; +}; + +/// A structure containing all data belonging to a single minidump thread. +struct ParsedThread { + static constexpr Stream::StreamKind Kind = Stream::StreamKind::ThreadList; + static constexpr minidump::StreamType Type = minidump::StreamType::ThreadList; + + minidump::Thread Entry; + yaml::BinaryRef Stack; + yaml::BinaryRef Context; +}; + +/// A structure containing all data describing a single memory region. +struct ParsedMemoryDescriptor { + static constexpr Stream::StreamKind Kind = Stream::StreamKind::MemoryList; + static constexpr minidump::StreamType Type = minidump::StreamType::MemoryList; + + minidump::MemoryDescriptor Entry; + yaml::BinaryRef Content; +}; +} // namespace detail + +using ModuleListStream = detail::ListStream<detail::ParsedModule>; +using ThreadListStream = detail::ListStream<detail::ParsedThread>; +using MemoryListStream = detail::ListStream<detail::ParsedMemoryDescriptor>; + +/// A minidump stream represented as a sequence of hex bytes. This is used as a +/// fallback when no other stream kind is suitable. +struct RawContentStream : public Stream { + yaml::BinaryRef Content; + yaml::Hex32 Size; + + RawContentStream(minidump::StreamType Type, ArrayRef<uint8_t> Content = {}) + : Stream(StreamKind::RawContent, Type), Content(Content), + Size(Content.size()) {} + + static bool classof(const Stream *S) { + return S->Kind == StreamKind::RawContent; + } +}; + +/// SystemInfo minidump stream. +struct SystemInfoStream : public Stream { + minidump::SystemInfo Info; + std::string CSDVersion; + + explicit SystemInfoStream(const minidump::SystemInfo &Info, + std::string CSDVersion) + : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo), + Info(Info), CSDVersion(std::move(CSDVersion)) {} + + SystemInfoStream() + : Stream(StreamKind::SystemInfo, minidump::StreamType::SystemInfo) { + memset(&Info, 0, sizeof(Info)); + } + + static bool classof(const Stream *S) { + return S->Kind == StreamKind::SystemInfo; + } +}; + +/// A StringRef, which is printed using YAML block notation. +LLVM_YAML_STRONG_TYPEDEF(StringRef, BlockStringRef) + +/// A minidump stream containing textual data (typically, the contents of a +/// /proc/<pid> file on linux). +struct TextContentStream : public Stream { + BlockStringRef Text; + + TextContentStream(minidump::StreamType Type, StringRef Text = {}) + : Stream(StreamKind::TextContent, Type), Text(Text) {} + + static bool classof(const Stream *S) { + return S->Kind == StreamKind::TextContent; + } +}; + +/// The top level structure representing a minidump object, consisting of a +/// minidump header, and zero or more streams. To construct an Object from a +/// minidump file, use the static create function. To serialize to/from yaml, +/// use the appropriate streaming operator on a yaml stream. +struct Object { + Object() = default; + Object(const Object &) = delete; + Object &operator=(const Object &) = delete; + Object(Object &&) = default; + Object &operator=(Object &&) = default; + + Object(const minidump::Header &Header, + std::vector<std::unique_ptr<Stream>> Streams) + : Header(Header), Streams(std::move(Streams)) {} + + /// The minidump header. + minidump::Header Header; + + /// The list of streams in this minidump object. + std::vector<std::unique_ptr<Stream>> Streams; + + static Expected<Object> create(const object::MinidumpFile &File); +}; + +/// Serialize the minidump file represented by Obj to OS in binary form. +void writeAsBinary(Object &Obj, raw_ostream &OS); + +/// Serialize the yaml string as a minidump file to OS in binary form. +Error writeAsBinary(StringRef Yaml, raw_ostream &OS); + +} // namespace MinidumpYAML + +namespace yaml { +template <> struct BlockScalarTraits<MinidumpYAML::BlockStringRef> { + static void output(const MinidumpYAML::BlockStringRef &Text, void *, + raw_ostream &OS) { + OS << Text; + } + + static StringRef input(StringRef Scalar, void *, + MinidumpYAML::BlockStringRef &Text) { + Text = Scalar; + return ""; + } +}; + +template <> struct MappingTraits<std::unique_ptr<MinidumpYAML::Stream>> { + static void mapping(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S); + static StringRef validate(IO &IO, std::unique_ptr<MinidumpYAML::Stream> &S); +}; + +template <> struct MappingContextTraits<minidump::MemoryDescriptor, BinaryRef> { + static void mapping(IO &IO, minidump::MemoryDescriptor &Memory, + BinaryRef &Content); +}; + +} // namespace yaml + +} // namespace llvm + +LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::ProcessorArchitecture) +LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::OSPlatform) +LLVM_YAML_DECLARE_ENUM_TRAITS(llvm::minidump::StreamType) + +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::ArmInfo) +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::OtherInfo) +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::CPUInfo::X86Info) +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::minidump::VSFixedFileInfo) + +LLVM_YAML_DECLARE_MAPPING_TRAITS( + llvm::MinidumpYAML::MemoryListStream::entry_type) +LLVM_YAML_DECLARE_MAPPING_TRAITS( + llvm::MinidumpYAML::ModuleListStream::entry_type) +LLVM_YAML_DECLARE_MAPPING_TRAITS( + llvm::MinidumpYAML::ThreadListStream::entry_type) + +LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::MinidumpYAML::Stream>) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::MemoryListStream::entry_type) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ModuleListStream::entry_type) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MinidumpYAML::ThreadListStream::entry_type) + +LLVM_YAML_DECLARE_MAPPING_TRAITS(llvm::MinidumpYAML::Object) + +#endif // LLVM_OBJECTYAML_MINIDUMPYAML_H diff --git a/include/llvm/ObjectYAML/ObjectYAML.h b/include/llvm/ObjectYAML/ObjectYAML.h index 00ce86430fca..0015fd3dc501 100644 --- a/include/llvm/ObjectYAML/ObjectYAML.h +++ b/include/llvm/ObjectYAML/ObjectYAML.h @@ -1,9 +1,8 @@ //===- ObjectYAML.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -13,6 +12,7 @@ #include "llvm/ObjectYAML/COFFYAML.h" #include "llvm/ObjectYAML/ELFYAML.h" #include "llvm/ObjectYAML/MachOYAML.h" +#include "llvm/ObjectYAML/MinidumpYAML.h" #include "llvm/ObjectYAML/WasmYAML.h" #include "llvm/Support/YAMLTraits.h" #include <memory> @@ -27,6 +27,7 @@ struct YamlObjectFile { std::unique_ptr<COFFYAML::Object> Coff; std::unique_ptr<MachOYAML::Object> MachO; std::unique_ptr<MachOYAML::UniversalBinary> FatMachO; + std::unique_ptr<MinidumpYAML::Object> Minidump; std::unique_ptr<WasmYAML::Object> Wasm; }; diff --git a/include/llvm/ObjectYAML/WasmYAML.h b/include/llvm/ObjectYAML/WasmYAML.h index 406dd7cb515f..2411dc7ac17d 100644 --- a/include/llvm/ObjectYAML/WasmYAML.h +++ b/include/llvm/ObjectYAML/WasmYAML.h @@ -1,9 +1,8 @@ //===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -39,6 +38,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind) LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags) LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, FeaturePolicyPrefix) struct FileHeader { yaml::Hex32 Version; @@ -112,8 +112,9 @@ struct Relocation { }; struct DataSegment { - uint32_t MemoryIndex; uint32_t SectionOffset; + uint32_t InitFlags; + uint32_t MemoryIndex; wasm::WasmInitExpr Offset; yaml::BinaryRef Content; }; @@ -123,6 +124,16 @@ struct NameEntry { StringRef Name; }; +struct ProducerEntry { + std::string Name; + std::string Version; +}; + +struct FeatureEntry { + FeaturePolicyPrefix Prefix; + std::string Name; +}; + struct SegmentInfo { uint32_t Index; StringRef Name; @@ -224,6 +235,30 @@ struct LinkingSection : CustomSection { std::vector<Comdat> Comdats; }; +struct ProducersSection : CustomSection { + ProducersSection() : CustomSection("producers") {} + + static bool classof(const Section *S) { + auto C = dyn_cast<CustomSection>(S); + return C && C->Name == "producers"; + } + + std::vector<ProducerEntry> Languages; + std::vector<ProducerEntry> Tools; + std::vector<ProducerEntry> SDKs; +}; + +struct TargetFeaturesSection : CustomSection { + TargetFeaturesSection() : CustomSection("target_features") {} + + static bool classof(const Section *S) { + auto C = dyn_cast<CustomSection>(S); + return C && C->Name == "target_features"; + } + + std::vector<FeatureEntry> Features; +}; + struct TypeSection : Section { TypeSection() : Section(wasm::WASM_SEC_TYPE) {} @@ -344,6 +379,16 @@ struct DataSection : Section { std::vector<DataSegment> Segments; }; +struct DataCountSection : Section { + DataCountSection() : Section(wasm::WASM_SEC_DATACOUNT) {} + + static bool classof(const Section *S) { + return S->Type == wasm::WASM_SEC_DATACOUNT; + } + + uint32_t Count; +}; + struct Object { FileHeader Header; std::vector<std::unique_ptr<Section>> Sections; @@ -366,6 +411,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ProducerEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::FeatureEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction) @@ -444,6 +491,18 @@ template <> struct MappingTraits<WasmYAML::NameEntry> { static void mapping(IO &IO, WasmYAML::NameEntry &NameEntry); }; +template <> struct MappingTraits<WasmYAML::ProducerEntry> { + static void mapping(IO &IO, WasmYAML::ProducerEntry &ProducerEntry); +}; + +template <> struct ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix> { + static void enumeration(IO &IO, WasmYAML::FeaturePolicyPrefix &Prefix); +}; + +template <> struct MappingTraits<WasmYAML::FeatureEntry> { + static void mapping(IO &IO, WasmYAML::FeatureEntry &FeatureEntry); +}; + template <> struct MappingTraits<WasmYAML::SegmentInfo> { static void mapping(IO &IO, WasmYAML::SegmentInfo &SegmentInfo); }; diff --git a/include/llvm/ObjectYAML/XCOFFYAML.h b/include/llvm/ObjectYAML/XCOFFYAML.h new file mode 100644 index 000000000000..f99004e69762 --- /dev/null +++ b/include/llvm/ObjectYAML/XCOFFYAML.h @@ -0,0 +1,71 @@ +//===----- XCOFFYAML.h - XCOFF YAMLIO 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 declares classes for handling the YAML representation of XCOFF. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_OBJECTYAML_XCOFFYAML_H +#define LLVM_OBJECTYAML_XCOFFYAML_H + +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/ObjectYAML/YAML.h" +#include <vector> + +namespace llvm { +namespace XCOFFYAML { + +struct FileHeader { + llvm::yaml::Hex16 Magic; + uint16_t NumberOfSections; + int32_t TimeStamp; + llvm::yaml::Hex32 SymbolTableOffset; // File offset to symbol table. + int32_t NumberOfSymTableEntries; + uint16_t AuxHeaderSize; + llvm::yaml::Hex16 Flags; +}; + +struct Symbol { + StringRef SymbolName; + llvm::yaml::Hex32 Value; // Symbol value; storage class-dependent. + StringRef SectionName; + llvm::yaml::Hex16 Type; + XCOFF::StorageClass StorageClass; + uint8_t NumberOfAuxEntries; // Number of auxiliary entries +}; + +struct Object { + FileHeader Header; + std::vector<Symbol> Symbols; + Object(); +}; +} // namespace XCOFFYAML +} // namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(XCOFFYAML::Symbol) +namespace llvm { +namespace yaml { + +template <> struct ScalarEnumerationTraits<XCOFF::StorageClass> { + static void enumeration(IO &IO, XCOFF::StorageClass &Value); +}; + +template <> struct MappingTraits<XCOFFYAML::FileHeader> { + static void mapping(IO &IO, XCOFFYAML::FileHeader &H); +}; + +template <> struct MappingTraits<XCOFFYAML::Object> { + static void mapping(IO &IO, XCOFFYAML::Object &Obj); +}; + +template <> struct MappingTraits<XCOFFYAML::Symbol> { + static void mapping(IO &IO, XCOFFYAML::Symbol &S); +}; + +} // namespace yaml +} // namespace llvm + +#endif // LLVM_OBJECTYAML_XCOFFYAML_H diff --git a/include/llvm/ObjectYAML/YAML.h b/include/llvm/ObjectYAML/YAML.h index 163cd8dfcf08..37014109a615 100644 --- a/include/llvm/ObjectYAML/YAML.h +++ b/include/llvm/ObjectYAML/YAML.h @@ -1,9 +1,8 @@ //===- YAML.h ---------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -74,8 +73,7 @@ class BinaryRef { public: BinaryRef() = default; BinaryRef(ArrayRef<uint8_t> Data) : Data(Data), DataIsHexString(false) {} - BinaryRef(StringRef Data) - : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()) {} + BinaryRef(StringRef Data) : Data(arrayRefFromStringRef(Data)) {} /// The number of bytes that are represented by this BinaryRef. /// This is the number of bytes that writeAsBinary() will write. diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index d0086bb6d611..22e2bcf06a6e 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -1,9 +1,8 @@ //===- Arg.h - Parsed Argument Classes --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// @@ -59,6 +58,11 @@ private: /// The argument values, as C strings. SmallVector<const char *, 2> Values; + /// If this arg was created through an alias, this is the original alias arg. + /// For example, *this might be "-finput-charset=utf-8" and Alias might + /// point to an arg representing "/source-charset:utf-8". + std::unique_ptr<Arg> Alias; + public: Arg(const Option Opt, StringRef Spelling, unsigned Index, const Arg *BaseArg = nullptr); @@ -71,7 +75,15 @@ public: ~Arg(); const Option &getOption() const { return Opt; } + + /// Returns the used prefix and name of the option: + /// For `--foo=bar`, returns `--foo=`. + /// This is often the wrong function to call: + /// * Use `getValue()` to get `bar`. + /// * Use `getAsString()` to get a string suitable for printing an Arg in + /// a diagnostic. StringRef getSpelling() const { return Spelling; } + unsigned getIndex() const { return Index; } /// Return the base argument which generated this arg. @@ -83,6 +95,11 @@ public: } void setBaseArg(const Arg *BaseArg) { this->BaseArg = BaseArg; } + /// Args are converted to their unaliased form. For args that originally + /// came from an alias, this returns the alias the arg was produced from. + const Arg* getAlias() const { return Alias.get(); } + void setAlias(std::unique_ptr<Arg> Alias) { this->Alias = std::move(Alias); } + bool getOwnsValues() const { return OwnsValues; } void setOwnsValues(bool Value) const { OwnsValues = Value; } @@ -120,8 +137,10 @@ public: void print(raw_ostream &O) const; void dump() const; - /// Return a formatted version of the argument and - /// its values, for debugging and diagnostics. + /// Return a formatted version of the argument and its values, for + /// diagnostics. Since this is for diagnostics, if this Arg was produced + /// through an alias, this returns the string representation of the alias + /// that the user wrote. std::string getAsString(const ArgList &Args) const; }; diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 687c8cbb02f9..74bfadcba726 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -1,9 +1,8 @@ //===- ArgList.h - Argument List Management ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -302,10 +301,12 @@ public: bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, bool Default = true) const; - /// AddLastArg - Render only the last argument match \p Id0, if present. - void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; - void AddLastArg(ArgStringList &Output, OptSpecifier Id0, - OptSpecifier Id1) const; + /// Render only the last argument match \p Id0, if present. + template<typename ...OptSpecifiers> + void AddLastArg(ArgStringList &Output, OptSpecifiers ...Ids) const { + if (Arg *A = getLastArg(Ids...)) // Calls claim() on all Ids's Args. + A->render(*this, Output); + } /// AddAllArgsExcept - Render all arguments matching any of the given ids /// and not matching any of the excluded ids. diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index 9c373741770b..a68f17a8b10b 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -1,9 +1,8 @@ //===--- OptParser.td - Common Option Parsing Interfaces ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index 84c3cf8ad534..7a5fcfb18b38 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -1,9 +1,8 @@ //===- OptSpecifier.h - Option Specifiers -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index fdb05d8a15af..5db30436069d 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -1,9 +1,8 @@ //===- OptTable.h - Option Table --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index b09f6043b7a9..33813d28d274 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -1,9 +1,8 @@ //===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -207,6 +206,11 @@ public: /// start. Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const; +private: + Arg *acceptInternal(const ArgList &Args, unsigned &Index, + unsigned ArgSize) const; + +public: void print(raw_ostream &O) const; void dump() const; }; diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 5935a0853d32..329f7eaba73d 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -1,9 +1,8 @@ //===- llvm/Pass.h - Base class for Passes ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index a075eb557472..1228534deb95 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -1,9 +1,8 @@ //===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h index 2f1ab4d43377..686fc044ebcb 100644 --- a/include/llvm/PassInfo.h +++ b/include/llvm/PassInfo.h @@ -1,9 +1,8 @@ //===- llvm/PassInfo.h - Pass Info class ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 57462138c5ae..b9a015430c10 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -1,9 +1,8 @@ //===- llvm/PassRegistry.h - Pass Information Registry ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index 1bf23dcba50b..ab90217ce4a8 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -1,9 +1,8 @@ //===- llvm/PassSupport.h - Pass Support code -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h index fa59345a02cf..5e6660599f93 100644 --- a/include/llvm/Passes/PassBuilder.h +++ b/include/llvm/Passes/PassBuilder.h @@ -1,9 +1,8 @@ //===- Parsing, selection, and construction of pass pipelines --*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -32,36 +31,85 @@ class ModuleSummaryIndex; /// A struct capturing PGO tunables. struct PGOOptions { - PGOOptions(std::string ProfileGenFile = "", std::string ProfileUseFile = "", - std::string SampleProfileFile = "", - std::string ProfileRemappingFile = "", - bool RunProfileGen = false, bool SamplePGOSupport = false) - : ProfileGenFile(ProfileGenFile), ProfileUseFile(ProfileUseFile), - SampleProfileFile(SampleProfileFile), - ProfileRemappingFile(ProfileRemappingFile), - RunProfileGen(RunProfileGen), - SamplePGOSupport(SamplePGOSupport || !SampleProfileFile.empty()) { - assert((RunProfileGen || - !SampleProfileFile.empty() || - !ProfileUseFile.empty() || - SamplePGOSupport) && "Illegal PGOOptions."); + enum PGOAction { NoAction, IRInstr, IRUse, SampleUse }; + enum CSPGOAction { NoCSAction, CSIRInstr, CSIRUse }; + PGOOptions(std::string ProfileFile = "", std::string CSProfileGenFile = "", + std::string ProfileRemappingFile = "", PGOAction Action = NoAction, + CSPGOAction CSAction = NoCSAction, bool SamplePGOSupport = false) + : ProfileFile(ProfileFile), CSProfileGenFile(CSProfileGenFile), + ProfileRemappingFile(ProfileRemappingFile), Action(Action), + CSAction(CSAction), + SamplePGOSupport(SamplePGOSupport || Action == SampleUse) { + // Note, we do allow ProfileFile.empty() for Action=IRUse LTO can + // callback with IRUse action without ProfileFile. + + // If there is a CSAction, PGOAction cannot be IRInstr or SampleUse. + assert(this->CSAction == NoCSAction || + (this->Action != IRInstr && this->Action != SampleUse)); + + // For CSIRInstr, CSProfileGenFile also needs to be nonempty. + assert(this->CSAction != CSIRInstr || !this->CSProfileGenFile.empty()); + + // If CSAction is CSIRUse, PGOAction needs to be IRUse as they share + // a profile. + assert(this->CSAction != CSIRUse || this->Action == IRUse); + + // If neither Action nor CSAction, SamplePGOSupport needs to be true. + assert(this->Action != NoAction || this->CSAction != NoCSAction || + this->SamplePGOSupport); } - std::string ProfileGenFile; - std::string ProfileUseFile; - std::string SampleProfileFile; + std::string ProfileFile; + std::string CSProfileGenFile; std::string ProfileRemappingFile; - bool RunProfileGen; + PGOAction Action; + CSPGOAction CSAction; bool SamplePGOSupport; }; +/// Tunable parameters for passes in the default pipelines. +class PipelineTuningOptions { +public: + /// Constructor sets pipeline tuning defaults based on cl::opts. Each option + /// can be set in the PassBuilder when using a LLVM as a library. + PipelineTuningOptions(); + + /// Tuning option to set loop interleaving on/off. Its default value is that + /// of the flag: `-interleave-loops`. + bool LoopInterleaving; + + /// Tuning option to enable/disable loop vectorization. Its default value is + /// that of the flag: `-vectorize-loops`. + bool LoopVectorization; + + /// Tuning option to enable/disable slp loop vectorization. Its default value + /// is that of the flag: `vectorize-slp`. + bool SLPVectorization; + + /// Tuning option to enable/disable loop unrolling. Its default value is true. + bool LoopUnrolling; + + /// Tuning option to forget all SCEV loops in LoopUnroll. Its default value + /// is that of the flag: `-forget-scev-loop-unroll`. + bool ForgetAllSCEVInLoopUnroll; + + /// Tuning option to cap the number of calls to retrive clobbering accesses in + /// MemorySSA, in LICM. + unsigned LicmMssaOptCap; + + /// Tuning option to disable promotion to scalars in LICM with MemorySSA, if + /// the number of access is too large. + unsigned LicmMssaNoAccForPromotionCap; +}; + /// This class provides access to building LLVM's passes. /// -/// It's members provide the baseline state available to passes during their +/// Its members provide the baseline state available to passes during their /// construction. The \c PassRegistry.def file specifies how to construct all /// of the built-in passes, and those may reference these members during /// construction. class PassBuilder { TargetMachine *TM; + PipelineTuningOptions PTO; Optional<PGOOptions> PGOOpt; PassInstrumentationCallbacks *PIC; @@ -85,9 +133,9 @@ public: enum class ThinLTOPhase { /// No ThinLTO behavior needed. None, - // ThinLTO prelink (summary) phase. + /// ThinLTO prelink (summary) phase. PreLink, - // ThinLTO postlink (backend compile) phase. + /// ThinLTO postlink (backend compile) phase. PostLink }; @@ -178,14 +226,15 @@ public: }; explicit PassBuilder(TargetMachine *TM = nullptr, + PipelineTuningOptions PTO = PipelineTuningOptions(), Optional<PGOOptions> PGOOpt = None, PassInstrumentationCallbacks *PIC = nullptr) - : TM(TM), PGOOpt(PGOOpt), PIC(PIC) {} + : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) {} /// Cross register the analysis managers through their proxies. /// /// This is an interface that can be used to cross register each - // AnalysisManager with all the others analysis managers. + /// AnalysisManager with all the others analysis managers. void crossRegisterProxies(LoopAnalysisManager &LAM, FunctionAnalysisManager &FAM, CGSCCAnalysisManager &CGAM, @@ -275,7 +324,8 @@ public: /// require some transformations for semantic reasons, they should explicitly /// build them. ModulePassManager buildModuleOptimizationPipeline(OptimizationLevel Level, - bool DebugLogging = false); + bool DebugLogging = false, + bool LTOPreLink = false); /// Build a per-module default optimization pipeline. /// @@ -289,7 +339,8 @@ public: /// require some transformations for semantic reasons, they should explicitly /// build them. ModulePassManager buildPerModuleDefaultPipeline(OptimizationLevel Level, - bool DebugLogging = false); + bool DebugLogging = false, + bool LTOPreLink = false); /// Build a pre-link, ThinLTO-targeting default optimization pipeline to /// a pass manager. @@ -392,7 +443,7 @@ public: /// {{@ Parse a textual pass pipeline description into a specific PassManager /// /// Automatic deduction of an appropriate pass manager stack is not supported. - /// For example, to insert a loop pass 'lpass' into a FunctinoPassManager, + /// For example, to insert a loop pass 'lpass' into a FunctionPassManager, /// this is the valid pipeline text: /// /// function(lpass) @@ -606,9 +657,8 @@ private: bool VerifyEachPass, bool DebugLogging); void addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, - OptimizationLevel Level, bool RunProfileGen, - std::string ProfileGenFile, - std::string ProfileUseFile, + OptimizationLevel Level, bool RunProfileGen, bool IsCS, + std::string ProfileFile, std::string ProfileRemappingFile); void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); diff --git a/include/llvm/Passes/PassPlugin.h b/include/llvm/Passes/PassPlugin.h index af8f11a7a352..013b7a827c47 100644 --- a/include/llvm/Passes/PassPlugin.h +++ b/include/llvm/Passes/PassPlugin.h @@ -1,9 +1,8 @@ //===- llvm/Passes/PassPlugin.h - Public Plugin API -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Passes/StandardInstrumentations.h b/include/llvm/Passes/StandardInstrumentations.h index 8c6f5e1e22f7..3d3002eecce9 100644 --- a/include/llvm/Passes/StandardInstrumentations.h +++ b/include/llvm/Passes/StandardInstrumentations.h @@ -1,9 +1,8 @@ //===- StandardInstrumentations.h ------------------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -64,6 +63,8 @@ public: StandardInstrumentations() = default; void registerCallbacks(PassInstrumentationCallbacks &PIC); + + TimePassesHandler &getTimePasses() { return TimePasses; } }; } // namespace llvm diff --git a/include/llvm/ProfileData/Coverage/CoverageMapping.h b/include/llvm/ProfileData/Coverage/CoverageMapping.h index beaa36553287..11758ac4cf2f 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -1,9 +1,8 @@ //===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index c88c71a6d6f4..57a2aaefd660 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -1,9 +1,8 @@ //===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -204,9 +203,15 @@ public: BinaryCoverageReader(const BinaryCoverageReader &) = delete; BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; + static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> + create(MemoryBufferRef ObjectBuffer, StringRef Arch, + SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers); + static Expected<std::unique_ptr<BinaryCoverageReader>> - create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, - StringRef Arch); + createCoverageReaderFromBuffer(StringRef Coverage, + InstrProfSymtab &&ProfileNames, + uint8_t BytesInAddress, + support::endianness Endian); Error readNextRecord(CoverageMappingRecord &Record) override; }; diff --git a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h index 86fb1bdf1773..5f88cacdfcbb 100644 --- a/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h +++ b/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h @@ -1,9 +1,8 @@ //===- CoverageMappingWriter.h - Code coverage mapping writer ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ProfileData/GCOV.h b/include/llvm/ProfileData/GCOV.h index a088f63a6915..004ff3f4a2e2 100644 --- a/include/llvm/ProfileData/GCOV.h +++ b/include/llvm/ProfileData/GCOV.h @@ -1,9 +1,8 @@ //===- GCOV.h - LLVM coverage tool ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -45,9 +44,10 @@ enum GCOVVersion { V402, V404, V704 }; /// A struct for passing gcov options between functions. struct Options { - Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) + Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N, bool X) : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), - PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} + PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N), + HashFilenames(X) {} bool AllBlocks; bool BranchInfo; @@ -57,6 +57,7 @@ struct Options { bool UncondBranch; bool LongFileNames; bool NoOutput; + bool HashFilenames; }; } // end namespace GCOV @@ -317,12 +318,6 @@ class GCOVBlock { uint64_t Count = 0; }; - struct SortDstEdgesFunctor { - bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { - return E1->Dst.Number < E2->Dst.Number; - } - }; - public: using EdgeIterator = SmallVectorImpl<GCOVEdge *>::const_iterator; using BlockVector = SmallVector<const GCOVBlock *, 4>; diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index dc45021fc47d..c7d764ade30d 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -1,9 +1,8 @@ //===- InstrProf.h - Instrumented profiling format support ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -235,7 +234,7 @@ bool isIRPGOFlagSet(const Module *M); bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false); enum InstrProfValueKind : uint32_t { -#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value, +#define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value, #include "llvm/ProfileData/InstrProfData.inc" }; @@ -591,6 +590,70 @@ StringRef InstrProfSymtab::getOrigFuncName(uint64_t FuncMD5Hash) { return PGOName.drop_front(S + 1); } +// To store the sums of profile count values, or the percentage of +// the sums of the total count values. +struct CountSumOrPercent { + uint64_t NumEntries; + double CountSum; + double ValueCounts[IPVK_Last - IPVK_First + 1]; + CountSumOrPercent() : NumEntries(0), CountSum(0.0f), ValueCounts() {} + void reset() { + NumEntries = 0; + CountSum = 0.0f; + for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) + ValueCounts[I] = 0.0f; + } +}; + +// Function level or program level overlap information. +struct OverlapStats { + enum OverlapStatsLevel { ProgramLevel, FunctionLevel }; + // Sum of the total count values for the base profile. + CountSumOrPercent Base; + // Sum of the total count values for the test profile. + CountSumOrPercent Test; + // Overlap lap score. Should be in range of [0.0f to 1.0f]. + CountSumOrPercent Overlap; + CountSumOrPercent Mismatch; + CountSumOrPercent Unique; + OverlapStatsLevel Level; + const std::string *BaseFilename; + const std::string *TestFilename; + StringRef FuncName; + uint64_t FuncHash; + bool Valid; + + OverlapStats(OverlapStatsLevel L = ProgramLevel) + : Level(L), BaseFilename(nullptr), TestFilename(nullptr), FuncHash(0), + Valid(false) {} + + void dump(raw_fd_ostream &OS) const; + + void setFuncInfo(StringRef Name, uint64_t Hash) { + FuncName = Name; + FuncHash = Hash; + } + + Error accumuateCounts(const std::string &BaseFilename, + const std::string &TestFilename, bool IsCS); + void addOneMismatch(const CountSumOrPercent &MismatchFunc); + void addOneUnique(const CountSumOrPercent &UniqueFunc); + + static inline double score(uint64_t Val1, uint64_t Val2, double Sum1, + double Sum2) { + if (Sum1 < 1.0f || Sum2 < 1.0f) + return 0.0f; + return std::min(Val1 / Sum1, Val2 / Sum2); + } +}; + +// This is used to filter the functions whose overlap information +// to be output. +struct OverlapFuncFilters { + uint64_t ValueCutoff; + const std::string NameFilter; +}; + struct InstrProfValueSiteRecord { /// Value profiling data pairs at a given value site. std::list<InstrProfValueData> ValueData; @@ -616,6 +679,10 @@ struct InstrProfValueSiteRecord { function_ref<void(instrprof_error)> Warn); /// Scale up value profile data counts. void scale(uint64_t Weight, function_ref<void(instrprof_error)> Warn); + + /// Compute the overlap b/w this record and Input record. + void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind, + OverlapStats &Overlap, OverlapStats &FuncLevelOverlap); }; /// Profiling information for a single function. @@ -704,6 +771,18 @@ struct InstrProfRecord { /// Clear value data entries void clearValueData() { ValueData = nullptr; } + /// Compute the sums of all counts and store in Sum. + void accumuateCounts(CountSumOrPercent &Sum) const; + + /// Compute the overlap b/w this IntrprofRecord and Other. + void overlap(InstrProfRecord &Other, OverlapStats &Overlap, + OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff); + + /// Compute the overlap of value profile counts. + void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src, + OverlapStats &Overlap, + OverlapStats &FuncLevelOverlap); + private: struct ValueProfData { std::vector<InstrProfValueSiteRecord> IndirectCallSites; @@ -768,10 +847,20 @@ struct NamedInstrProfRecord : InstrProfRecord { StringRef Name; uint64_t Hash; + // We reserve this bit as the flag for context sensitive profile record. + static const int CS_FLAG_IN_FUNC_HASH = 60; + NamedInstrProfRecord() = default; NamedInstrProfRecord(StringRef Name, uint64_t Hash, std::vector<uint64_t> Counts) : InstrProfRecord(std::move(Counts)), Name(Name), Hash(Hash) {} + + static bool hasCSFlagInHash(uint64_t FuncHash) { + return ((FuncHash >> CS_FLAG_IN_FUNC_HASH) & 1); + } + static void setCSFlagInHash(uint64_t &FuncHash) { + FuncHash |= ((uint64_t)1 << CS_FLAG_IN_FUNC_HASH); + } }; uint32_t InstrProfRecord::getNumValueKinds() const { @@ -1005,6 +1094,8 @@ namespace RawInstrProf { // from control data struct is changed from raw pointer to Name's MD5 value. // Version 4: ValueDataBegin and ValueDataSizes fields are removed from the // raw header. +// Version 5: Bit 60 of FuncHash is reserved for the flag for the context +// sensitive records. const uint64_t Version = INSTR_PROF_RAW_VERSION; template <class IntPtrT> inline uint64_t getMagic(); @@ -1041,6 +1132,12 @@ struct Header { void getMemOPSizeRangeFromOption(StringRef Str, int64_t &RangeStart, int64_t &RangeLast); -} // end namespace llvm +// Create a COMDAT variable INSTR_PROF_RAW_VERSION_VAR to make the runtime +// aware this is an ir_level profile so it can set the version flag. +void createIRLevelProfileFlagVar(Module &M, bool IsCS); +// Create the variable for the profile file name. +void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput); + +} // end namespace llvm #endif // LLVM_PROFILEDATA_INSTRPROF_H diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc index 454620ed997a..749781b9ac2d 100644 --- a/include/llvm/ProfileData/InstrProfData.inc +++ b/include/llvm/ProfileData/InstrProfData.inc @@ -1,9 +1,8 @@ /*===-- InstrProfData.inc - instr profiling runtime structures -*- C++ -*-=== *\ |* -|* The LLVM Compiler Infrastructure -|* -|* This file is distributed under the University of Illinois Open Source -|* License. See LICENSE.TXT for details. +|* 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 |* \*===----------------------------------------------------------------------===*/ /* @@ -170,7 +169,7 @@ VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx)) /* VALUE_PROF_KIND start */ #ifndef VALUE_PROF_KIND -#define VALUE_PROF_KIND(Enumerator, Value) +#define VALUE_PROF_KIND(Enumerator, Value, Descr) #else #define INSTR_PROF_DATA_DEFINED #endif @@ -183,16 +182,16 @@ VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx)) * For this remapping the ProfData is used. ProfData contains both the function * name hash and the function address. */ -VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0) +VALUE_PROF_KIND(IPVK_IndirectCallTarget, 0, "indirect call target") /* For memory intrinsic functions size profiling. */ -VALUE_PROF_KIND(IPVK_MemOPSize, 1) +VALUE_PROF_KIND(IPVK_MemOPSize, 1, "memory intrinsic functions size") /* These two kinds must be the last to be * declared. This is to make sure the string * array created with the template can be * indexed with the kind value. */ -VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget) -VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize) +VALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget, "first") +VALUE_PROF_KIND(IPVK_Last, IPVK_MemOPSize, "last") #undef VALUE_PROF_KIND /* VALUE_PROF_KIND end */ @@ -250,22 +249,25 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \ #define INSTR_PROF_DATA_DEFINED INSTR_PROF_SECT_ENTRY(IPSK_data, \ INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_DATA_COFF), "__DATA,") + INSTR_PROF_DATA_COFF, "__DATA,") INSTR_PROF_SECT_ENTRY(IPSK_cnts, \ INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COFF), "__DATA,") + INSTR_PROF_CNTS_COFF, "__DATA,") INSTR_PROF_SECT_ENTRY(IPSK_name, \ INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_NAME_COFF), "__DATA,") + INSTR_PROF_NAME_COFF, "__DATA,") INSTR_PROF_SECT_ENTRY(IPSK_vals, \ INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_VALS_COFF), "__DATA,") + INSTR_PROF_VALS_COFF, "__DATA,") INSTR_PROF_SECT_ENTRY(IPSK_vnodes, \ INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COFF), "__DATA,") + INSTR_PROF_VNODES_COFF, "__DATA,") INSTR_PROF_SECT_ENTRY(IPSK_covmap, \ INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \ - INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COFF), "__LLVM_COV,") + INSTR_PROF_COVMAP_COFF, "__LLVM_COV,") +INSTR_PROF_SECT_ENTRY(IPSK_orderfile, \ + INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \ + INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,") #undef INSTR_PROF_SECT_ENTRY #endif @@ -636,10 +638,12 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, * version for other variants of profile. We set the lowest bit of the upper 8 * bits (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentaiton * generated profile, and 0 if this is a Clang FE generated profile. + * 1 in bit 57 indicates there are context-sensitive records in the profile. */ #define VARIANT_MASKS_ALL 0xff00000000000000ULL #define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) #define VARIANT_MASK_IR_PROF (0x1ULL << 56) +#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57) #define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version #define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime @@ -655,13 +659,17 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_VALS_COMMON __llvm_prf_vals #define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds #define INSTR_PROF_COVMAP_COMMON __llvm_covmap -/* Win32 */ -#define INSTR_PROF_DATA_COFF .lprfd -#define INSTR_PROF_NAME_COFF .lprfn -#define INSTR_PROF_CNTS_COFF .lprfc -#define INSTR_PROF_VALS_COFF .lprfv -#define INSTR_PROF_VNODES_COFF .lprfnd -#define INSTR_PROF_COVMAP_COFF .lcovmap +#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile +/* Windows section names. Because these section names contain dollar characters, + * they must be quoted. + */ +#define INSTR_PROF_DATA_COFF ".lprfd$M" +#define INSTR_PROF_NAME_COFF ".lprfn$M" +#define INSTR_PROF_CNTS_COFF ".lprfc$M" +#define INSTR_PROF_VALS_COFF ".lprfv$M" +#define INSTR_PROF_VNODES_COFF ".lprfnd$M" +#define INSTR_PROF_COVMAP_COFF ".lcovmap$M" +#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" #ifdef _WIN32 /* Runtime section names and name strings. */ @@ -675,32 +683,30 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, /* Value profile nodes section. */ #define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF #define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF +#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF #else /* Runtime section names and name strings. */ -#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COMMON -#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COMMON -#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COMMON +#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON) +#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON) +#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON) /* Array of pointers. Each pointer points to a list * of value nodes associated with one value site. */ -#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COMMON +#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON) /* Value profile nodes section. */ -#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COMMON -#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COMMON +#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON) +#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON) +/* Order file instrumentation. */ +#define INSTR_PROF_ORDERFILE_SECT_NAME \ + INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON) #endif -#define INSTR_PROF_DATA_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_DATA_SECT_NAME) -#define INSTR_PROF_NAME_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_NAME_SECT_NAME) -#define INSTR_PROF_CNTS_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_CNTS_SECT_NAME) -#define INSTR_PROF_COVMAP_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_SECT_NAME) -#define INSTR_PROF_VALS_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_VALS_SECT_NAME) -#define INSTR_PROF_VNODES_SECT_NAME_STR \ - INSTR_PROF_QUOTE(INSTR_PROF_VNODES_SECT_NAME) +#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer +#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME) +#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx +#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \ + INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME) /* Macros to define start/stop section symbol for a given * section on Linux. For instance @@ -735,6 +741,12 @@ typedef struct InstrProfValueData { #endif /* INSTR_PROF_DATA_INC */ +#ifndef INSTR_ORDER_FILE_INC +// The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB). +#define INSTR_ORDER_FILE_BUFFER_SIZE 131072 +#define INSTR_ORDER_FILE_BUFFER_BITS 17 +#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff +#endif /* INSTR_ORDER_FILE_INC */ #else #undef INSTR_PROF_DATA_DEFINED #endif diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 08d782276117..73751faab88e 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -1,9 +1,8 @@ //===- InstrProfReader.h - Instrumented profiling readers -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -78,6 +77,8 @@ public: virtual bool isIRLevelProfile() const = 0; + virtual bool hasCSIRLevelProfile() const = 0; + /// Return the PGO symtab. There are three different readers: /// Raw, Text, and Indexed profile readers. The first two types /// of readers are used only by llvm-profdata tool, while the indexed @@ -90,6 +91,9 @@ public: /// compiler. virtual InstrProfSymtab &getSymtab() = 0; + /// Compute the sum of counts and return in Sum. + void accumuateCounts(CountSumOrPercent &Sum, bool IsCS); + protected: std::unique_ptr<InstrProfSymtab> Symtab; @@ -143,6 +147,7 @@ private: /// Iterator over the profile data. line_iterator Line; bool IsIRLevelProfile = false; + bool HasCSIRLevelProfile = false; Error readValueProfileData(InstrProfRecord &Record); @@ -157,6 +162,8 @@ public: bool isIRLevelProfile() const override { return IsIRLevelProfile; } + bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; } + /// Read the header. Error readHeader() override; @@ -213,6 +220,10 @@ public: return (Version & VARIANT_MASK_IR_PROF) != 0; } + bool hasCSIRLevelProfile() const override { + return (Version & VARIANT_MASK_CSIR_PROF) != 0; + } + InstrProfSymtab &getSymtab() override { assert(Symtab.get()); return *Symtab.get(); @@ -342,6 +353,7 @@ struct InstrProfReaderIndexBase { virtual void setValueProfDataEndianness(support::endianness Endianness) = 0; virtual uint64_t getVersion() const = 0; virtual bool isIRLevelProfile() const = 0; + virtual bool hasCSIRLevelProfile() const = 0; virtual Error populateSymtab(InstrProfSymtab &) = 0; }; @@ -386,6 +398,10 @@ public: return (FormatVersion & VARIANT_MASK_IR_PROF) != 0; } + bool hasCSIRLevelProfile() const override { + return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0; + } + Error populateSymtab(InstrProfSymtab &Symtab) override { return Symtab.create(HashTable->keys()); } @@ -413,13 +429,16 @@ private: std::unique_ptr<InstrProfReaderRemapper> Remapper; /// Profile summary data. std::unique_ptr<ProfileSummary> Summary; + /// Context sensitive profile summary data. + std::unique_ptr<ProfileSummary> CS_Summary; // Index to the current record in the record array. unsigned RecordIndex; // Read the profile summary. Return a pointer pointing to one byte past the // end of the summary data if it exists or the input \c Cur. + // \c UseCS indicates whether to use the context-sensitive profile summary. const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version, - const unsigned char *Cur); + const unsigned char *Cur, bool UseCS); public: IndexedInstrProfReader( @@ -433,6 +452,9 @@ public: /// Return the profile version. uint64_t getVersion() const { return Index->getVersion(); } bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); } + bool hasCSIRLevelProfile() const override { + return Index->hasCSIRLevelProfile(); + } /// Return true if the given buffer is in an indexed instrprof format. static bool hasFormat(const MemoryBuffer &DataBuffer); @@ -451,7 +473,16 @@ public: std::vector<uint64_t> &Counts); /// Return the maximum of all known function counts. - uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); } + /// \c UseCS indicates whether to use the context-sensitive count. + uint64_t getMaximumFunctionCount(bool UseCS) { + if (UseCS) { + assert(CS_Summary && "No context sensitive profile summary"); + return CS_Summary->getMaxFunctionCount(); + } else { + assert(Summary && "No profile summary"); + return Summary->getMaxFunctionCount(); + } + } /// Factory method to create an indexed reader. static Expected<std::unique_ptr<IndexedInstrProfReader>> @@ -470,7 +501,18 @@ public: // to be used by llvm-profdata (for dumping). Avoid using this when // the client is the compiler. InstrProfSymtab &getSymtab() override; - ProfileSummary &getSummary() { return *(Summary.get()); } + + /// Return the profile summary. + /// \c UseCS indicates whether to use the context-sensitive summary. + ProfileSummary &getSummary(bool UseCS) { + if (UseCS) { + assert(CS_Summary && "No context sensitive summary"); + return *(CS_Summary.get()); + } else { + assert(Summary && "No profile summary"); + return *(Summary.get()); + } + } }; } // end namespace llvm diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index 8107ab386fe2..5882fa2781e2 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -1,9 +1,8 @@ //===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -34,7 +33,8 @@ class raw_fd_ostream; class InstrProfWriter { public: using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord>; - enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel }; + // PF_IRLevelWithCS is the profile from context sensitive IR instrumentation. + enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel, PF_IRLevelWithCS }; private: bool Sparse; @@ -75,20 +75,36 @@ public: std::unique_ptr<MemoryBuffer> writeBuffer(); /// Set the ProfileKind. Report error if mixing FE and IR level profiles. - Error setIsIRLevelProfile(bool IsIRLevel) { + /// \c WithCS indicates if this is for contenxt sensitive instrumentation. + Error setIsIRLevelProfile(bool IsIRLevel, bool WithCS) { if (ProfileKind == PF_Unknown) { - ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE; + if (IsIRLevel) + ProfileKind = WithCS ? PF_IRLevelWithCS : PF_IRLevel; + else + ProfileKind = PF_FE; return Error::success(); } - return (IsIRLevel == (ProfileKind == PF_IRLevel)) - ? Error::success() - : make_error<InstrProfError>( - instrprof_error::unsupported_version); + + if (((ProfileKind != PF_FE) && !IsIRLevel) || + ((ProfileKind == PF_FE) && IsIRLevel)) + return make_error<InstrProfError>(instrprof_error::unsupported_version); + + // When merging a context-sensitive profile (WithCS == true) with an IRLevel + // profile, set the kind to PF_IRLevelWithCS. + if (ProfileKind == PF_IRLevel && WithCS) + ProfileKind = PF_IRLevelWithCS; + + return Error::success(); } // Internal interface for testing purpose only. void setValueProfDataEndianness(support::endianness Endianness); void setOutputSparse(bool Sparse); + // Compute the overlap b/w this object and Other. Program level result is + // stored in Overlap and function level result is stored in FuncLevelOverlap. + void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap, + OverlapStats &FuncLevelOverlap, + const OverlapFuncFilters &FuncFilter); private: void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I, diff --git a/include/llvm/ProfileData/ProfileCommon.h b/include/llvm/ProfileData/ProfileCommon.h index 087588f06340..f98a34387fdf 100644 --- a/include/llvm/ProfileData/ProfileCommon.h +++ b/include/llvm/ProfileData/ProfileCommon.h @@ -1,9 +1,8 @@ //===- ProfileCommon.h - Common profiling APIs. -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -84,7 +83,8 @@ public: SampleProfileSummaryBuilder(std::vector<uint32_t> Cutoffs) : ProfileSummaryBuilder(std::move(Cutoffs)) {} - void addRecord(const sampleprof::FunctionSamples &FS); + void addRecord(const sampleprof::FunctionSamples &FS, + bool isCallsiteSample = false); std::unique_ptr<ProfileSummary> getSummary(); }; diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index 927dfd246878..7fbc857b7230 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -1,9 +1,8 @@ //===- SampleProf.h - Sampling profiling format support ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -411,6 +410,34 @@ public: return getNameInModule(Name, M); } + /// Return the canonical name for a function, taking into account + /// suffix elision policy attributes. + static StringRef getCanonicalFnName(const Function &F) { + static const char *knownSuffixes[] = { ".llvm.", ".part." }; + auto AttrName = "sample-profile-suffix-elision-policy"; + auto Attr = F.getFnAttribute(AttrName).getValueAsString(); + if (Attr == "" || Attr == "all") { + return F.getName().split('.').first; + } else if (Attr == "selected") { + StringRef Cand(F.getName()); + for (const auto &Suf : knownSuffixes) { + StringRef Suffix(Suf); + auto It = Cand.rfind(Suffix); + if (It == StringRef::npos) + return Cand; + auto Dit = Cand.rfind('.'); + if (Dit == It + Suffix.size() - 1) + Cand = Cand.substr(0, It); + } + return Cand; + } else if (Attr == "none") { + return F.getName(); + } else { + assert(false && "internal error: unknown suffix elision policy"); + } + return F.getName(); + } + /// Translate \p Name into its original name in Module. /// When the Format is not SPF_Compact_Binary, \p Name needs no translation. /// When the Format is SPF_Compact_Binary, \p Name in current FunctionSamples @@ -466,11 +493,9 @@ public: /// built in post-thin-link phase and var promotion has been done, /// we need to add the substring of function name without the suffix /// into the GUIDToFuncNameMap. - auto pos = OrigName.find('.'); - if (pos != StringRef::npos) { - StringRef NewName = OrigName.substr(0, pos); - GUIDToFuncNameMap.insert({Function::getGUID(NewName), NewName}); - } + StringRef CanonName = getCanonicalFnName(F); + if (CanonName != OrigName) + GUIDToFuncNameMap.insert({Function::getGUID(CanonName), CanonName}); } CurrentModule = &M; } @@ -547,10 +572,9 @@ public: SampleSorter(const std::map<LocationT, SampleT> &Samples) { for (const auto &I : Samples) V.push_back(&I); - std::stable_sort(V.begin(), V.end(), - [](const SamplesWithLoc *A, const SamplesWithLoc *B) { - return A->first < B->first; - }); + llvm::stable_sort(V, [](const SamplesWithLoc *A, const SamplesWithLoc *B) { + return A->first < B->first; + }); } const SamplesWithLocList &get() const { return V; } diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h index 5cc729e42cc8..969cdea859c9 100644 --- a/include/llvm/ProfileData/SampleProfReader.h +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -1,9 +1,8 @@ //===- SampleProfReader.h - Read LLVM sample profile data -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -287,10 +286,11 @@ public: /// Return the samples collected for function \p F. FunctionSamples *getSamplesFor(const Function &F) { - // The function name may have been updated by adding suffix. In sample - // profile, the function names are all stripped, so we need to strip - // the function name suffix before matching with profile. - return getSamplesFor(F.getName().split('.').first); + // The function name may have been updated by adding suffix. Call + // a helper to (optionally) strip off suffixes so that we can + // match against the original function name in the profile. + StringRef CanonName = FunctionSamples::getCanonicalFnName(F); + return getSamplesFor(CanonName); } /// Return the samples collected for function \p F. diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h index d5ac6e53e4f7..81e6e3ab0b4a 100644 --- a/include/llvm/ProfileData/SampleProfWriter.h +++ b/include/llvm/ProfileData/SampleProfWriter.h @@ -1,9 +1,8 @@ //===- SampleProfWriter.h - Write LLVM sample profile data ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Remarks/Remark.h b/include/llvm/Remarks/Remark.h new file mode 100644 index 000000000000..05d0ea60accd --- /dev/null +++ b/include/llvm/Remarks/Remark.h @@ -0,0 +1,113 @@ +//===-- llvm/Remarks/Remark.h - The remark 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 defines an abstraction for handling remarks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_REMARK_H +#define LLVM_REMARKS_REMARK_H + +#include "llvm-c/Remarks.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CBindingWrapping.h" +#include <string> + +namespace llvm { +namespace remarks { + +constexpr uint64_t Version = 0; + +/// The debug location used to track a remark back to the source file. +struct RemarkLocation { + /// Absolute path of the source file corresponding to this remark. + StringRef SourceFilePath; + unsigned SourceLine; + unsigned SourceColumn; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RemarkLocation, LLVMRemarkDebugLocRef) + +/// A key-value pair with a debug location that is used to display the remarks +/// at the right place in the source. +struct Argument { + StringRef Key; + // FIXME: We might want to be able to store other types than strings here. + StringRef Val; + // If set, the debug location corresponding to the value. + Optional<RemarkLocation> Loc; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Argument, LLVMRemarkArgRef) + +/// The type of the remark. +enum class Type { + Unknown, + Passed, + Missed, + Analysis, + AnalysisFPCommute, + AnalysisAliasing, + Failure, + LastTypeValue = Failure +}; + +/// A remark type used for both emission and parsing. +struct Remark { + /// The type of the remark. + Type RemarkType = Type::Unknown; + + /// Name of the pass that triggers the emission of this remark. + StringRef PassName; + + /// Textual identifier for the remark (single-word, camel-case). Can be used + /// by external tools reading the output file for remarks to identify the + /// remark. + StringRef RemarkName; + + /// Mangled name of the function that triggers the emssion of this remark. + StringRef FunctionName; + + /// The location in the source file of the remark. + Optional<RemarkLocation> Loc; + + /// If profile information is available, this is the number of times the + /// corresponding code was executed in a profile instrumentation run. + Optional<uint64_t> Hotness; + + /// Arguments collected via the streaming interface. + SmallVector<Argument, 5> Args; + + Remark() = default; + Remark(Remark &&) = default; + Remark &operator=(Remark &&) = default; + + /// Return a message composed from the arguments as a string. + std::string getArgsAsMsg() const; + + /// Clone this remark to explicitly ask for a copy. + Remark clone() const { return *this; } + +private: + /// In order to avoid unwanted copies, "delete" the copy constructor. + /// If a copy is needed, it should be done through `Remark::clone()`. + Remark(const Remark &) = default; + Remark& operator=(const Remark &) = default; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Remark, LLVMRemarkEntryRef) + +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_REMARK_H */ diff --git a/include/llvm/Remarks/RemarkFormat.h b/include/llvm/Remarks/RemarkFormat.h new file mode 100644 index 000000000000..e167d99d2517 --- /dev/null +++ b/include/llvm/Remarks/RemarkFormat.h @@ -0,0 +1,33 @@ +//===-- llvm/Remarks/RemarkFormat.h - The format of remarks -----*- 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 to deal with the format of remarks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_REMARK_FORMAT_H +#define LLVM_REMARKS_REMARK_FORMAT_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace remarks { + +constexpr StringRef Magic("REMARKS", 7); + +/// The format used for serializing/deserializing remarks. +enum class Format { Unknown, YAML }; + +/// Parse and validate a string for the remark format. +Expected<Format> parseFormat(StringRef FormatStr); + +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_REMARK_FORMAT_H */ diff --git a/include/llvm/Remarks/RemarkParser.h b/include/llvm/Remarks/RemarkParser.h new file mode 100644 index 000000000000..671e1abe5ec7 --- /dev/null +++ b/include/llvm/Remarks/RemarkParser.h @@ -0,0 +1,77 @@ +//===-- llvm/Remarks/Remark.h - The remark 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 an interface for parsing remarks in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_REMARK_PARSER_H +#define LLVM_REMARKS_REMARK_PARSER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Remarks/Remark.h" +#include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Support/Error.h" +#include <memory> + +namespace llvm { +namespace remarks { + +struct ParserImpl; +struct ParsedStringTable; + +class EndOfFileError : public ErrorInfo<EndOfFileError> { +public: + static char ID; + + EndOfFileError() {} + + void log(raw_ostream &OS) const override { OS << "End of file reached."; } + std::error_code convertToErrorCode() const override { + return inconvertibleErrorCode(); + } +}; + +/// Parser used to parse a raw buffer to remarks::Remark objects. +struct Parser { + /// The format of the parser. + Format ParserFormat; + + Parser(Format ParserFormat) : ParserFormat(ParserFormat) {} + + /// If no error occurs, this returns a valid Remark object. + /// If an error of type EndOfFileError occurs, it is safe to recover from it + /// by stopping the parsing. + /// If any other error occurs, it should be propagated to the user. + /// The pointer should never be null. + virtual Expected<std::unique_ptr<Remark>> next() = 0; + + virtual ~Parser() = default; +}; + +/// In-memory representation of the string table parsed from a buffer (e.g. the +/// remarks section). +struct ParsedStringTable { + /// The buffer mapped from the section contents. + StringRef Buffer; + /// Collection of offsets in the buffer for each string entry. + SmallVector<size_t, 8> Offsets; + + Expected<StringRef> operator[](size_t Index) const; + ParsedStringTable(StringRef Buffer); +}; + +Expected<std::unique_ptr<Parser>> +createRemarkParser(Format ParserFormat, StringRef Buf, + Optional<const ParsedStringTable *> StrTab = None); + +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_REMARK_PARSER_H */ diff --git a/include/llvm/Remarks/RemarkSerializer.h b/include/llvm/Remarks/RemarkSerializer.h new file mode 100644 index 000000000000..def5c2e16620 --- /dev/null +++ b/include/llvm/Remarks/RemarkSerializer.h @@ -0,0 +1,68 @@ +//===-- RemarkSerializer.h - Remark serialization 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 provides an interface for serializing remarks to different formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_REMARK_SERIALIZER_H +#define LLVM_REMARKS_REMARK_SERIALIZER_H + +#include "llvm/Remarks/Remark.h" +#include "llvm/Remarks/RemarkStringTable.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace remarks { + +/// This is the base class for a remark serializer. +/// It includes support for using a string table while emitting. +struct Serializer { + /// The open raw_ostream that the remark diagnostics are emitted to. + raw_ostream &OS; + /// The string table containing all the unique strings used in the output. + /// The table can be serialized to be consumed after the compilation. + Optional<StringTable> StrTab; + + Serializer(raw_ostream &OS) : OS(OS), StrTab() {} + + /// This is just an interface. + virtual ~Serializer() = default; + virtual void emit(const Remark &Remark) = 0; +}; + +/// Wether the serializer should use a string table while emitting. +enum class UseStringTable { No, Yes }; + +/// Serialize the remarks to YAML. One remark entry looks like this: +/// --- !<TYPE> +/// Pass: <PASSNAME> +/// Name: <REMARKNAME> +/// DebugLoc: { File: <SOURCEFILENAME>, Line: <SOURCELINE>, +/// Column: <SOURCECOLUMN> } +/// Function: <FUNCTIONNAME> +/// Args: +/// - <KEY>: <VALUE> +/// DebugLoc: { File: <FILE>, Line: <LINE>, Column: <COL> } +/// ... +struct YAMLSerializer : public Serializer { + /// The YAML streamer. + yaml::Output YAMLOutput; + + YAMLSerializer(raw_ostream &OS, + UseStringTable UseStringTable = remarks::UseStringTable::No); + + /// Emit a remark to the stream. + void emit(const Remark &Remark) override; +}; + +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_REMARK_SERIALIZER_H */ diff --git a/include/llvm/Remarks/RemarkStringTable.h b/include/llvm/Remarks/RemarkStringTable.h new file mode 100644 index 000000000000..f9b4fdbbfb8d --- /dev/null +++ b/include/llvm/Remarks/RemarkStringTable.h @@ -0,0 +1,59 @@ +//===-- RemarkStringTable.h - Serializing string 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 class is used to deduplicate and serialize a string table used for +// generating remarks. +// +// For parsing a string table, use ParsedStringTable in RemarkParser.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_REMARK_STRING_TABLE_H +#define LLVM_REMARKS_REMARK_STRING_TABLE_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include <vector> + +namespace llvm { + +class raw_ostream; + +namespace remarks { + +/// The string table used for serializing remarks. +/// This table can be for example serialized in a section to be consumed after +/// the compilation. +struct StringTable { + /// Allocator holding all the memory used by the map. + BumpPtrAllocator Allocator; + /// The string table containing all the unique strings used in the output. + /// It maps a string to an unique ID. + StringMap<unsigned, BumpPtrAllocator &> StrTab; + /// Total size of the string table when serialized. + size_t SerializedSize = 0; + + StringTable() : Allocator(), StrTab(Allocator) {} + /// Add a string to the table. It returns an unique ID of the string. + std::pair<unsigned, StringRef> add(StringRef Str); + /// Serialize the string table to a stream. It is serialized as a little + /// endian uint64 (the size of the table in bytes) followed by a sequence of + /// NULL-terminated strings, where the N-th string is the string with the ID N + /// in the StrTab map. + void serialize(raw_ostream &OS) const; + /// Serialize the string table to a vector. This allows users to do the actual + /// writing to file/memory/other. + /// The string with the ID == N should be the N-th element in the vector. + std::vector<StringRef> serialize() const; +}; + +} // end namespace remarks +} // end namespace llvm + +#endif /* LLVM_REMARKS_REMARK_STRING_TABLE_H */ diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def index e03297b7c3c3..e152f383b3ec 100644 --- a/include/llvm/Support/AArch64TargetParser.def +++ b/include/llvm/Support/AArch64TargetParser.def @@ -1,9 +1,8 @@ //===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -51,78 +50,92 @@ AARCH64_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a", #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) #endif // FIXME: This would be nicer were it tablegen -AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) -AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) -AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") -AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse") -AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm") -AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") -AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4") -AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3") -AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2") -AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes") -AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod") -AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") -AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") -AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") -AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml") -AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") -AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") -AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve") -AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc") -AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand") -AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte") -AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs") -AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb") -AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres") +AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") +AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse") +AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm") +AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") +AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4") +AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3") +AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2") +AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes") +AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod") +AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") +AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") +AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") +AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml") +AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") +AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve") +AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2") +AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes") +AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4") +AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3") +AARCH64_ARCH_EXT_NAME("bitperm", AArch64::AEK_BITPERM, "+bitperm", "-bitperm") +AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc") +AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand") +AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte") +AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs") +AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb") +AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres") #undef AARCH64_ARCH_EXT_NAME #ifndef AARCH64_CPU_NAME #define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) #endif AARCH64_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("cortex-a55", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)) AARCH64_CPU_NAME("cortex-a57", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("cortex-a75", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC)) +AARCH64_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | + AArch64::AEK_SSBS)) +AARCH64_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC | + AArch64::AEK_SSBS)) AARCH64_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_NONE)) + (AArch64::AEK_NONE)) AARCH64_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD)) + (AArch64::AEK_DOTPROD | AArch64::AEK_FP16)) +AARCH64_CPU_NAME("exynos-m5", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_DOTPROD | AArch64::AEK_FP16)) AARCH64_CPU_NAME("falkor", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC | AArch64::AEK_RDM)) + (AArch64::AEK_CRC | AArch64::AEK_RDM)) AARCH64_CPU_NAME("saphira", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_PROFILE)) + (AArch64::AEK_PROFILE)) AARCH64_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC)) + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("thunderx2t99", ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_NONE)) + (AArch64::AEK_NONE)) AARCH64_CPU_NAME("thunderx", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) + (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) AARCH64_CPU_NAME("thunderxt88", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) + (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) AARCH64_CPU_NAME("thunderxt81", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) + (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) AARCH64_CPU_NAME("thunderxt83", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) + (AArch64::AEK_CRC | AArch64::AEK_PROFILE)) AARCH64_CPU_NAME("tsv110", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, - (AArch64::AEK_PROFILE | AArch64::AEK_FP16 | AArch64::AEK_FP16FML | - AArch64::AEK_DOTPROD)) + (AArch64::AEK_DOTPROD | + AArch64::AEK_FP16 | AArch64::AEK_FP16FML | + AArch64::AEK_PROFILE)) // Invalid CPU AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID) #undef AARCH64_CPU_NAME diff --git a/include/llvm/Support/AArch64TargetParser.h b/include/llvm/Support/AArch64TargetParser.h index 76b77d474428..965d38535e74 100644 --- a/include/llvm/Support/AArch64TargetParser.h +++ b/include/llvm/Support/AArch64TargetParser.h @@ -1,9 +1,8 @@ //===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -50,6 +49,11 @@ enum ArchExtKind : unsigned { AEK_SSBS = 1 << 20, AEK_SB = 1 << 21, AEK_PREDRES = 1 << 22, + AEK_SVE2 = 1 << 23, + AEK_SVE2AES = 1 << 24, + AEK_SVE2SM4 = 1 << 25, + AEK_SVE2SHA3 = 1 << 26, + AEK_BITPERM = 1 << 27, }; enum class ArchKind { diff --git a/include/llvm/Support/AMDGPUMetadata.h b/include/llvm/Support/AMDGPUMetadata.h index 84851c07499d..f7f1ec40dde9 100644 --- a/include/llvm/Support/AMDGPUMetadata.h +++ b/include/llvm/Support/AMDGPUMetadata.h @@ -1,9 +1,8 @@ //===--- AMDGPUMetadata.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -75,6 +74,7 @@ enum class ValueKind : uint8_t { HiddenPrintfBuffer = 11, HiddenDefaultQueue = 12, HiddenCompletionAction = 13, + HiddenMultiGridSyncArg = 14, Unknown = 0xff }; @@ -157,6 +157,8 @@ constexpr char Name[] = "Name"; constexpr char TypeName[] = "TypeName"; /// Key for Kernel::Arg::Metadata::mSize. constexpr char Size[] = "Size"; +/// Key for Kernel::Arg::Metadata::mOffset. +constexpr char Offset[] = "Offset"; /// Key for Kernel::Arg::Metadata::mAlign. constexpr char Align[] = "Align"; /// Key for Kernel::Arg::Metadata::mValueKind. @@ -189,6 +191,8 @@ struct Metadata final { std::string mTypeName = std::string(); /// Size in bytes. Required. uint32_t mSize = 0; + /// Offset in bytes. Required for code object v3, unused for code object v2. + uint32_t mOffset = 0; /// Alignment in bytes. Required. uint32_t mAlign = 0; /// Value kind. Required. @@ -453,11 +457,30 @@ constexpr char AssemblerDirectiveEnd[] = ".end_amdgpu_metadata"; //===----------------------------------------------------------------------===// namespace PALMD { -/// PAL metadata assembler directive. +/// PAL metadata (old linear format) assembler directive. constexpr char AssemblerDirective[] = ".amd_amdgpu_pal_metadata"; +/// PAL metadata (new MsgPack format) beginning assembler directive. +constexpr char AssemblerDirectiveBegin[] = ".amdgpu_pal_metadata"; + +/// PAL metadata (new MsgPack format) ending assembler directive. +constexpr char AssemblerDirectiveEnd[] = ".end_amdgpu_pal_metadata"; + /// PAL metadata keys. enum Key : uint32_t { + R_2E12_COMPUTE_PGM_RSRC1 = 0x2e12, + R_2D4A_SPI_SHADER_PGM_RSRC1_LS = 0x2d4a, + R_2D0A_SPI_SHADER_PGM_RSRC1_HS = 0x2d0a, + R_2CCA_SPI_SHADER_PGM_RSRC1_ES = 0x2cca, + R_2C8A_SPI_SHADER_PGM_RSRC1_GS = 0x2c8a, + R_2C4A_SPI_SHADER_PGM_RSRC1_VS = 0x2c4a, + R_2C0A_SPI_SHADER_PGM_RSRC1_PS = 0x2c0a, + R_2E00_COMPUTE_DISPATCH_INITIATOR = 0x2e00, + R_A1B3_SPI_PS_INPUT_ENA = 0xa1b3, + R_A1B4_SPI_PS_INPUT_ADDR = 0xa1b4, + R_A1B6_SPI_PS_IN_CONTROL = 0xa1b6, + R_A2D5_VGT_SHADER_STAGES_EN = 0xa2d5, + LS_NUM_USED_VGPRS = 0x10000021, HS_NUM_USED_VGPRS = 0x10000022, ES_NUM_USED_VGPRS = 0x10000023, @@ -483,12 +506,6 @@ enum Key : uint32_t { CS_SCRATCH_SIZE = 0x1000004a }; -/// PAL metadata represented as a vector. -typedef std::vector<uint32_t> Metadata; - -/// Converts \p PALMetadata to \p String. -std::error_code toString(const Metadata &PALMetadata, std::string &String); - } // end namespace PALMD } // end namespace AMDGPU } // end namespace llvm diff --git a/include/llvm/Support/AMDHSAKernelDescriptor.h b/include/llvm/Support/AMDHSAKernelDescriptor.h index 751699e3a19f..d1c2147536a7 100644 --- a/include/llvm/Support/AMDHSAKernelDescriptor.h +++ b/include/llvm/Support/AMDHSAKernelDescriptor.h @@ -1,9 +1,8 @@ //===--- AMDHSAKernelDescriptor.h -----------------------------*- C++ -*---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -89,8 +88,11 @@ enum : int32_t { COMPUTE_PGM_RSRC1(ENABLE_IEEE_MODE, 23, 1), COMPUTE_PGM_RSRC1(BULKY, 24, 1), COMPUTE_PGM_RSRC1(CDBG_USER, 25, 1), - COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+ - COMPUTE_PGM_RSRC1(RESERVED0, 27, 5), + COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+ + COMPUTE_PGM_RSRC1(RESERVED0, 27, 2), + COMPUTE_PGM_RSRC1(WGP_MODE, 29, 1), // GFX10+ + COMPUTE_PGM_RSRC1(MEM_ORDERED, 30, 1), // GFX10+ + COMPUTE_PGM_RSRC1(FWD_PROGRESS, 31, 1), // GFX10+ }; #undef COMPUTE_PGM_RSRC1 @@ -120,6 +122,15 @@ enum : int32_t { }; #undef COMPUTE_PGM_RSRC2 +// Compute program resource register 3. Must match hardware definition. +#define COMPUTE_PGM_RSRC3(NAME, SHIFT, WIDTH) \ + AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC3_ ## NAME, SHIFT, WIDTH) +enum : int32_t { + COMPUTE_PGM_RSRC3(SHARED_VGPR_COUNT, 0, 4), // GFX10+ + COMPUTE_PGM_RSRC3(RESERVED0, 4, 28), +}; +#undef COMPUTE_PGM_RSRC3 + // Kernel code properties. Must be kept backwards compatible. #define KERNEL_CODE_PROPERTY(NAME, SHIFT, WIDTH) \ AMDHSA_BITS_ENUM_ENTRY(KERNEL_CODE_PROPERTY_ ## NAME, SHIFT, WIDTH) @@ -131,7 +142,9 @@ enum : int32_t { KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_ID, 4, 1), KERNEL_CODE_PROPERTY(ENABLE_SGPR_FLAT_SCRATCH_INIT, 5, 1), KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 6, 1), - KERNEL_CODE_PROPERTY(RESERVED0, 7, 9), + KERNEL_CODE_PROPERTY(RESERVED0, 7, 3), + KERNEL_CODE_PROPERTY(ENABLE_WAVEFRONT_SIZE32, 10, 1), // GFX10+ + KERNEL_CODE_PROPERTY(RESERVED1, 11, 5), }; #undef KERNEL_CODE_PROPERTY @@ -141,7 +154,8 @@ struct kernel_descriptor_t { uint32_t private_segment_fixed_size; uint8_t reserved0[8]; int64_t kernel_code_entry_byte_offset; - uint8_t reserved1[24]; + uint8_t reserved1[20]; + uint32_t compute_pgm_rsrc3; // GFX10+ uint32_t compute_pgm_rsrc1; uint32_t compute_pgm_rsrc2; uint16_t kernel_code_properties; @@ -167,6 +181,9 @@ static_assert( offsetof(kernel_descriptor_t, reserved1) == 24, "invalid offset for reserved1"); static_assert( + offsetof(kernel_descriptor_t, compute_pgm_rsrc3) == 44, + "invalid offset for compute_pgm_rsrc3"); +static_assert( offsetof(kernel_descriptor_t, compute_pgm_rsrc1) == 48, "invalid offset for compute_pgm_rsrc1"); static_assert( diff --git a/include/llvm/Support/ARMAttributeParser.h b/include/llvm/Support/ARMAttributeParser.h index 919f39721f86..f6c39abb4f21 100644 --- a/include/llvm/Support/ARMAttributeParser.h +++ b/include/llvm/Support/ARMAttributeParser.h @@ -1,9 +1,8 @@ //===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -54,6 +53,8 @@ class ARMAttributeParser { uint32_t &Offset); void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, uint32_t &Offset); + void MVE_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, + uint32_t &Offset); void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, uint32_t &Offset); void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data, diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index b8a03765a7c0..90481eaa1677 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -1,9 +1,8 @@ //===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -68,6 +67,7 @@ enum AttrType { MPextension_use = 42, // recoded from 70 (ABI r2.08) DIV_use = 44, DSP_extension = 46, + MVE_arch = 48, also_compatible_with = 65, conformance = 67, Virtualization_use = 68, @@ -111,6 +111,7 @@ enum CPUArch { v8_R = 15, // e.g. Cortex R52 v8_M_Base= 16, // v8_M_Base AArch32 v8_M_Main= 17, // v8_M_Main AArch32 + v8_1_M_Main=21, // v8_1_M_Main AArch32 }; enum CPUArchProfile { // (=7), uleb128 @@ -152,6 +153,10 @@ enum { AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA) + // Tag_MVE_arch, (=48), uleb128 + AllowMVEInteger = 1, // integer-only MVE was permitted + AllowMVEIntegerAndFloat = 2, // both integer and floating point MVE were permitted + // Tag_ABI_PCS_R9_use, (=14), uleb128 R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) R9IsSB = 1, // R9 used as a global static base rgister diff --git a/include/llvm/Support/ARMEHABI.h b/include/llvm/Support/ARMEHABI.h index 9b052df0a908..3fbb56d65eb8 100644 --- a/include/llvm/Support/ARMEHABI.h +++ b/include/llvm/Support/ARMEHABI.h @@ -1,9 +1,8 @@ //===--- ARMEHABI.h - ARM Exception Handling ABI ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def index 9e844e2b464d..f466b3252748 100644 --- a/include/llvm/Support/ARMTargetParser.def +++ b/include/llvm/Support/ARMTargetParser.def @@ -1,9 +1,8 @@ //===- ARMTargetParser.def - ARM target parsing defines ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -32,6 +31,8 @@ ARM_FPU("fpv4-sp-d16", FK_FPV4_SP_D16, FPUVersion::VFPV4, NeonSupportLevel::None ARM_FPU("fpv5-d16", FK_FPV5_D16, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::D16) ARM_FPU("fpv5-sp-d16", FK_FPV5_SP_D16, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::SP_D16) ARM_FPU("fp-armv8", FK_FP_ARMV8, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::None) +ARM_FPU("fp-armv8-fullfp16-d16", FK_FP_ARMV8_FULLFP16_D16, FPUVersion::VFPV5_FULLFP16, NeonSupportLevel::None, FPURestriction::D16) +ARM_FPU("fp-armv8-fullfp16-sp-d16", FK_FP_ARMV8_FULLFP16_SP_D16, FPUVersion::VFPV5_FULLFP16, NeonSupportLevel::None, FPURestriction::SP_D16) ARM_FPU("neon", FK_NEON, FPUVersion::VFPV3, NeonSupportLevel::Neon, FPURestriction::None) ARM_FPU("neon-fp16", FK_NEON_FP16, FPUVersion::VFPV3_FP16, NeonSupportLevel::Neon, FPURestriction::None) ARM_FPU("neon-vfpv4", FK_NEON_VFPV4, FPUVersion::VFPV4, NeonSupportLevel::Neon, FPURestriction::None) @@ -119,6 +120,8 @@ ARM_ARCH("armv8-m.base", ARMV8MBaseline, "8-M.Baseline", "v8m.base", ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIVTHUMB) ARM_ARCH("armv8-m.main", ARMV8MMainline, "8-M.Mainline", "v8m.main", ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIVTHUMB) +ARM_ARCH("armv8.1-m.main", ARMV8_1MMainline, "8.1-M.Mainline", "v8.1m.main", + ARMBuildAttrs::CPUArch::v8_1_M_Main, FK_FP_ARMV8_FULLFP16_SP_D16, ARM::AEK_HWDIVTHUMB | ARM::AEK_RAS | ARM::AEK_LOB) // Non-standard Arch names. ARM_ARCH("iwmmxt", IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE, FK_NONE, ARM::AEK_NONE) @@ -145,6 +148,9 @@ ARM_ARCH_EXT_NAME("aes", ARM::AEK_AES, "+aes", "-aes") ARM_ARCH_EXT_NAME("dotprod", ARM::AEK_DOTPROD, "+dotprod","-dotprod") ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp") ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("fp.dp", ARM::AEK_FP_DP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("mve", (ARM::AEK_DSP | ARM::AEK_SIMD), "+mve", "-mve") +ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP), "+mve.fp", "-mve.fp") ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB), nullptr, nullptr) ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr) ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr) @@ -159,6 +165,7 @@ ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr) ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr) ARM_ARCH_EXT_NAME("fp16fml", ARM::AEK_FP16FML, "+fp16fml", "-fp16fml") ARM_ARCH_EXT_NAME("sb", ARM::AEK_SB, "+sb", "-sb") +ARM_ARCH_EXT_NAME("lob", ARM::AEK_LOB, "+lob", "-lob") #undef ARM_ARCH_EXT_NAME #ifndef ARM_HW_DIV_NAME @@ -252,6 +259,7 @@ ARM_CPU_NAME("cortex-m4", ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE) ARM_CPU_NAME("cortex-m7", ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE) ARM_CPU_NAME("cortex-m23", ARMV8MBaseline, FK_NONE, false, ARM::AEK_NONE) ARM_CPU_NAME("cortex-m33", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP) +ARM_CPU_NAME("cortex-m35p", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP) ARM_CPU_NAME("cortex-a32", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) @@ -262,12 +270,18 @@ ARM_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("cortex-a75", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, (ARM::AEK_FP16 | ARM::AEK_DOTPROD)) +ARM_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (ARM::AEK_FP16 | ARM::AEK_DOTPROD)) +ARM_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (ARM::AEK_FP16 | ARM::AEK_DOTPROD)) ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, (ARM::AEK_FP16 | ARM::AEK_DOTPROD)) +ARM_CPU_NAME("exynos-m5", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false, + (ARM::AEK_FP16 | ARM::AEK_DOTPROD)) ARM_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) // Non-standard Arch names. ARM_CPU_NAME("iwmmxt", IWMMXT, FK_NONE, true, ARM::AEK_NONE) diff --git a/include/llvm/Support/ARMTargetParser.h b/include/llvm/Support/ARMTargetParser.h index 71acc0dc72d0..4b9070dea596 100644 --- a/include/llvm/Support/ARMTargetParser.h +++ b/include/llvm/Support/ARMTargetParser.h @@ -1,9 +1,8 @@ //===-- ARMTargetParser - Parser for ARM target features --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,6 +45,13 @@ enum ArchExtKind : unsigned { AEK_AES = 1 << 16, AEK_FP16FML = 1 << 17, AEK_SB = 1 << 18, + AEK_SVE2 = 1 << 19, + AEK_SVE2AES = 1 << 20, + AEK_SVE2SM4 = 1 << 21, + AEK_SVE2SHA3 = 1 << 22, + AEK_BITPERM = 1 << 23, + AEK_FP_DP = 1 << 24, + AEK_LOB = 1 << 25, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, @@ -127,7 +133,8 @@ enum class FPUVersion { VFPV3, VFPV3_FP16, VFPV4, - VFPV5 + VFPV5, + VFPV5_FULLFP16, }; // An FPU name restricts the FPU in one of three ways: @@ -234,6 +241,8 @@ StringRef getCPUAttr(ArchKind AK); StringRef getSubArch(ArchKind AK); StringRef getArchExtName(unsigned ArchExtKind); StringRef getArchExtFeature(StringRef ArchExt); +bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt, + std::vector<StringRef> &Features); StringRef getHWDivName(unsigned HWDivKind); // Information by Name diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h index 60174503ad49..857a0d3814a8 100644 --- a/include/llvm/Support/ARMWinEH.h +++ b/include/llvm/Support/ARMWinEH.h @@ -1,9 +1,8 @@ -//===-- llvm/Support/WinARMEH.h - Windows on ARM EH Constants ---*- C++ -*-===// +//===-- llvm/Support/ARMWinEH.h - Windows on ARM EH Constants ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -383,7 +382,7 @@ struct ExceptionDataRecord { return ((Data[0] & 0x00400000) >> 22); } - uint8_t EpilogueCount() const { + uint16_t EpilogueCount() const { if (HeaderWords(*this) == 1) { if (isAArch64) return (Data[0] & 0x07C00000) >> 22; diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 9e7a62b85e34..d12401f0eb49 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -1,9 +1,8 @@ //===--- AlignOf.h - Portable calculation of type alignment -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 42d08378a677..09e967b98abc 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -1,9 +1,8 @@ //===- Allocator.h - Simple memory allocation abstraction -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h index 68696be6bf3d..5256ce80c028 100644 --- a/include/llvm/Support/ArrayRecycler.h +++ b/include/llvm/Support/ArrayRecycler.h @@ -1,9 +1,8 @@ //==- llvm/Support/ArrayRecycler.h - Recycling of Arrays ---------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h index 552313f0c241..a8445fddc1a8 100644 --- a/include/llvm/Support/Atomic.h +++ b/include/llvm/Support/Atomic.h @@ -1,9 +1,8 @@ //===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/AtomicOrdering.h b/include/llvm/Support/AtomicOrdering.h index a679ab30243e..763bc3ea7b28 100644 --- a/include/llvm/Support/AtomicOrdering.h +++ b/include/llvm/Support/AtomicOrdering.h @@ -1,9 +1,8 @@ //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/BinaryByteStream.h b/include/llvm/Support/BinaryByteStream.h index 9808d3b72157..7acce9a03888 100644 --- a/include/llvm/Support/BinaryByteStream.h +++ b/include/llvm/Support/BinaryByteStream.h @@ -1,9 +1,8 @@ //===- BinaryByteStream.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 //===----------------------------------------------------------------------===// // A BinaryStream which stores data in a single continguous memory buffer. //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryItemStream.h b/include/llvm/Support/BinaryItemStream.h index 278723ddf8da..4cd66adcc01a 100644 --- a/include/llvm/Support/BinaryItemStream.h +++ b/include/llvm/Support/BinaryItemStream.h @@ -1,9 +1,8 @@ //===- BinaryItemStream.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryStream.h b/include/llvm/Support/BinaryStream.h index 7677214e48ee..fcf4398550ee 100644 --- a/include/llvm/Support/BinaryStream.h +++ b/include/llvm/Support/BinaryStream.h @@ -1,9 +1,8 @@ //===- BinaryStream.h - Base interface for a stream of data -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h index 7c110fcb6a4b..96d09db69ae5 100644 --- a/include/llvm/Support/BinaryStreamArray.h +++ b/include/llvm/Support/BinaryStreamArray.h @@ -1,9 +1,8 @@ //===- BinaryStreamArray.h - Array backed by an arbitrary stream *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryStreamError.h b/include/llvm/Support/BinaryStreamError.h index 7d9699d53639..cf6e034ffd2c 100644 --- a/include/llvm/Support/BinaryStreamError.h +++ b/include/llvm/Support/BinaryStreamError.h @@ -1,9 +1,8 @@ //===- BinaryStreamError.h - Error extensions for Binary Streams *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h index 392958de30d5..d8fddde66bfa 100644 --- a/include/llvm/Support/BinaryStreamReader.h +++ b/include/llvm/Support/BinaryStreamReader.h @@ -1,9 +1,8 @@ //===- BinaryStreamReader.h - Reads objects from a binary stream *- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -97,6 +96,18 @@ public: return Error::success(); } + /// Read an unsigned LEB128 encoded value. + /// + /// \returns a success error code if the data was successfully read, otherwise + /// returns an appropriate error code. + Error readULEB128(uint64_t &Dest); + + /// Read a signed LEB128 encoded value. + /// + /// \returns a success error code if the data was successfully read, otherwise + /// returns an appropriate error code. + Error readSLEB128(int64_t &Dest); + /// Read a null terminated string from \p Dest. Whether a copy occurs depends /// on the implementation of the underlying stream. Updates the stream's /// offset to point after the newly read data. diff --git a/include/llvm/Support/BinaryStreamRef.h b/include/llvm/Support/BinaryStreamRef.h index d8dc1392c01c..7427b8da5b43 100644 --- a/include/llvm/Support/BinaryStreamRef.h +++ b/include/llvm/Support/BinaryStreamRef.h @@ -1,9 +1,8 @@ //===- BinaryStreamRef.h - A copyable reference to a stream -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/BinaryStreamWriter.h b/include/llvm/Support/BinaryStreamWriter.h index 6e8a68a30474..86d2389d9182 100644 --- a/include/llvm/Support/BinaryStreamWriter.h +++ b/include/llvm/Support/BinaryStreamWriter.h @@ -1,9 +1,8 @@ //===- BinaryStreamWriter.h - Writes objects to a BinaryStream ---*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -80,6 +79,20 @@ public: return writeInteger<U>(static_cast<U>(Num)); } + /// Write the unsigned integer Value to the underlying stream using ULEB128 + /// encoding. + /// + /// \returns a success error code if the data was successfully written, + /// otherwise returns an appropriate error code. + Error writeULEB128(uint64_t Value); + + /// Write the unsigned integer Value to the underlying stream using ULEB128 + /// encoding. + /// + /// \returns a success error code if the data was successfully written, + /// otherwise returns an appropriate error code. + Error writeSLEB128(int64_t Value); + /// Write the string \p Str to the underlying stream followed by a null /// terminator. On success, updates the offset so that subsequent writes /// occur at the next unwritten position. \p Str need not be null terminated diff --git a/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h index 4b468f7acb32..18fb60e1904b 100644 --- a/include/llvm/Support/BlockFrequency.h +++ b/include/llvm/Support/BlockFrequency.h @@ -1,9 +1,8 @@ //===-------- BlockFrequency.h - Block Frequency Wrapper --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 3a88e71c2480..cd9d369b4f4e 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -1,9 +1,8 @@ //===- BranchProbability.h - Branch Probability Wrapper ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -119,6 +118,13 @@ public: return *this; } + BranchProbability &operator/=(BranchProbability RHS) { + assert(N != UnknownN && RHS.N != UnknownN && + "Unknown probability cannot participate in arithmetics."); + N = (static_cast<uint64_t>(N) * D + RHS.N / 2) / RHS.N; + return *this; + } + BranchProbability &operator/=(uint32_t RHS) { assert(N != UnknownN && "Unknown probability cannot participate in arithmetics."); @@ -129,27 +135,38 @@ public: BranchProbability operator+(BranchProbability RHS) const { BranchProbability Prob(*this); - return Prob += RHS; + Prob += RHS; + return Prob; } BranchProbability operator-(BranchProbability RHS) const { BranchProbability Prob(*this); - return Prob -= RHS; + Prob -= RHS; + return Prob; } BranchProbability operator*(BranchProbability RHS) const { BranchProbability Prob(*this); - return Prob *= RHS; + Prob *= RHS; + return Prob; } BranchProbability operator*(uint32_t RHS) const { BranchProbability Prob(*this); - return Prob *= RHS; + Prob *= RHS; + return Prob; + } + + BranchProbability operator/(BranchProbability RHS) const { + BranchProbability Prob(*this); + Prob /= RHS; + return Prob; } BranchProbability operator/(uint32_t RHS) const { BranchProbability Prob(*this); - return Prob /= RHS; + Prob /= RHS; + return Prob; } bool operator==(BranchProbability RHS) const { return N == RHS.N; } diff --git a/include/llvm/Support/BuryPointer.h b/include/llvm/Support/BuryPointer.h index 53f1f395b922..276a5b7089c3 100644 --- a/include/llvm/Support/BuryPointer.h +++ b/include/llvm/Support/BuryPointer.h @@ -1,9 +1,8 @@ //===- llvm/Support/BuryPointer.h - Memory Manipulation/Leak ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/CBindingWrapping.h b/include/llvm/Support/CBindingWrapping.h index f60f99d376ad..46d6b4e3fa7d 100644 --- a/include/llvm/Support/CBindingWrapping.h +++ b/include/llvm/Support/CBindingWrapping.h @@ -1,9 +1,8 @@ -//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// +//===- llvm/Support/CBindingWrapping.h - C Interface Wrapping ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/CFGUpdate.h b/include/llvm/Support/CFGUpdate.h index 63c24a3d2a20..eeaf5d0a21ac 100644 --- a/include/llvm/Support/CFGUpdate.h +++ b/include/llvm/Support/CFGUpdate.h @@ -1,9 +1,8 @@ //===- CFGUpdate.h - Encode a CFG Edge Update. ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/COM.h b/include/llvm/Support/COM.h index a2d5a7a68ba9..d59966f849b4 100644 --- a/include/llvm/Support/COM.h +++ b/include/llvm/Support/COM.h @@ -1,9 +1,8 @@ //===- llvm/Support/COM.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Support/CRC.h b/include/llvm/Support/CRC.h new file mode 100644 index 000000000000..6ea8e3edcea4 --- /dev/null +++ b/include/llvm/Support/CRC.h @@ -0,0 +1,25 @@ +//===-- llvm/Support/CRC.h - Cyclic Redundancy Check-------------*- 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 basic functions for calculating Cyclic Redundancy Check +// or CRC. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CRC_H +#define LLVM_SUPPORT_CRC_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +/// zlib independent CRC32 calculation. +uint32_t crc32(uint32_t CRC, StringRef S); +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/CachePruning.h b/include/llvm/Support/CachePruning.h index cf3f8ec67a52..a72a86439f6a 100644 --- a/include/llvm/Support/CachePruning.h +++ b/include/llvm/Support/CachePruning.h @@ -1,9 +1,8 @@ //=- CachePruning.h - Helper to manage the pruning of a cache dir -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Capacity.h b/include/llvm/Support/Capacity.h index 7460f9825bd3..6b99e0aaa488 100644 --- a/include/llvm/Support/Capacity.h +++ b/include/llvm/Support/Capacity.h @@ -1,9 +1,8 @@ //===--- Capacity.h - Generic computation of ADT memory use -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 3f21e0f9ebc3..46bdedb04cfe 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -1,9 +1,8 @@ //===- llvm/Support/Casting.h - Allow flexible, checked, casts --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -144,6 +143,16 @@ template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) { typename simplify_type<const Y>::SimpleType>::doit(Val); } +// isa_and_nonnull<X> - Functionally identical to isa, except that a null value +// is accepted. +// +template <class X, class Y> +LLVM_NODISCARD inline bool isa_and_nonnull(const Y &Val) { + if (!Val) + return false; + return isa<X>(Val); +} + //===----------------------------------------------------------------------===// // cast<x> Support Templates //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/CheckedArithmetic.h b/include/llvm/Support/CheckedArithmetic.h index 039c374136ff..8a50e3d5ddf6 100644 --- a/include/llvm/Support/CheckedArithmetic.h +++ b/include/llvm/Support/CheckedArithmetic.h @@ -1,9 +1,8 @@ //==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- C++ // // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -50,6 +49,15 @@ checkedAdd(T LHS, T RHS) { return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov); } +/// Subtract two signed integers \p LHS and \p RHS. +/// \return Optional of sum if no signed overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type +checkedSub(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov); +} + /// Multiply two signed integers \p LHS and \p RHS. /// \return Optional of product if no signed overflow occurred, /// \c None otherwise. diff --git a/include/llvm/Support/Chrono.h b/include/llvm/Support/Chrono.h index 57677e8d5cf1..334ab60835a4 100644 --- a/include/llvm/Support/Chrono.h +++ b/include/llvm/Support/Chrono.h @@ -1,9 +1,8 @@ //===- llvm/Support/Chrono.h - Utilities for Timing Manipulation-*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -34,21 +33,21 @@ template <typename D = std::chrono::nanoseconds> using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>; /// Convert a TimePoint to std::time_t -LLVM_ATTRIBUTE_ALWAYS_INLINE inline std::time_t toTimeT(TimePoint<> TP) { +inline std::time_t toTimeT(TimePoint<> TP) { using namespace std::chrono; return system_clock::to_time_t( time_point_cast<system_clock::time_point::duration>(TP)); } /// Convert a std::time_t to a TimePoint -LLVM_ATTRIBUTE_ALWAYS_INLINE inline TimePoint<std::chrono::seconds> +inline TimePoint<std::chrono::seconds> toTimePoint(std::time_t T) { using namespace std::chrono; return time_point_cast<seconds>(system_clock::from_time_t(T)); } /// Convert a std::time_t + nanoseconds to a TimePoint -LLVM_ATTRIBUTE_ALWAYS_INLINE inline TimePoint<> +inline TimePoint<> toTimePoint(std::time_t T, uint32_t nsec) { using namespace std::chrono; return time_point_cast<nanoseconds>(system_clock::from_time_t(T)) diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h index 22e74167266c..a3f423e558cf 100644 --- a/include/llvm/Support/CodeGen.h +++ b/include/llvm/Support/CodeGen.h @@ -1,9 +1,8 @@ //===-- llvm/Support/CodeGen.h - CodeGen Concepts ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,13 +18,14 @@ namespace llvm { // Relocation model types. namespace Reloc { - enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI }; + // Cannot be named PIC due to collision with -DPIC + enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI }; } // Code model types. namespace CodeModel { // Sync changes with CodeGenCWrappers.h. - enum Model { Tiny, Small, Kernel, Medium, Large }; + enum Model { Tiny, Small, Kernel, Medium, Large }; } namespace PICLevel { @@ -50,10 +50,10 @@ namespace llvm { // Code generation optimization level. namespace CodeGenOpt { enum Level { - None, // -O0 - Less, // -O1 - Default, // -O2, -Os - Aggressive // -O3 + None = 0, // -O0 + Less = 1, // -O1 + Default = 2, // -O2, -Os + Aggressive = 3 // -O3 }; } diff --git a/include/llvm/Support/CodeGenCoverage.h b/include/llvm/Support/CodeGenCoverage.h index c863be35b822..0b1af779ffb0 100644 --- a/include/llvm/Support/CodeGenCoverage.h +++ b/include/llvm/Support/CodeGenCoverage.h @@ -1,9 +1,8 @@ //== llvm/Support/CodeGenCoverage.h ------------------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 rule coverage tracking for tablegen-erated CodeGen. diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index a8ad89384d17..3cc2c3c0121b 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -1,9 +1,8 @@ //===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -67,7 +66,8 @@ namespace cl { bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview = "", raw_ostream *Errs = nullptr, - const char *EnvVar = nullptr); + const char *EnvVar = nullptr, + bool LongOptionsUseDoubleDash = false); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate @@ -159,23 +159,27 @@ enum OptionHidden { // Control whether -help shows this option // AlwaysPrefix - Only allow the behavior enabled by the Prefix flag and reject // the Option=Value form. // -// Grouping - With this option enabled, multiple letter options are allowed to -// bunch together with only a single hyphen for the whole group. This allows -// emulation of the behavior that ls uses for example: ls -la === ls -l -a -// enum FormattingFlags { NormalFormatting = 0x00, // Nothing special Positional = 0x01, // Is a positional argument, no '-' required Prefix = 0x02, // Can this option directly prefix its value? - AlwaysPrefix = 0x03, // Can this option only directly prefix its value? - Grouping = 0x04 // Can this option group with other options? + AlwaysPrefix = 0x03 // Can this option only directly prefix its value? }; enum MiscFlags { // Miscellaneous flags to adjust argument CommaSeparated = 0x01, // Should this cl::list split between commas? PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? - Sink = 0x04 // Should this cl::list eat all unknown options? + Sink = 0x04, // Should this cl::list eat all unknown options? + + // Grouping - Can this option group with other options? + // If this is enabled, multiple letter options are allowed to bunch together + // with only a single hyphen for the whole group. This allows emulation + // of the behavior that ls uses for example: ls -la === ls -l -a + Grouping = 0x08, + + // Default option + DefaultOption = 0x10 }; //===----------------------------------------------------------------------===// @@ -261,26 +265,27 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences = 0; // The number of times specified + uint16_t NumOccurrences; // The number of times specified // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid // problems with signed enums in bitfields. - unsigned Occurrences : 3; // enum NumOccurrencesFlag + uint16_t Occurrences : 3; // enum NumOccurrencesFlag // not using the enum type for 'Value' because zero is an implementation // detail representing the non-value - unsigned Value : 2; - unsigned HiddenFlag : 2; // enum OptionHidden - unsigned Formatting : 3; // enum FormattingFlags - unsigned Misc : 3; - unsigned Position = 0; // Position of last occurrence of the option - unsigned AdditionalVals = 0; // Greater than 0 for multi-valued option. + uint16_t Value : 2; + uint16_t HiddenFlag : 2; // enum OptionHidden + uint16_t Formatting : 2; // enum FormattingFlags + uint16_t Misc : 5; + uint16_t FullyInitialized : 1; // Has addArgument been called? + uint16_t Position; // Position of last occurrence of the option + uint16_t AdditionalVals; // Greater than 0 for multi-valued option. public: StringRef ArgStr; // The argument string itself (ex: "help", "o") StringRef HelpStr; // The descriptive text message for -help StringRef ValueStr; // String describing what the value of this option is - OptionCategory *Category; // The Category this option belongs to - SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to. - bool FullyInitialized = false; // Has addArgument been called? + SmallVector<OptionCategory *, 1> + Categories; // The Categories this option belongs to + SmallPtrSet<SubCommand *, 1> Subs; // The subcommands this option belongs to. inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { return (enum NumOccurrencesFlag)Occurrences; @@ -306,6 +311,7 @@ public: bool hasArgStr() const { return !ArgStr.empty(); } bool isPositional() const { return getFormattingFlag() == cl::Positional; } bool isSink() const { return getMiscFlags() & cl::Sink; } + bool isDefaultOption() const { return getMiscFlags() & cl::DefaultOption; } bool isConsumeAfter() const { return getNumOccurrencesFlag() == cl::ConsumeAfter; @@ -329,14 +335,17 @@ public: void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } - void setCategory(OptionCategory &C) { Category = &C; } + void addCategory(OptionCategory &C); void addSubCommand(SubCommand &S) { Subs.insert(&S); } protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), - Formatting(NormalFormatting), Misc(0), Category(&GeneralCategory) {} + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), + FullyInitialized(false), Position(0), AdditionalVals(0) { + Categories.push_back(&GeneralCategory); + } inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } @@ -382,7 +391,7 @@ public: } inline int getNumOccurrences() const { return NumOccurrences; } - inline void reset() { NumOccurrences = 0; } + void reset(); }; //===----------------------------------------------------------------------===// @@ -447,7 +456,7 @@ struct cat { cat(OptionCategory &c) : Category(c) {} - template <class Opt> void apply(Opt &O) const { O.setCategory(Category); } + template <class Opt> void apply(Opt &O) const { O.addCategory(Category); } }; // sub - Specify the subcommand that this option belongs to. @@ -823,6 +832,8 @@ class basic_parser_impl { // non-template implementation of basic_parser<t> public: basic_parser_impl(Option &) {} + virtual ~basic_parser_impl() {} + enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; } @@ -850,8 +861,6 @@ public: virtual void anchor(); protected: - ~basic_parser_impl() = default; - // A helper for basic_parser::printOptionDiff. void printOptionName(const Option &O, size_t GlobalWidth) const; }; @@ -865,15 +874,12 @@ public: using OptVal = OptionValue<DataType>; basic_parser(Option &O) : basic_parser_impl(O) {} - -protected: - ~basic_parser() = default; }; //-------------------------------------------------- // parser<bool> // -template <> class parser<bool> final : public basic_parser<bool> { +template <> class parser<bool> : public basic_parser<bool> { public: parser(Option &O) : basic_parser(O) {} @@ -900,8 +906,7 @@ extern template class basic_parser<bool>; //-------------------------------------------------- // parser<boolOrDefault> -template <> -class parser<boolOrDefault> final : public basic_parser<boolOrDefault> { +template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> { public: parser(Option &O) : basic_parser(O) {} @@ -927,7 +932,7 @@ extern template class basic_parser<boolOrDefault>; //-------------------------------------------------- // parser<int> // -template <> class parser<int> final : public basic_parser<int> { +template <> class parser<int> : public basic_parser<int> { public: parser(Option &O) : basic_parser(O) {} @@ -949,7 +954,7 @@ extern template class basic_parser<int>; //-------------------------------------------------- // parser<unsigned> // -template <> class parser<unsigned> final : public basic_parser<unsigned> { +template <> class parser<unsigned> : public basic_parser<unsigned> { public: parser(Option &O) : basic_parser(O) {} @@ -969,11 +974,33 @@ public: extern template class basic_parser<unsigned>; //-------------------------------------------------- +// parser<unsigned long> +// +template <> +class parser<unsigned long> final : public basic_parser<unsigned long> { +public: + parser(Option &O) : basic_parser(O) {} + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long &Val); + + // getValueName - Overload in subclass to provide a better default value. + StringRef getValueName() const override { return "ulong"; } + + void printOptionDiff(const Option &O, unsigned long V, OptVal Default, + size_t GlobalWidth) const; + + // An out-of-line virtual method to provide a 'home' for this class. + void anchor() override; +}; + +extern template class basic_parser<unsigned long>; + +//-------------------------------------------------- // parser<unsigned long long> // template <> -class parser<unsigned long long> final - : public basic_parser<unsigned long long> { +class parser<unsigned long long> : public basic_parser<unsigned long long> { public: parser(Option &O) : basic_parser(O) {} @@ -982,7 +1009,7 @@ public: unsigned long long &Val); // getValueName - Overload in subclass to provide a better default value. - StringRef getValueName() const override { return "uint"; } + StringRef getValueName() const override { return "ulong"; } void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, size_t GlobalWidth) const; @@ -996,7 +1023,7 @@ extern template class basic_parser<unsigned long long>; //-------------------------------------------------- // parser<double> // -template <> class parser<double> final : public basic_parser<double> { +template <> class parser<double> : public basic_parser<double> { public: parser(Option &O) : basic_parser(O) {} @@ -1018,7 +1045,7 @@ extern template class basic_parser<double>; //-------------------------------------------------- // parser<float> // -template <> class parser<float> final : public basic_parser<float> { +template <> class parser<float> : public basic_parser<float> { public: parser(Option &O) : basic_parser(O) {} @@ -1040,7 +1067,7 @@ extern template class basic_parser<float>; //-------------------------------------------------- // parser<std::string> // -template <> class parser<std::string> final : public basic_parser<std::string> { +template <> class parser<std::string> : public basic_parser<std::string> { public: parser(Option &O) : basic_parser(O) {} @@ -1065,7 +1092,7 @@ extern template class basic_parser<std::string>; //-------------------------------------------------- // parser<char> // -template <> class parser<char> final : public basic_parser<char> { +template <> class parser<char> : public basic_parser<char> { public: parser(Option &O) : basic_parser(O) {} @@ -1178,7 +1205,11 @@ template <> struct applicator<FormattingFlags> { }; template <> struct applicator<MiscFlags> { - static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } + static void opt(MiscFlags MF, Option &O) { + assert((MF != Grouping || O.ArgStr.size() == 1) && + "cl::Grouping can only apply to single charater Options."); + O.setMiscFlag(MF); + } }; // apply method - Apply modifiers to an option in a type safe way. @@ -1398,6 +1429,8 @@ template <class DataType, class StorageClass> class list_storage { public: list_storage() = default; + void clear() {} + bool setLocation(Option &O, StorageClass &L) { if (Location) return O.error("cl::location(x) specified more than once!"); @@ -1449,6 +1482,10 @@ public: reference operator[](size_type pos) { return Storage[pos]; } const_reference operator[](size_type pos) const { return Storage[pos]; } + void clear() { + Storage.clear(); + } + iterator erase(const_iterator pos) { return Storage.erase(pos); } iterator erase(const_iterator first, const_iterator last) { return Storage.erase(first, last); @@ -1526,7 +1563,10 @@ class list : public Option, public list_storage<DataType, StorageClass> { void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { } - void setDefault() override {} + void setDefault() override { + Positions.clear(); + list_storage<DataType, StorageClass>::clear(); + } void done() { addArgument(); @@ -1732,7 +1772,10 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); + if (!Subs.empty()) + error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!"); Subs = AliasFor->Subs; + Categories = AliasFor->Categories; addArgument(); } diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 14e4d6e97140..3f4f465f3960 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -1,9 +1,8 @@ //===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -255,6 +254,15 @@ #define LLVM_FALLTHROUGH #endif +/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that +/// they are constant initialized. +#if __has_cpp_attribute(clang::require_constant_initialization) +#define LLVM_REQUIRE_CONSTANT_INITIALIZATION \ + [[clang::require_constant_initialization]] +#else +#define LLVM_REQUIRE_CONSTANT_INITIALIZATION +#endif + /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress /// pedantic diagnostics. #ifdef __GNUC__ diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index f7258f4bf8f8..5bc0e56913fe 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -1,9 +1,8 @@ //===-- llvm/Support/Compression.h ---Compression----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 6ae56c2470bb..1add185330fa 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -1,9 +1,8 @@ /*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. + * 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 * *==------------------------------------------------------------------------==*/ /* diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 7b3fd4f882e4..feb449e2899c 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -1,9 +1,8 @@ //===--- CrashRecoveryContext.h - Crash Recovery ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/DJB.h b/include/llvm/Support/DJB.h index e03111473362..8a04a324a5dc 100644 --- a/include/llvm/Support/DJB.h +++ b/include/llvm/Support/DJB.h @@ -1,9 +1,8 @@ //===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h index 4381b5bf1633..ec01b7d9576a 100644 --- a/include/llvm/Support/DOTGraphTraits.h +++ b/include/llvm/Support/DOTGraphTraits.h @@ -1,9 +1,8 @@ -//===-- llvm/Support/DotGraphTraits.h - Customize .dot output ---*- C++ -*-===// +//===-- llvm/Support/DOTGraphTraits.h - Customize .dot output ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 2b1639856e79..6b08a2a2a445 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -1,9 +1,8 @@ //===-- DataExtractor.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/DataTypes.h b/include/llvm/Support/DataTypes.h index ad60a5b3f300..a3fcc82531b7 100644 --- a/include/llvm/Support/DataTypes.h +++ b/include/llvm/Support/DataTypes.h @@ -1,9 +1,8 @@ //===-- llvm/Support/DataTypes.h - Define fixed size types ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index df86dbb82414..64b730951bda 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -1,9 +1,8 @@ //===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/DebugCounter.h b/include/llvm/Support/DebugCounter.h index 6eadd5c6aeff..e7d1fa68f21a 100644 --- a/include/llvm/Support/DebugCounter.h +++ b/include/llvm/Support/DebugCounter.h @@ -1,9 +1,8 @@ //===- llvm/Support/DebugCounter.h - Debug counter support ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index 9563b483f6d5..95d5ba281e22 100644 --- a/include/llvm/Support/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -1,9 +1,8 @@ //===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index a4d3f4ff793d..d8be94427d7e 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -1,9 +1,8 @@ //===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -204,10 +203,14 @@ inline void writeAtBitAlignment(void *memory, value_type value, namespace detail { -template<typename value_type, - endianness endian, - std::size_t alignment> +template<typename ValueType, + endianness Endian, + std::size_t Alignment> struct packed_endian_specific_integral { + using value_type = ValueType; + static constexpr endianness endian = Endian; + static constexpr std::size_t alignment = Alignment; + packed_endian_specific_integral() = default; explicit packed_endian_specific_integral(value_type val) { *this = val; } @@ -335,6 +338,17 @@ using unaligned_int32_t = using unaligned_int64_t = detail::packed_endian_specific_integral<int64_t, native, unaligned>; +template <typename T> +using little_t = detail::packed_endian_specific_integral<T, little, unaligned>; +template <typename T> +using big_t = detail::packed_endian_specific_integral<T, big, unaligned>; + +template <typename T> +using aligned_little_t = + detail::packed_endian_specific_integral<T, little, aligned>; +template <typename T> +using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>; + namespace endian { template <typename T> inline T read(const void *P, endianness E) { diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h index 9742e253ad3e..87898038d216 100644 --- a/include/llvm/Support/EndianStream.h +++ b/include/llvm/Support/EndianStream.h @@ -1,9 +1,8 @@ //===- EndianStream.h - Stream ops with endian specific data ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Errc.h b/include/llvm/Support/Errc.h index dce42782a0d3..9be8e5705a54 100644 --- a/include/llvm/Support/Errc.h +++ b/include/llvm/Support/Errc.h @@ -1,9 +1,8 @@ //===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Errno.h b/include/llvm/Support/Errno.h index 8069c3639df3..aedb5fb292b8 100644 --- a/include/llvm/Support/Errno.h +++ b/include/llvm/Support/Errno.h @@ -1,9 +1,8 @@ //===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Error.h b/include/llvm/Support/Error.h index ee2cbeec97a8..299fce7a1368 100644 --- a/include/llvm/Support/Error.h +++ b/include/llvm/Support/Error.h @@ -1,9 +1,8 @@ //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -1161,8 +1160,8 @@ private: /// Create formatted StringError object. template <typename... Ts> -Error createStringError(std::error_code EC, char const *Fmt, - const Ts &... Vals) { +inline Error createStringError(std::error_code EC, char const *Fmt, + const Ts &... Vals) { std::string Buffer; raw_string_ostream Stream(Buffer); Stream << format(Fmt, Vals...); @@ -1171,18 +1170,27 @@ Error createStringError(std::error_code EC, char const *Fmt, Error createStringError(std::error_code EC, char const *Msg); +template <typename... Ts> +inline Error createStringError(std::errc EC, char const *Fmt, + const Ts &... Vals) { + return createStringError(std::make_error_code(EC), Fmt, Vals...); +} + /// This class wraps a filename and another Error. /// /// In some cases, an error needs to live along a 'source' name, in order to /// show more detailed information to the user. class FileError final : public ErrorInfo<FileError> { - friend Error createFileError(std::string, Error); + friend Error createFileError(const Twine &, Error); + friend Error createFileError(const Twine &, size_t, Error); public: void log(raw_ostream &OS) const override { assert(Err && !FileName.empty() && "Trying to log after takeError()."); OS << "'" << FileName << "': "; + if (Line.hasValue()) + OS << "line " << Line.getValue() << ": "; Err->log(OS); } @@ -1194,29 +1202,51 @@ public: static char ID; private: - FileError(std::string F, std::unique_ptr<ErrorInfoBase> E) { + FileError(const Twine &F, Optional<size_t> LineNum, + std::unique_ptr<ErrorInfoBase> E) { assert(E && "Cannot create FileError from Error success value."); - assert(!F.empty() && + assert(!F.isTriviallyEmpty() && "The file name provided to FileError must not be empty."); - FileName = F; + FileName = F.str(); Err = std::move(E); + Line = std::move(LineNum); } - static Error build(std::string F, Error E) { - return Error(std::unique_ptr<FileError>(new FileError(F, E.takePayload()))); + static Error build(const Twine &F, Optional<size_t> Line, Error E) { + return Error( + std::unique_ptr<FileError>(new FileError(F, Line, E.takePayload()))); } std::string FileName; + Optional<size_t> Line; std::unique_ptr<ErrorInfoBase> Err; }; /// Concatenate a source file path and/or name with an Error. The resulting /// Error is unchecked. -inline Error createFileError(std::string F, Error E) { - return FileError::build(F, std::move(E)); +inline Error createFileError(const Twine &F, Error E) { + return FileError::build(F, Optional<size_t>(), std::move(E)); +} + +/// Concatenate a source file path and/or name with line number and an Error. +/// The resulting Error is unchecked. +inline Error createFileError(const Twine &F, size_t Line, Error E) { + return FileError::build(F, Optional<size_t>(Line), std::move(E)); +} + +/// Concatenate a source file path and/or name with a std::error_code +/// to form an Error object. +inline Error createFileError(const Twine &F, std::error_code EC) { + return createFileError(F, errorCodeToError(EC)); +} + +/// Concatenate a source file path and/or name with line number and +/// std::error_code to form an Error object. +inline Error createFileError(const Twine &F, size_t Line, std::error_code EC) { + return createFileError(F, Line, errorCodeToError(EC)); } -Error createFileError(std::string F, ErrorSuccess) = delete; +Error createFileError(const Twine &F, ErrorSuccess) = delete; /// Helper for check-and-exit error handling. /// diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index fec39e59a717..f75c2984a9ff 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -1,9 +1,8 @@ //===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index e6ce764ad822..8211f4d8a098 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -1,9 +1,8 @@ //===- llvm/Support/ErrorOr.h - Error Smart Pointer -------------*- C++ -*-===// // -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/FileCheck.h b/include/llvm/Support/FileCheck.h index 4061a26e22c5..0cd25a71a3b3 100644 --- a/include/llvm/Support/FileCheck.h +++ b/include/llvm/Support/FileCheck.h @@ -1,9 +1,8 @@ //==-- llvm/Support/FileCheck.h ---------------------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -37,9 +36,218 @@ struct FileCheckRequest { bool VerboseVerbose = false; }; +//===----------------------------------------------------------------------===// +// Numeric substitution handling code. +//===----------------------------------------------------------------------===// + +/// Base class representing the AST of a given expression. +class FileCheckExpressionAST { +public: + virtual ~FileCheckExpressionAST() = default; + + /// Evaluates and \returns the value of the expression represented by this + /// AST or an error if evaluation fails. + virtual Expected<uint64_t> eval() const = 0; +}; + +/// Class representing an unsigned literal in the AST of an expression. +class FileCheckExpressionLiteral : public FileCheckExpressionAST { +private: + /// Actual value of the literal. + uint64_t Value; + +public: + /// Constructs a literal with the specified value. + FileCheckExpressionLiteral(uint64_t Val) : Value(Val) {} + + /// \returns the literal's value. + Expected<uint64_t> eval() const { return Value; } +}; + +/// Class to represent an undefined variable error, which quotes that +/// variable's name when printed. +class FileCheckUndefVarError : public ErrorInfo<FileCheckUndefVarError> { +private: + StringRef VarName; + +public: + static char ID; + + FileCheckUndefVarError(StringRef VarName) : VarName(VarName) {} + + StringRef getVarName() const { return VarName; } + + std::error_code convertToErrorCode() const override { + return inconvertibleErrorCode(); + } + + /// Print name of variable associated with this error. + void log(raw_ostream &OS) const override { + OS << "\""; + OS.write_escaped(VarName) << "\""; + } +}; + +/// Class representing a numeric variable and its associated current value. +class FileCheckNumericVariable { +private: + /// Name of the numeric variable. + StringRef Name; + + /// Value of numeric variable, if defined, or None otherwise. + Optional<uint64_t> Value; + + /// Line number where this variable is defined, or None if defined before + /// input is parsed. Used to determine whether a variable is defined on the + /// same line as a given use. + Optional<size_t> DefLineNumber; + +public: + /// Constructor for a variable \p Name defined at line \p DefLineNumber or + /// defined before input is parsed if DefLineNumber is None. + FileCheckNumericVariable(StringRef Name, + Optional<size_t> DefLineNumber = None) + : Name(Name), DefLineNumber(DefLineNumber) {} + + /// \returns name of this numeric variable. + StringRef getName() const { return Name; } + + /// \returns this variable's value. + Optional<uint64_t> getValue() const { return Value; } + + /// Sets value of this numeric variable, if undefined. Triggers an assertion + /// failure if the variable is actually defined. + void setValue(uint64_t Value); + + /// Clears value of this numeric variable, regardless of whether it is + /// currently defined or not. + void clearValue(); + + /// \returns the line number where this variable is defined, if any, or None + /// if defined before input is parsed. + Optional<size_t> getDefLineNumber() { return DefLineNumber; } +}; + +/// Class representing the use of a numeric variable in the AST of an +/// expression. +class FileCheckNumericVariableUse : public FileCheckExpressionAST { +private: + /// Name of the numeric variable. + StringRef Name; + + /// Pointer to the class instance for the variable this use is about. + FileCheckNumericVariable *NumericVariable; + +public: + FileCheckNumericVariableUse(StringRef Name, + FileCheckNumericVariable *NumericVariable) + : Name(Name), NumericVariable(NumericVariable) {} + + /// \returns the value of the variable referenced by this instance. + Expected<uint64_t> eval() const; +}; + +/// Type of functions evaluating a given binary operation. +using binop_eval_t = uint64_t (*)(uint64_t, uint64_t); + +/// Class representing a single binary operation in the AST of an expression. +class FileCheckASTBinop : public FileCheckExpressionAST { +private: + /// Left operand. + std::unique_ptr<FileCheckExpressionAST> LeftOperand; + + /// Right operand. + std::unique_ptr<FileCheckExpressionAST> RightOperand; + + /// Pointer to function that can evaluate this binary operation. + binop_eval_t EvalBinop; + +public: + FileCheckASTBinop(binop_eval_t EvalBinop, + std::unique_ptr<FileCheckExpressionAST> LeftOp, + std::unique_ptr<FileCheckExpressionAST> RightOp) + : EvalBinop(EvalBinop) { + LeftOperand = std::move(LeftOp); + RightOperand = std::move(RightOp); + } + + /// Evaluates the value of the binary operation represented by this AST, + /// using EvalBinop on the result of recursively evaluating the operands. + /// \returns the expression value or an error if an undefined numeric + /// variable is used in one of the operands. + Expected<uint64_t> eval() const; +}; + +class FileCheckPatternContext; + +/// Class representing a substitution to perform in the RegExStr string. +class FileCheckSubstitution { +protected: + /// Pointer to a class instance holding, among other things, the table with + /// the values of live string variables at the start of any given CHECK line. + /// Used for substituting string variables with the text they were defined + /// as. Expressions are linked to the numeric variables they use at + /// parse time and directly access the value of the numeric variable to + /// evaluate their value. + FileCheckPatternContext *Context; + + /// The string that needs to be substituted for something else. For a + /// string variable this is its name, otherwise this is the whole expression. + StringRef FromStr; + + // Index in RegExStr of where to do the substitution. + size_t InsertIdx; + +public: + FileCheckSubstitution(FileCheckPatternContext *Context, StringRef VarName, + size_t InsertIdx) + : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {} + + virtual ~FileCheckSubstitution() = default; + + /// \returns the string to be substituted for something else. + StringRef getFromString() const { return FromStr; } + + /// \returns the index where the substitution is to be performed in RegExStr. + size_t getIndex() const { return InsertIdx; } + + /// \returns a string containing the result of the substitution represented + /// by this class instance or an error if substitution failed. + virtual Expected<std::string> getResult() const = 0; +}; + +class FileCheckStringSubstitution : public FileCheckSubstitution { +public: + FileCheckStringSubstitution(FileCheckPatternContext *Context, + StringRef VarName, size_t InsertIdx) + : FileCheckSubstitution(Context, VarName, InsertIdx) {} + + /// \returns the text that the string variable in this substitution matched + /// when defined, or an error if the variable is undefined. + Expected<std::string> getResult() const override; +}; + +class FileCheckNumericSubstitution : public FileCheckSubstitution { +private: + /// Pointer to the class representing the expression whose value is to be + /// substituted. + std::unique_ptr<FileCheckExpressionAST> ExpressionAST; + +public: + FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr, + std::unique_ptr<FileCheckExpressionAST> ExprAST, + size_t InsertIdx) + : FileCheckSubstitution(Context, Expr, InsertIdx) { + ExpressionAST = std::move(ExprAST); + } + + /// \returns a string containing the result of evaluating the expression in + /// this substitution, or an error if evaluation failed. + Expected<std::string> getResult() const override; +}; //===----------------------------------------------------------------------===// -// Pattern Handling Code. +// Pattern handling code. //===----------------------------------------------------------------------===// namespace Check { @@ -78,12 +286,133 @@ public: int getCount() const { return Count; } FileCheckType &setCount(int C); + // \returns a description of \p Prefix. std::string getDescription(StringRef Prefix) const; }; -} +} // namespace Check struct FileCheckDiag; +/// Class holding the FileCheckPattern global state, shared by all patterns: +/// tables holding values of variables and whether they are defined or not at +/// any given time in the matching process. +class FileCheckPatternContext { + friend class FileCheckPattern; + +private: + /// When matching a given pattern, this holds the value of all the string + /// variables defined in previous patterns. In a pattern, only the last + /// definition for a given variable is recorded in this table. + /// Back-references are used for uses after any the other definition. + StringMap<StringRef> GlobalVariableTable; + + /// Map of all string variables defined so far. Used at parse time to detect + /// a name conflict between a numeric variable and a string variable when + /// the former is defined on a later line than the latter. + StringMap<bool> DefinedVariableTable; + + /// When matching a given pattern, this holds the pointers to the classes + /// representing the numeric variables defined in previous patterns. When + /// matching a pattern all definitions for that pattern are recorded in the + /// NumericVariableDefs table in the FileCheckPattern instance of that + /// pattern. + StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable; + + /// Pointer to the class instance representing the @LINE pseudo variable for + /// easily updating its value. + FileCheckNumericVariable *LineVariable = nullptr; + + /// Vector holding pointers to all parsed numeric variables. Used to + /// automatically free them once they are guaranteed to no longer be used. + std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables; + + /// Vector holding pointers to all substitutions. Used to automatically free + /// them once they are guaranteed to no longer be used. + std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions; + +public: + /// \returns the value of string variable \p VarName or an error if no such + /// variable has been defined. + Expected<StringRef> getPatternVarValue(StringRef VarName); + + /// Defines string and numeric variables from definitions given on the + /// command line, passed as a vector of [#]VAR=VAL strings in + /// \p CmdlineDefines. \returns an error list containing diagnostics against + /// \p SM for all definition parsing failures, if any, or Success otherwise. + Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines, + SourceMgr &SM); + + /// Create @LINE pseudo variable. Value is set when pattern are being + /// matched. + void createLineVariable(); + + /// Undefines local variables (variables whose name does not start with a '$' + /// sign), i.e. removes them from GlobalVariableTable and from + /// GlobalNumericVariableTable and also clears the value of numeric + /// variables. + void clearLocalVars(); + +private: + /// Makes a new numeric variable and registers it for destruction when the + /// context is destroyed. + template <class... Types> + FileCheckNumericVariable *makeNumericVariable(Types... args); + + /// Makes a new string substitution and registers it for destruction when the + /// context is destroyed. + FileCheckSubstitution *makeStringSubstitution(StringRef VarName, + size_t InsertIdx); + + /// Makes a new numeric substitution and registers it for destruction when + /// the context is destroyed. + FileCheckSubstitution * + makeNumericSubstitution(StringRef ExpressionStr, + std::unique_ptr<FileCheckExpressionAST> ExpressionAST, + size_t InsertIdx); +}; + +/// Class to represent an error holding a diagnostic with location information +/// used when printing it. +class FileCheckErrorDiagnostic : public ErrorInfo<FileCheckErrorDiagnostic> { +private: + SMDiagnostic Diagnostic; + +public: + static char ID; + + FileCheckErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {} + + std::error_code convertToErrorCode() const override { + return inconvertibleErrorCode(); + } + + /// Print diagnostic associated with this error when printing the error. + void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); } + + static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) { + return make_error<FileCheckErrorDiagnostic>( + SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg)); + } + + static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) { + return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg); + } +}; + +class FileCheckNotFoundError : public ErrorInfo<FileCheckNotFoundError> { +public: + static char ID; + + std::error_code convertToErrorCode() const override { + return inconvertibleErrorCode(); + } + + /// Print diagnostic associated with this error when printing the error. + void log(raw_ostream &OS) const override { + OS << "String not found in input"; + } +}; + class FileCheckPattern { SMLoc PatternLoc; @@ -95,43 +424,143 @@ class FileCheckPattern { /// a fixed string to match. std::string RegExStr; - /// Entries in this vector map to uses of a variable in the pattern, e.g. - /// "foo[[bar]]baz". In this case, the RegExStr will contain "foobaz" and - /// we'll get an entry in this vector that tells us to insert the value of - /// bar at offset 3. - std::vector<std::pair<StringRef, unsigned>> VariableUses; + /// Entries in this vector represent a substitution of a string variable or + /// an expression in the RegExStr regex at match time. For example, in the + /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]", + /// RegExStr will contain "foobaz" and we'll get two entries in this vector + /// that tells us to insert the value of string variable "bar" at offset 3 + /// and the value of expression "N+1" at offset 6. + std::vector<FileCheckSubstitution *> Substitutions; - /// Maps definitions of variables to their parenthesized capture numbers. + /// Maps names of string variables defined in a pattern to the number of + /// their parenthesis group in RegExStr capturing their last definition. + /// + /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])", + /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is + /// the value captured for QUUX on the earlier line where it was defined, and + /// VariableDefs will map "bar" to the third parenthesis group which captures + /// the second definition of "bar". /// - /// E.g. for the pattern "foo[[bar:.*]]baz", VariableDefs will map "bar" to - /// 1. + /// Note: uses std::map rather than StringMap to be able to get the key when + /// iterating over values. std::map<StringRef, unsigned> VariableDefs; + /// Structure representing the definition of a numeric variable in a pattern. + /// It holds the pointer to the class representing the numeric variable whose + /// value is being defined and the number of the parenthesis group in + /// RegExStr to capture that value. + struct FileCheckNumericVariableMatch { + /// Pointer to class representing the numeric variable whose value is being + /// defined. + FileCheckNumericVariable *DefinedNumericVariable; + + /// Number of the parenthesis group in RegExStr that captures the value of + /// this numeric variable definition. + unsigned CaptureParenGroup; + }; + + /// Holds the number of the parenthesis group in RegExStr and pointer to the + /// corresponding FileCheckNumericVariable class instance of all numeric + /// variable definitions. Used to set the matched value of all those + /// variables. + StringMap<FileCheckNumericVariableMatch> NumericVariableDefs; + + /// Pointer to a class instance holding the global state shared by all + /// patterns: + /// - separate tables with the values of live string and numeric variables + /// respectively at the start of any given CHECK line; + /// - table holding whether a string variable has been defined at any given + /// point during the parsing phase. + FileCheckPatternContext *Context; + Check::FileCheckType CheckTy; - /// Contains the number of line this pattern is in. - unsigned LineNumber; + /// Line number for this CHECK pattern or None if it is an implicit pattern. + /// Used to determine whether a variable definition is made on an earlier + /// line to the one with this CHECK. + Optional<size_t> LineNumber; public: - explicit FileCheckPattern(Check::FileCheckType Ty) - : CheckTy(Ty) {} + FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context, + Optional<size_t> Line = None) + : Context(Context), CheckTy(Ty), LineNumber(Line) {} - /// Returns the location in source code. + /// \returns the location in source code. SMLoc getLoc() const { return PatternLoc; } - bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, - unsigned LineNumber, const FileCheckRequest &Req); - size_t Match(StringRef Buffer, size_t &MatchLen, - StringMap<StringRef> &VariableTable) const; - void PrintVariableUses(const SourceMgr &SM, StringRef Buffer, - const StringMap<StringRef> &VariableTable, - SMRange MatchRange = None) const; - void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer, - const StringMap<StringRef> &VariableTable, + /// \returns the pointer to the global state for all patterns in this + /// FileCheck instance. + FileCheckPatternContext *getContext() const { return Context; } + + /// \returns whether \p C is a valid first character for a variable name. + static bool isValidVarNameStart(char C); + + /// Parsing information about a variable. + struct VariableProperties { + StringRef Name; + bool IsPseudo; + }; + + /// Parses the string at the start of \p Str for a variable name. \returns + /// a VariableProperties structure holding the variable name and whether it + /// is the name of a pseudo variable, or an error holding a diagnostic + /// against \p SM if parsing fail. If parsing was successful, also strips + /// \p Str from the variable name. + static Expected<VariableProperties> parseVariable(StringRef &Str, + const SourceMgr &SM); + /// Parses \p Expr for the name of a numeric variable to be defined at line + /// \p LineNumber or before input is parsed if \p LineNumber is None. + /// \returns a pointer to the class instance representing that variable, + /// creating it if needed, or an error holding a diagnostic against \p SM + /// should defining such a variable be invalid. + static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition( + StringRef &Expr, FileCheckPatternContext *Context, + Optional<size_t> LineNumber, const SourceMgr &SM); + /// Parses \p Expr for a numeric substitution block. Parameter + /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE + /// expression. \returns a pointer to the class instance representing the AST + /// of the expression whose value must be substituted, or an error holding a + /// diagnostic against \p SM if parsing fails. If substitution was + /// successful, sets \p DefinedNumericVariable to point to the class + /// representing the numeric variable being defined in this numeric + /// substitution block, or None if this block does not define any variable. + Expected<std::unique_ptr<FileCheckExpressionAST>> + parseNumericSubstitutionBlock( + StringRef Expr, + Optional<FileCheckNumericVariable *> &DefinedNumericVariable, + bool IsLegacyLineExpr, const SourceMgr &SM) const; + /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern + /// instance accordingly. + /// + /// \p Prefix provides which prefix is being matched, \p Req describes the + /// global options that influence the parsing such as whitespace + /// canonicalization, \p SM provides the SourceMgr used for error reports. + /// \returns true in case of an error, false otherwise. + bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM, + const FileCheckRequest &Req); + /// Matches the pattern string against the input buffer \p Buffer + /// + /// \returns the position that is matched or an error indicating why matching + /// failed. If there is a match, updates \p MatchLen with the size of the + /// matched string. + /// + /// The GlobalVariableTable StringMap in the FileCheckPatternContext class + /// instance provides the current values of FileCheck string variables and + /// is updated if this match defines new values. Likewise, the + /// GlobalNumericVariableTable StringMap in the same class provides the + /// current values of FileCheck numeric variables and is updated if this + /// match defines new numeric values. + Expected<size_t> match(StringRef Buffer, size_t &MatchLen, + const SourceMgr &SM) const; + /// Prints the value of successful substitutions or the name of the undefined + /// string or numeric variables preventing a successful substitution. + void printSubstitutions(const SourceMgr &SM, StringRef Buffer, + SMRange MatchRange = None) const; + void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, std::vector<FileCheckDiag> *Diags) const; bool hasVariable() const { - return !(VariableUses.empty() && VariableDefs.empty()); + return !(Substitutions.empty() && VariableDefs.empty()); } Check::FileCheckType getCheckTy() const { return CheckTy; } @@ -141,11 +570,40 @@ public: private: bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); void AddBackrefToRegEx(unsigned BackrefNum); - unsigned - ComputeMatchDistance(StringRef Buffer, - const StringMap<StringRef> &VariableTable) const; - bool EvaluateExpression(StringRef Expr, std::string &Value) const; + /// Computes an arbitrary estimate for the quality of matching this pattern + /// at the start of \p Buffer; a distance of zero should correspond to a + /// perfect match. + unsigned computeMatchDistance(StringRef Buffer) const; + /// Finds the closing sequence of a regex variable usage or definition. + /// + /// \p Str has to point in the beginning of the definition (right after the + /// opening sequence). \p SM holds the SourceMgr used for error repporting. + /// \returns the offset of the closing sequence within Str, or npos if it + /// was not found. size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); + + /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use. + /// \returns the pointer to the class instance representing that variable if + /// successful, or an error holding a diagnostic against \p SM otherwise. + Expected<std::unique_ptr<FileCheckNumericVariableUse>> + parseNumericVariableUse(StringRef Name, bool IsPseudo, + const SourceMgr &SM) const; + enum class AllowedOperand { LineVar, Literal, Any }; + /// Parses \p Expr for use of a numeric operand. Accepts both literal values + /// and numeric variables, depending on the value of \p AO. \returns the + /// class representing that operand in the AST of the expression or an error + /// holding a diagnostic against \p SM otherwise. + Expected<std::unique_ptr<FileCheckExpressionAST>> + parseNumericOperand(StringRef &Expr, AllowedOperand AO, + const SourceMgr &SM) const; + /// Parses \p Expr for a binary operation. The left operand of this binary + /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether + /// we are parsing a legacy @LINE expression. \returns the class representing + /// the binary operation in the AST of the expression, or an error holding a + /// diagnostic against \p SM otherwise. + Expected<std::unique_ptr<FileCheckExpressionAST>> + parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp, + bool IsLegacyLineExpr, const SourceMgr &SM) const; }; //===----------------------------------------------------------------------===// @@ -223,20 +681,27 @@ struct FileCheckString { FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L) : Pat(P), Prefix(S), Loc(L) {} + /// Matches check string and its "not strings" and/or "dag strings". size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode, - size_t &MatchLen, StringMap<StringRef> &VariableTable, - FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const; + size_t &MatchLen, FileCheckRequest &Req, + std::vector<FileCheckDiag> *Diags) const; + /// Verifies that there is a single line in the given \p Buffer. Errors are + /// reported against \p SM. bool CheckNext(const SourceMgr &SM, StringRef Buffer) const; + /// Verifies that there is no newline in the given \p Buffer. Errors are + /// reported against \p SM. bool CheckSame(const SourceMgr &SM, StringRef Buffer) const; + /// Verifies that none of the strings in \p NotStrings are found in the given + /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in + /// \p Diags according to the verbosity level set in \p Req. bool CheckNot(const SourceMgr &SM, StringRef Buffer, const std::vector<const FileCheckPattern *> &NotStrings, - StringMap<StringRef> &VariableTable, const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const; + /// Matches "dag strings" and their mixed "not strings". size_t CheckDag(const SourceMgr &SM, StringRef Buffer, std::vector<const FileCheckPattern *> &NotStrings, - StringMap<StringRef> &VariableTable, const FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const; }; @@ -245,6 +710,7 @@ struct FileCheckString { /// use information from the request. class FileCheck { FileCheckRequest Req; + FileCheckPatternContext PatternContext; public: FileCheck(FileCheckRequest Req) : Req(Req) {} @@ -256,24 +722,27 @@ public: // library. Regex buildCheckPrefixRegex(); - /// Read the check file, which specifies the sequence of expected strings. + /// Reads the check file from \p Buffer and records the expected strings it + /// contains in the \p CheckStrings vector. Errors are reported against + /// \p SM. /// - /// The strings are added to the CheckStrings vector. Returns true in case of - /// an error, false otherwise. + /// Only expected strings whose prefix is one of those listed in \p PrefixRE + /// are recorded. \returns true in case of an error, false otherwise. bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, std::vector<FileCheckString> &CheckStrings); bool ValidateCheckPrefixes(); - /// Canonicalize whitespaces in the file. Line endings are replaced with + /// Canonicalizes whitespaces in the file. Line endings are replaced with /// UNIX-style '\n'. StringRef CanonicalizeFile(MemoryBuffer &MB, SmallVectorImpl<char> &OutputBuffer); - /// Check the input to FileCheck provided in the \p Buffer against the \p - /// CheckStrings read from the check file. + /// Checks the input to FileCheck provided in the \p Buffer against the + /// \p CheckStrings read from the check file and record diagnostics emitted + /// in \p Diags. Errors are recorded against \p SM. /// - /// Returns false if the input fails to satisfy the checks. + /// \returns false if the input fails to satisfy the checks. bool CheckInput(SourceMgr &SM, StringRef Buffer, ArrayRef<FileCheckString> CheckStrings, std::vector<FileCheckDiag> *Diags = nullptr); diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 68226ca55502..999f551ebf2d 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -1,9 +1,8 @@ //=== FileOutputBuffer.h - File Output Buffer -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -33,11 +32,6 @@ public: enum { /// set the 'x' bit on the resulting file F_executable = 1, - - /// the contents of the new file are initialized from the file that exists - /// at the location (if present). This allows in-place modification of an - /// existing file. - F_modify = 2 }; /// Factory method to create an OutputBuffer object which manages a read/write diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index d2042f51d8c1..1bec27bddad9 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -1,9 +1,8 @@ //===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -649,6 +648,19 @@ std::error_code status(const Twine &path, file_status &result, /// A version for when a file descriptor is already available. std::error_code status(int FD, file_status &Result); +#ifdef _WIN32 +/// A version for when a file descriptor is already available. +std::error_code status(file_t FD, file_status &Result); +#endif + +/// Get file creation mode mask of the process. +/// +/// @returns Mask reported by umask(2) +/// @note There is no umask on Windows. This function returns 0 always +/// on Windows. This function does not return an error_code because +/// umask(2) never fails. It is not thread safe. +unsigned getUmask(); + /// Set file permissions. /// /// @param Path File to set permissions on. @@ -660,6 +672,11 @@ std::error_code status(int FD, file_status &Result); /// Otherwise, the file will be marked as read-only. std::error_code setPermissions(const Twine &Path, perms Permissions); +/// Vesion of setPermissions accepting a file descriptor. +/// TODO Delete the path based overload once we implement the FD based overload +/// on Windows. +std::error_code setPermissions(int FD, perms Permissions); + /// Get file permissions. /// /// @param Path File to get permissions from. @@ -765,11 +782,32 @@ enum OpenFlags : unsigned { OF_UpdateAtime = 16, }; +/// Create a potentially unique file name but does not create it. +/// +/// Generates a unique path suitable for a temporary file but does not +/// open or create the file. The name is based on \a Model with '%' +/// replaced by a random char in [0-9a-f]. If \a MakeAbsolute is true +/// then the system's temp directory is prepended first. If \a MakeAbsolute +/// is false the current directory will be used instead. +/// +/// This function does not check if the file exists. If you want to be sure +/// that the file does not yet exist, you should use use enough '%' characters +/// in your model to ensure this. Each '%' gives 4-bits of entropy so you can +/// use 32 of them to get 128 bits of entropy. +/// +/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s +/// +/// @param Model Name to base unique path off of. +/// @param ResultPath Set to the file's path. +/// @param MakeAbsolute Whether to use the system temp directory. +void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath, + bool MakeAbsolute); + /// Create a uniquely named file. /// /// Generates a unique path suitable for a temporary file and then opens it as a -/// file. The name is based on \a model with '%' replaced by a random char in -/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be +/// file. The name is based on \a Model with '%' replaced by a random char in +/// [0-9a-f]. If \a Model is not an absolute path, the temporary file will be /// created in the current directory. /// /// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s @@ -932,6 +970,51 @@ Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp, FileAccess Access, OpenFlags Flags, unsigned Mode = 0666); +/// Converts from a Posix file descriptor number to a native file handle. +/// On Windows, this retreives the underlying handle. On non-Windows, this is a +/// no-op. +file_t convertFDToNativeFile(int FD); + +#ifndef _WIN32 +inline file_t convertFDToNativeFile(int FD) { return FD; } +#endif + +/// Return an open handle to standard in. On Unix, this is typically FD 0. +/// Returns kInvalidFile when the stream is closed. +file_t getStdinHandle(); + +/// Return an open handle to standard out. On Unix, this is typically FD 1. +/// Returns kInvalidFile when the stream is closed. +file_t getStdoutHandle(); + +/// Return an open handle to standard error. On Unix, this is typically FD 2. +/// Returns kInvalidFile when the stream is closed. +file_t getStderrHandle(); + +/// Reads \p Buf.size() bytes from \p FileHandle into \p Buf. The number of +/// bytes actually read is returned in \p BytesRead. On Unix, this is equivalent +/// to `*BytesRead = ::read(FD, Buf.data(), Buf.size())`, with error reporting. +/// BytesRead will contain zero when reaching EOF. +/// +/// @param FileHandle File to read from. +/// @param Buf Buffer to read into. +/// @param BytesRead Output parameter of the number of bytes read. +/// @returns The error, if any, or errc::success. +std::error_code readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf, + size_t *BytesRead); + +/// Reads \p Buf.size() bytes from \p FileHandle at offset \p Offset into \p +/// Buf. If 'pread' is available, this will use that, otherwise it will use +/// 'lseek'. Bytes requested beyond the end of the file will be zero +/// initialized. +/// +/// @param FileHandle File to read from. +/// @param Buf Buffer to read into. +/// @param Offset Offset into the file at which the read should occur. +/// @returns The error, if any, or errc::success. +std::error_code readNativeFileSlice(file_t FileHandle, + MutableArrayRef<char> Buf, size_t Offset); + /// @brief Opens the file with the given name in a write-only or read-write /// mode, returning its open file descriptor. If the file does not exist, it /// is created. @@ -1051,11 +1134,15 @@ openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None, SmallVectorImpl<char> *RealPath = nullptr); /// @brief Close the file object. This should be used instead of ::close for -/// portability. +/// portability. On error, the caller should assume the file is closed, as is +/// the case for Process::SafelyCloseFileDescriptor /// /// @param F On input, this is the file to close. On output, the file is /// set to kInvalidFile. -void closeFile(file_t &F); +/// +/// @returns An error code if closing the file failed. Typically, an error here +/// means that the filesystem may have failed to perform some buffered writes. +std::error_code closeFile(file_t &F); std::error_code getUniqueID(const Twine Path, UniqueID &Result); @@ -1085,21 +1172,19 @@ private: size_t Size; void *Mapping; #ifdef _WIN32 - void *FileHandle; + sys::fs::file_t FileHandle; #endif mapmode Mode; - std::error_code init(int FD, uint64_t Offset, mapmode Mode); + std::error_code init(sys::fs::file_t FD, uint64_t Offset, mapmode Mode); public: mapped_file_region() = delete; mapped_file_region(mapped_file_region&) = delete; mapped_file_region &operator =(mapped_file_region&) = delete; - /// \param fd An open file descriptor to map. mapped_file_region takes - /// ownership if closefd is true. It must have been opended in the correct - /// mode. - mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset, + /// \param fd An open file descriptor to map. Does not take ownership of fd. + mapped_file_region(sys::fs::file_t fd, mapmode mode, size_t length, uint64_t offset, std::error_code &ec); ~mapped_file_region(); diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index 2ee2c60b9964..16b2206924c3 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -1,9 +1,8 @@ //===- llvm/Support/FileUtilities.h - File System Utilities -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index bcbd2bec5722..77dcbaebf1a3 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -1,9 +1,8 @@ //===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/FormatAdapters.h b/include/llvm/Support/FormatAdapters.h index 8320eaad39a9..a0e8cc439191 100644 --- a/include/llvm/Support/FormatAdapters.h +++ b/include/llvm/Support/FormatAdapters.h @@ -1,9 +1,8 @@ //===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/FormatCommon.h b/include/llvm/Support/FormatCommon.h index 36fbad296c3f..3c119d12529a 100644 --- a/include/llvm/Support/FormatCommon.h +++ b/include/llvm/Support/FormatCommon.h @@ -1,9 +1,8 @@ -//===- FormatAdapters.h - Formatters for common LLVM types -----*- C++ -*-===// +//===- FormatCommon.h - Formatters for common LLVM types --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/FormatProviders.h b/include/llvm/Support/FormatProviders.h index 4e57034ff98e..629a4845716a 100644 --- a/include/llvm/Support/FormatProviders.h +++ b/include/llvm/Support/FormatProviders.h @@ -1,9 +1,8 @@ //===- FormatProviders.h - Formatters for common LLVM types -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/FormatVariadic.h b/include/llvm/Support/FormatVariadic.h index b0f582513e07..5bbda9dd626e 100644 --- a/include/llvm/Support/FormatVariadic.h +++ b/include/llvm/Support/FormatVariadic.h @@ -1,9 +1,8 @@ //===- FormatVariadic.h - Efficient type-safe string formatting --*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/FormatVariadicDetails.h b/include/llvm/Support/FormatVariadicDetails.h index e8bd90f50941..e3c185134daa 100644 --- a/include/llvm/Support/FormatVariadicDetails.h +++ b/include/llvm/Support/FormatVariadicDetails.h @@ -1,9 +1,8 @@ //===- FormatVariadicDetails.h - Helpers for FormatVariadic.h ----*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 4a135cd23174..b49c8d86531d 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -1,9 +1,8 @@ //===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index b3018bac310a..99620802505b 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -1,9 +1,8 @@ //===- GenericDomTree.h - Generic dominator trees for graphs ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -670,14 +669,12 @@ protected: // The postdom tree can have a null root if there are no returns. if (getRootNode()) PrintDomTree<NodeT>(getRootNode(), O, 1); - if (IsPostDominator) { - O << "Roots: "; - for (const NodePtr Block : Roots) { - Block->printAsOperand(O, false); - O << " "; - } - O << "\n"; + O << "Roots: "; + for (const NodePtr Block : Roots) { + Block->printAsOperand(O, false); + O << " "; } + O << "\n"; } public: diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index 971e8305a112..ccceba881718 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -1,9 +1,8 @@ //===- GenericDomTreeConstruction.h - Dominator Calculation ------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -16,9 +15,12 @@ /// Loukas Georgiadis, Princeton University, November 2005, pp. 21-23: /// ftp://ftp.cs.princeton.edu/reports/2005/737.pdf /// -/// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns -/// out that the theoretically slower O(n*log(n)) implementation is actually -/// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. +/// Semi-NCA algorithm runs in O(n^2) worst-case time but usually slightly +/// faster than Simple Lengauer-Tarjan in practice. +/// +/// O(n^2) worst cases happen when the computation of nearest common ancestors +/// requires O(n) average time, which is very unlikely in real world. If this +/// ever turns out to be an issue, consider implementing a hybrid algorithm. /// /// The file uses the Depth Based Search algorithm to perform incremental /// updates (insertion and deletions). The implemented algorithm is based on @@ -255,42 +257,47 @@ struct SemiNCAInfo { return LastNum; } - NodePtr eval(NodePtr VIn, unsigned LastLinked) { - auto &VInInfo = NodeToInfo[VIn]; - if (VInInfo.DFSNum < LastLinked) - return VIn; - - SmallVector<NodePtr, 32> Work; - SmallPtrSet<NodePtr, 32> Visited; - - if (VInInfo.Parent >= LastLinked) - Work.push_back(VIn); - - while (!Work.empty()) { - NodePtr V = Work.back(); - auto &VInfo = NodeToInfo[V]; - NodePtr VAncestor = NumToNode[VInfo.Parent]; - - // Process Ancestor first - if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) { - Work.push_back(VAncestor); - continue; - } - Work.pop_back(); - - // Update VInfo based on Ancestor info - if (VInfo.Parent < LastLinked) - continue; - - auto &VAInfo = NodeToInfo[VAncestor]; - NodePtr VAncestorLabel = VAInfo.Label; - NodePtr VLabel = VInfo.Label; - if (NodeToInfo[VAncestorLabel].Semi < NodeToInfo[VLabel].Semi) - VInfo.Label = VAncestorLabel; - VInfo.Parent = VAInfo.Parent; - } - - return VInInfo.Label; + // V is a predecessor of W. eval() returns V if V < W, otherwise the minimum + // of sdom(U), where U > W and there is a virtual forest path from U to V. The + // virtual forest consists of linked edges of processed vertices. + // + // We can follow Parent pointers (virtual forest edges) to determine the + // ancestor U with minimum sdom(U). But it is slow and thus we employ the path + // compression technique to speed up to O(m*log(n)). Theoretically the virtual + // forest can be organized as balanced trees to achieve almost linear + // O(m*alpha(m,n)) running time. But it requires two auxiliary arrays (Size + // and Child) and is unlikely to be faster than the simple implementation. + // + // For each vertex V, its Label points to the vertex with the minimal sdom(U) + // (Semi) in its path from V (included) to NodeToInfo[V].Parent (excluded). + NodePtr eval(NodePtr V, unsigned LastLinked, + SmallVectorImpl<InfoRec *> &Stack) { + InfoRec *VInfo = &NodeToInfo[V]; + if (VInfo->Parent < LastLinked) + return VInfo->Label; + + // Store ancestors except the last (root of a virtual tree) into a stack. + assert(Stack.empty()); + do { + Stack.push_back(VInfo); + VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; + } while (VInfo->Parent >= LastLinked); + + // Path compression. Point each vertex's Parent to the root and update its + // Label if any of its ancestors (PInfo->Label) has a smaller Semi. + const InfoRec *PInfo = VInfo; + const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; + do { + VInfo = Stack.pop_back_val(); + VInfo->Parent = PInfo->Parent; + const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; + if (PLabelInfo->Semi < VLabelInfo->Semi) + VInfo->Label = PInfo->Label; + else + PLabelInfo = VLabelInfo; + PInfo = VInfo; + } while (!Stack.empty()); + return VInfo->Label; } // This function requires DFS to be run before calling it. @@ -304,6 +311,7 @@ struct SemiNCAInfo { } // Step #1: Calculate the semidominators of all vertices. + SmallVector<InfoRec *, 32> EvalStack; for (unsigned i = NextDFSNum - 1; i >= 2; --i) { NodePtr W = NumToNode[i]; auto &WInfo = NodeToInfo[W]; @@ -319,7 +327,7 @@ struct SemiNCAInfo { if (TN && TN->getLevel() < MinLevel) continue; - unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi; + unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; if (SemiU < WInfo.Semi) WInfo.Semi = SemiU; } } @@ -620,21 +628,22 @@ struct SemiNCAInfo { // Helper struct used during edge insertions. struct InsertionInfo { - using BucketElementTy = std::pair<unsigned, TreeNodePtr>; - struct DecreasingLevel { - bool operator()(const BucketElementTy &First, - const BucketElementTy &Second) const { - return First.first > Second.first; + struct Compare { + bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const { + return LHS->getLevel() < RHS->getLevel(); } }; - std::priority_queue<BucketElementTy, SmallVector<BucketElementTy, 8>, - DecreasingLevel> - Bucket; // Queue of tree nodes sorted by level in descending order. - SmallDenseSet<TreeNodePtr, 8> Affected; - SmallDenseMap<TreeNodePtr, unsigned, 8> Visited; - SmallVector<TreeNodePtr, 8> AffectedQueue; - SmallVector<TreeNodePtr, 8> VisitedNotAffectedQueue; + // Bucket queue of tree nodes ordered by descending level. For simplicity, + // we use a priority_queue here. + std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>, + Compare> + Bucket; + SmallDenseSet<TreeNodePtr, 8> Visited; + SmallVector<TreeNodePtr, 8> Affected; +#ifndef NDEBUG + SmallVector<TreeNodePtr, 8> VisitedUnaffected; +#endif }; static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI, @@ -689,6 +698,17 @@ struct SemiNCAInfo { return true; } + static bool isPermutation(const SmallVectorImpl<NodePtr> &A, + const SmallVectorImpl<NodePtr> &B) { + if (A.size() != B.size()) + return false; + SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end()); + for (NodePtr N : B) + if (Set.count(N) == 0) + return false; + return true; + } + // Updates the set of roots after insertion or deletion. This ensures that // roots are the same when after a series of updates and when the tree would // be built from scratch. @@ -702,9 +722,8 @@ struct SemiNCAInfo { return; // Recalculate the set of roots. - auto Roots = FindRoots(DT, BUI); - if (DT.Roots.size() != Roots.size() || - !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), Roots.begin())) { + RootsT Roots = FindRoots(DT, BUI); + if (!isPermutation(DT.Roots, Roots)) { // The roots chosen in the CFG have changed. This is because the // incremental algorithm does not really know or use the set of roots and // can make a different (implicit) decision about which node within an @@ -715,7 +734,6 @@ struct SemiNCAInfo { // It may be possible to update the tree without recalculating it, but // we do not know yet how to do it, and it happens rarely in practise. CalculateFromScratch(DT, BUI); - return; } } @@ -737,128 +755,113 @@ struct SemiNCAInfo { assert(NCD); LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); - const TreeNodePtr ToIDom = To->getIDom(); + const unsigned NCDLevel = NCD->getLevel(); - // Nothing affected -- NCA property holds. - // (Based on the lemma 2.5 from the second paper.) - if (NCD == To || NCD == ToIDom) return; + // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v + // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists + // where every w on P s.t. depth(v) <= depth(w) + // + // This reduces to a widest path problem (maximizing the depth of the + // minimum vertex in the path) which can be solved by a modified version of + // Dijkstra with a bucket queue (named depth-based search in the paper). + + // To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing + // affected if this does not hold. + if (NCDLevel + 1 >= To->getLevel()) + return; - // Identify and collect affected nodes. InsertionInfo II; - LLVM_DEBUG(dbgs() << "Marking " << BlockNamePrinter(To) - << " as affected\n"); - II.Affected.insert(To); - const unsigned ToLevel = To->getLevel(); - LLVM_DEBUG(dbgs() << "Putting " << BlockNamePrinter(To) - << " into a Bucket\n"); - II.Bucket.push({ToLevel, To}); + SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel; + II.Bucket.push(To); + II.Visited.insert(To); while (!II.Bucket.empty()) { - const TreeNodePtr CurrentNode = II.Bucket.top().second; - const unsigned CurrentLevel = CurrentNode->getLevel(); + TreeNodePtr TN = II.Bucket.top(); II.Bucket.pop(); - LLVM_DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: " - << BlockNamePrinter(CurrentNode) << "\n"); - - II.Visited.insert({CurrentNode, CurrentLevel}); - II.AffectedQueue.push_back(CurrentNode); + II.Affected.push_back(TN); + + const unsigned CurrentLevel = TN->getLevel(); + LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) << + "as affected, CurrentLevel " << CurrentLevel << "\n"); + + assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); + + while (true) { + // Unlike regular Dijkstra, we have an inner loop to expand more + // vertices. The first iteration is for the (affected) vertex popped + // from II.Bucket and the rest are for vertices in + // UnaffectedOnCurrentLevel, which may eventually expand to affected + // vertices. + // + // Invariant: there is an optimal path from `To` to TN with the minimum + // depth being CurrentLevel. + for (const NodePtr Succ : + ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) { + const TreeNodePtr SuccTN = DT.getNode(Succ); + assert(SuccTN && + "Unreachable successor found at reachable insertion"); + const unsigned SuccLevel = SuccTN->getLevel(); + + LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) + << ", level = " << SuccLevel << "\n"); + + // There is an optimal path from `To` to Succ with the minimum depth + // being min(CurrentLevel, SuccLevel). + // + // If depth(NCD)+1 < depth(Succ) is not satisfied, Succ is unaffected + // and no affected vertex may be reached by a path passing through it. + // Stop here. Also, Succ may be visited by other predecessors but the + // first visit has the optimal path. Stop if Succ has been visited. + if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second) + continue; + + if (SuccLevel > CurrentLevel) { + // Succ is unaffected but it may (transitively) expand to affected + // vertices. Store it in UnaffectedOnCurrentLevel. + LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " + << BlockNamePrinter(Succ) << "\n"); + UnaffectedOnCurrentLevel.push_back(SuccTN); +#ifndef NDEBUG + II.VisitedUnaffected.push_back(SuccTN); +#endif + } else { + // The condition is satisfied (Succ is affected). Add Succ to the + // bucket queue. + LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ) + << " to a Bucket\n"); + II.Bucket.push(SuccTN); + } + } - // Discover and collect affected successors of the current node. - VisitInsertion(DT, BUI, CurrentNode, CurrentLevel, NCD, II); + if (UnaffectedOnCurrentLevel.empty()) + break; + TN = UnaffectedOnCurrentLevel.pop_back_val(); + LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n"); + } } // Finish by updating immediate dominators and levels. UpdateInsertion(DT, BUI, NCD, II); } - // Visits an affected node and collect its affected successors. - static void VisitInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, - const TreeNodePtr TN, const unsigned RootLevel, - const TreeNodePtr NCD, InsertionInfo &II) { - const unsigned NCDLevel = NCD->getLevel(); - LLVM_DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel " - << RootLevel << "\n"); - - SmallVector<TreeNodePtr, 8> Stack = {TN}; - assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); - - SmallPtrSet<TreeNodePtr, 8> Processed; - - do { - TreeNodePtr Next = Stack.pop_back_val(); - LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n"); - - for (const NodePtr Succ : - ChildrenGetter<IsPostDom>::Get(Next->getBlock(), BUI)) { - const TreeNodePtr SuccTN = DT.getNode(Succ); - assert(SuccTN && "Unreachable successor found at reachable insertion"); - const unsigned SuccLevel = SuccTN->getLevel(); - - LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) - << ", level = " << SuccLevel << "\n"); - - // Do not process the same node multiple times. - if (Processed.count(Next) > 0) - continue; - - // Succ dominated by subtree From -- not affected. - // (Based on the lemma 2.5 from the second paper.) - if (SuccLevel > RootLevel) { - LLVM_DEBUG(dbgs() << "\t\tDominated by subtree From\n"); - if (II.Visited.count(SuccTN) != 0) { - LLVM_DEBUG(dbgs() << "\t\t\talready visited at level " - << II.Visited[SuccTN] << "\n\t\t\tcurrent level " - << RootLevel << ")\n"); - - // A node can be necessary to visit again if we see it again at - // a lower level than before. - if (II.Visited[SuccTN] >= RootLevel) - continue; - } - - LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " - << BlockNamePrinter(Succ) << "\n"); - II.Visited.insert({SuccTN, RootLevel}); - II.VisitedNotAffectedQueue.push_back(SuccTN); - Stack.push_back(SuccTN); - } else if ((SuccLevel > NCDLevel + 1) && - II.Affected.count(SuccTN) == 0) { - LLVM_DEBUG(dbgs() << "\t\tMarking affected and adding " - << BlockNamePrinter(Succ) << " to a Bucket\n"); - II.Affected.insert(SuccTN); - II.Bucket.push({SuccLevel, SuccTN}); - } - } - - Processed.insert(Next); - } while (!Stack.empty()); - } - // Updates immediate dominators and levels after insertion. static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr NCD, InsertionInfo &II) { LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); - for (const TreeNodePtr TN : II.AffectedQueue) { + for (const TreeNodePtr TN : II.Affected) { LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) << ") = " << BlockNamePrinter(NCD) << "\n"); TN->setIDom(NCD); } - UpdateLevelsAfterInsertion(II); - if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI); - } - - static void UpdateLevelsAfterInsertion(InsertionInfo &II) { - LLVM_DEBUG( - dbgs() << "Updating levels for visited but not affected nodes\n"); +#ifndef NDEBUG + for (const TreeNodePtr TN : II.VisitedUnaffected) + assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 && + "TN should have been updated by an affected ancestor"); +#endif - for (const TreeNodePtr TN : II.VisitedNotAffectedQueue) { - LLVM_DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = (" - << BlockNamePrinter(TN->getIDom()) << ") " - << TN->getIDom()->getLevel() << " + 1\n"); - TN->UpdateLevel(); - } + if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI); } // Handles insertion to previously unreachable nodes. @@ -1182,6 +1185,10 @@ struct SemiNCAInfo { BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); } +#if 0 + // FIXME: The LLVM_DEBUG macro only plays well with a modular + // build of LLVM when the header is marked as textual, but doing + // so causes redefinition errors. LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U : reverse(BUI.Updates)) { @@ -1190,6 +1197,7 @@ struct SemiNCAInfo { dbgs() << "\n"; }); LLVM_DEBUG(dbgs() << "\n"); +#endif // Recalculate the DominatorTree when the number of updates // exceeds a threshold, which usually makes direct updating slower than @@ -1215,8 +1223,13 @@ struct SemiNCAInfo { static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) { assert(!BUI.Updates.empty() && "No updates to apply!"); UpdateT CurrentUpdate = BUI.Updates.pop_back_val(); +#if 0 + // FIXME: The LLVM_DEBUG macro only plays well with a modular + // build of LLVM when the header is marked as textual, but doing + // so causes redefinition errors. LLVM_DEBUG(dbgs() << "Applying update: "); LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n"); +#endif // Move to the next snapshot of the CFG by removing the reverse-applied // current update. Since updates are performed in the same order they are @@ -1270,9 +1283,7 @@ struct SemiNCAInfo { } RootsT ComputedRoots = FindRoots(DT, nullptr); - if (DT.Roots.size() != ComputedRoots.size() || - !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), - ComputedRoots.begin())) { + if (!isPermutation(DT.Roots, ComputedRoots)) { errs() << "Tree has different roots than freshly computed ones!\n"; errs() << "\tPDT roots: "; for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", "; diff --git a/include/llvm/Support/GenericIteratedDominanceFrontier.h b/include/llvm/Support/GenericIteratedDominanceFrontier.h new file mode 100644 index 000000000000..25eb7cd7b6d5 --- /dev/null +++ b/include/llvm/Support/GenericIteratedDominanceFrontier.h @@ -0,0 +1,209 @@ +//===- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// Compute iterated dominance frontiers using a linear time algorithm. +/// +/// The algorithm used here is based on: +/// +/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes. +/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of +/// Programming Languages +/// POPL '95. ACM, New York, NY, 62-73. +/// +/// It has been modified to not explicitly use the DJ graph data structure and +/// to directly compute pruned SSA using per-variable liveness information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GENERIC_IDF_H +#define LLVM_SUPPORT_GENERIC_IDF_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/GenericDomTree.h" +#include <queue> + +namespace llvm { + +namespace IDFCalculatorDetail { + +/// Generic utility class used for getting the children of a basic block. +/// May be specialized if, for example, one wouldn't like to return nullpointer +/// successors. +template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy { + using NodeRef = typename GraphTraits<NodeTy>::NodeRef; + using ChildrenTy = SmallVector<NodeRef, 8>; + + ChildrenTy get(const NodeRef &N); +}; + +} // end of namespace IDFCalculatorDetail + +/// Determine the iterated dominance frontier, given a set of defining +/// blocks, and optionally, a set of live-in blocks. +/// +/// In turn, the results can be used to place phi nodes. +/// +/// This algorithm is a linear time computation of Iterated Dominance Frontiers, +/// pruned using the live-in set. +/// By default, liveness is not used to prune the IDF computation. +/// The template parameters should be of a CFG block type. +template <class NodeTy, bool IsPostDom> class IDFCalculatorBase { +public: + using OrderedNodeTy = + typename std::conditional<IsPostDom, Inverse<NodeTy *>, NodeTy *>::type; + using ChildrenGetterTy = + IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>; + + IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT) : DT(DT) {} + + IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT, + const ChildrenGetterTy &C) + : DT(DT), ChildrenGetter(C) {} + + /// Give the IDF calculator the set of blocks in which the value is + /// defined. This is equivalent to the set of starting blocks it should be + /// calculating the IDF for (though later gets pruned based on liveness). + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setDefiningBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) { + DefBlocks = &Blocks; + } + + /// Give the IDF calculator the set of blocks in which the value is + /// live on entry to the block. This is used to prune the IDF calculation to + /// not include blocks where any phi insertion would be dead. + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setLiveInBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) { + LiveInBlocks = &Blocks; + useLiveIn = true; + } + + /// Reset the live-in block set to be empty, and tell the IDF + /// calculator to not use liveness anymore. + void resetLiveInBlocks() { + LiveInBlocks = nullptr; + useLiveIn = false; + } + + /// Calculate iterated dominance frontiers + /// + /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in + /// the file-level comment. It performs DF->IDF pruning using the live-in + /// set, to avoid computing the IDF for blocks where an inserted PHI node + /// would be dead. + void calculate(SmallVectorImpl<NodeTy *> &IDFBlocks); + +private: + DominatorTreeBase<NodeTy, IsPostDom> &DT; + ChildrenGetterTy ChildrenGetter; + bool useLiveIn = false; + const SmallPtrSetImpl<NodeTy *> *LiveInBlocks; + const SmallPtrSetImpl<NodeTy *> *DefBlocks; +}; + +//===----------------------------------------------------------------------===// +// Implementation. +//===----------------------------------------------------------------------===// + +namespace IDFCalculatorDetail { + +template <class NodeTy, bool IsPostDom> +typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy +ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) { + using OrderedNodeTy = + typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy; + + auto Children = children<OrderedNodeTy>(N); + return {Children.begin(), Children.end()}; +} + +} // end of namespace IDFCalculatorDetail + +template <class NodeTy, bool IsPostDom> +void IDFCalculatorBase<NodeTy, IsPostDom>::calculate( + SmallVectorImpl<NodeTy *> &PHIBlocks) { + // Use a priority queue keyed on dominator tree level so that inserted nodes + // are handled from the bottom of the dominator tree upwards. We also augment + // the level with a DFS number to ensure that the blocks are ordered in a + // deterministic way. + using DomTreeNodePair = + std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>; + using IDFPriorityQueue = + std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>, + less_second>; + + IDFPriorityQueue PQ; + + DT.updateDFSNumbers(); + + for (NodeTy *BB : *DefBlocks) { + if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) + PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())}); + } + + SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist; + SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ; + SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist; + + while (!PQ.empty()) { + DomTreeNodePair RootPair = PQ.top(); + PQ.pop(); + DomTreeNodeBase<NodeTy> *Root = RootPair.first; + unsigned RootLevel = RootPair.second.first; + + // Walk all dominator tree children of Root, inspecting their CFG edges with + // targets elsewhere on the dominator tree. Only targets whose level is at + // most Root's level are added to the iterated dominance frontier of the + // definition set. + + Worklist.clear(); + Worklist.push_back(Root); + VisitedWorklist.insert(Root); + + while (!Worklist.empty()) { + DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val(); + NodeTy *BB = Node->getBlock(); + // Succ is the successor in the direction we are calculating IDF, so it is + // successor for IDF, and predecessor for Reverse IDF. + auto DoWork = [&](NodeTy *Succ) { + DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ); + + const unsigned SuccLevel = SuccNode->getLevel(); + if (SuccLevel > RootLevel) + return; + + if (!VisitedPQ.insert(SuccNode).second) + return; + + NodeTy *SuccBB = SuccNode->getBlock(); + if (useLiveIn && !LiveInBlocks->count(SuccBB)) + return; + + PHIBlocks.emplace_back(SuccBB); + if (!DefBlocks->count(SuccBB)) + PQ.push(std::make_pair( + SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn()))); + }; + + for (auto Succ : ChildrenGetter.get(BB)) + DoWork(Succ); + + for (auto DomChild : *Node) { + if (VisitedWorklist.insert(DomChild).second) + Worklist.push_back(DomChild); + } + } + } +} + +} // end of namespace llvm + +#endif diff --git a/include/llvm/Support/GlobPattern.h b/include/llvm/Support/GlobPattern.h index c9436a13c1a3..66a4cd94c12a 100644 --- a/include/llvm/Support/GlobPattern.h +++ b/include/llvm/Support/GlobPattern.h @@ -1,9 +1,8 @@ //===-- GlobPattern.h - glob pattern matcher implementation -*- C++ -*-----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 02d98bec16e2..466a0449e257 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -1,9 +1,8 @@ //===- llvm/Support/GraphWriter.h - Write graph to a .dot file --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 57c79c0b9fdf..b37cc514c92e 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -1,9 +1,8 @@ //===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/InitLLVM.h b/include/llvm/Support/InitLLVM.h index 0f629c9ac92d..8069859a3e0b 100644 --- a/include/llvm/Support/InitLLVM.h +++ b/include/llvm/Support/InitLLVM.h @@ -1,9 +1,8 @@ //===- InitLLVM.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -20,7 +19,10 @@ // 1. Setting up a signal handler so that pretty stack trace is printed out // if a process crashes. // -// 2. If running on Windows, obtain command line arguments using a +// 2. Set up the global new-handler which is called when a memory allocation +// attempt fails. +// +// 3. If running on Windows, obtain command line arguments using a // multibyte character-aware API and convert arguments into UTF-8 // encoding, so that you can assume that command line arguments are // always encoded in UTF-8 on any platform. diff --git a/include/llvm/Support/ItaniumManglingCanonicalizer.h b/include/llvm/Support/ItaniumManglingCanonicalizer.h index 34eb9f7deaaf..6920000340d4 100644 --- a/include/llvm/Support/ItaniumManglingCanonicalizer.h +++ b/include/llvm/Support/ItaniumManglingCanonicalizer.h @@ -1,9 +1,8 @@ //===--- ItaniumManglingCanonicalizer.h -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/JSON.h b/include/llvm/Support/JSON.h index 7a04fd52bc50..0ca41097dddd 100644 --- a/include/llvm/Support/JSON.h +++ b/include/llvm/Support/JSON.h @@ -1,9 +1,8 @@ //===--- JSON.h - JSON values, parsing and serialization -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// /// @@ -22,6 +21,9 @@ /// - a convention and helpers for mapping between json::Value and user-defined /// types. See fromJSON(), ObjectMapper, and the class comment on Value. /// +/// - an output API json::OStream which can emit JSON without materializing +/// all structures as json::Value. +/// /// Typically, JSON data would be read from an external source, parsed into /// a Value, and then converted into some native data structure before doing /// real work on it. (And vice versa when writing). @@ -37,7 +39,7 @@ /// /// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it /// encodes LLVM IR ("bitcode"), but it can be a container for other data. -/// Low-level reader/writer libraries are in Bitcode/Bitstream*.h +/// Low-level reader/writer libraries are in Bitstream/Bitstream*.h /// //===---------------------------------------------------------------------===// @@ -96,7 +98,7 @@ public: using iterator = Storage::iterator; using const_iterator = Storage::const_iterator; - explicit Object() = default; + Object() = default; // KV is a trivial key-value struct for list-initialization. // (using std::pair forces extra copies). struct KV; @@ -157,7 +159,7 @@ public: using iterator = std::vector<Value>::iterator; using const_iterator = std::vector<Value>::const_iterator; - explicit Array() = default; + Array() = default; explicit Array(std::initializer_list<Value> Elements); template <typename Collection> explicit Array(const Collection &C) { for (const auto &V : C) @@ -180,6 +182,7 @@ public: bool empty() const { return V.empty(); } size_t size() const { return V.size(); } + void reserve(size_t S) { V.reserve(S); } void clear() { V.clear(); } void push_back(const Value &E) { V.push_back(E); } @@ -310,8 +313,8 @@ public: create<std::string>(std::move(V)); } Value(const llvm::SmallVectorImpl<char> &V) - : Value(std::string(V.begin(), V.end())){}; - Value(const llvm::formatv_object_base &V) : Value(V.str()){}; + : Value(std::string(V.begin(), V.end())) {} + Value(const llvm::formatv_object_base &V) : Value(V.str()) {} // Strings: types with reference semantics. Must be valid UTF-8. Value(StringRef V) : Type(T_StringRef) { create<llvm::StringRef>(V); @@ -437,11 +440,6 @@ public: return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr; } - /// Serializes this Value to JSON, writing it to the provided stream. - /// The formatting is compact (no extra whitespace) and deterministic. - /// For pretty-printing, use the formatv() format_provider below. - friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); - private: void destroy(); void copyFrom(const Value &M); @@ -462,9 +460,7 @@ private: return *static_cast<T *>(Storage); } - template <typename Indenter> - void print(llvm::raw_ostream &, const Indenter &) const; - friend struct llvm::format_provider<llvm::json::Value>; + friend class OStream; enum ValueType : char { T_Null, @@ -481,11 +477,11 @@ private: mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef, std::string, json::Array, json::Object> Union; + friend bool operator==(const Value &, const Value &); }; bool operator==(const Value &, const Value &); inline bool operator!=(const Value &L, const Value &R) { return !(L == R); } -llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); /// ObjectKey is a used to capture keys in Object. Like Value but: /// - only strings are allowed @@ -698,6 +694,154 @@ public: return llvm::inconvertibleErrorCode(); } }; + +/// json::OStream allows writing well-formed JSON without materializing +/// all structures as json::Value ahead of time. +/// It's faster, lower-level, and less safe than OS << json::Value. +/// +/// Only one "top-level" object can be written to a stream. +/// Simplest usage involves passing lambdas (Blocks) to fill in containers: +/// +/// json::OStream J(OS); +/// J.array([&]{ +/// for (const Event &E : Events) +/// J.object([&] { +/// J.attribute("timestamp", int64_t(E.Time)); +/// J.attributeArray("participants", [&] { +/// for (const Participant &P : E.Participants) +/// J.string(P.toString()); +/// }); +/// }); +/// }); +/// +/// This would produce JSON like: +/// +/// [ +/// { +/// "timestamp": 19287398741, +/// "participants": [ +/// "King Kong", +/// "Miley Cyrus", +/// "Cleopatra" +/// ] +/// }, +/// ... +/// ] +/// +/// The lower level begin/end methods (arrayBegin()) are more flexible but +/// care must be taken to pair them correctly: +/// +/// json::OStream J(OS); +// J.arrayBegin(); +/// for (const Event &E : Events) { +/// J.objectBegin(); +/// J.attribute("timestamp", int64_t(E.Time)); +/// J.attributeBegin("participants"); +/// for (const Participant &P : E.Participants) +/// J.value(P.toString()); +/// J.attributeEnd(); +/// J.objectEnd(); +/// } +/// J.arrayEnd(); +/// +/// If the call sequence isn't valid JSON, asserts will fire in debug mode. +/// This can be mismatched begin()/end() pairs, trying to emit attributes inside +/// an array, and so on. +/// With asserts disabled, this is undefined behavior. +class OStream { + public: + using Block = llvm::function_ref<void()>; + // If IndentSize is nonzero, output is pretty-printed. + explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0) + : OS(OS), IndentSize(IndentSize) { + Stack.emplace_back(); + } + ~OStream() { + assert(Stack.size() == 1 && "Unmatched begin()/end()"); + assert(Stack.back().Ctx == Singleton); + assert(Stack.back().HasValue && "Did not write top-level value"); + } + + /// Flushes the underlying ostream. OStream does not buffer internally. + void flush() { OS.flush(); } + + // High level functions to output a value. + // Valid at top-level (exactly once), in an attribute value (exactly once), + // or in an array (any number of times). + + /// Emit a self-contained value (number, string, vector<string> etc). + void value(const Value &V); + /// Emit an array whose elements are emitted in the provided Block. + void array(Block Contents) { + arrayBegin(); + Contents(); + arrayEnd(); + } + /// Emit an object whose elements are emitted in the provided Block. + void object(Block Contents) { + objectBegin(); + Contents(); + objectEnd(); + } + + // High level functions to output object attributes. + // Valid only within an object (any number of times). + + /// Emit an attribute whose value is self-contained (number, vector<int> etc). + void attribute(llvm::StringRef Key, const Value& Contents) { + attributeImpl(Key, [&] { value(Contents); }); + } + /// Emit an attribute whose value is an array with elements from the Block. + void attributeArray(llvm::StringRef Key, Block Contents) { + attributeImpl(Key, [&] { array(Contents); }); + } + /// Emit an attribute whose value is an object with attributes from the Block. + void attributeObject(llvm::StringRef Key, Block Contents) { + attributeImpl(Key, [&] { object(Contents); }); + } + + // Low-level begin/end functions to output arrays, objects, and attributes. + // Must be correctly paired. Allowed contexts are as above. + + void arrayBegin(); + void arrayEnd(); + void objectBegin(); + void objectEnd(); + void attributeBegin(llvm::StringRef Key); + void attributeEnd(); + + private: + void attributeImpl(llvm::StringRef Key, Block Contents) { + attributeBegin(Key); + Contents(); + attributeEnd(); + } + + void valueBegin(); + void newline(); + + enum Context { + Singleton, // Top level, or object attribute. + Array, + Object, + }; + struct State { + Context Ctx = Singleton; + bool HasValue = false; + }; + llvm::SmallVector<State, 16> Stack; // Never empty. + llvm::raw_ostream &OS; + unsigned IndentSize; + unsigned Indent = 0; +}; + +/// Serializes this Value to JSON, writing it to the provided stream. +/// The formatting is compact (no extra whitespace) and deterministic. +/// For pretty-printing, use the formatv() format_provider below. +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Value &V) { + OStream(OS).value(V); + return OS; +} } // namespace json /// Allow printing json::Value with formatv(). diff --git a/include/llvm/Support/JamCRC.h b/include/llvm/Support/JamCRC.h index 846d6cea9828..b6fc4e7b9b03 100644 --- a/include/llvm/Support/JamCRC.h +++ b/include/llvm/Support/JamCRC.h @@ -1,9 +1,8 @@ //===-- llvm/Support/JamCRC.h - Cyclic Redundancy Check ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/KnownBits.h b/include/llvm/Support/KnownBits.h index 259df9546c57..07fd94e29a1f 100644 --- a/include/llvm/Support/KnownBits.h +++ b/include/llvm/Support/KnownBits.h @@ -1,9 +1,8 @@ //===- llvm/Support/KnownBits.h - Stores known zeros/ones -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -110,25 +109,36 @@ public: /// Truncate the underlying known Zero and One bits. This is equivalent /// to truncating the value we're tracking. - KnownBits trunc(unsigned BitWidth) { + KnownBits trunc(unsigned BitWidth) const { return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth)); } - /// Zero extends the underlying known Zero and One bits. This is equivalent - /// to zero extending the value we're tracking. - KnownBits zext(unsigned BitWidth) { - return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth)); + /// Extends the underlying known Zero and One bits. + /// By setting ExtendedBitsAreKnownZero=true this will be equivalent to + /// zero extending the value we're tracking. + /// With ExtendedBitsAreKnownZero=false the extended bits are set to unknown. + KnownBits zext(unsigned BitWidth, bool ExtendedBitsAreKnownZero) const { + unsigned OldBitWidth = getBitWidth(); + APInt NewZero = Zero.zext(BitWidth); + if (ExtendedBitsAreKnownZero) + NewZero.setBitsFrom(OldBitWidth); + return KnownBits(NewZero, One.zext(BitWidth)); } /// Sign extends the underlying known Zero and One bits. This is equivalent /// to sign extending the value we're tracking. - KnownBits sext(unsigned BitWidth) { + KnownBits sext(unsigned BitWidth) const { return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth)); } - /// Zero extends or truncates the underlying known Zero and One bits. This is - /// equivalent to zero extending or truncating the value we're tracking. - KnownBits zextOrTrunc(unsigned BitWidth) { + /// Extends or truncates the underlying known Zero and One bits. When + /// extending the extended bits can either be set as known zero (if + /// ExtendedBitsAreKnownZero=true) or as unknown (if + /// ExtendedBitsAreKnownZero=false). + KnownBits zextOrTrunc(unsigned BitWidth, + bool ExtendedBitsAreKnownZero) const { + if (BitWidth > getBitWidth()) + return zext(BitWidth, ExtendedBitsAreKnownZero); return KnownBits(Zero.zextOrTrunc(BitWidth), One.zextOrTrunc(BitWidth)); } @@ -192,6 +202,10 @@ public: return getBitWidth() - Zero.countPopulation(); } + /// Compute known bits resulting from adding LHS, RHS and a 1-bit Carry. + static KnownBits computeForAddCarry( + const KnownBits &LHS, const KnownBits &RHS, const KnownBits &Carry); + /// Compute known bits resulting from adding LHS and RHS. static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS, KnownBits RHS); diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 9feb07229225..a02b83ca9597 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -1,9 +1,8 @@ //===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -166,6 +165,8 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, int64_t Value = 0; unsigned Shift = 0; uint8_t Byte; + if (error) + *error = nullptr; do { if (end && p == end) { if (error) @@ -175,11 +176,11 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, return 0; } Byte = *p++; - Value |= (int64_t(Byte & 0x7f) << Shift); + Value |= (uint64_t(Byte & 0x7f) << Shift); Shift += 7; } while (Byte >= 128); - // Sign extend negative numbers. - if (Byte & 0x40) + // Sign extend negative numbers if needed. + if (Shift < 64 && (Byte & 0x40)) Value |= (-1ULL) << Shift; if (n) *n = (unsigned)(p - orig_p); diff --git a/include/llvm/Support/LineIterator.h b/include/llvm/Support/LineIterator.h index 892d289976cb..c9f10ca975ae 100644 --- a/include/llvm/Support/LineIterator.h +++ b/include/llvm/Support/LineIterator.h @@ -1,9 +1,8 @@ //===- LineIterator.h - Iterator to read a text buffer's lines --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 86db0b2b1020..57e4fbd84cd9 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -1,9 +1,8 @@ //===--- LockFileManager.h - File-level locking utility ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_SUPPORT_LOCKFILEMANAGER_H diff --git a/include/llvm/Support/LowLevelTypeImpl.h b/include/llvm/Support/LowLevelTypeImpl.h index 2a1075c9a48d..0e02b6e7d750 100644 --- a/include/llvm/Support/LowLevelTypeImpl.h +++ b/include/llvm/Support/LowLevelTypeImpl.h @@ -1,9 +1,8 @@ //== llvm/Support/LowLevelTypeImpl.h --------------------------- -*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,8 +45,8 @@ public: SizeInBits, /*AddressSpace=*/0}; } - /// Get a low-level pointer in the given address space (defaulting to 0). - static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits) { + /// Get a low-level pointer in the given address space. + static LLT pointer(unsigned AddressSpace, unsigned SizeInBits) { assert(SizeInBits > 0 && "invalid pointer size"); return LLT{/*isPointer=*/true, /*isVector=*/false, /*NumElements=*/0, SizeInBits, AddressSpace}; @@ -71,6 +70,14 @@ public: ScalarTy.isPointer() ? ScalarTy.getAddressSpace() : 0}; } + static LLT scalarOrVector(uint16_t NumElements, LLT ScalarTy) { + return NumElements == 1 ? ScalarTy : LLT::vector(NumElements, ScalarTy); + } + + static LLT scalarOrVector(uint16_t NumElements, unsigned ScalarSize) { + return scalarOrVector(NumElements, LLT::scalar(ScalarSize)); + } + explicit LLT(bool isPointer, bool isVector, uint16_t NumElements, unsigned SizeInBits, unsigned AddressSpace) { init(isPointer, isVector, NumElements, SizeInBits, AddressSpace); @@ -104,6 +111,32 @@ public: return getScalarSizeInBits() * getNumElements(); } + /// Returns the total size of the type in bytes, i.e. number of whole bytes + /// needed to represent the size in bits. Must only be called on sized types. + unsigned getSizeInBytes() const { + return (getSizeInBits() + 7) / 8; + } + + LLT getScalarType() const { + return isVector() ? getElementType() : *this; + } + + /// If this type is a vector, return a vector with the same number of elements + /// but the new element type. Otherwise, return the new element type. + LLT changeElementType(LLT NewEltTy) const { + return isVector() ? LLT::vector(getNumElements(), NewEltTy) : NewEltTy; + } + + /// If this type is a vector, return a vector with the same number of elements + /// but the new element size. Otherwise, return the new element type. Invalid + /// for pointer types. For pointer types, use changeElementType. + LLT changeElementSize(unsigned NewEltSize) const { + assert(!getScalarType().isPointer() && + "invalid to directly change element size for pointers"); + return isVector() ? LLT::vector(getNumElements(), NewEltSize) + : LLT::scalar(NewEltSize); + } + unsigned getScalarSizeInBits() const { assert(RawData != 0 && "Invalid Type"); if (!IsVector) { @@ -170,10 +203,10 @@ private: static const constexpr BitFieldInfo ScalarSizeFieldInfo{32, 0}; /// * Pointer (isPointer == 1 && isVector == 0): /// SizeInBits: 16; - /// AddressSpace: 23; + /// AddressSpace: 24; static const constexpr BitFieldInfo PointerSizeFieldInfo{16, 0}; static const constexpr BitFieldInfo PointerAddressSpaceFieldInfo{ - 23, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]}; + 24, PointerSizeFieldInfo[0] + PointerSizeFieldInfo[1]}; /// * Vector-of-non-pointer (isPointer == 0 && isVector == 1): /// NumElements: 16; /// SizeOfElement: 32; @@ -183,13 +216,13 @@ private: /// * Vector-of-pointer (isPointer == 1 && isVector == 1): /// NumElements: 16; /// SizeOfElement: 16; - /// AddressSpace: 23; + /// AddressSpace: 24; static const constexpr BitFieldInfo PointerVectorElementsFieldInfo{16, 0}; static const constexpr BitFieldInfo PointerVectorSizeFieldInfo{ 16, PointerVectorElementsFieldInfo[1] + PointerVectorElementsFieldInfo[0]}; static const constexpr BitFieldInfo PointerVectorAddressSpaceFieldInfo{ - 23, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]}; + 24, PointerVectorSizeFieldInfo[1] + PointerVectorSizeFieldInfo[0]}; uint64_t IsPointer : 1; uint64_t IsVector : 1; diff --git a/include/llvm/Support/MSVCErrorWorkarounds.h b/include/llvm/Support/MSVCErrorWorkarounds.h index 053ecf64d1e9..30e8febae20b 100644 --- a/include/llvm/Support/MSVCErrorWorkarounds.h +++ b/include/llvm/Support/MSVCErrorWorkarounds.h @@ -1,9 +1,8 @@ //===--- MSVCErrorWorkarounds.h - Enable future<Error> in MSVC --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/MachineValueType.h b/include/llvm/Support/MachineValueType.h index 552dea05029c..b94d2c4836cc 100644 --- a/include/llvm/Support/MachineValueType.h +++ b/include/llvm/Support/MachineValueType.h @@ -1,9 +1,8 @@ //===- Support/MachineValueType.h - Machine-Level types ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -87,58 +86,65 @@ namespace llvm { v64i16 = 39, // 64 x i16 v128i16 = 40, //128 x i16 - v1i32 = 41, // 1 x i32 - v2i32 = 42, // 2 x i32 - v4i32 = 43, // 4 x i32 - v8i32 = 44, // 8 x i32 - v16i32 = 45, // 16 x i32 - v32i32 = 46, // 32 x i32 - v64i32 = 47, // 64 x i32 - - v1i64 = 48, // 1 x i64 - v2i64 = 49, // 2 x i64 - v4i64 = 50, // 4 x i64 - v8i64 = 51, // 8 x i64 - v16i64 = 52, // 16 x i64 - v32i64 = 53, // 32 x i64 - - v1i128 = 54, // 1 x i128 + v1i32 = 41, // 1 x i32 + v2i32 = 42, // 2 x i32 + v3i32 = 43, // 3 x i32 + v4i32 = 44, // 4 x i32 + v5i32 = 45, // 5 x i32 + v8i32 = 46, // 8 x i32 + v16i32 = 47, // 16 x i32 + v32i32 = 48, // 32 x i32 + v64i32 = 49, // 64 x i32 + v128i32 = 50, // 128 x i32 + v256i32 = 51, // 256 x i32 + v512i32 = 52, // 512 x i32 + v1024i32 = 53, // 1024 x i32 + v2048i32 = 54, // 2048 x i32 + + v1i64 = 55, // 1 x i64 + v2i64 = 56, // 2 x i64 + v4i64 = 57, // 4 x i64 + v8i64 = 58, // 8 x i64 + v16i64 = 59, // 16 x i64 + v32i64 = 60, // 32 x i64 + + v1i128 = 61, // 1 x i128 // Scalable integer types - nxv1i1 = 55, // n x 1 x i1 - nxv2i1 = 56, // n x 2 x i1 - nxv4i1 = 57, // n x 4 x i1 - nxv8i1 = 58, // n x 8 x i1 - nxv16i1 = 59, // n x 16 x i1 - nxv32i1 = 60, // n x 32 x i1 - - nxv1i8 = 61, // n x 1 x i8 - nxv2i8 = 62, // n x 2 x i8 - nxv4i8 = 63, // n x 4 x i8 - nxv8i8 = 64, // n x 8 x i8 - nxv16i8 = 65, // n x 16 x i8 - nxv32i8 = 66, // n x 32 x i8 - - nxv1i16 = 67, // n x 1 x i16 - nxv2i16 = 68, // n x 2 x i16 - nxv4i16 = 69, // n x 4 x i16 - nxv8i16 = 70, // n x 8 x i16 - nxv16i16 = 71, // n x 16 x i16 - nxv32i16 = 72, // n x 32 x i16 - - nxv1i32 = 73, // n x 1 x i32 - nxv2i32 = 74, // n x 2 x i32 - nxv4i32 = 75, // n x 4 x i32 - nxv8i32 = 76, // n x 8 x i32 - nxv16i32 = 77, // n x 16 x i32 - nxv32i32 = 78, // n x 32 x i32 - - nxv1i64 = 79, // n x 1 x i64 - nxv2i64 = 80, // n x 2 x i64 - nxv4i64 = 81, // n x 4 x i64 - nxv8i64 = 82, // n x 8 x i64 - nxv16i64 = 83, // n x 16 x i64 - nxv32i64 = 84, // n x 32 x i64 + nxv1i1 = 62, // n x 1 x i1 + nxv2i1 = 63, // n x 2 x i1 + nxv4i1 = 64, // n x 4 x i1 + nxv8i1 = 65, // n x 8 x i1 + nxv16i1 = 66, // n x 16 x i1 + nxv32i1 = 67, // n x 32 x i1 + + nxv1i8 = 68, // n x 1 x i8 + nxv2i8 = 69, // n x 2 x i8 + nxv4i8 = 70, // n x 4 x i8 + nxv8i8 = 71, // n x 8 x i8 + nxv16i8 = 72, // n x 16 x i8 + nxv32i8 = 73, // n x 32 x i8 + + nxv1i16 = 74, // n x 1 x i16 + nxv2i16 = 75, // n x 2 x i16 + nxv4i16 = 76, // n x 4 x i16 + nxv8i16 = 77, // n x 8 x i16 + nxv16i16 = 78, // n x 16 x i16 + nxv32i16 = 79, // n x 32 x i16 + + nxv1i32 = 80, // n x 1 x i32 + nxv2i32 = 81, // n x 2 x i32 + nxv4i32 = 82, // n x 4 x i32 + nxv8i32 = 83, // n x 8 x i32 + nxv16i32 = 84, // n x 16 x i32 + nxv32i32 = 85, // n x 32 x i32 + + nxv1i64 = 86, // n x 1 x i64 + nxv2i64 = 87, // n x 2 x i64 + nxv4i64 = 88, // n x 4 x i64 + nxv8i64 = 89, // n x 8 x i64 + nxv16i64 = 90, // n x 16 x i64 + nxv32i64 = 91, // n x 32 x i64 FIRST_INTEGER_VECTOR_VALUETYPE = v1i1, LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64, @@ -146,31 +152,40 @@ namespace llvm { FIRST_INTEGER_SCALABLE_VALUETYPE = nxv1i1, LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64, - v2f16 = 85, // 2 x f16 - v4f16 = 86, // 4 x f16 - v8f16 = 87, // 8 x f16 - v1f32 = 88, // 1 x f32 - v2f32 = 89, // 2 x f32 - v4f32 = 90, // 4 x f32 - v8f32 = 91, // 8 x f32 - v16f32 = 92, // 16 x f32 - v1f64 = 93, // 1 x f64 - v2f64 = 94, // 2 x f64 - v4f64 = 95, // 4 x f64 - v8f64 = 96, // 8 x f64 - - nxv2f16 = 97, // n x 2 x f16 - nxv4f16 = 98, // n x 4 x f16 - nxv8f16 = 99, // n x 8 x f16 - nxv1f32 = 100, // n x 1 x f32 - nxv2f32 = 101, // n x 2 x f32 - nxv4f32 = 102, // n x 4 x f32 - nxv8f32 = 103, // n x 8 x f32 - nxv16f32 = 104, // n x 16 x f32 - nxv1f64 = 105, // n x 1 x f64 - nxv2f64 = 106, // n x 2 x f64 - nxv4f64 = 107, // n x 4 x f64 - nxv8f64 = 108, // n x 8 x f64 + v2f16 = 92, // 2 x f16 + v4f16 = 93, // 4 x f16 + v8f16 = 94, // 8 x f16 + v1f32 = 95, // 1 x f32 + v2f32 = 96, // 2 x f32 + v3f32 = 97, // 3 x f32 + v4f32 = 98, // 4 x f32 + v5f32 = 99, // 5 x f32 + v8f32 = 100, // 8 x f32 + v16f32 = 101, // 16 x f32 + v32f32 = 102, // 32 x f32 + v64f32 = 103, // 64 x f32 + v128f32 = 104, // 128 x f32 + v256f32 = 105, // 256 x f32 + v512f32 = 106, // 512 x f32 + v1024f32 = 107, // 1024 x f32 + v2048f32 = 108, // 2048 x f32 + v1f64 = 109, // 1 x f64 + v2f64 = 110, // 2 x f64 + v4f64 = 111, // 4 x f64 + v8f64 = 112, // 8 x f64 + + nxv2f16 = 113, // n x 2 x f16 + nxv4f16 = 114, // n x 4 x f16 + nxv8f16 = 115, // n x 8 x f16 + nxv1f32 = 116, // n x 1 x f32 + nxv2f32 = 117, // n x 2 x f32 + nxv4f32 = 118, // n x 4 x f32 + nxv8f32 = 119, // n x 8 x f32 + nxv16f32 = 120, // n x 16 x f32 + nxv1f64 = 121, // n x 1 x f64 + nxv2f64 = 122, // n x 2 x f64 + nxv4f64 = 123, // n x 4 x f64 + nxv8f64 = 124, // n x 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = nxv8f64, @@ -181,25 +196,25 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v1i1, LAST_VECTOR_VALUETYPE = nxv8f64, - x86mmx = 109, // This is an X86 MMX value + x86mmx = 125, // This is an X86 MMX value - Glue = 110, // This glues nodes together during pre-RA sched + Glue = 126, // This glues nodes together during pre-RA sched - isVoid = 111, // This has no value + isVoid = 127, // This has no value - Untyped = 112, // This value takes a register, but has + Untyped = 128, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. - ExceptRef = 113, // WebAssembly's except_ref type + exnref = 129, // WebAssembly's exnref type FIRST_VALUETYPE = 1, // This is always the beginning of the list. - LAST_VALUETYPE = 114, // This always remains at the end of the list. + LAST_VALUETYPE = 130, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors // This value must be a multiple of 32. - MAX_ALLOWED_VALUETYPE = 128, + MAX_ALLOWED_VALUETYPE = 160, // A value of type llvm::TokenTy token = 248, @@ -464,11 +479,18 @@ namespace llvm { case nxv32i16: return i16; case v1i32: case v2i32: + case v3i32: case v4i32: + case v5i32: case v8i32: case v16i32: case v32i32: case v64i32: + case v128i32: + case v256i32: + case v512i32: + case v1024i32: + case v2048i32: case nxv1i32: case nxv2i32: case nxv4i32: @@ -496,9 +518,18 @@ namespace llvm { case nxv8f16: return f16; case v1f32: case v2f32: + case v3f32: case v4f32: + case v5f32: case v8f32: case v16f32: + case v32f32: + case v64f32: + case v128f32: + case v256f32: + case v512f32: + case v1024f32: + case v2048f32: case nxv1f32: case nxv2f32: case nxv4f32: @@ -519,21 +550,33 @@ namespace llvm { switch (SimpleTy) { default: llvm_unreachable("Not a vector MVT!"); - case v1024i1: return 1024; - case v512i1: return 512; - case v256i8: return 256; + case v2048i32: + case v2048f32: return 2048; + case v1024i1: + case v1024i32: + case v1024f32: return 1024; + case v512i1: + case v512i32: + case v512f32: return 512; + case v256i8: + case v256i32: + case v256f32: return 256; case v128i1: case v128i8: - case v128i16: return 128; + case v128i16: + case v128i32: + case v128f32: return 128; case v64i1: case v64i8: case v64i16: - case v64i32: return 64; + case v64i32: + case v64f32: return 64; case v32i1: case v32i8: case v32i16: case v32i32: case v32i64: + case v32f32: case nxv32i1: case nxv32i8: case nxv32i16: @@ -567,6 +610,8 @@ namespace llvm { case nxv8f16: case nxv8f32: case nxv8f64: return 8; + case v5i32: + case v5f32: return 5; case v4i1: case v4i8: case v4i16: @@ -583,6 +628,8 @@ namespace llvm { case nxv4f16: case nxv4f32: case nxv4f64: return 4; + case v3i32: + case v3f32: return 3; case v2i1: case v2i8: case v2i16: @@ -693,6 +740,8 @@ namespace llvm { case nxv2f32: case nxv1f64: return 64; case f80 : return 80; + case v3i32: + case v3f32: return 96; case f128: case ppcf128: case i128: @@ -712,6 +761,8 @@ namespace llvm { case nxv8f16: case nxv4f32: case nxv2f64: return 128; + case v5i32: + case v5f32: return 160; case v32i8: case v16i16: case v8i32: @@ -741,14 +792,26 @@ namespace llvm { case v64i16: case v32i32: case v16i64: + case v32f32: case nxv32i32: case nxv16i64: return 1024; case v256i8: case v128i16: case v64i32: case v32i64: + case v64f32: case nxv32i64: return 2048; - case ExceptRef: return 0; // opaque type + case v128i32: + case v128f32: return 4096; + case v256i32: + case v256f32: return 8192; + case v512i32: + case v512f32: return 16384; + case v1024i32: + case v1024f32: return 32768; + case v2048i32: + case v2048f32: return 65536; + case exnref: return 0; // opaque type } } @@ -862,13 +925,20 @@ namespace llvm { if (NumElements == 128) return MVT::v128i16; break; case MVT::i32: - if (NumElements == 1) return MVT::v1i32; - if (NumElements == 2) return MVT::v2i32; - if (NumElements == 4) return MVT::v4i32; - if (NumElements == 8) return MVT::v8i32; - if (NumElements == 16) return MVT::v16i32; - if (NumElements == 32) return MVT::v32i32; - if (NumElements == 64) return MVT::v64i32; + if (NumElements == 1) return MVT::v1i32; + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 3) return MVT::v3i32; + if (NumElements == 4) return MVT::v4i32; + if (NumElements == 5) return MVT::v5i32; + if (NumElements == 8) return MVT::v8i32; + if (NumElements == 16) return MVT::v16i32; + if (NumElements == 32) return MVT::v32i32; + if (NumElements == 64) return MVT::v64i32; + if (NumElements == 128) return MVT::v128i32; + if (NumElements == 256) return MVT::v256i32; + if (NumElements == 512) return MVT::v512i32; + if (NumElements == 1024) return MVT::v1024i32; + if (NumElements == 2048) return MVT::v2048i32; break; case MVT::i64: if (NumElements == 1) return MVT::v1i64; @@ -887,11 +957,20 @@ namespace llvm { if (NumElements == 8) return MVT::v8f16; break; case MVT::f32: - if (NumElements == 1) return MVT::v1f32; - if (NumElements == 2) return MVT::v2f32; - if (NumElements == 4) return MVT::v4f32; - if (NumElements == 8) return MVT::v8f32; - if (NumElements == 16) return MVT::v16f32; + if (NumElements == 1) return MVT::v1f32; + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 3) return MVT::v3f32; + if (NumElements == 4) return MVT::v4f32; + if (NumElements == 5) return MVT::v5f32; + if (NumElements == 8) return MVT::v8f32; + if (NumElements == 16) return MVT::v16f32; + if (NumElements == 32) return MVT::v32f32; + if (NumElements == 64) return MVT::v64f32; + if (NumElements == 128) return MVT::v128f32; + if (NumElements == 256) return MVT::v256f32; + if (NumElements == 512) return MVT::v512f32; + if (NumElements == 1024) return MVT::v1024f32; + if (NumElements == 2048) return MVT::v2048f32; break; case MVT::f64: if (NumElements == 1) return MVT::v1f64; diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index b4bf3210cc73..e65bb051f181 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -1,9 +1,8 @@ //===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -33,18 +32,41 @@ template <typename T, size_t N> struct object_deleter<T[N]> { static void call(void *Ptr) { delete[](T *)Ptr; } }; +// ManagedStatic must be initialized to zero, and it must *not* have a dynamic +// initializer because managed statics are often created while running other +// dynamic initializers. In standard C++11, the best way to accomplish this is +// with a constexpr default constructor. However, different versions of the +// Visual C++ compiler have had bugs where, even though the constructor may be +// constexpr, a dynamic initializer may be emitted depending on optimization +// settings. For the affected versions of MSVC, use the old linker +// initialization pattern of not providing a constructor and leaving the fields +// uninitialized. +#if !defined(_MSC_VER) || defined(__clang__) +#define LLVM_USE_CONSTEXPR_CTOR +#endif + /// ManagedStaticBase - Common base class for ManagedStatic instances. class ManagedStaticBase { protected: +#ifdef LLVM_USE_CONSTEXPR_CTOR + mutable std::atomic<void *> Ptr{}; + mutable void (*DeleterFn)(void *) = nullptr; + mutable const ManagedStaticBase *Next = nullptr; +#else // This should only be used as a static variable, which guarantees that this // will be zero initialized. mutable std::atomic<void *> Ptr; - mutable void (*DeleterFn)(void*); + mutable void (*DeleterFn)(void *); mutable const ManagedStaticBase *Next; +#endif void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; public: +#ifdef LLVM_USE_CONSTEXPR_CTOR + constexpr ManagedStaticBase() = default; +#endif + /// isConstructed - Return true if this object has not been created yet. bool isConstructed() const { return Ptr != nullptr; } diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index b59f21b4998e..249139e824b5 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -1,9 +1,8 @@ //===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -52,14 +51,14 @@ enum ZeroBehavior { namespace detail { template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { - static std::size_t count(T Val, ZeroBehavior) { + static unsigned count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits<T>::digits; if (Val & 0x1) return 0; // Bisection method. - std::size_t ZeroBits = 0; + unsigned ZeroBits = 0; T Shift = std::numeric_limits<T>::digits >> 1; T Mask = std::numeric_limits<T>::max() >> Shift; while (Shift) { @@ -76,7 +75,7 @@ template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { #if __GNUC__ >= 4 || defined(_MSC_VER) template <typename T> struct TrailingZerosCounter<T, 4> { - static std::size_t count(T Val, ZeroBehavior ZB) { + static unsigned count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; @@ -92,7 +91,7 @@ template <typename T> struct TrailingZerosCounter<T, 4> { #if !defined(_MSC_VER) || defined(_M_X64) template <typename T> struct TrailingZerosCounter<T, 8> { - static std::size_t count(T Val, ZeroBehavior ZB) { + static unsigned count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; @@ -117,7 +116,7 @@ template <typename T> struct TrailingZerosCounter<T, 8> { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { +unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); @@ -126,12 +125,12 @@ std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { namespace detail { template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { - static std::size_t count(T Val, ZeroBehavior) { + static unsigned count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits<T>::digits; // Bisection method. - std::size_t ZeroBits = 0; + unsigned ZeroBits = 0; for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { T Tmp = Val >> Shift; if (Tmp) @@ -145,7 +144,7 @@ template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { #if __GNUC__ >= 4 || defined(_MSC_VER) template <typename T> struct LeadingZerosCounter<T, 4> { - static std::size_t count(T Val, ZeroBehavior ZB) { + static unsigned count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; @@ -161,7 +160,7 @@ template <typename T> struct LeadingZerosCounter<T, 4> { #if !defined(_MSC_VER) || defined(_M_X64) template <typename T> struct LeadingZerosCounter<T, 8> { - static std::size_t count(T Val, ZeroBehavior ZB) { + static unsigned count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; @@ -186,7 +185,7 @@ template <typename T> struct LeadingZerosCounter<T, 8> { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { +unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); @@ -459,7 +458,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) { /// \param ZB the behavior on an input of all ones. Only ZB_Width and /// ZB_Undefined are valid arguments. template <typename T> -std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { +unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); @@ -475,7 +474,7 @@ std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { /// \param ZB the behavior on an input of all ones. Only ZB_Width and /// ZB_Undefined are valid arguments. template <typename T> -std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { +unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); @@ -560,15 +559,20 @@ inline unsigned Log2_64_Ceil(uint64_t Value) { } /// Return the greatest common divisor of the values using Euclid's algorithm. -inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { +template <typename T> +inline T greatestCommonDivisor(T A, T B) { while (B) { - uint64_t T = B; + T Tmp = B; B = A % B; - A = T; + A = Tmp; } return A; } +inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { + return greatestCommonDivisor<uint64_t>(A, B); +} + /// This function takes a 64-bit integer and returns the bit equivalent double. inline double BitsToDouble(uint64_t Bits) { double D; diff --git a/include/llvm/Support/MemAlloc.h b/include/llvm/Support/MemAlloc.h index d06c659cfba6..0e5869141fd3 100644 --- a/include/llvm/Support/MemAlloc.h +++ b/include/llvm/Support/MemAlloc.h @@ -1,9 +1,8 @@ //===- MemAlloc.h - Memory allocation functions -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -25,23 +24,41 @@ namespace llvm { LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) { void *Result = std::malloc(Sz); - if (Result == nullptr) + if (Result == nullptr) { + // It is implementation-defined whether allocation occurs if the space + // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting + // non-zero, if the space requested was zero. + if (Sz == 0) + return safe_malloc(1); report_bad_alloc_error("Allocation failed"); + } return Result; } LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count, size_t Sz) { void *Result = std::calloc(Count, Sz); - if (Result == nullptr) + if (Result == nullptr) { + // It is implementation-defined whether allocation occurs if the space + // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting + // non-zero, if the space requested was zero. + if (Count == 0 || Sz == 0) + return safe_malloc(1); report_bad_alloc_error("Allocation failed"); + } return Result; } LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) { void *Result = std::realloc(Ptr, Sz); - if (Result == nullptr) + if (Result == nullptr) { + // It is implementation-defined whether allocation occurs if the space + // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting + // non-zero, if the space requested was zero. + if (Sz == 0) + return safe_malloc(1); report_bad_alloc_error("Allocation failed"); + } return Result; } diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index fa026d49a61b..6f22dd7080cd 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -1,9 +1,8 @@ //===- llvm/Support/Memory.h - Memory Support -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,10 @@ #include <system_error> namespace llvm { + +// Forward declare raw_ostream: it is used for debug dumping below. +class raw_ostream; + namespace sys { /// This class encapsulates the notion of a memory block which has an address @@ -28,14 +31,18 @@ namespace sys { /// Memory block abstraction. class MemoryBlock { public: - MemoryBlock() : Address(nullptr), Size(0) { } - MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } + MemoryBlock() : Address(nullptr), AllocatedSize(0) {} + MemoryBlock(void *addr, size_t allocatedSize) + : Address(addr), AllocatedSize(allocatedSize) {} void *base() const { return Address; } - size_t size() const { return Size; } - + /// The size as it was allocated. This is always greater or equal to the + /// size that was originally requested. + size_t allocatedSize() const { return AllocatedSize; } + private: void *Address; ///< Address of first byte of memory area - size_t Size; ///< Size, in bytes of the memory area + size_t AllocatedSize; ///< Size, in bytes of the memory area + unsigned Flags = 0; friend class Memory; }; @@ -46,9 +53,11 @@ namespace sys { class Memory { public: enum ProtectionFlags { - MF_READ = 0x1000000, + MF_READ = 0x1000000, MF_WRITE = 0x2000000, - MF_EXEC = 0x4000000 + MF_EXEC = 0x4000000, + MF_RWE_MASK = 0x7000000, + MF_HUGE_HINT = 0x0000001 }; /// This method allocates a block of memory that is suitable for loading @@ -133,13 +142,22 @@ namespace sys { Memory::releaseMappedMemory(M); } void *base() const { return M.base(); } - size_t size() const { return M.size(); } + /// The size as it was allocated. This is always greater or equal to the + /// size that was originally requested. + size_t allocatedSize() const { return M.allocatedSize(); } MemoryBlock getMemoryBlock() const { return M; } private: MemoryBlock M; }; -} -} +#ifndef NDEBUG + /// Debugging output for Memory::ProtectionFlags. + raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF); + + /// Debugging output for MemoryBlock. + raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB); +#endif // ifndef NDEBUG + } // end namespace sys + } // end namespace llvm #endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 8933295d4ea4..b5196cd84cb4 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -1,9 +1,8 @@ //===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -91,7 +90,7 @@ public: /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. /// Since this is in the middle of a file, the buffer is not null terminated. static ErrorOr<std::unique_ptr<MemoryBuffer>> - getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize, + getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset, bool IsVolatile = false); /// Given an already-open file descriptor, read the file and return a @@ -101,7 +100,7 @@ public: /// can change outside the user's control, e.g. when libclang tries to parse /// while the user is editing/updating the file or if the file is on an NFS. static ErrorOr<std::unique_ptr<MemoryBuffer>> - getOpenFile(int FD, const Twine &Filename, uint64_t FileSize, + getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize, bool RequiresNullTerminator = true, bool IsVolatile = false); /// Open the specified memory range as a MemoryBuffer. Note that InputData @@ -265,7 +264,7 @@ class MemoryBufferRef { public: MemoryBufferRef() = default; - MemoryBufferRef(MemoryBuffer& Buffer) + MemoryBufferRef(const MemoryBuffer& Buffer) : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {} MemoryBufferRef(StringRef Buffer, StringRef Identifier) : Buffer(Buffer), Identifier(Identifier) {} diff --git a/include/llvm/Support/MipsABIFlags.h b/include/llvm/Support/MipsABIFlags.h index 12c350015b21..d3233f645fb9 100644 --- a/include/llvm/Support/MipsABIFlags.h +++ b/include/llvm/Support/MipsABIFlags.h @@ -1,9 +1,8 @@ //===--- MipsABIFlags.h - MIPS ABI flags ----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 680d94b24ef5..c3abfc7a7806 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -1,9 +1,8 @@ //===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index 641d64d94988..d86ced145816 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -1,9 +1,8 @@ //===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/NativeFormatting.h b/include/llvm/Support/NativeFormatting.h index 6d1dd7b422fe..825a44c77c00 100644 --- a/include/llvm/Support/NativeFormatting.h +++ b/include/llvm/Support/NativeFormatting.h @@ -1,9 +1,8 @@ //===- NativeFormatting.h - Low level formatting helpers ---------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index 912e2700d1a0..d84da92aab9b 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -1,9 +1,8 @@ //===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h index dd321c6a1984..d02ef85a75bf 100644 --- a/include/llvm/Support/Options.h +++ b/include/llvm/Support/Options.h @@ -1,9 +1,8 @@ //===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Support/Parallel.h b/include/llvm/Support/Parallel.h index 1462265343be..eab9b492c4a5 100644 --- a/include/llvm/Support/Parallel.h +++ b/include/llvm/Support/Parallel.h @@ -1,9 +1,8 @@ //===- llvm/Support/Parallel.h - Parallel algorithms ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -74,8 +73,12 @@ public: class TaskGroup { Latch L; + bool Parallel; public: + TaskGroup(); + ~TaskGroup(); + void spawn(std::function<void()> f); void sync() const { L.sync(); } diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index 76de887b7cb4..5c0bee58f188 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -1,9 +1,8 @@ //===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/PluginLoader.h b/include/llvm/Support/PluginLoader.h index bdbb134b28eb..c0c516bdae03 100644 --- a/include/llvm/Support/PluginLoader.h +++ b/include/llvm/Support/PluginLoader.h @@ -1,9 +1,8 @@ //===-- llvm/Support/PluginLoader.h - Plugin Loader for Tools ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index 1710b57131d1..1e7e5b53ca65 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -1,9 +1,8 @@ //===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 4d64fe4ef727..6eb070b2297e 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -1,9 +1,8 @@ //===- llvm/Support/PrettyStackTrace.h - Pretty Crash Handling --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,8 +21,22 @@ namespace llvm { class raw_ostream; + /// Enables dumping a "pretty" stack trace when the program crashes. + /// + /// \see PrettyStackTraceEntry void EnablePrettyStackTrace(); + /// Enables (or disables) dumping a "pretty" stack trace when the user sends + /// SIGINFO or SIGUSR1 to the current process. + /// + /// This is a per-thread decision so that a program can choose to print stack + /// traces only on a primary thread, or on all threads that use + /// PrettyStackTraceEntry. + /// + /// \see EnablePrettyStackTrace + /// \see PrettyStackTraceEntry + void EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable = true); + /// PrettyStackTraceEntry - This class is used to represent a frame of the /// "pretty" stack trace that is dumped when a program crashes. You can define /// subclasses of this and declare them on the program stack: when they are diff --git a/include/llvm/Support/Printable.h b/include/llvm/Support/Printable.h index cb55d41316e3..0f8670d0419c 100644 --- a/include/llvm/Support/Printable.h +++ b/include/llvm/Support/Printable.h @@ -1,9 +1,8 @@ //===--- Printable.h - Print function helpers -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index f9f1cac86278..67e37912519b 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -1,9 +1,8 @@ //===- llvm/Support/Process.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -29,6 +28,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Error.h" #include <system_error> namespace llvm { @@ -42,7 +42,25 @@ namespace sys { /// current executing process. class Process { public: - static unsigned getPageSize(); + /// Get the process's page size. + /// This may fail if the underlying syscall returns an error. In most cases, + /// page size information is used for optimization, and this error can be + /// safely discarded by calling consumeError, and an estimated page size + /// substituted instead. + static Expected<unsigned> getPageSize(); + + /// Get the process's estimated page size. + /// This function always succeeds, but if the underlying syscall to determine + /// the page size fails then this will silently return an estimated page size. + /// The estimated page size is guaranteed to be a power of 2. + static unsigned getPageSizeEstimate() { + if (auto PageSize = getPageSize()) + return *PageSize; + else { + consumeError(PageSize.takeError()); + return 4096; + } + } /// Return process memory usage. /// This static function will return the total amount of memory allocated diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 1f4dbdce3323..6b2315c5da8d 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -1,9 +1,8 @@ //===- llvm/Support/Program.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h index 5ac3e558999b..9cd57cbd65a1 100644 --- a/include/llvm/Support/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -1,9 +1,8 @@ //===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h index 1399dab815f8..55d6876cc5e4 100644 --- a/include/llvm/Support/RandomNumberGenerator.h +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -1,9 +1,8 @@ //==- llvm/Support/RandomNumberGenerator.h - RNG for diversity ---*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index 53db2e86d12d..bbd9ae321ae3 100644 --- a/include/llvm/Support/Recycler.h +++ b/include/llvm/Support/Recycler.h @@ -1,9 +1,8 @@ //==- llvm/Support/Recycler.h - Recycling Allocator --------------*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/RecyclingAllocator.h b/include/llvm/Support/RecyclingAllocator.h index 32b033b17946..2c29dacfe212 100644 --- a/include/llvm/Support/RecyclingAllocator.h +++ b/include/llvm/Support/RecyclingAllocator.h @@ -1,9 +1,8 @@ //==- llvm/Support/RecyclingAllocator.h - Recycling Allocator ----*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index d901eb1e3ffb..2d19b10fd890 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -1,9 +1,8 @@ //===-- Regex.h - Regular Expression matcher implementation -*- C++ -*-----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index 02fd5b9354a1..4d8aa5f1470d 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -1,9 +1,8 @@ //=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -81,17 +80,17 @@ namespace llvm { /// Iterators for registry entries. /// - class iterator { + class iterator + : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag, + const entry> { const node *Cur; public: explicit iterator(const node *N) : Cur(N) {} bool operator==(const iterator &That) const { return Cur == That.Cur; } - bool operator!=(const iterator &That) const { return Cur != That.Cur; } iterator &operator++() { Cur = Cur->Next; return *this; } const entry &operator*() const { return Cur->Val; } - const entry *operator->() const { return &Cur->Val; } }; // begin is not defined here in order to avoid usage of an undefined static diff --git a/include/llvm/Support/SHA1.h b/include/llvm/Support/SHA1.h index 1fc60a878f94..87fe94bbd5cd 100644 --- a/include/llvm/Support/SHA1.h +++ b/include/llvm/Support/SHA1.h @@ -1,9 +1,8 @@ //==- SHA1.h - SHA1 implementation for LLVM --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 code is taken from public domain diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index c74feff378d6..d8607034ee86 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -1,9 +1,8 @@ //===- SMLoc.h - Source location for use with diagnostics -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/SMTAPI.h b/include/llvm/Support/SMTAPI.h new file mode 100644 index 000000000000..24dcd124593e --- /dev/null +++ b/include/llvm/Support/SMTAPI.h @@ -0,0 +1,447 @@ +//===- SMTAPI.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 SMT generic Solver API, which will be the base class +// for every SMT solver specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SMTAPI_H +#define LLVM_SUPPORT_SMTAPI_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> + +namespace llvm { + +/// Generic base class for SMT sorts +class SMTSort { +public: + SMTSort() = default; + virtual ~SMTSort() = default; + + /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl(). + virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); } + + /// Returns true if the sort is a floating-point, calls isFloatSortImpl(). + virtual bool isFloatSort() const { return isFloatSortImpl(); } + + /// Returns true if the sort is a boolean, calls isBooleanSortImpl(). + virtual bool isBooleanSort() const { return isBooleanSortImpl(); } + + /// Returns the bitvector size, fails if the sort is not a bitvector + /// Calls getBitvectorSortSizeImpl(). + virtual unsigned getBitvectorSortSize() const { + assert(isBitvectorSort() && "Not a bitvector sort!"); + unsigned Size = getBitvectorSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + /// Returns the floating-point size, fails if the sort is not a floating-point + /// Calls getFloatSortSizeImpl(). + virtual unsigned getFloatSortSize() const { + assert(isFloatSort() && "Not a floating-point sort!"); + unsigned Size = getFloatSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; + + bool operator<(const SMTSort &Other) const { + llvm::FoldingSetNodeID ID1, ID2; + Profile(ID1); + Other.Profile(ID2); + return ID1 < ID2; + } + + friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const; + +protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. + virtual bool equal_to(SMTSort const &other) const = 0; + + /// Query the SMT solver and checks if a sort is bitvector. + virtual bool isBitvectorSortImpl() const = 0; + + /// Query the SMT solver and checks if a sort is floating-point. + virtual bool isFloatSortImpl() const = 0; + + /// Query the SMT solver and checks if a sort is boolean. + virtual bool isBooleanSortImpl() const = 0; + + /// Query the SMT solver and returns the sort bit width. + virtual unsigned getBitvectorSortSizeImpl() const = 0; + + /// Query the SMT solver and returns the sort bit width. + virtual unsigned getFloatSortSizeImpl() const = 0; +}; + +/// Shared pointer for SMTSorts, used by SMTSolver API. +using SMTSortRef = const SMTSort *; + +/// Generic base class for SMT exprs +class SMTExpr { +public: + SMTExpr() = default; + virtual ~SMTExpr() = default; + + bool operator<(const SMTExpr &Other) const { + llvm::FoldingSetNodeID ID1, ID2; + Profile(ID1); + Other.Profile(ID2); + return ID1 < ID2; + } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; + + friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const; + +protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. + virtual bool equal_to(SMTExpr const &other) const = 0; +}; + +/// Shared pointer for SMTExprs, used by SMTSolver API. +using SMTExprRef = const SMTExpr *; + +/// Generic base class for SMT Solvers +/// +/// This class is responsible for wrapping all sorts and expression generation, +/// through the mk* methods. It also provides methods to create SMT expressions +/// straight from clang's AST, through the from* methods. +class SMTSolver { +public: + SMTSolver() = default; + virtual ~SMTSolver() = default; + + LLVM_DUMP_METHOD void dump() const; + + // Returns an appropriate floating-point sort for the given bitwidth. + SMTSortRef getFloatSort(unsigned BitWidth) { + switch (BitWidth) { + case 16: + return getFloat16Sort(); + case 32: + return getFloat32Sort(); + case 64: + return getFloat64Sort(); + case 128: + return getFloat128Sort(); + default:; + } + llvm_unreachable("Unsupported floating-point bitwidth!"); + } + + // Returns a boolean sort. + virtual SMTSortRef getBoolSort() = 0; + + // Returns an appropriate bitvector sort for the given bitwidth. + virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0; + + // Returns a floating-point sort of width 16 + virtual SMTSortRef getFloat16Sort() = 0; + + // Returns a floating-point sort of width 32 + virtual SMTSortRef getFloat32Sort() = 0; + + // Returns a floating-point sort of width 64 + virtual SMTSortRef getFloat64Sort() = 0; + + // Returns a floating-point sort of width 128 + virtual SMTSortRef getFloat128Sort() = 0; + + // Returns an appropriate sort for the given AST. + virtual SMTSortRef getSort(const SMTExprRef &AST) = 0; + + /// Given a constraint, adds it to the solver + virtual void addConstraint(const SMTExprRef &Exp) const = 0; + + /// Creates a bitvector addition operation + virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector subtraction operation + virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector multiplication operation + virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed modulus operation + virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned modulus operation + virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed division operation + virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned division operation + virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector logical shift left operation + virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector arithmetic shift right operation + virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector logical shift right operation + virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector negation operation + virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0; + + /// Creates a bitvector not operation + virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0; + + /// Creates a bitvector xor operation + virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector or operation + virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector and operation + virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned less-than operation + virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed less-than operation + virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned greater-than operation + virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed greater-than operation + virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned less-equal-than operation + virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed less-equal-than operation + virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned greater-equal-than operation + virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed greater-equal-than operation + virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean not operation + virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0; + + /// Creates a boolean equality operation + virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean and operation + virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean or operation + virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean ite operation + virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, + const SMTExprRef &F) = 0; + + /// Creates a bitvector sign extension operation + virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0; + + /// Creates a bitvector zero extension operation + virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0; + + /// Creates a bitvector extract operation + virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) = 0; + + /// Creates a bitvector concat operation + virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a predicate that checks for overflow in a bitvector addition + /// operation + virtual SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS, + const SMTExprRef &RHS, + bool isSigned) = 0; + + /// Creates a predicate that checks for underflow in a signed bitvector + /// addition operation + virtual SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a predicate that checks for overflow in a signed bitvector + /// subtraction operation + virtual SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a predicate that checks for underflow in a bitvector subtraction + /// operation + virtual SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS, + const SMTExprRef &RHS, + bool isSigned) = 0; + + /// Creates a predicate that checks for overflow in a signed bitvector + /// division/modulus operation + virtual SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a predicate that checks for overflow in a bitvector negation + /// operation + virtual SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) = 0; + + /// Creates a predicate that checks for overflow in a bitvector multiplication + /// operation + virtual SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS, + const SMTExprRef &RHS, + bool isSigned) = 0; + + /// Creates a predicate that checks for underflow in a signed bitvector + /// multiplication operation + virtual SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a floating-point negation operation + virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isInfinite operation + virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isNaN operation + virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isNormal operation + virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isZero operation + virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point multiplication operation + virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point division operation + virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point remainder operation + virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point addition operation + virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point subtraction operation + virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point less-than operation + virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point greater-than operation + virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point less-than-or-equal operation + virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point greater-than-or-equal operation + virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point equality operation + virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a floating-point conversion from floatint-point to floating-point + /// operation + virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from signed bitvector to + /// floatint-point operation + virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from unsigned bitvector to + /// floatint-point operation + virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from floatint-point to signed + /// bitvector operation + virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0; + + /// Creates a floating-point conversion from floatint-point to unsigned + /// bitvector operation + virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0; + + /// Creates a new symbol, given a name and a sort + virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0; + + // Returns an appropriate floating-point rounding mode. + virtual SMTExprRef getFloatRoundingMode() = 0; + + // If the a model is available, returns the value of a given bitvector symbol + virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, + bool isUnsigned) = 0; + + // If the a model is available, returns the value of a given boolean symbol + virtual bool getBoolean(const SMTExprRef &Exp) = 0; + + /// Constructs an SMTExprRef from a boolean. + virtual SMTExprRef mkBoolean(const bool b) = 0; + + /// Constructs an SMTExprRef from a finite APFloat. + virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0; + + /// Constructs an SMTExprRef from an APSInt and its bit width + virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0; + + /// Given an expression, extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0; + + /// Given an expression extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, + llvm::APFloat &Float) = 0; + + /// Check if the constraints are satisfiable + virtual Optional<bool> check() const = 0; + + /// Push the current solver state + virtual void push() = 0; + + /// Pop the previous solver state + virtual void pop(unsigned NumStates = 1) = 0; + + /// Reset the solver and remove all constraints. + virtual void reset() = 0; + + /// Checks if the solver supports floating-points. + virtual bool isFPSupported() = 0; + + virtual void print(raw_ostream &OS) const = 0; +}; + +/// Shared pointer for SMTSolvers. +using SMTSolverRef = std::shared_ptr<SMTSolver>; + +/// Convenience method to create and Z3Solver object +SMTSolverRef CreateZ3Solver(); + +} // namespace llvm + +#endif diff --git a/include/llvm/Support/SaveAndRestore.h b/include/llvm/Support/SaveAndRestore.h index 8e11789907ad..3c0333b7119a 100644 --- a/include/llvm/Support/SaveAndRestore.h +++ b/include/llvm/Support/SaveAndRestore.h @@ -1,9 +1,8 @@ //===-- SaveAndRestore.h - Utility -------------------------------*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/ScalableSize.h b/include/llvm/Support/ScalableSize.h new file mode 100644 index 000000000000..96bf043773a0 --- /dev/null +++ b/include/llvm/Support/ScalableSize.h @@ -0,0 +1,43 @@ +//===- ScalableSize.h - Scalable vector size info ---------------*- 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 a struct that can be used to query the size of IR types +// which may be scalable vectors. It provides convenience operators so that +// it can be used in much the same way as a single scalar value. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SCALABLESIZE_H +#define LLVM_SUPPORT_SCALABLESIZE_H + +namespace llvm { + +class ElementCount { +public: + unsigned Min; // Minimum number of vector elements. + bool Scalable; // If true, NumElements is a multiple of 'Min' determined + // at runtime rather than compile time. + + ElementCount(unsigned Min, bool Scalable) + : Min(Min), Scalable(Scalable) {} + + ElementCount operator*(unsigned RHS) { + return { Min * RHS, Scalable }; + } + ElementCount operator/(unsigned RHS) { + return { Min / RHS, Scalable }; + } + + bool operator==(const ElementCount& RHS) const { + return Min == RHS.Min && Scalable == RHS.Scalable; + } +}; + +} // end namespace llvm + +#endif // LLVM_SUPPORT_SCALABLESIZE_H diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index 3bd3ccedc42c..552da34f357b 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -1,9 +1,8 @@ //===- llvm/Support/ScaledNumber.h - Support for scaled numbers -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -887,10 +886,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { Digits >>= Shift; } -template <typename T> struct isPodLike; -template <typename T> struct isPodLike<ScaledNumber<T>> { - static const bool value = true; -}; } // end namespace llvm diff --git a/include/llvm/Support/ScopedPrinter.h b/include/llvm/Support/ScopedPrinter.h index 34c1a287ee10..88daedc8713b 100644 --- a/include/llvm/Support/ScopedPrinter.h +++ b/include/llvm/Support/ScopedPrinter.h @@ -1,9 +1,8 @@ -//===-- ScopedPrinter.h ---------------------------------------------------===// +//===-- ScopedPrinter.h ----------------------------------------*- C++ -*--===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index f25a04969904..a6b215a24311 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -1,9 +1,8 @@ //===- llvm/Support/Signals.h - Signal Handling support ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -66,13 +65,25 @@ namespace sys { /// This function registers a function to be called when the user "interrupts" /// the program (typically by pressing ctrl-c). When the user interrupts the /// program, the specified interrupt function is called instead of the program - /// being killed, and the interrupt function automatically disabled. Note - /// that interrupt functions are not allowed to call any non-reentrant + /// being killed, and the interrupt function automatically disabled. + /// + /// Note that interrupt functions are not allowed to call any non-reentrant /// functions. An null interrupt function pointer disables the current /// installed function. Note also that the handler may be executed on a /// different thread on some platforms. - /// Register a function to be called when ctrl-c is pressed. void SetInterruptFunction(void (*IF)()); + + /// Registers a function to be called when an "info" signal is delivered to + /// the process. + /// + /// On POSIX systems, this will be SIGUSR1; on systems that have it, SIGINFO + /// will also be used (typically ctrl-t). + /// + /// Note that signal handlers are not allowed to call any non-reentrant + /// functions. An null function pointer disables the current installed + /// function. Note also that the handler may be executed on a different + /// thread on some platforms. + void SetInfoSignalFunction(void (*Handler)()); } // End sys namespace } // End llvm namespace diff --git a/include/llvm/Support/Signposts.h b/include/llvm/Support/Signposts.h new file mode 100644 index 000000000000..b5a8c3d61e3e --- /dev/null +++ b/include/llvm/Support/Signposts.h @@ -0,0 +1,43 @@ +//===-- llvm/Support/Signposts.h - Interval debug annotations ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file Some OS's provide profilers that allow applications to provide custom +/// annotations to the profiler. For example, on Xcode 10 and later 'signposts' +/// can be emitted by the application and these will be rendered to the Points +/// of Interest track on the instruments timeline. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SIGNPOSTS_H +#define LLVM_SUPPORT_SIGNPOSTS_H + +namespace llvm { +class SignpostEmitterImpl; +class Timer; + +/// Manages the emission of signposts into the recording method supported by +/// the OS. +class SignpostEmitter { + SignpostEmitterImpl *Impl; + +public: + SignpostEmitter(); + ~SignpostEmitter(); + + bool isEnabled() const; + + /// Begin a signposted interval for the given timer. + void startTimerInterval(Timer *T); + /// End a signposted interval for the given timer. + void endTimerInterval(Timer *T); +}; + +} // end namespace llvm + +#endif // ifndef LLVM_SUPPORT_SIGNPOSTS_H diff --git a/include/llvm/Support/SmallVectorMemoryBuffer.h b/include/llvm/Support/SmallVectorMemoryBuffer.h index c4a600e7f37d..b63b58e3a8ba 100644 --- a/include/llvm/Support/SmallVectorMemoryBuffer.h +++ b/include/llvm/Support/SmallVectorMemoryBuffer.h @@ -1,9 +1,8 @@ //===- SmallVectorMemoryBuffer.h --------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Solaris/sys/regset.h b/include/llvm/Support/Solaris/sys/regset.h index 6a69ebe718a1..6bd98fa826a6 100644 --- a/include/llvm/Support/Solaris/sys/regset.h +++ b/include/llvm/Support/Solaris/sys/regset.h @@ -1,9 +1,8 @@ /*===- llvm/Support/Solaris/sys/regset.h ------------------------*- C++ -*-===* * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. + * 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 * *===----------------------------------------------------------------------===* * diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 63ac893239d1..aa6026c23d07 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -1,9 +1,8 @@ //===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -107,6 +106,8 @@ public: SourceMgr() = default; SourceMgr(const SourceMgr &) = delete; SourceMgr &operator=(const SourceMgr &) = delete; + SourceMgr(SourceMgr &&) = default; + SourceMgr &operator=(SourceMgr &&) = default; ~SourceMgr() = default; void setIncludeDirs(const std::vector<std::string> &Dirs) { diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h index fd62fc48047b..b7400266f4df 100644 --- a/include/llvm/Support/SpecialCaseList.h +++ b/include/llvm/Support/SpecialCaseList.h @@ -1,9 +1,8 @@ //===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 a utility class used to parse user-provided text files with diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index bb5fd07f0d00..a4f45916f53d 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -1,9 +1,8 @@ //===- StringPool.h - Interned string pool ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/StringSaver.h b/include/llvm/Support/StringSaver.h index 6b77d487333b..c54044e3986c 100644 --- a/include/llvm/Support/StringSaver.h +++ b/include/llvm/Support/StringSaver.h @@ -1,9 +1,8 @@ //===- llvm/Support/StringSaver.h -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 71d3724950ab..06a447a27c2a 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -1,9 +1,8 @@ //===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cstddef> +#include <type_traits> #if defined(_MSC_VER) && !defined(_DEBUG) #include <stdlib.h> #endif @@ -116,6 +116,13 @@ inline double getSwappedBytes(double C) { return out.d; } +template <typename T> +inline typename std::enable_if<std::is_enum<T>::value, T>::type +getSwappedBytes(T C) { + return static_cast<T>( + getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C))); +} + template<typename T> inline void swapByteOrder(T &Value) { Value = getSwappedBytes(Value); diff --git a/include/llvm/Support/SymbolRemappingReader.h b/include/llvm/Support/SymbolRemappingReader.h index b457b9e817e4..2b9ab570eb8b 100644 --- a/include/llvm/Support/SymbolRemappingReader.h +++ b/include/llvm/Support/SymbolRemappingReader.h @@ -1,9 +1,8 @@ //===- SymbolRemappingReader.h - Read symbol remapping file -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h index bd60793d1554..77deddb9ee1c 100644 --- a/include/llvm/Support/SystemUtils.h +++ b/include/llvm/Support/SystemUtils.h @@ -1,9 +1,8 @@ //===- SystemUtils.h - Utilities to do low-level system stuff ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/TarWriter.h b/include/llvm/Support/TarWriter.h index 639f61b53892..71164e2ef961 100644 --- a/include/llvm/Support/TarWriter.h +++ b/include/llvm/Support/TarWriter.h @@ -1,9 +1,8 @@ //===-- llvm/Support/TarWriter.h - Tar archive file creator -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/TargetOpcodes.def b/include/llvm/Support/TargetOpcodes.def index 3e8193a5cdcf..598c1064efd0 100644 --- a/include/llvm/Support/TargetOpcodes.def +++ b/include/llvm/Support/TargetOpcodes.def @@ -1,9 +1,8 @@ //===-- llvm/Support/TargetOpcodes.def - Target Indep Opcodes ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -29,6 +28,7 @@ /// HANDLE_TARGET_OPCODE(PHI) HANDLE_TARGET_OPCODE(INLINEASM) +HANDLE_TARGET_OPCODE(INLINEASM_BR) HANDLE_TARGET_OPCODE(CFI_INSTRUCTION) HANDLE_TARGET_OPCODE(EH_LABEL) HANDLE_TARGET_OPCODE(GC_LABEL) @@ -316,6 +316,9 @@ HANDLE_TARGET_OPCODE(G_ATOMICRMW_MIN) HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMAX) HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMIN) +// Generic atomic fence +HANDLE_TARGET_OPCODE(G_FENCE) + /// Generic conditional branch instruction. HANDLE_TARGET_OPCODE(G_BRCOND) @@ -481,6 +484,27 @@ HANDLE_TARGET_OPCODE(G_UITOFP) /// Generic FP absolute value. HANDLE_TARGET_OPCODE(G_FABS) +/// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This does +/// not require that X and Y have the same type, just that they are both +/// floating point. X and the result must have the same type. FCOPYSIGN(f32, +/// f64) is allowed. +HANDLE_TARGET_OPCODE(G_FCOPYSIGN) + +/// Generic FP canonicalize value. +HANDLE_TARGET_OPCODE(G_FCANONICALIZE) + +/// FP min/max matching libm's fmin/fmax +HANDLE_TARGET_OPCODE(G_FMINNUM) +HANDLE_TARGET_OPCODE(G_FMAXNUM) + +/// FP min/max matching IEEE-754 2008's minnum/maxnum semantics. +HANDLE_TARGET_OPCODE(G_FMINNUM_IEEE) +HANDLE_TARGET_OPCODE(G_FMAXNUM_IEEE) + +/// FP min/max matching IEEE-754 2018 draft semantics. +HANDLE_TARGET_OPCODE(G_FMINIMUM) +HANDLE_TARGET_OPCODE(G_FMAXIMUM) + /// Generic pointer offset HANDLE_TARGET_OPCODE(G_GEP) @@ -488,9 +512,24 @@ HANDLE_TARGET_OPCODE(G_GEP) /// *down* to the given alignment. HANDLE_TARGET_OPCODE(G_PTR_MASK) +/// Generic signed integer minimum. +HANDLE_TARGET_OPCODE(G_SMIN) + +/// Generic signed integer maximum. +HANDLE_TARGET_OPCODE(G_SMAX) + +/// Generic unsigned integer maximum. +HANDLE_TARGET_OPCODE(G_UMIN) + +/// Generic unsigned integer maximum. +HANDLE_TARGET_OPCODE(G_UMAX) + /// Generic BRANCH instruction. This is an unconditional branch. HANDLE_TARGET_OPCODE(G_BR) +/// Generic branch to jump table entry. +HANDLE_TARGET_OPCODE(G_BRJT) + /// Generic insertelement. HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT) @@ -521,18 +560,39 @@ HANDLE_TARGET_OPCODE(G_BSWAP) /// Floating point ceil. HANDLE_TARGET_OPCODE(G_FCEIL) +/// Floating point cosine. +HANDLE_TARGET_OPCODE(G_FCOS) + +/// Floating point sine. +HANDLE_TARGET_OPCODE(G_FSIN) + +/// Floating point square root. +HANDLE_TARGET_OPCODE(G_FSQRT) + +/// Floating point floor. +HANDLE_TARGET_OPCODE(G_FFLOOR) + +/// Floating point round to next integer. +HANDLE_TARGET_OPCODE(G_FRINT) + +/// Floating point round to nearest integer. +HANDLE_TARGET_OPCODE(G_FNEARBYINT) + /// Generic AddressSpaceCast. HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST) /// Generic block address HANDLE_TARGET_OPCODE(G_BLOCK_ADDR) +/// Generic jump table address +HANDLE_TARGET_OPCODE(G_JUMP_TABLE) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BLOCK_ADDR) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_JUMP_TABLE) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h index ace11ed410a3..a7e1a752d081 100644 --- a/include/llvm/Support/TargetParser.h +++ b/include/llvm/Support/TargetParser.h @@ -1,9 +1,8 @@ //===-- TargetParser - Parser for target features ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -122,10 +121,15 @@ enum GPUKind : uint32_t { GK_GFX902 = 61, GK_GFX904 = 62, GK_GFX906 = 63, + GK_GFX908 = 64, GK_GFX909 = 65, + GK_GFX1010 = 71, + GK_GFX1011 = 72, + GK_GFX1012 = 73, + GK_AMDGCN_FIRST = GK_GFX600, - GK_AMDGCN_LAST = GK_GFX909, + GK_AMDGCN_LAST = GK_GFX1012, }; /// Instruction set architecture version. diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 1bafc4e687da..bf75650760d0 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -1,9 +1,8 @@ //===- Support/TargetRegistry.h - Target Registration -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -101,6 +100,11 @@ MCStreamer *createWasmStreamer(MCContext &Ctx, std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE, bool RelaxAll); +MCStreamer *createXCOFFStreamer(MCContext &Ctx, + std::unique_ptr<MCAsmBackend> &&TAB, + std::unique_ptr<MCObjectWriter> &&OW, + std::unique_ptr<MCCodeEmitter> &&CE, + bool RelaxAll); MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx); @@ -471,7 +475,7 @@ public: bool DWARFMustBeAtTheEnd) const { MCStreamer *S; switch (T.getObjectFormat()) { - default: + case Triple::UnknownObjectFormat: llvm_unreachable("Unknown object format"); case Triple::COFF: assert(T.isOSWindows() && "only Windows COFF is supported"); @@ -505,6 +509,10 @@ public: S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW), std::move(Emitter), RelaxAll); break; + case Triple::XCOFF: + S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); + break; } if (ObjectTargetStreamerCtorFn) ObjectTargetStreamerCtorFn(*S, STI); diff --git a/include/llvm/Support/TargetSelect.h b/include/llvm/Support/TargetSelect.h index 582785cb69a5..9ffb84c4a570 100644 --- a/include/llvm/Support/TargetSelect.h +++ b/include/llvm/Support/TargetSelect.h @@ -1,9 +1,8 @@ //===- TargetSelect.h - Target Selection & Registration ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/TaskQueue.h b/include/llvm/Support/TaskQueue.h index 49981adb763d..df2ffdee2cc2 100644 --- a/include/llvm/Support/TaskQueue.h +++ b/include/llvm/Support/TaskQueue.h @@ -1,9 +1,8 @@ //===-- llvm/Support/TaskQueue.h - A TaskQueue implementation ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 885bd18e8356..d6838c15fc34 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -1,9 +1,8 @@ //===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h index 4fdbd528b212..4bcbaa3142fd 100644 --- a/include/llvm/Support/ThreadPool.h +++ b/include/llvm/Support/ThreadPool.h @@ -1,9 +1,8 @@ //===-- llvm/Support/ThreadPool.h - A ThreadPool implementation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index ba7ece5e72ba..46d413dc487b 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -1,9 +1,8 @@ //===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -33,6 +32,9 @@ // implementations like libstdc++ are known to have problems on NetBSD, // OpenBSD and PowerPC. #define LLVM_THREADING_USE_STD_CALL_ONCE 1 +#elif defined(LLVM_ON_UNIX) && \ + ((defined(__ppc__) || defined(__PPC__)) && defined(__LITTLE_ENDIAN__)) +#define LLVM_THREADING_USE_STD_CALL_ONCE 1 #else #define LLVM_THREADING_USE_STD_CALL_ONCE 0 #endif @@ -165,6 +167,19 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, /// purposes, and as with setting a thread's name no indication of whether /// the operation succeeded or failed is returned. void get_thread_name(SmallVectorImpl<char> &Name); + + enum class ThreadPriority { + Background = 0, + Default = 1, + }; + /// If priority is Background tries to lower current threads priority such + /// that it does not affect foreground tasks significantly. Can be used for + /// long-running, latency-insensitive tasks to make sure cpu is not hogged by + /// this task. + /// If the priority is default tries to restore current threads priority to + /// default scheduling priority. + enum class SetThreadPriorityResult { FAILURE, SUCCESS }; + SetThreadPriorityResult set_thread_priority(ThreadPriority Priority); } #endif diff --git a/include/llvm/Support/TimeProfiler.h b/include/llvm/Support/TimeProfiler.h new file mode 100644 index 000000000000..72b6f7180bde --- /dev/null +++ b/include/llvm/Support/TimeProfiler.h @@ -0,0 +1,76 @@ +//===- llvm/Support/TimeProfiler.h - Hierarchical Time Profiler -*- 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_SUPPORT_TIME_PROFILER_H +#define LLVM_SUPPORT_TIME_PROFILER_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +struct TimeTraceProfiler; +extern TimeTraceProfiler *TimeTraceProfilerInstance; + +/// Initialize the time trace profiler. +/// This sets up the global \p TimeTraceProfilerInstance +/// variable to be the profiler instance. +void timeTraceProfilerInitialize(); + +/// Cleanup the time trace profiler, if it was initialized. +void timeTraceProfilerCleanup(); + +/// Is the time trace profiler enabled, i.e. initialized? +inline bool timeTraceProfilerEnabled() { + return TimeTraceProfilerInstance != nullptr; +} + +/// Write profiling data to output file. +/// Data produced is JSON, in Chrome "Trace Event" format, see +/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview +void timeTraceProfilerWrite(raw_pwrite_stream &OS); + +/// Manually begin a time section, with the given \p Name and \p Detail. +/// Profiler copies the string data, so the pointers can be given into +/// temporaries. Time sections can be hierarchical; every Begin must have a +/// matching End pair but they can nest. +void timeTraceProfilerBegin(StringRef Name, StringRef Detail); +void timeTraceProfilerBegin(StringRef Name, + llvm::function_ref<std::string()> Detail); + +/// Manually end the last time section. +void timeTraceProfilerEnd(); + +/// The TimeTraceScope is a helper class to call the begin and end functions +/// of the time trace profiler. When the object is constructed, it begins +/// the section; and when it is destroyed, it stops it. If the time profiler +/// is not initialized, the overhead is a single branch. +struct TimeTraceScope { + + TimeTraceScope() = delete; + TimeTraceScope(const TimeTraceScope &) = delete; + TimeTraceScope &operator=(const TimeTraceScope &) = delete; + TimeTraceScope(TimeTraceScope &&) = delete; + TimeTraceScope &operator=(TimeTraceScope &&) = delete; + + TimeTraceScope(StringRef Name, StringRef Detail) { + if (TimeTraceProfilerInstance != nullptr) + timeTraceProfilerBegin(Name, Detail); + } + TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) { + if (TimeTraceProfilerInstance != nullptr) + timeTraceProfilerBegin(Name, Detail); + } + ~TimeTraceScope() { + if (TimeTraceProfilerInstance != nullptr) + timeTraceProfilerEnd(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index a11c3ce3ff22..76c9bc7b6863 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -1,9 +1,8 @@ //===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -206,8 +205,9 @@ public: Description.assign(NewDescription.begin(), NewDescription.end()); } - /// Print any started timers in this group. - void print(raw_ostream &OS); + /// Print any started timers in this group, optionally resetting timers after + /// printing them. + void print(raw_ostream &OS, bool ResetAfterPrint = false); /// Clear all timers in this group. void clear(); @@ -234,7 +234,7 @@ private: friend void PrintStatisticsJSON(raw_ostream &OS); void addTimer(Timer &T); void removeTimer(Timer &T); - void prepareToPrintList(); + void prepareToPrintList(bool reset_time = false); void PrintQueuedTimers(raw_ostream &OS); void printJSONValue(raw_ostream &OS, const PrintRecord &R, const char *suffix, double Value); diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index cf3bc2fb0171..a99e327f8db7 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -1,9 +1,8 @@ //===- ToolOutputFile.h - Output files for compiler-like tools -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/TrailingObjects.h b/include/llvm/Support/TrailingObjects.h index 490bd94f4cd5..8cf4f7aed7f8 100644 --- a/include/llvm/Support/TrailingObjects.h +++ b/include/llvm/Support/TrailingObjects.h @@ -1,9 +1,8 @@ //===--- TrailingObjects.h - Variable-length classes ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/TrigramIndex.h b/include/llvm/Support/TrigramIndex.h index da0b6daf47ed..9351c2db169a 100644 --- a/include/llvm/Support/TrigramIndex.h +++ b/include/llvm/Support/TrigramIndex.h @@ -1,9 +1,8 @@ //===-- TrigramIndex.h - a heuristic for SpecialCaseList --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 //===----------------------------------------------------------------------===// // // TrigramIndex implements a heuristic for SpecialCaseList that allows to diff --git a/include/llvm/Support/TypeName.h b/include/llvm/Support/TypeName.h index 0eb7ead98b21..236490a25011 100644 --- a/include/llvm/Support/TypeName.h +++ b/include/llvm/Support/TypeName.h @@ -1,9 +1,8 @@ //===- TypeName.h -----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/Unicode.h b/include/llvm/Support/Unicode.h index 983acaf03635..ca17bba2fbb4 100644 --- a/include/llvm/Support/Unicode.h +++ b/include/llvm/Support/Unicode.h @@ -1,9 +1,8 @@ //===- llvm/Support/Unicode.h - Unicode character properties -*- C++ -*-=====// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 3cf4a6d96602..4b59f8a92b76 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -1,9 +1,8 @@ //===--- UnicodeCharRanges.h - Types and functions for character ranges ---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_SUPPORT_UNICODECHARRANGES_H diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h index 91dc911036d5..0a887ad5965d 100644 --- a/include/llvm/Support/UniqueLock.h +++ b/include/llvm/Support/UniqueLock.h @@ -1,9 +1,8 @@ //===- Support/UniqueLock.h - Acquire/Release Mutex In Scope ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index 084b901b326c..1e14dfec9a61 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -1,9 +1,8 @@ //===- llvm/Support/Valgrind.h - Communication with Valgrind ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/VersionTuple.h b/include/llvm/Support/VersionTuple.h index e85a188e54b4..14736d6b28f0 100644 --- a/include/llvm/Support/VersionTuple.h +++ b/include/llvm/Support/VersionTuple.h @@ -1,9 +1,8 @@ //===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Support/VirtualFileSystem.h b/include/llvm/Support/VirtualFileSystem.h index 61c3d2f46e9c..31c9e851daed 100644 --- a/include/llvm/Support/VirtualFileSystem.h +++ b/include/llvm/Support/VirtualFileSystem.h @@ -1,9 +1,8 @@ //===- VirtualFileSystem.h - Virtual File System Layer ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -59,15 +58,15 @@ public: Status() = default; Status(const llvm::sys::fs::file_status &Status); - Status(StringRef Name, llvm::sys::fs::UniqueID UID, + Status(const Twine &Name, llvm::sys::fs::UniqueID UID, llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, uint64_t Size, llvm::sys::fs::file_type Type, llvm::sys::fs::perms Perms); /// Get a copy of a Status with a different name. - static Status copyWithNewName(const Status &In, StringRef NewName); + static Status copyWithNewName(const Status &In, const Twine &NewName); static Status copyWithNewName(const llvm::sys::fs::file_status &In, - StringRef NewName); + const Twine &NewName); /// Returns the name that should be used for this file or directory. StringRef getName() const { return Name; } @@ -299,8 +298,16 @@ public: /// Gets an \p vfs::FileSystem for the 'real' file system, as seen by /// the operating system. +/// The working directory is linked to the process's working directory. +/// (This is usually thread-hostile). IntrusiveRefCntPtr<FileSystem> getRealFileSystem(); +/// Create an \p vfs::FileSystem for the 'real' file system, as seen by +/// the operating system. +/// It has its own working directory, independent of (but initially equal to) +/// that of the process. +std::unique_ptr<FileSystem> createPhysicalFileSystem(); + /// A file system that allows overlaying one \p AbstractFileSystem on top /// of another. /// @@ -336,15 +343,24 @@ public: using iterator = FileSystemList::reverse_iterator; using const_iterator = FileSystemList::const_reverse_iterator; + using reverse_iterator = FileSystemList::iterator; + using const_reverse_iterator = FileSystemList::const_iterator; /// Get an iterator pointing to the most recently added file system. iterator overlays_begin() { return FSList.rbegin(); } const_iterator overlays_begin() const { return FSList.rbegin(); } - /// Get an iterator pointing one-past the least recently added file - /// system. + /// Get an iterator pointing one-past the least recently added file system. iterator overlays_end() { return FSList.rend(); } const_iterator overlays_end() const { return FSList.rend(); } + + /// Get an iterator pointing to the least recently added file system. + reverse_iterator overlays_rbegin() { return FSList.begin(); } + const_reverse_iterator overlays_rbegin() const { return FSList.begin(); } + + /// Get an iterator pointing one-past the most recently added file system. + reverse_iterator overlays_rend() { return FSList.end(); } + const_reverse_iterator overlays_rend() const { return FSList.end(); } }; /// By default, this delegates all calls to the underlying file system. This diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h index 01e1d926eb95..281595e8f272 100644 --- a/include/llvm/Support/Watchdog.h +++ b/include/llvm/Support/Watchdog.h @@ -1,9 +1,8 @@ //===--- Watchdog.h - Watchdog timer ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h index e27bf1b3a1a5..bdd23b41594e 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -1,9 +1,8 @@ //===-- llvm/Support/Win64EH.h ---Win64 EH Constants-------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h index 63bfe5976546..195405224124 100644 --- a/include/llvm/Support/WindowsError.h +++ b/include/llvm/Support/WindowsError.h @@ -1,9 +1,8 @@ //===-- WindowsError.h - Support for mapping windows errors to posix-------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/WithColor.h b/include/llvm/Support/WithColor.h index 76842d1c3dc8..f4e107581179 100644 --- a/include/llvm/Support/WithColor.h +++ b/include/llvm/Support/WithColor.h @@ -1,9 +1,8 @@ //===- WithColor.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/X86DisassemblerDecoderCommon.h b/include/llvm/Support/X86DisassemblerDecoderCommon.h index 466dd309909a..baf842b12a27 100644 --- a/include/llvm/Support/X86DisassemblerDecoderCommon.h +++ b/include/llvm/Support/X86DisassemblerDecoderCommon.h @@ -1,9 +1,8 @@ //===-- X86DisassemblerDecoderCommon.h - Disassembler decoder ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -47,29 +46,23 @@ namespace X86Disassembler { // Attributes of an instruction that must be known before the opcode can be // processed correctly. Most of these indicate the presence of particular // prefixes, but ATTR_64BIT is simply an attribute of the decoding context. -#define ATTRIBUTE_BITS \ - ENUM_ENTRY(ATTR_NONE, 0x00) \ - ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \ - ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \ - ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \ - ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \ - ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \ - ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \ - ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \ - ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \ - ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \ - ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \ - ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \ - ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \ - ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \ - ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) - -#define ENUM_ENTRY(n, v) n = v, enum attributeBits { - ATTRIBUTE_BITS - ATTR_max + ATTR_NONE = 0x00, + ATTR_64BIT = 0x1 << 0, + ATTR_XS = 0x1 << 1, + ATTR_XD = 0x1 << 2, + ATTR_REXW = 0x1 << 3, + ATTR_OPSIZE = 0x1 << 4, + ATTR_ADSIZE = 0x1 << 5, + ATTR_VEX = 0x1 << 6, + ATTR_VEXL = 0x1 << 7, + ATTR_EVEX = 0x1 << 8, + ATTR_EVEXL2 = 0x1 << 9, + ATTR_EVEXK = 0x1 << 10, + ATTR_EVEXKZ = 0x1 << 11, + ATTR_EVEXB = 0x1 << 12, + ATTR_max = 0x1 << 13, }; -#undef ENUM_ENTRY // Combinations of the above attributes that are relevant to instruction // decode. Although other combinations are possible, they can be reduced to @@ -394,6 +387,7 @@ enum ModRMDecisionType { ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \ ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \ "opcode byte") \ + ENUM_ENTRY(ENCODING_CC, "Condition code encoded in opcode") \ ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \ "in type") \ ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \ @@ -415,9 +409,6 @@ enum OperandEncoding { ENUM_ENTRY(TYPE_R32, "4-byte") \ ENUM_ENTRY(TYPE_R64, "8-byte") \ ENUM_ENTRY(TYPE_IMM, "immediate operand") \ - ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \ - ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \ - ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \ ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \ ENUM_ENTRY(TYPE_M, "Memory operand") \ ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \ @@ -432,6 +423,7 @@ enum OperandEncoding { ENUM_ENTRY(TYPE_YMM, "32-byte") \ ENUM_ENTRY(TYPE_ZMM, "64-byte") \ ENUM_ENTRY(TYPE_VK, "mask register") \ + ENUM_ENTRY(TYPE_VK_PAIR, "mask register pair") \ ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \ ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \ ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \ diff --git a/include/llvm/Support/X86TargetParser.def b/include/llvm/Support/X86TargetParser.def index e9bede545d3f..1749be3b3ae2 100644 --- a/include/llvm/Support/X86TargetParser.def +++ b/include/llvm/Support/X86TargetParser.def @@ -1,9 +1,8 @@ //===- X86TargetParser.def - X86 target parsing defines ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -34,6 +33,8 @@ X86_VENDOR(VENDOR_AMD, "amd") #ifndef X86_CPU_TYPE #define X86_CPU_TYPE(ARCHNAME, ENUM) #endif +// The first part of this list must match what is implemented in libgcc and +// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is. X86_CPU_TYPE_COMPAT_WITH_ALIAS("bonnell", INTEL_BONNELL, "bonnell", "atom") X86_CPU_TYPE_COMPAT ("core2", INTEL_CORE2, "core2") X86_CPU_TYPE_COMPAT ("nehalem", INTEL_COREI7, "corei7") @@ -80,6 +81,8 @@ X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3) #define X86_CPU_SUBTYPE(ARCHNAME, ENUM) #endif +// The first part of this list must match what is implemented in libgcc and +// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is. X86_CPU_SUBTYPE_COMPAT("nehalem", INTEL_COREI7_NEHALEM, "nehalem") X86_CPU_SUBTYPE_COMPAT("westmere", INTEL_COREI7_WESTMERE, "westmere") X86_CPU_SUBTYPE_COMPAT("sandybridge", INTEL_COREI7_SANDYBRIDGE, "sandybridge") @@ -99,14 +102,16 @@ X86_CPU_SUBTYPE_COMPAT("skylake-avx512", INTEL_COREI7_SKYLAKE_AVX512, "skylake-a X86_CPU_SUBTYPE_COMPAT("cannonlake", INTEL_COREI7_CANNONLAKE, "cannonlake") X86_CPU_SUBTYPE_COMPAT("icelake-client", INTEL_COREI7_ICELAKE_CLIENT, "icelake-client") X86_CPU_SUBTYPE_COMPAT("icelake-server", INTEL_COREI7_ICELAKE_SERVER, "icelake-server") +X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2") +X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake") // Entries below this are not in libgcc/compiler-rt. X86_CPU_SUBTYPE ("core2", INTEL_CORE2_65) X86_CPU_SUBTYPE ("penryn", INTEL_CORE2_45) -X86_CPU_SUBTYPE ("cascadelake", INTEL_COREI7_CASCADELAKE) X86_CPU_SUBTYPE ("k6", AMDPENTIUM_K6) X86_CPU_SUBTYPE ("k6-2", AMDPENTIUM_K62) X86_CPU_SUBTYPE ("k6-3", AMDPENTIUM_K63) X86_CPU_SUBTYPE ("geode", AMDPENTIUM_GEODE) +X86_CPU_SUBTYPE ("cooperlake", INTEL_COREI7_COOPERLAKE) #undef X86_CPU_SUBTYPE_COMPAT #undef X86_CPU_SUBTYPE @@ -161,5 +166,6 @@ X86_FEATURE (65, FEATURE_ADX) X86_FEATURE (66, FEATURE_EM64T) X86_FEATURE (67, FEATURE_CLFLUSHOPT) X86_FEATURE (68, FEATURE_SHA) +X86_FEATURE (69, FEATURE_AVX512BF16) #undef X86_FEATURE_COMPAT #undef X86_FEATURE diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 5b031a9a4270..3570119a3bfd 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -1,9 +1,8 @@ //===- YAMLParser.h - Simple YAML parser ------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 3d790e96fff7..5181dc56d81d 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -1,9 +1,8 @@ //===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// // -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -102,8 +101,7 @@ template <class T, class Context> struct MappingContextTraits { /// io.enumCase(value, "green", cGreen); /// } /// }; -template<typename T> -struct ScalarEnumerationTraits { +template <typename T, typename Enable = void> struct ScalarEnumerationTraits { // Must provide: // static void enumeration(IO &io, T &value); }; @@ -119,8 +117,7 @@ struct ScalarEnumerationTraits { /// io.bitSetCase(value, "round", flagRound); /// } /// }; -template<typename T> -struct ScalarBitSetTraits { +template <typename T, typename Enable = void> struct ScalarBitSetTraits { // Must provide: // static void bitset(IO &io, T &value); }; @@ -146,8 +143,7 @@ enum class QuotingType { None, Single, Double }; /// } /// static QuotingType mustQuote(StringRef) { return QuotingType::Single; } /// }; -template<typename T> -struct ScalarTraits { +template <typename T, typename Enable = void> struct ScalarTraits { // Must provide: // // Function to write the value as a string: @@ -864,8 +860,8 @@ public: mapOptionalWithContext(Key, Val, Ctx); } - template <typename T> - void mapOptional(const char *Key, T &Val, const T &Default) { + template <typename T, typename DefaultT> + void mapOptional(const char *Key, T &Val, const DefaultT &Default) { EmptyContext Ctx; mapOptionalWithContext(Key, Val, Default, Ctx); } @@ -891,10 +887,13 @@ public: this->processKey(Key, Val, false, Ctx); } - template <typename T, typename Context> - void mapOptionalWithContext(const char *Key, T &Val, const T &Default, + template <typename T, typename Context, typename DefaultT> + void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default, Context &Ctx) { - this->processKeyWithDefault(Key, Val, Default, false, Ctx); + static_assert(std::is_convertible<DefaultT, T>::value, + "Default type must be implicitly convertible to value type!"); + this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default), + false, Ctx); } private: @@ -978,7 +977,7 @@ yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { bool DoClear; if ( io.beginBitSetScalar(DoClear) ) { if ( DoClear ) - Val = static_cast<T>(0); + Val = T(); ScalarBitSetTraits<T>::bitset(io, Val); io.endBitSetScalar(); } @@ -1243,12 +1242,14 @@ struct ScalarTraits<double> { static QuotingType mustQuote(StringRef) { return QuotingType::None; } }; -// For endian types, we just use the existing ScalarTraits for the underlying -// type. This way endian aware types are supported whenever a ScalarTraits -// is defined for the underlying type. +// For endian types, we use existing scalar Traits class for the underlying +// type. This way endian aware types are supported whenever the traits are +// defined for the underlying type. template <typename value_type, support::endianness endian, size_t alignment> -struct ScalarTraits<support::detail::packed_endian_specific_integral< - value_type, endian, alignment>> { +struct ScalarTraits< + support::detail::packed_endian_specific_integral<value_type, endian, + alignment>, + typename std::enable_if<has_ScalarTraits<value_type>::value>::type> { using endian_type = support::detail::packed_endian_specific_integral<value_type, endian, alignment>; @@ -1269,6 +1270,38 @@ struct ScalarTraits<support::detail::packed_endian_specific_integral< } }; +template <typename value_type, support::endianness endian, size_t alignment> +struct ScalarEnumerationTraits< + support::detail::packed_endian_specific_integral<value_type, endian, + alignment>, + typename std::enable_if< + has_ScalarEnumerationTraits<value_type>::value>::type> { + using endian_type = + support::detail::packed_endian_specific_integral<value_type, endian, + alignment>; + + static void enumeration(IO &io, endian_type &E) { + value_type V = E; + ScalarEnumerationTraits<value_type>::enumeration(io, V); + E = V; + } +}; + +template <typename value_type, support::endianness endian, size_t alignment> +struct ScalarBitSetTraits< + support::detail::packed_endian_specific_integral<value_type, endian, + alignment>, + typename std::enable_if<has_ScalarBitSetTraits<value_type>::value>::type> { + using endian_type = + support::detail::packed_endian_specific_integral<value_type, endian, + alignment>; + static void bitset(IO &io, endian_type &E) { + value_type V = E; + ScalarBitSetTraits<value_type>::bitset(io, V); + E = V; + } +}; + // Utility for use within MappingTraits<>::mapping() method // to [de]normalize an object for use with YAML conversion. template <typename TNorm, typename TFinal> @@ -1587,8 +1620,9 @@ private: bool NeedBitValueComma = false; bool NeedFlowSequenceComma = false; bool EnumerationMatchFound = false; - bool NeedsNewLine = false; bool WriteDefaultValues = false; + StringRef Padding; + StringRef PaddingBeforeContainer; }; /// YAML I/O does conversion based on types. But often native data types @@ -1872,6 +1906,11 @@ struct SequenceTraits<SmallVector<T, N>, typename std::enable_if<CheckIsBool< SequenceElementTraits<T>::flow>::value>::type> : SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {}; +template <typename T> +struct SequenceTraits<SmallVectorImpl<T>, + typename std::enable_if<CheckIsBool< + SequenceElementTraits<T>::flow>::value>::type> + : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {}; // Sequences of fundamental types use flow formatting. template <typename T> diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index b46fd7f730c9..4ecdb17376f1 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -1,9 +1,8 @@ //===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index a983aeb90879..c51a94da3a28 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -1,9 +1,8 @@ //===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index d062e716209d..48bb623b0638 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -1,9 +1,8 @@ //===--- raw_ostream.h - Raw output stream ----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -346,7 +345,7 @@ public: explicit raw_pwrite_stream(bool Unbuffered = false) : raw_ostream(Unbuffered) {} void pwrite(const char *Ptr, size_t Size, uint64_t Offset) { -#ifndef NDBEBUG +#ifndef NDEBUG uint64_t Pos = tell(); // /dev/null always reports a pos of 0, so we cannot perform this check // in that case. diff --git a/include/llvm/Support/raw_sha1_ostream.h b/include/llvm/Support/raw_sha1_ostream.h index bd55d98b7c1d..3991691796b5 100644 --- a/include/llvm/Support/raw_sha1_ostream.h +++ b/include/llvm/Support/raw_sha1_ostream.h @@ -1,9 +1,8 @@ //==- raw_sha1_ostream.h - raw_ostream that compute SHA1 --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h index 787a513d6017..084ed16166fe 100644 --- a/include/llvm/Support/thread.h +++ b/include/llvm/Support/thread.h @@ -1,9 +1,8 @@ //===-- llvm/Support/thread.h - Wrapper for <thread> ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index e7b8f2517b8a..c8c6a76a90f1 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -1,9 +1,8 @@ //===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,35 +24,6 @@ namespace llvm { -/// isPodLike - This is a type trait that is used to determine whether a given -/// type can be copied around with memcpy instead of running ctors etc. -template <typename T> -struct isPodLike { - // std::is_trivially_copyable is available in libc++ with clang, libstdc++ - // that comes with GCC 5. MSVC 2015 and newer also have - // std::is_trivially_copyable. -#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ - (defined(__GNUC__) && __GNUC__ >= 5) || defined(_MSC_VER) - // If the compiler supports the is_trivially_copyable trait use it, as it - // matches the definition of isPodLike closely. - static const bool value = std::is_trivially_copyable<T>::value; -#elif __has_feature(is_trivially_copyable) - // Use the internal name if the compiler supports is_trivially_copyable but we - // don't know if the standard library does. This is the case for clang in - // conjunction with libstdc++ from GCC 4.x. - static const bool value = __is_trivially_copyable(T); -#else - // If we don't know anything else, we can (at least) assume that all non-class - // types are PODs. - static const bool value = !std::is_class<T>::value; -#endif -}; - -// std::pair's are pod-like if their elements are. -template<typename T, typename U> -struct isPodLike<std::pair<T, U>> { - static const bool value = isPodLike<T>::value && isPodLike<U>::value; -}; /// Metafunction that determines whether the given type is either an /// integral type or an enumeration type, including enum classes. @@ -120,6 +90,12 @@ template<typename T> union move_construction_triviality_helper { move_construction_triviality_helper(move_construction_triviality_helper&&) = default; ~move_construction_triviality_helper() = default; }; + +template<class T> +union trivial_helper { + T t; +}; + } // end namespace detail /// An implementation of `std::is_trivially_copy_constructible` since we have @@ -144,6 +120,78 @@ struct is_trivially_move_constructible<T &> : std::true_type {}; template <typename T> struct is_trivially_move_constructible<T &&> : std::true_type {}; + +template <typename T> +struct is_copy_assignable { + template<class F> + static auto get(F*) -> decltype(std::declval<F &>() = std::declval<const F &>(), std::true_type{}); + static std::false_type get(...); + static constexpr bool value = decltype(get((T*)nullptr))::value; +}; + +template <typename T> +struct is_move_assignable { + template<class F> + static auto get(F*) -> decltype(std::declval<F &>() = std::declval<F &&>(), std::true_type{}); + static std::false_type get(...); + static constexpr bool value = decltype(get((T*)nullptr))::value; +}; + + +// An implementation of `std::is_trivially_copyable` since STL version +// is not equally supported by all compilers, especially GCC 4.9. +// Uniform implementation of this trait is important for ABI compatibility +// as it has an impact on SmallVector's ABI (among others). +template <typename T> +class is_trivially_copyable { + + // copy constructors + static constexpr bool has_trivial_copy_constructor = + std::is_copy_constructible<detail::trivial_helper<T>>::value; + static constexpr bool has_deleted_copy_constructor = + !std::is_copy_constructible<T>::value; + + // move constructors + static constexpr bool has_trivial_move_constructor = + std::is_move_constructible<detail::trivial_helper<T>>::value; + static constexpr bool has_deleted_move_constructor = + !std::is_move_constructible<T>::value; + + // copy assign + static constexpr bool has_trivial_copy_assign = + is_copy_assignable<detail::trivial_helper<T>>::value; + static constexpr bool has_deleted_copy_assign = + !is_copy_assignable<T>::value; + + // move assign + static constexpr bool has_trivial_move_assign = + is_move_assignable<detail::trivial_helper<T>>::value; + static constexpr bool has_deleted_move_assign = + !is_move_assignable<T>::value; + + // destructor + static constexpr bool has_trivial_destructor = + std::is_destructible<detail::trivial_helper<T>>::value; + + public: + + static constexpr bool value = + has_trivial_destructor && + (has_deleted_move_assign || has_trivial_move_assign) && + (has_deleted_move_constructor || has_trivial_move_constructor) && + (has_deleted_copy_assign || has_trivial_copy_assign) && + (has_deleted_copy_constructor || has_trivial_copy_constructor); + +#ifdef HAVE_STD_IS_TRIVIALLY_COPYABLE + static_assert(value == std::is_trivially_copyable<T>::value, + "inconsistent behavior between llvm:: and std:: implementation of is_trivially_copyable"); +#endif +}; +template <typename T> +class is_trivially_copyable<T*> : public std::true_type { +}; + + } // end namespace llvm // If the compiler supports detecting whether a class is final, define diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h index de4d3bf54782..7c83b6298620 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -1,9 +1,8 @@ //===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h index 670572dc8103..e464cd4d4fb5 100644 --- a/include/llvm/TableGen/Main.h +++ b/include/llvm/TableGen/Main.h @@ -1,9 +1,8 @@ //===- llvm/TableGen/Main.h - tblgen entry point ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index e022bc82b4e4..bf7f02208c28 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1,9 +1,8 @@ //===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -316,6 +315,7 @@ protected: IK_TernOpInit, IK_UnOpInit, IK_LastOpInit, + IK_CondOpInit, IK_FoldOpInit, IK_IsAOpInit, IK_StringInit, @@ -623,10 +623,11 @@ public: class CodeInit : public TypedInit { StringRef Value; + SMLoc Loc; - explicit CodeInit(StringRef V) + explicit CodeInit(StringRef V, const SMLoc &Loc) : TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())), - Value(V) {} + Value(V), Loc(Loc) {} public: CodeInit(const StringInit &) = delete; @@ -636,9 +637,10 @@ public: return I->getKind() == IK_CodeInit; } - static CodeInit *get(StringRef); + static CodeInit *get(StringRef, const SMLoc &Loc); StringRef getValue() const { return Value; } + const SMLoc &getLoc() const { return Loc; } Init *convertInitializerTo(RecTy *Ty) const override; @@ -798,8 +800,9 @@ public: /// !op (X, Y) - Combine two inits. class BinOpInit : public OpInit, public FoldingSetNode { public: - enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT, - STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT }; + enum BinaryOp : uint8_t { ADD, MUL, AND, OR, SHL, SRA, SRL, LISTCONCAT, + LISTSPLAT, STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, + GT }; private: Init *LHS, *RHS; @@ -818,6 +821,8 @@ public: static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type); static Init *getStrConcat(Init *lhs, Init *rhs); + static Init *getListConcat(TypedInit *lhs, Init *rhs); + static Init *getListSplat(TypedInit *lhs, Init *rhs); void Profile(FoldingSetNodeID &ID) const; @@ -912,6 +917,83 @@ public: std::string getAsString() const override; }; +/// !cond(condition_1: value1, ... , condition_n: value) +/// Selects the first value for which condition is true. +/// Otherwise reports an error. +class CondOpInit final : public TypedInit, public FoldingSetNode, + public TrailingObjects<CondOpInit, Init *> { + unsigned NumConds; + RecTy *ValType; + + CondOpInit(unsigned NC, RecTy *Type) + : TypedInit(IK_CondOpInit, Type), + NumConds(NC), ValType(Type) {} + + size_t numTrailingObjects(OverloadToken<Init *>) const { + return 2*NumConds; + } + +public: + CondOpInit(const CondOpInit &) = delete; + CondOpInit &operator=(const CondOpInit &) = delete; + + static bool classof(const Init *I) { + return I->getKind() == IK_CondOpInit; + } + + static CondOpInit *get(ArrayRef<Init*> C, ArrayRef<Init*> V, + RecTy *Type); + + void Profile(FoldingSetNodeID &ID) const; + + RecTy *getValType() const { return ValType; } + + unsigned getNumConds() const { return NumConds; } + + Init *getCond(unsigned Num) const { + assert(Num < NumConds && "Condition number out of range!"); + return getTrailingObjects<Init *>()[Num]; + } + + Init *getVal(unsigned Num) const { + assert(Num < NumConds && "Val number out of range!"); + return getTrailingObjects<Init *>()[Num+NumConds]; + } + + ArrayRef<Init *> getConds() const { + return makeArrayRef(getTrailingObjects<Init *>(), NumConds); + } + + ArrayRef<Init *> getVals() const { + return makeArrayRef(getTrailingObjects<Init *>()+NumConds, NumConds); + } + + Init *Fold(Record *CurRec) const; + + Init *resolveReferences(Resolver &R) const override; + + bool isConcrete() const override; + bool isComplete() const override; + std::string getAsString() const override; + + using const_case_iterator = SmallVectorImpl<Init*>::const_iterator; + using const_val_iterator = SmallVectorImpl<Init*>::const_iterator; + + inline const_case_iterator arg_begin() const { return getConds().begin(); } + inline const_case_iterator arg_end () const { return getConds().end(); } + + inline size_t case_size () const { return NumConds; } + inline bool case_empty() const { return NumConds == 0; } + + inline const_val_iterator name_begin() const { return getVals().begin();} + inline const_val_iterator name_end () const { return getVals().end(); } + + inline size_t val_size () const { return NumConds; } + inline bool val_empty() const { return NumConds == 0; } + + Init *getBit(unsigned Bit) const override; +}; + /// !foldl (a, b, expr, start, lst) - Fold over a list. class FoldOpInit : public TypedInit, public FoldingSetNode { private: diff --git a/include/llvm/TableGen/SearchableTable.td b/include/llvm/TableGen/SearchableTable.td index 1089d363eb6f..2680c71218ea 100644 --- a/include/llvm/TableGen/SearchableTable.td +++ b/include/llvm/TableGen/SearchableTable.td @@ -1,9 +1,8 @@ //===- SearchableTable.td ----------------------------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h index 4b32f9e3da8f..35156424b0d3 100644 --- a/include/llvm/TableGen/SetTheory.h +++ b/include/llvm/TableGen/SetTheory.h @@ -1,9 +1,8 @@ //===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h index 3aa3540d616d..795b7a6d41dc 100644 --- a/include/llvm/TableGen/StringMatcher.h +++ b/include/llvm/TableGen/StringMatcher.h @@ -1,9 +1,8 @@ //===- StringMatcher.h - Generate a matcher for input strings ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h index 4b11e889ea6c..76ce51893907 100644 --- a/include/llvm/TableGen/StringToOffsetTable.h +++ b/include/llvm/TableGen/StringToOffsetTable.h @@ -1,9 +1,8 @@ //===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h index d226f1f1af7b..a426e4217578 100644 --- a/include/llvm/TableGen/TableGenBackend.h +++ b/include/llvm/TableGen/TableGenBackend.h @@ -1,9 +1,8 @@ //===- llvm/TableGen/TableGenBackend.h - Backend utilities ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,6 +22,8 @@ class raw_ostream; /// raw_ostream. void emitSourceFileHeader(StringRef Desc, raw_ostream &OS); +extern bool TimeRegions; + } // End llvm namespace #endif diff --git a/include/llvm/Target/CodeGenCWrappers.h b/include/llvm/Target/CodeGenCWrappers.h index 3ad77c5d5e00..a99546357053 100644 --- a/include/llvm/Target/CodeGenCWrappers.h +++ b/include/llvm/Target/CodeGenCWrappers.h @@ -1,9 +1,8 @@ //===- llvm/Target/CodeGenCWrappers.h - CodeGen C Wrappers ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/GenericOpcodes.td b/include/llvm/Target/GenericOpcodes.td index 045fe2520047..45718327b4a7 100644 --- a/include/llvm/Target/GenericOpcodes.td +++ b/include/llvm/Target/GenericOpcodes.td @@ -1,9 +1,8 @@ //===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -93,12 +92,14 @@ def G_BITCAST : GenericInstruction { let hasSideEffects = 0; } +// Only supports scalar result types def G_CONSTANT : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins unknown:$imm); let hasSideEffects = 0; } +// Only supports scalar result types def G_FCONSTANT : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins unknown:$imm); @@ -122,31 +123,31 @@ def G_VAARG : GenericInstruction { def G_CTLZ : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } def G_CTLZ_ZERO_UNDEF : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } def G_CTTZ : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } def G_CTTZ_ZERO_UNDEF : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } def G_CTPOP : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src); + let InOperandList = (ins type1:$src); let hasSideEffects = 0; } @@ -168,6 +169,12 @@ def G_BLOCK_ADDR : GenericInstruction { let hasSideEffects = 0; } +def G_JUMP_TABLE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$jti); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ @@ -255,21 +262,21 @@ def G_XOR : GenericInstruction { // Generic left-shift. def G_SHL : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } // Generic logical right-shift. def G_LSHR : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } // Generic arithmetic right-shift. def G_ASHR : GenericInstruction { let OutOperandList = (outs type0:$dst); - let InOperandList = (ins type0:$src1, type0:$src2); + let InOperandList = (ins type0:$src1, type1:$src2); let hasSideEffects = 0; } @@ -307,6 +314,38 @@ def G_PTR_MASK : GenericInstruction { let hasSideEffects = 0; } +// Generic signed integer minimum. +def G_SMIN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic signed integer maximum. +def G_SMAX : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic unsigned integer minimum. +def G_UMIN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic unsigned integer maximum. +def G_UMAX : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + //------------------------------------------------------------------------------ // Overflow ops //------------------------------------------------------------------------------ @@ -454,6 +493,74 @@ def G_FABS : GenericInstruction { let hasSideEffects = 0; } +def G_FCOPYSIGN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src0, type1:$src1); + let hasSideEffects = 0; +} + +def G_FCANONICALIZE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + +// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two +// values. +// +// In the case where a single input is a NaN (either signaling or quiet), +// the non-NaN input is returned. +// +// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. +def G_FMINNUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXNUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on +// two values, following the IEEE-754 2008 definition. This differs from +// FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a +// signaling NaN, returns a quiet NaN. +def G_FMINNUM_IEEE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXNUM_IEEE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 +// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008 +// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics. +def G_FMINIMUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +def G_FMAXIMUM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + //------------------------------------------------------------------------------ // Floating Point Binary ops. //------------------------------------------------------------------------------ @@ -554,6 +661,51 @@ def G_FCEIL : GenericInstruction { let hasSideEffects = 0; } +// Floating point cosine of a value. +def G_FCOS : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point sine of a value. +def G_FSIN : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point square root of a value. +// This returns NaN for negative nonzero values. +// NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's +// libm-conformant. +def G_FSQRT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point floor of a value. +def G_FFLOOR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point round to next integer. +def G_FRINT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point round to the nearest integer. +def G_FNEARBYINT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Opcodes for LLVM Intrinsics //------------------------------------------------------------------------------ @@ -647,6 +799,12 @@ def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; +def G_FENCE : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$ordering, i32imm:$scope); + let hasSideEffects = 1; +} + //------------------------------------------------------------------------------ // Variadic ops //------------------------------------------------------------------------------ @@ -689,7 +847,9 @@ def G_MERGE_VALUES : GenericInstruction { let hasSideEffects = 0; } -/// Create a vector from multiple scalar registers. +/// Create a vector from multiple scalar registers. No implicit +/// conversion is performed (i.e. the result element type must be the +/// same as all source operands) def G_BUILD_VECTOR : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins type1:$src0, variable_ops); @@ -759,6 +919,15 @@ def G_BRINDIRECT : GenericInstruction { let isTerminator = 1; } +// Generic branch to jump table entry +def G_BRJT : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; +} + //------------------------------------------------------------------------------ // Vector ops //------------------------------------------------------------------------------ diff --git a/include/llvm/Target/GlobalISel/RegisterBank.td b/include/llvm/Target/GlobalISel/RegisterBank.td index 4dfd139e9fb6..51578b66b160 100644 --- a/include/llvm/Target/GlobalISel/RegisterBank.td +++ b/include/llvm/Target/GlobalISel/RegisterBank.td @@ -1,9 +1,8 @@ //===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index 31d26361260d..6cc58d6521da 100644 --- a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -1,9 +1,8 @@ //===- TargetGlobalISel.td - Common code for GlobalISel ----*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -50,6 +49,8 @@ def : GINodeEquiv<G_FCONSTANT, fpimm>; def : GINodeEquiv<G_ADD, add>; def : GINodeEquiv<G_SUB, sub>; def : GINodeEquiv<G_MUL, mul>; +def : GINodeEquiv<G_UMULH, mulhu>; +def : GINodeEquiv<G_SMULH, mulhs>; def : GINodeEquiv<G_SDIV, sdiv>; def : GINodeEquiv<G_UDIV, udiv>; def : GINodeEquiv<G_SREM, srem>; @@ -77,6 +78,7 @@ def : GINodeEquiv<G_FREM, frem>; def : GINodeEquiv<G_FPOW, fpow>; def : GINodeEquiv<G_FEXP2, fexp2>; def : GINodeEquiv<G_FLOG2, flog2>; +def : GINodeEquiv<G_FCANONICALIZE, fcanonicalize>; def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain>; // ISD::INTRINSIC_VOID can also be handled with G_INTRINSIC_W_SIDE_EFFECTS. def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_void>; @@ -89,7 +91,19 @@ def : GINodeEquiv<G_CTLZ_ZERO_UNDEF, ctlz_zero_undef>; def : GINodeEquiv<G_CTTZ_ZERO_UNDEF, cttz_zero_undef>; def : GINodeEquiv<G_CTPOP, ctpop>; def : GINodeEquiv<G_EXTRACT_VECTOR_ELT, vector_extract>; +def : GINodeEquiv<G_CONCAT_VECTORS, concat_vectors>; def : GINodeEquiv<G_FCEIL, fceil>; +def : GINodeEquiv<G_FCOS, fcos>; +def : GINodeEquiv<G_FSIN, fsin>; +def : GINodeEquiv<G_FABS, fabs>; +def : GINodeEquiv<G_FSQRT, fsqrt>; +def : GINodeEquiv<G_FFLOOR, ffloor>; +def : GINodeEquiv<G_FRINT, frint>; +def : GINodeEquiv<G_FNEARBYINT, fnearbyint>; +def : GINodeEquiv<G_SMIN, smin>; +def : GINodeEquiv<G_SMAX, smax>; +def : GINodeEquiv<G_UMIN, umin>; +def : GINodeEquiv<G_UMAX, umax>; // Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some // complications that tablegen must take care of. For example, Predicates such @@ -124,6 +138,7 @@ def : GINodeEquiv<G_ATOMICRMW_MIN, atomic_load_min>; def : GINodeEquiv<G_ATOMICRMW_MAX, atomic_load_max>; def : GINodeEquiv<G_ATOMICRMW_UMIN, atomic_load_umin>; def : GINodeEquiv<G_ATOMICRMW_UMAX, atomic_load_umax>; +def : GINodeEquiv<G_FENCE, atomic_fence>; // Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. // Should be used on defs that subclass GIComplexOperandMatcher<>. diff --git a/include/llvm/Target/GlobalISel/Target.td b/include/llvm/Target/GlobalISel/Target.td index 6740f404a9d3..538ca65e1162 100644 --- a/include/llvm/Target/GlobalISel/Target.td +++ b/include/llvm/Target/GlobalISel/Target.td @@ -1,9 +1,8 @@ //===- Target.td - Define GlobalISel rules -----------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index e4b827babb92..d58662e128e0 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -1,9 +1,8 @@ //===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -122,6 +121,10 @@ class ComposedSubRegIndex<SubRegIndex A, SubRegIndex B> // this register class when printing. class RegAltNameIndex { string Namespace = ""; + + // A set to be used if the name for a register is not defined in this set. + // This allows creating name sets with only a few alternative names. + RegAltNameIndex FallbackRegAltNameIndex = ?; } def NoRegAltName : RegAltNameIndex; @@ -395,11 +398,49 @@ include "llvm/Target/TargetSchedule.td" class Predicate; // Forward def +class InstructionEncoding { + // Size of encoded instruction. + int Size; + + // The "namespace" in which this instruction exists, on targets like ARM + // which multiple ISA namespaces exist. + string DecoderNamespace = ""; + + // List of predicates which will be turned into isel matching code. + list<Predicate> Predicates = []; + + string DecoderMethod = ""; + + // Is the instruction decoder method able to completely determine if the + // given instruction is valid or not. If the TableGen definition of the + // instruction specifies bitpattern A??B where A and B are static bits, the + // hasCompleteDecoder flag says whether the decoder method fully handles the + // ?? space, i.e. if it is a final arbiter for the instruction validity. + // If not then the decoder attempts to continue decoding when the decoder + // method fails. + // + // This allows to handle situations where the encoding is not fully + // orthogonal. Example: + // * InstA with bitpattern 0b0000????, + // * InstB with bitpattern 0b000000?? but the associated decoder method + // DecodeInstB() returns Fail when ?? is 0b00 or 0b11. + // + // The decoder tries to decode a bitpattern that matches both InstA and + // InstB bitpatterns first as InstB (because it is the most specific + // encoding). In the default case (hasCompleteDecoder = 1), when + // DecodeInstB() returns Fail the bitpattern gets rejected. By setting + // hasCompleteDecoder = 0 in InstB, the decoder is informed that + // DecodeInstB() is not able to determine if all possible values of ?? are + // valid or not. If DecodeInstB() returns Fail the decoder will attempt to + // decode the bitpattern as InstA too. + bit hasCompleteDecoder = 1; +} + //===----------------------------------------------------------------------===// // Instruction set description - These classes correspond to the C++ classes in // the Target/TargetInstrInfo.h file. // -class Instruction { +class Instruction : InstructionEncoding { string Namespace = ""; dag OutOperandList; // An dag containing the MI def operand list. @@ -424,10 +465,6 @@ class Instruction { // from the opcode. int Size = 0; - // DecoderNamespace - The "namespace" in which this instruction exists, on - // targets like ARM which multiple ISA namespaces exist. - string DecoderNamespace = ""; - // Code size, for instruction selection. // FIXME: What does this actually mean? int CodeSize = 0; @@ -453,11 +490,16 @@ class Instruction { bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? bit mayLoad = ?; // Is it possible for this inst to read memory? bit mayStore = ?; // Is it possible for this inst to write memory? + bit mayRaiseFPException = 0; // Can this raise a floating-point exception? bit isConvertibleToThreeAddress = 0; // Can this 2-addr instruction promote? bit isCommutable = 0; // Is this 3 operand instruction commutable? bit isTerminator = 0; // Is this part of the terminator for a basic block? bit isReMaterializable = 0; // Is this instruction re-materializable? - bit isPredicable = 0; // Is this instruction predicable? + bit isPredicable = 0; // 1 means this instruction is predicable + // even if it does not have any operand + // tablegen can identify as a predicate + bit isUnpredicable = 0; // 1 means this instruction is not predicable + // even if it _does_ have a predicate operand bit hasDelaySlot = 0; // Does this instruction have an delay slot? bit usesCustomInserter = 0; // Pseudo instr needing special help. bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook. @@ -524,31 +566,6 @@ class Instruction { string DisableEncoding = ""; string PostEncoderMethod = ""; - string DecoderMethod = ""; - - // Is the instruction decoder method able to completely determine if the - // given instruction is valid or not. If the TableGen definition of the - // instruction specifies bitpattern A??B where A and B are static bits, the - // hasCompleteDecoder flag says whether the decoder method fully handles the - // ?? space, i.e. if it is a final arbiter for the instruction validity. - // If not then the decoder attempts to continue decoding when the decoder - // method fails. - // - // This allows to handle situations where the encoding is not fully - // orthogonal. Example: - // * InstA with bitpattern 0b0000????, - // * InstB with bitpattern 0b000000?? but the associated decoder method - // DecodeInstB() returns Fail when ?? is 0b00 or 0b11. - // - // The decoder tries to decode a bitpattern that matches both InstA and - // InstB bitpatterns first as InstB (because it is the most specific - // encoding). In the default case (hasCompleteDecoder = 1), when - // DecodeInstB() returns Fail the bitpattern gets rejected. By setting - // hasCompleteDecoder = 0 in InstB, the decoder is informed that - // DecodeInstB() is not able to determine if all possible values of ?? are - // valid or not. If DecodeInstB() returns Fail the decoder will attempt to - // decode the bitpattern as InstA too. - bit hasCompleteDecoder = 1; /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. bits<64> TSFlags = 0; @@ -585,6 +602,13 @@ class Instruction { bit FastISelShouldIgnore = 0; } +/// Defines an additional encoding that disassembles to the given instruction +/// Like Instruction, the Inst and SoftFail fields are omitted to allow targets +// to specify their size. +class AdditionalEncoding<Instruction I> : InstructionEncoding { + Instruction AliasOf = I; +} + /// PseudoInstExpansion - Expansion information for a pseudo-instruction. /// Which instruction it expands to and how the operands map from the /// pseudo. @@ -909,7 +933,7 @@ class InstrInfo { } // Standard Pseudo Instructions. -// This list must match TargetOpcodes.h and CodeGenTarget.cpp. +// This list must match TargetOpcodes.def. // Only these instructions are allowed in the TargetOpcode namespace. // Ensure mayLoad and mayStore have a default value, so as not to break // targets that set guessInstructionProperties=0. Any local definition of @@ -934,6 +958,15 @@ def INLINEASM : StandardPseudoInstruction { let AsmString = ""; let hasSideEffects = 0; // Note side effect is encoded in an operand. } +def INLINEASM_BR : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let hasSideEffects = 0; // Note side effect is encoded in an operand. + let isTerminator = 1; + let isBranch = 1; + let isIndirectBranch = 1; +} def CFI_INSTRUCTION : StandardPseudoInstruction { let OutOperandList = (outs); let InOperandList = (ins i32imm:$id); @@ -1037,7 +1070,7 @@ def BUNDLE : StandardPseudoInstruction { let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "BUNDLE"; - let hasSideEffects = 1; + let hasSideEffects = 0; } def LIFETIME_START : StandardPseudoInstruction { let OutOperandList = (outs); @@ -1174,7 +1207,7 @@ def FENTRY_CALL : StandardPseudoInstruction { let hasSideEffects = 1; } def ICALL_BRANCH_FUNNEL : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); + let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = ""; let hasSideEffects = 1; diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index 95d2b4226294..1bc03cf8a49d 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -1,9 +1,8 @@ //===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -83,6 +82,15 @@ class CCIfVarArg<CCAction A> : CCIf<"State.isVarArg()", A> {} /// CCIfNotVarArg - If the current function is not vararg - apply the action class CCIfNotVarArg<CCAction A> : CCIf<"!State.isVarArg()", A> {} +/// CCIfPtrAddrSpace - If the top-level parent of the current argument has +/// pointer type in the specified address-space. +class CCIfPtrAddrSpace<int AS, CCAction A> + : CCIf<"(ArgFlags.isPointer() && ArgFlags.getPointerAddrSpace() == " # AS # ")", A> {} + +/// CCIfPtr - If the top-level parent of the current argument had +/// pointer type in some address-space. +class CCIfPtr<CCAction A> : CCIf<"ArgFlags.isPointer()", A> {} + /// CCAssignToReg - This action matches if there is a register in the specified /// list that is still available. If so, it assigns the value to the first /// available register and succeeds. @@ -160,6 +168,11 @@ class CCDelegateTo<CallingConv cc> : CCAction { /// that the target supports. class CallingConv<list<CCAction> actions> { list<CCAction> Actions = actions; + + /// If true, this calling convention will be emitted as externally visible in + /// the llvm namespaces instead of as a static function. + bit Entry = 0; + bit Custom = 0; } diff --git a/include/llvm/Target/TargetInstrPredicate.td b/include/llvm/Target/TargetInstrPredicate.td index 4b2c57b34c2e..5623461c648d 100644 --- a/include/llvm/Target/TargetInstrPredicate.td +++ b/include/llvm/Target/TargetInstrPredicate.td @@ -1,9 +1,8 @@ //===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index 6a92bdee747e..ef571b15153e 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -1,9 +1,8 @@ //===-- llvm/Target/TargetIntrinsicInfo.h - Instruction Info ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/TargetItinerary.td b/include/llvm/Target/TargetItinerary.td index 182054d8444e..b68ed045520c 100644 --- a/include/llvm/Target/TargetItinerary.td +++ b/include/llvm/Target/TargetItinerary.td @@ -1,9 +1,8 @@ //===- TargetItinerary.td - Target Itinierary Description --*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index e80f2bf82f26..3a2497bff11e 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -1,9 +1,8 @@ //===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -52,6 +51,7 @@ protected: unsigned PersonalityEncoding = 0; unsigned LSDAEncoding = 0; unsigned TTypeEncoding = 0; + unsigned CallSiteEncoding = 0; /// This section contains the static constructor pointer list. MCSection *StaticCtorSection = nullptr; @@ -80,6 +80,9 @@ public: /// Emit the module-level metadata that the platform cares about. virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {} + /// Get the module-level metadata that the platform cares about. + virtual void getModuleMetadata(Module &M) {} + /// Given a constant with the SectionKind, return a section that it should be /// placed in. virtual MCSection *getSectionForConstant(const DataLayout &DL, @@ -145,6 +148,7 @@ public: unsigned getPersonalityEncoding() const { return PersonalityEncoding; } unsigned getLSDAEncoding() const { return LSDAEncoding; } unsigned getTTypeEncoding() const { return TTypeEncoding; } + unsigned getCallSiteEncoding() const { return CallSiteEncoding; } const MCExpr *getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, MCStreamer &Streamer) const; diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 3eafcc25583a..cdf9f8bfd5ea 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -1,9 +1,8 @@ //===-- llvm/Target/TargetMachine.h - Target Information --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -36,6 +35,9 @@ class MCSubtargetInfo; class MCSymbol; class raw_pwrite_stream; class PassManagerBuilder; +struct PerFunctionMIParsingState; +class SMDiagnostic; +class SMRange; class Target; class TargetIntrinsicInfo; class TargetIRAnalysis; @@ -50,6 +52,10 @@ class PassManagerBase; } using legacy::PassManagerBase; +namespace yaml { +struct MachineFunctionInfo; +} + //===----------------------------------------------------------------------===// /// /// Primary interface to the complete machine description for the target @@ -115,6 +121,27 @@ public: return nullptr; } + /// Allocate and return a default initialized instance of the YAML + /// representation for the MachineFunctionInfo. + virtual yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const { + return nullptr; + } + + /// Allocate and initialize an instance of the YAML representation of the + /// MachineFunctionInfo. + virtual yaml::MachineFunctionInfo * + convertFuncInfoToYAML(const MachineFunction &MF) const { + return nullptr; + } + + /// Parse out the target's MachineFunctionInfo from the YAML reprsentation. + virtual bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, + PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, + SMRange &SourceRange) const { + return false; + } + /// This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being /// returned is of the correct type. @@ -363,9 +390,9 @@ inline CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM, if (CM) { // By default, targets do not support the tiny and kernel models. if (*CM == CodeModel::Tiny) - report_fatal_error("Target does not support the tiny CodeModel"); + report_fatal_error("Target does not support the tiny CodeModel", false); if (*CM == CodeModel::Kernel) - report_fatal_error("Target does not support the kernel CodeModel"); + report_fatal_error("Target does not support the kernel CodeModel", false); return *CM; } return Default; diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index b18101d92833..8cc2a6010879 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -1,9 +1,8 @@ //===-- llvm/Target/TargetOptions.h - Target Options ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -119,7 +118,8 @@ namespace llvm { NoTrapAfterNoreturn(false), EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), - SupportsDefaultOutlining(false), EmitAddrsig(false) {} + SupportsDefaultOutlining(false), EmitAddrsig(false), + EnableDebugEntryValues(false) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -253,6 +253,9 @@ namespace llvm { /// Emit address-significance table. unsigned EmitAddrsig : 1; + /// Emit debug info about parameter's entry values. + unsigned EnableDebugEntryValues : 1; + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for diff --git a/include/llvm/Target/TargetPfmCounters.td b/include/llvm/Target/TargetPfmCounters.td index dac150f03445..e1d5013c1291 100644 --- a/include/llvm/Target/TargetPfmCounters.td +++ b/include/llvm/Target/TargetPfmCounters.td @@ -1,9 +1,8 @@ //===- TargetPfmCounters.td - Target Pfm Counters -*- tablegen ----------*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 808e183f5a5f..a36d259df831 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -1,9 +1,8 @@ //===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -136,7 +135,7 @@ class ProcResourceKind; // // An optional Super resource may be given to model these resources as // a subset of the more general super resources. Using one of these -// resources implies using one of the super resoruces. +// resources implies using one of the super resources. // // ProcResourceUnits normally model a few buffered resources within an // out-of-order engine. Buffered resources may be held for multiple diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index eb5a14bd21b8..b913a054ac2c 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -1,9 +1,8 @@ //===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -125,7 +124,7 @@ def SDTIntSatNoShOp : SDTypeProfile<1, 2, [ // ssat with no shift def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0> ]>; -def SDTIntScaledBinOp : SDTypeProfile<1, 3, [ // smulfix +def SDTIntScaledBinOp : SDTypeProfile<1, 3, [ // smulfix, umulfix SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0>, SDTCisInt<3> ]>; @@ -265,6 +264,11 @@ def SDTAtomic3 : SDTypeProfile<1, 3, [ def SDTAtomic2 : SDTypeProfile<1, 2, [ SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> ]>; + +def SDTFPAtomic2 : SDTypeProfile<1, 2, [ + SDTCisSameAs<0,2>, SDTCisFP<0>, SDTCisPtrTy<1> +]>; + def SDTAtomicStore : SDTypeProfile<0, 2, [ SDTCisPtrTy<0>, SDTCisInt<1> ]>; @@ -385,7 +389,10 @@ def saddsat : SDNode<"ISD::SADDSAT" , SDTIntBinOp, [SDNPCommutative]>; def uaddsat : SDNode<"ISD::UADDSAT" , SDTIntBinOp, [SDNPCommutative]>; def ssubsat : SDNode<"ISD::SSUBSAT" , SDTIntBinOp>; def usubsat : SDNode<"ISD::USUBSAT" , SDTIntBinOp>; + def smulfix : SDNode<"ISD::SMULFIX" , SDTIntScaledBinOp, [SDNPCommutative]>; +def smulfixsat : SDNode<"ISD::SMULFIXSAT", SDTIntScaledBinOp, [SDNPCommutative]>; +def umulfix : SDNode<"ISD::UMULFIX" , SDTIntScaledBinOp, [SDNPCommutative]>; def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>; @@ -444,6 +451,11 @@ def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; +def lround : SDNode<"ISD::LROUND" , SDTFPToIntOp>; +def llround : SDNode<"ISD::LLROUND" , SDTFPToIntOp>; +def lrint : SDNode<"ISD::LRINT" , SDTFPToIntOp>; +def llrint : SDNode<"ISD::LLRINT" , SDTFPToIntOp>; + def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; @@ -455,6 +467,53 @@ def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; +def strict_fadd : SDNode<"ISD::STRICT_FADD", + SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; +def strict_fsub : SDNode<"ISD::STRICT_FSUB", + SDTFPBinOp, [SDNPHasChain]>; +def strict_fmul : SDNode<"ISD::STRICT_FMUL", + SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; +def strict_fdiv : SDNode<"ISD::STRICT_FDIV", + SDTFPBinOp, [SDNPHasChain]>; +def strict_frem : SDNode<"ISD::STRICT_FREM", + SDTFPBinOp, [SDNPHasChain]>; +def strict_fma : SDNode<"ISD::STRICT_FMA", + SDTFPTernaryOp, [SDNPHasChain]>; +def strict_fsqrt : SDNode<"ISD::STRICT_FSQRT", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fsin : SDNode<"ISD::STRICT_FSIN", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fcos : SDNode<"ISD::STRICT_FCOS", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fexp2 : SDNode<"ISD::STRICT_FEXP2", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fpow : SDNode<"ISD::STRICT_FPOW", + SDTFPBinOp, [SDNPHasChain]>; +def strict_flog2 : SDNode<"ISD::STRICT_FLOG2", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_frint : SDNode<"ISD::STRICT_FRINT", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fnearbyint : SDNode<"ISD::STRICT_FNEARBYINT", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fceil : SDNode<"ISD::STRICT_FCEIL", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_ffloor : SDNode<"ISD::STRICT_FFLOOR", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fround : SDNode<"ISD::STRICT_FROUND", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_ftrunc : SDNode<"ISD::STRICT_FTRUNC", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fminnum : SDNode<"ISD::STRICT_FMINNUM", + SDTFPBinOp, [SDNPHasChain, + SDNPCommutative, SDNPAssociative]>; +def strict_fmaxnum : SDNode<"ISD::STRICT_FMAXNUM", + SDTFPBinOp, [SDNPHasChain, + SDNPCommutative, SDNPAssociative]>; +def strict_fpround : SDNode<"ISD::STRICT_FP_ROUND", + SDTFPRoundOp, [SDNPHasChain]>; +def strict_fpextend : SDNode<"ISD::STRICT_FP_EXTEND", + SDTFPExtendOp, [SDNPHasChain]>; + def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; def select : SDNode<"ISD::SELECT" , SDTSelect>; def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; @@ -511,14 +570,19 @@ def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_fadd : SDNode<"ISD::ATOMIC_LOAD_FADD" , SDTFPAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_fsub : SDNode<"ISD::ATOMIC_LOAD_FSUB" , SDTFPAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; + def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, +def masked_st : SDNode<"ISD::MSTORE", SDTMaskedStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; -def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, +def masked_ld : SDNode<"ISD::MLOAD", SDTMaskedLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; // Do not use ld, st directly. Use load, extload, sextload, zextload, store, @@ -673,6 +737,10 @@ class PatFrags<dag ops, list<dag> frags, code pred = [{}], // cast<StoreSDNode>(N)->isTruncatingStore(); bit IsTruncStore = ?; + // cast<MemSDNode>(N)->getAddressSpace() == + // If this empty, accept any address space. + list<int> AddressSpaces = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic bit IsAtomicOrderingMonotonic = ?; // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire @@ -698,6 +766,8 @@ class PatFrags<dag ops, list<dag> frags, code pred = [{}], // cast<LoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; // cast<StoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; ValueType ScalarMemoryVT = ?; + + // TODO: Add alignment } // PatFrag - A version of PatFrags matching only a single fragment. @@ -771,14 +841,11 @@ class FPImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm> def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; -def immAllOnesV: PatLeaf<(build_vector), [{ - return ISD::isBuildVectorAllOnes(N); -}]>; -def immAllZerosV: PatLeaf<(build_vector), [{ - return ISD::isBuildVectorAllZeros(N); -}]>; - - +// Use ISD::isBuildVectorAllOnes or ISD::isBuildVectorAllZeros to look for +// the corresponding build_vector. Will look through bitcasts except when used +// as a pattern root. +def immAllOnesV; // ISD::isBuildVectorAllOnes +def immAllZerosV; // ISD::isBuildVectorAllZeros // Other helper fragments. def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; @@ -1163,6 +1230,87 @@ def setle : PatFrag<(ops node:$lhs, node:$rhs), def setne : PatFrag<(ops node:$lhs, node:$rhs), (setcc node:$lhs, node:$rhs, SETNE)>; +// We don't have strict FP extended loads as single DAG nodes, but we can +// still provide convenience fragments to match those operations. +def strict_extloadf32 : PatFrag<(ops node:$ptr), + (strict_fpextend (f32 (load node:$ptr)))>; +def strict_extloadf64 : PatFrag<(ops node:$ptr), + (strict_fpextend (f64 (load node:$ptr)))>; + +// Convenience fragments to match both strict and non-strict fp operations +def any_fadd : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fadd node:$lhs, node:$rhs), + (fadd node:$lhs, node:$rhs)]>; +def any_fsub : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fsub node:$lhs, node:$rhs), + (fsub node:$lhs, node:$rhs)]>; +def any_fmul : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fmul node:$lhs, node:$rhs), + (fmul node:$lhs, node:$rhs)]>; +def any_fdiv : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fdiv node:$lhs, node:$rhs), + (fdiv node:$lhs, node:$rhs)]>; +def any_frem : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_frem node:$lhs, node:$rhs), + (frem node:$lhs, node:$rhs)]>; +def any_fma : PatFrags<(ops node:$src1, node:$src2, node:$src3), + [(strict_fma node:$src1, node:$src2, node:$src3), + (fma node:$src1, node:$src2, node:$src3)]>; +def any_fsqrt : PatFrags<(ops node:$src), + [(strict_fsqrt node:$src), + (fsqrt node:$src)]>; +def any_fsin : PatFrags<(ops node:$src), + [(strict_fsin node:$src), + (fsin node:$src)]>; +def any_fcos : PatFrags<(ops node:$src), + [(strict_fcos node:$src), + (fcos node:$src)]>; +def any_fexp2 : PatFrags<(ops node:$src), + [(strict_fexp2 node:$src), + (fexp2 node:$src)]>; +def any_fpow : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fpow node:$lhs, node:$rhs), + (fpow node:$lhs, node:$rhs)]>; +def any_flog2 : PatFrags<(ops node:$src), + [(strict_flog2 node:$src), + (flog2 node:$src)]>; +def any_frint : PatFrags<(ops node:$src), + [(strict_frint node:$src), + (frint node:$src)]>; +def any_fnearbyint : PatFrags<(ops node:$src), + [(strict_fnearbyint node:$src), + (fnearbyint node:$src)]>; +def any_fceil : PatFrags<(ops node:$src), + [(strict_fceil node:$src), + (fceil node:$src)]>; +def any_ffloor : PatFrags<(ops node:$src), + [(strict_ffloor node:$src), + (ffloor node:$src)]>; +def any_fround : PatFrags<(ops node:$src), + [(strict_fround node:$src), + (fround node:$src)]>; +def any_ftrunc : PatFrags<(ops node:$src), + [(strict_ftrunc node:$src), + (ftrunc node:$src)]>; +def any_fmaxnum : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fmaxnum node:$lhs, node:$rhs), + (fmaxnum node:$lhs, node:$rhs)]>; +def any_fminnum : PatFrags<(ops node:$lhs, node:$rhs), + [(strict_fminnum node:$lhs, node:$rhs), + (fminnum node:$lhs, node:$rhs)]>; +def any_fpround : PatFrags<(ops node:$src), + [(strict_fpround node:$src), + (fpround node:$src)]>; +def any_fpextend : PatFrags<(ops node:$src), + [(strict_fpextend node:$src), + (fpextend node:$src)]>; +def any_extloadf32 : PatFrags<(ops node:$ptr), + [(strict_extloadf32 node:$ptr), + (extloadf32 node:$ptr)]>; +def any_extloadf64 : PatFrags<(ops node:$ptr), + [(strict_extloadf64 node:$ptr), + (extloadf64 node:$ptr)]>; + multiclass binary_atomic_op_ord<SDNode atomic_op> { def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { diff --git a/include/llvm/Testing/Support/Annotations.h b/include/llvm/Testing/Support/Annotations.h new file mode 100644 index 000000000000..aad1a44f4ec9 --- /dev/null +++ b/include/llvm/Testing/Support/Annotations.h @@ -0,0 +1,90 @@ +//===--- Annotations.h - Annotated source code for tests ---------*- 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_TESTING_SUPPORT_ANNOTATIONS_H +#define LLVM_TESTING_SUPPORT_ANNOTATIONS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <tuple> +#include <vector> + +namespace llvm { + +/// Annotations lets you mark points and ranges inside source code, for tests: +/// +/// Annotations Example(R"cpp( +/// int complete() { x.pri^ } // ^ indicates a point +/// void err() { [["hello" == 42]]; } // [[this is a range]] +/// $definition^class Foo{}; // points can be named: "definition" +/// $fail[[static_assert(false, "")]] // ranges can be named too: "fail" +/// )cpp"); +/// +/// StringRef Code = Example.code(); // annotations stripped. +/// std::vector<size_t> PP = Example.points(); // all unnamed points +/// size_t P = Example.point(); // there must be exactly one +/// llvm::Range R = Example.range("fail"); // find named ranges +/// +/// Points/ranges are coordinated into `code()` which is stripped of +/// annotations. +/// +/// Ranges may be nested (and points can be inside ranges), but there's no way +/// to define general overlapping ranges. +/// +/// FIXME: the choice of the marking syntax makes it impossible to represent +/// some of the C++ and Objective C constructs (including common ones +/// like C++ attributes). We can fix this by: +/// 1. introducing an escaping mechanism for the special characters, +/// 2. making characters for marking points and ranges configurable, +/// 3. changing the syntax to something less commonly used, +/// 4. ... +class Annotations { +public: + /// Two offsets pointing to a continuous substring. End is not included, i.e. + /// represents a half-open range. + struct Range { + size_t Begin = 0; + size_t End = 0; + + friend bool operator==(const Range &L, const Range &R) { + return std::tie(L.Begin, L.End) == std::tie(R.Begin, R.End); + } + friend bool operator!=(const Range &L, const Range &R) { return !(L == R); } + }; + + /// Parses the annotations from Text. Crashes if it's malformed. + Annotations(llvm::StringRef Text); + + /// The input text with all annotations stripped. + /// All points and ranges are relative to this stripped text. + llvm::StringRef code() const { return Code; } + + /// Returns the position of the point marked by ^ (or $name^) in the text. + /// Crashes if there isn't exactly one. + size_t point(llvm::StringRef Name = "") const; + /// Returns the position of all points marked by ^ (or $name^) in the text. + std::vector<size_t> points(llvm::StringRef Name = "") const; + + /// Returns the location of the range marked by [[ ]] (or $name[[ ]]). + /// Crashes if there isn't exactly one. + Range range(llvm::StringRef Name = "") const; + /// Returns the location of all ranges marked by [[ ]] (or $name[[ ]]). + std::vector<Range> ranges(llvm::StringRef Name = "") const; + +private: + std::string Code; + llvm::StringMap<llvm::SmallVector<size_t, 1>> Points; + llvm::StringMap<llvm::SmallVector<Range, 1>> Ranges; +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream &O, + const llvm::Annotations::Range &R); + +} // namespace llvm + +#endif diff --git a/include/llvm/Testing/Support/Error.h b/include/llvm/Testing/Support/Error.h index 0e5b5403ce87..85328f26440b 100644 --- a/include/llvm/Testing/Support/Error.h +++ b/include/llvm/Testing/Support/Error.h @@ -1,9 +1,8 @@ //===- llvm/Testing/Support/Error.h ---------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Testing/Support/SupportHelpers.h b/include/llvm/Testing/Support/SupportHelpers.h index b2975ec395d5..38726b1cfaf7 100644 --- a/include/llvm/Testing/Support/SupportHelpers.h +++ b/include/llvm/Testing/Support/SupportHelpers.h @@ -1,18 +1,19 @@ //===- Testing/Support/SupportHelpers.h -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_TESTING_SUPPORT_SUPPORTHELPERS_H #define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_os_ostream.h" +#include "gmock/gmock-matchers.h" #include "gtest/gtest-printers.h" #include <string> @@ -54,11 +55,56 @@ void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) { PrintTo(static_cast<const ErrorHolder &>(Item), Out); } } + +template <class InnerMatcher> class ValueIsMatcher { +public: + explicit ValueIsMatcher(InnerMatcher ValueMatcher) + : ValueMatcher(ValueMatcher) {} + + template <class T> + operator ::testing::Matcher<const llvm::Optional<T> &>() const { + return ::testing::MakeMatcher( + new Impl<T>(::testing::SafeMatcherCast<T>(ValueMatcher))); + } + + template <class T> + class Impl : public ::testing::MatcherInterface<const llvm::Optional<T> &> { + public: + explicit Impl(const ::testing::Matcher<T> &ValueMatcher) + : ValueMatcher(ValueMatcher) {} + + bool MatchAndExplain(const llvm::Optional<T> &Input, + testing::MatchResultListener *L) const override { + return Input && ValueMatcher.MatchAndExplain(Input.getValue(), L); + } + + void DescribeTo(std::ostream *OS) const override { + *OS << "has a value that "; + ValueMatcher.DescribeTo(OS); + } + void DescribeNegationTo(std::ostream *OS) const override { + *OS << "does not have a value that "; + ValueMatcher.DescribeTo(OS); + } + + private: + testing::Matcher<T> ValueMatcher; + }; + +private: + InnerMatcher ValueMatcher; +}; } // namespace detail +/// Matches an llvm::Optional<T> with a value that conforms to an inner matcher. +/// To match llvm::None you could use Eq(llvm::None). +template <class InnerMatcher> +detail::ValueIsMatcher<InnerMatcher> ValueIs(const InnerMatcher &ValueMatcher) { + return detail::ValueIsMatcher<InnerMatcher>(ValueMatcher); +} namespace unittest { SmallString<128> getInputFileDirectory(const char *Argv0); -} +} // namespace unittest } // namespace llvm #endif diff --git a/include/llvm/TextAPI/ELF/ELFStub.h b/include/llvm/TextAPI/ELF/ELFStub.h index fa54e6f8b711..76b2af121662 100644 --- a/include/llvm/TextAPI/ELF/ELFStub.h +++ b/include/llvm/TextAPI/ELF/ELFStub.h @@ -1,9 +1,8 @@ //===- ELFStub.h ------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===-----------------------------------------------------------------------===/ /// diff --git a/include/llvm/TextAPI/ELF/TBEHandler.h b/include/llvm/TextAPI/ELF/TBEHandler.h index 91521c656fa2..1748fd13f3dc 100644 --- a/include/llvm/TextAPI/ELF/TBEHandler.h +++ b/include/llvm/TextAPI/ELF/TBEHandler.h @@ -1,9 +1,8 @@ //===- TBEHandler.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===-----------------------------------------------------------------------===/ /// diff --git a/include/llvm/TextAPI/MachO/Architecture.def b/include/llvm/TextAPI/MachO/Architecture.def new file mode 100644 index 000000000000..4c695fe18eec --- /dev/null +++ b/include/llvm/TextAPI/MachO/Architecture.def @@ -0,0 +1,38 @@ +//===- llvm/TextAPI/MachO/Architecture.def - Architecture -----------------===// +// +// 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 ARCHINFO +#define ARCHINFO(arch) +#endif + +/// +/// X86 architectures sorted by cpu type and sub type id. +/// +ARCHINFO(i386, MachO::CPU_TYPE_I386, MachO::CPU_SUBTYPE_I386_ALL) +ARCHINFO(x86_64, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_ALL) +ARCHINFO(x86_64h, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_H) + + +/// +/// ARM architectures sorted by cpu sub type id. +/// +ARCHINFO(armv4t, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V4T) +ARCHINFO(armv6, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6) +ARCHINFO(armv5, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V5TEJ) +ARCHINFO(armv7, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7) +ARCHINFO(armv7s, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7S) +ARCHINFO(armv7k, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7K) +ARCHINFO(armv6m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6M) +ARCHINFO(armv7m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7M) +ARCHINFO(armv7em, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7EM) + + +/// +/// ARM64 architectures sorted by cpu sub type id. +/// +ARCHINFO(arm64, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64_ALL) diff --git a/include/llvm/TextAPI/MachO/Architecture.h b/include/llvm/TextAPI/MachO/Architecture.h new file mode 100644 index 000000000000..055baeb0c0f0 --- /dev/null +++ b/include/llvm/TextAPI/MachO/Architecture.h @@ -0,0 +1,47 @@ +//===- llvm/TextAPI/MachO/Architecture.h - Architecture ---------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the architecture enum and helper methods. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_MACHO_ARCHITECTURE_H +#define LLVM_TEXTAPI_MACHO_ARCHITECTURE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace MachO { + +/// Defines the architecture slices that are supported by Text-based Stub files. +enum Architecture : uint8_t { +#define ARCHINFO(Arch, Type, SubType) AK_##Arch, +#include "llvm/TextAPI/MachO/Architecture.def" +#undef ARCHINFO + AK_unknown, // this has to go last. +}; + +/// Convert a CPU Type and Subtype pair to an architecture slice. +Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType); + +/// Convert a name to an architecture slice. +Architecture getArchitectureFromName(StringRef Name); + +/// Convert an architecture slice to a string. +StringRef getArchitectureName(Architecture Arch); + +/// Convert an architecture slice to a CPU Type and Subtype pair. +std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch); + +raw_ostream &operator<<(raw_ostream &OS, Architecture Arch); + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_ARCHITECTURE_H diff --git a/include/llvm/TextAPI/MachO/ArchitectureSet.h b/include/llvm/TextAPI/MachO/ArchitectureSet.h new file mode 100644 index 000000000000..d8dfc7f1af21 --- /dev/null +++ b/include/llvm/TextAPI/MachO/ArchitectureSet.h @@ -0,0 +1,159 @@ +//===- llvm/TextAPI/MachO/ArchitectureSet.h - ArchitectureSet ---*- 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the architecture set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H +#define LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H + +#include "llvm/Support/raw_ostream.h" +#include "llvm/TextAPI/MachO/Architecture.h" +#include <cstddef> +#include <iterator> +#include <limits> +#include <vector> + +namespace llvm { +namespace MachO { + +class ArchitectureSet { +private: + using ArchSetType = uint32_t; + + const static ArchSetType EndIndexVal = + std::numeric_limits<ArchSetType>::max(); + ArchSetType ArchSet{0}; + +public: + constexpr ArchitectureSet() = default; + constexpr ArchitectureSet(ArchSetType Raw) : ArchSet(Raw) {} + ArchitectureSet(Architecture Arch) : ArchitectureSet() { set(Arch); } + ArchitectureSet(const std::vector<Architecture> &Archs); + + void set(Architecture Arch) { + if (Arch == AK_unknown) + return; + ArchSet |= 1U << static_cast<int>(Arch); + } + + void clear(Architecture Arch) { ArchSet &= ~(1U << static_cast<int>(Arch)); } + + bool has(Architecture Arch) const { + return ArchSet & (1U << static_cast<int>(Arch)); + } + + bool contains(ArchitectureSet Archs) const { + return (ArchSet & Archs.ArchSet) == Archs.ArchSet; + } + + size_t count() const; + + bool empty() const { return ArchSet == 0; } + + ArchSetType rawValue() const { return ArchSet; } + + template <typename Ty> + class arch_iterator + : public std::iterator<std::forward_iterator_tag, Architecture, size_t> { + private: + ArchSetType Index; + Ty *ArchSet; + + void findNextSetBit() { + if (Index == EndIndexVal) + return; + while (++Index < sizeof(Ty) * 8) { + if (*ArchSet & (1UL << Index)) + return; + } + + Index = EndIndexVal; + } + + public: + arch_iterator(Ty *ArchSet, ArchSetType Index = 0) + : Index(Index), ArchSet(ArchSet) { + if (Index != EndIndexVal && !(*ArchSet & (1UL << Index))) + findNextSetBit(); + } + + Architecture operator*() const { return static_cast<Architecture>(Index); } + + arch_iterator &operator++() { + findNextSetBit(); + return *this; + } + + arch_iterator operator++(int) { + auto tmp = *this; + findNextSetBit(); + return tmp; + } + + bool operator==(const arch_iterator &o) const { + return std::tie(Index, ArchSet) == std::tie(o.Index, o.ArchSet); + } + + bool operator!=(const arch_iterator &o) const { return !(*this == o); } + }; + + ArchitectureSet operator&(const ArchitectureSet &o) { + return {ArchSet & o.ArchSet}; + } + + ArchitectureSet operator|(const ArchitectureSet &o) { + return {ArchSet | o.ArchSet}; + } + + ArchitectureSet &operator|=(const ArchitectureSet &o) { + ArchSet |= o.ArchSet; + return *this; + } + + ArchitectureSet &operator|=(const Architecture &Arch) { + set(Arch); + return *this; + } + + bool operator==(const ArchitectureSet &o) const { + return ArchSet == o.ArchSet; + } + + bool operator!=(const ArchitectureSet &o) const { + return ArchSet != o.ArchSet; + } + + bool operator<(const ArchitectureSet &o) const { return ArchSet < o.ArchSet; } + + using iterator = arch_iterator<ArchSetType>; + using const_iterator = arch_iterator<const ArchSetType>; + + iterator begin() { return {&ArchSet}; } + iterator end() { return {&ArchSet, EndIndexVal}; } + + const_iterator begin() const { return {&ArchSet}; } + const_iterator end() const { return {&ArchSet, EndIndexVal}; } + + operator std::string() const; + operator std::vector<Architecture>() const; + void print(raw_ostream &OS) const; +}; + +inline ArchitectureSet operator|(const Architecture &lhs, + const Architecture &rhs) { + return ArchitectureSet(lhs) | ArchitectureSet(rhs); +} + +raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set); + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H diff --git a/include/llvm/TextAPI/MachO/InterfaceFile.h b/include/llvm/TextAPI/MachO/InterfaceFile.h new file mode 100644 index 000000000000..e722449d52f1 --- /dev/null +++ b/include/llvm/TextAPI/MachO/InterfaceFile.h @@ -0,0 +1,436 @@ +//===- llvm/TextAPI/MachO/IntefaceFile.h - TAPI Interface File --*- 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 +// +//===----------------------------------------------------------------------===// +// +// A generic and abstract interface representation for linkable objects. This +// could be an MachO executable, bundle, dylib, or text-based stub file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H +#define LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/BinaryFormat/MachO.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Error.h" +#include "llvm/TextAPI/MachO/Architecture.h" +#include "llvm/TextAPI/MachO/ArchitectureSet.h" +#include "llvm/TextAPI/MachO/PackedVersion.h" +#include "llvm/TextAPI/MachO/Symbol.h" + +namespace llvm { +namespace MachO { + +/// Defines the list of MachO platforms. +enum class PlatformKind : unsigned { + unknown, + macOS = MachO::PLATFORM_MACOS, + iOS = MachO::PLATFORM_IOS, + tvOS = MachO::PLATFORM_TVOS, + watchOS = MachO::PLATFORM_WATCHOS, + bridgeOS = MachO::PLATFORM_BRIDGEOS, +}; + +/// Defines a list of Objective-C constraints. +enum class ObjCConstraintType : unsigned { + /// No constraint. + None = 0, + + /// Retain/Release. + Retain_Release = 1, + + /// Retain/Release for Simulator. + Retain_Release_For_Simulator = 2, + + /// Retain/Release or Garbage Collection. + Retain_Release_Or_GC = 3, + + /// Garbage Collection. + GC = 4, +}; + +// clang-format off + +/// Defines the file type this file represents. +enum FileType : unsigned { + /// Invalid file type. + Invalid = 0U, + + /// Text-based stub file (.tbd) version 1.0 + TBD_V1 = 1U << 0, + + /// Text-based stub file (.tbd) version 2.0 + TBD_V2 = 1U << 1, + + /// Text-based stub file (.tbd) version 3.0 + TBD_V3 = 1U << 2, + + All = ~0U, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All), +}; + +// clang-format on + +/// Reference to an interface file. +class InterfaceFileRef { +public: + InterfaceFileRef() = default; + + InterfaceFileRef(StringRef InstallName) : InstallName(InstallName) {} + + InterfaceFileRef(StringRef InstallName, ArchitectureSet Archs) + : InstallName(InstallName), Architectures(Archs) {} + + StringRef getInstallName() const { return InstallName; }; + void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; } + ArchitectureSet getArchitectures() const { return Architectures; } + bool hasArchitecture(Architecture Arch) const { + return Architectures.has(Arch); + } + + bool operator==(const InterfaceFileRef &O) const { + return std::tie(InstallName, Architectures) == + std::tie(O.InstallName, O.Architectures); + } + + bool operator<(const InterfaceFileRef &O) const { + return std::tie(InstallName, Architectures) < + std::tie(O.InstallName, O.Architectures); + } + +private: + std::string InstallName; + ArchitectureSet Architectures; +}; + +} // end namespace MachO. + +struct SymbolsMapKey { + MachO::SymbolKind Kind; + StringRef Name; + + SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name) + : Kind(Kind), Name(Name) {} +}; +template <> struct DenseMapInfo<SymbolsMapKey> { + static inline SymbolsMapKey getEmptyKey() { + return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{}); + } + + static inline SymbolsMapKey getTombstoneKey() { + return SymbolsMapKey(MachO::SymbolKind::ObjectiveCInstanceVariable, + StringRef{}); + } + + static unsigned getHashValue(const SymbolsMapKey &Key) { + return hash_combine(hash_value(Key.Kind), hash_value(Key.Name)); + } + + static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) { + return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name); + } +}; + +namespace MachO { + +/// Defines the interface file. +class InterfaceFile { +public: + /// Set the path from which this file was generated (if applicable). + /// + /// \param Path_ The path to the source file. + void setPath(StringRef Path_) { Path = Path_; } + + /// Get the path from which this file was generated (if applicable). + /// + /// \return The path to the source file or empty. + StringRef getPath() const { return Path; } + + /// Set the file type. + /// + /// This is used by the YAML writer to identify the specification it should + /// use for writing the file. + /// + /// \param Kind The file type. + void setFileType(FileType Kind) { FileKind = Kind; } + + /// Get the file type. + /// + /// \return The file type. + FileType getFileType() const { return FileKind; } + + /// Set the platform. + void setPlatform(PlatformKind Platform_) { Platform = Platform_; } + + /// Get the platform. + PlatformKind getPlatform() const { return Platform; } + + /// Specify the set of supported architectures by this file. + void setArchitectures(ArchitectureSet Architectures_) { + Architectures = Architectures_; + } + + /// Add the set of supported architectures by this file. + void addArchitectures(ArchitectureSet Architectures_) { + Architectures |= Architectures_; + } + + /// Add supported architecture by this file.. + void addArch(Architecture Arch) { Architectures.set(Arch); } + + /// Get the set of supported architectures. + ArchitectureSet getArchitectures() const { return Architectures; } + + /// Set the install name of the library. + void setInstallName(StringRef InstallName_) { InstallName = InstallName_; } + + /// Get the install name of the library. + StringRef getInstallName() const { return InstallName; } + + /// Set the current version of the library. + void setCurrentVersion(PackedVersion Version) { CurrentVersion = Version; } + + /// Get the current version of the library. + PackedVersion getCurrentVersion() const { return CurrentVersion; } + + /// Set the compatibility version of the library. + void setCompatibilityVersion(PackedVersion Version) { + CompatibilityVersion = Version; + } + + /// Get the compatibility version of the library. + PackedVersion getCompatibilityVersion() const { return CompatibilityVersion; } + + /// Set the Swift ABI version of the library. + void setSwiftABIVersion(uint8_t Version) { SwiftABIVersion = Version; } + + /// Get the Swift ABI version of the library. + uint8_t getSwiftABIVersion() const { return SwiftABIVersion; } + + /// Specify if the library uses two-level namespace (or flat namespace). + void setTwoLevelNamespace(bool V = true) { IsTwoLevelNamespace = V; } + + /// Check if the library uses two-level namespace. + bool isTwoLevelNamespace() const { return IsTwoLevelNamespace; } + + /// Specify if the library is application extension safe (or not). + void setApplicationExtensionSafe(bool V = true) { IsAppExtensionSafe = V; } + + /// Check if the library is application extension safe. + bool isApplicationExtensionSafe() const { return IsAppExtensionSafe; } + + /// Set the Objective-C constraint. + void setObjCConstraint(ObjCConstraintType Constraint) { + ObjcConstraint = Constraint; + } + + /// Get the Objective-C constraint. + ObjCConstraintType getObjCConstraint() const { return ObjcConstraint; } + + /// Specify if this file was generated during InstallAPI (or not). + void setInstallAPI(bool V = true) { IsInstallAPI = V; } + + /// Check if this file was generated during InstallAPI. + bool isInstallAPI() const { return IsInstallAPI; } + + /// Set the parent umbrella framework. + void setParentUmbrella(StringRef Parent) { ParentUmbrella = Parent; } + + /// Get the parent umbrella framework. + StringRef getParentUmbrella() const { return ParentUmbrella; } + + /// Add an allowable client. + /// + /// Mach-O Dynamic libraries have the concept of allowable clients that are + /// checked during static link time. The name of the application or library + /// that is being generated needs to match one of the allowable clients or the + /// linker refuses to link this library. + /// + /// \param Name The name of the client that is allowed to link this library. + /// \param Architectures The set of architecture for which this applies. + void addAllowableClient(StringRef Name, ArchitectureSet Architectures); + + /// Get the list of allowable clients. + /// + /// \return Returns a list of allowable clients. + const std::vector<InterfaceFileRef> &allowableClients() const { + return AllowableClients; + } + + /// Add a re-exported library. + /// + /// \param InstallName The name of the library to re-export. + /// \param Architectures The set of architecture for which this applies. + void addReexportedLibrary(StringRef InstallName, + ArchitectureSet Architectures); + + /// Get the list of re-exported libraries. + /// + /// \return Returns a list of re-exported libraries. + const std::vector<InterfaceFileRef> &reexportedLibraries() const { + return ReexportedLibraries; + } + + /// Add an architecture/UUID pair. + /// + /// \param Arch The architecture for which this applies. + /// \param UUID The UUID of the library for the specified architecture. + void addUUID(Architecture Arch, StringRef UUID); + + /// Add an architecture/UUID pair. + /// + /// \param Arch The architecture for which this applies. + /// \param UUID The UUID of the library for the specified architecture. + void addUUID(Architecture Arch, uint8_t UUID[16]); + + /// Get the list of architecture/UUID pairs. + /// + /// \return Returns a list of architecture/UUID pairs. + const std::vector<std::pair<Architecture, std::string>> &uuids() const { + return UUIDs; + } + + /// Add a symbol to the symbols list or extend an existing one. + void addSymbol(SymbolKind Kind, StringRef Name, ArchitectureSet Architectures, + SymbolFlags Flags = SymbolFlags::None); + + using SymbolMapType = DenseMap<SymbolsMapKey, Symbol *>; + struct const_symbol_iterator + : public iterator_adaptor_base< + const_symbol_iterator, SymbolMapType::const_iterator, + std::forward_iterator_tag, const Symbol *, ptrdiff_t, + const Symbol *, const Symbol *> { + const_symbol_iterator() = default; + + template <typename U> + const_symbol_iterator(U &&u) + : iterator_adaptor_base(std::forward<U &&>(u)) {} + + reference operator*() const { return I->second; } + pointer operator->() const { return I->second; } + }; + using const_symbol_range = iterator_range<const_symbol_iterator>; + + // Custom iterator to return only exported symbols. + struct const_export_iterator + : public iterator_adaptor_base< + const_export_iterator, const_symbol_iterator, + std::forward_iterator_tag, const Symbol *> { + const_symbol_iterator _end; + + void skipToNextSymbol() { + while (I != _end && I->isUndefined()) + ++I; + } + + const_export_iterator() = default; + template <typename U> + const_export_iterator(U &&it, U &&end) + : iterator_adaptor_base(std::forward<U &&>(it)), + _end(std::forward<U &&>(end)) { + skipToNextSymbol(); + } + + const_export_iterator &operator++() { + ++I; + skipToNextSymbol(); + return *this; + } + + const_export_iterator operator++(int) { + const_export_iterator tmp(*this); + ++(*this); + return tmp; + } + }; + using const_export_range = llvm::iterator_range<const_export_iterator>; + + // Custom iterator to return only undefined symbols. + struct const_undefined_iterator + : public iterator_adaptor_base< + const_undefined_iterator, const_symbol_iterator, + std::forward_iterator_tag, const Symbol *> { + const_symbol_iterator _end; + + void skipToNextSymbol() { + while (I != _end && !I->isUndefined()) + ++I; + } + + const_undefined_iterator() = default; + template <typename U> + const_undefined_iterator(U &&it, U &&end) + : iterator_adaptor_base(std::forward<U &&>(it)), + _end(std::forward<U &&>(end)) { + skipToNextSymbol(); + } + + const_undefined_iterator &operator++() { + ++I; + skipToNextSymbol(); + return *this; + } + + const_undefined_iterator operator++(int) { + const_undefined_iterator tmp(*this); + ++(*this); + return tmp; + } + }; + using const_undefined_range = llvm::iterator_range<const_undefined_iterator>; + + const_symbol_range symbols() const { + return {Symbols.begin(), Symbols.end()}; + } + const_export_range exports() const { + return {{Symbols.begin(), Symbols.end()}, {Symbols.end(), Symbols.end()}}; + } + const_undefined_range undefineds() const { + return {{Symbols.begin(), Symbols.end()}, {Symbols.end(), Symbols.end()}}; + } + +private: + llvm::BumpPtrAllocator Allocator; + StringRef copyString(StringRef String) { + if (String.empty()) + return {}; + + void *Ptr = Allocator.Allocate(String.size(), 1); + memcpy(Ptr, String.data(), String.size()); + return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); + } + + std::string Path; + FileType FileKind; + PlatformKind Platform; + ArchitectureSet Architectures; + std::string InstallName; + PackedVersion CurrentVersion; + PackedVersion CompatibilityVersion; + uint8_t SwiftABIVersion{0}; + bool IsTwoLevelNamespace{false}; + bool IsAppExtensionSafe{false}; + bool IsInstallAPI{false}; + ObjCConstraintType ObjcConstraint = ObjCConstraintType::None; + std::string ParentUmbrella; + std::vector<InterfaceFileRef> AllowableClients; + std::vector<InterfaceFileRef> ReexportedLibraries; + std::vector<std::pair<Architecture, std::string>> UUIDs; + SymbolMapType Symbols; +}; + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H diff --git a/include/llvm/TextAPI/MachO/PackedVersion.h b/include/llvm/TextAPI/MachO/PackedVersion.h new file mode 100644 index 000000000000..2d0138097dd9 --- /dev/null +++ b/include/llvm/TextAPI/MachO/PackedVersion.h @@ -0,0 +1,64 @@ +//===- llvm/TextAPI/MachO/PackedVersion.h - PackedVersion -------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Defines the Mach-O packed version format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TEXTAPI_MACHO_PACKED_VERSION_H +#define LLVM_TEXTAPI_MACHO_PACKED_VERSION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace MachO { + +class PackedVersion { + uint32_t Version{0}; + +public: + constexpr PackedVersion() = default; + explicit constexpr PackedVersion(uint32_t RawVersion) : Version(RawVersion) {} + PackedVersion(unsigned Major, unsigned Minor, unsigned Subminor) + : Version((Major << 16) | ((Minor & 0xff) << 8) | (Subminor & 0xff)) {} + + bool empty() const { return Version == 0; } + + /// Retrieve the major version number. + unsigned getMajor() const { return Version >> 16; } + + /// Retrieve the minor version number, if provided. + unsigned getMinor() const { return (Version >> 8) & 0xff; } + + /// Retrieve the subminor version number, if provided. + unsigned getSubminor() const { return Version & 0xff; } + + bool parse32(StringRef Str); + std::pair<bool, bool> parse64(StringRef Str); + + bool operator<(const PackedVersion &O) const { return Version < O.Version; } + + bool operator==(const PackedVersion &O) const { return Version == O.Version; } + + bool operator!=(const PackedVersion &O) const { return Version != O.Version; } + + uint32_t rawValue() const { return Version; } + + void print(raw_ostream &OS) const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const PackedVersion &Version) { + Version.print(OS); + return OS; +} + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_PACKED_VERSION_H diff --git a/include/llvm/TextAPI/MachO/Symbol.h b/include/llvm/TextAPI/MachO/Symbol.h new file mode 100644 index 000000000000..3c7ff5e0f4ea --- /dev/null +++ b/include/llvm/TextAPI/MachO/Symbol.h @@ -0,0 +1,96 @@ +//===- llvm/TextAPI/Symbol.h - TAPI Symbol ----------------------*- 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_TEXTAPI_MACHO_SYMBOL_H +#define LLVM_TEXTAPI_MACHO_SYMBOL_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TextAPI/MachO/ArchitectureSet.h" + +namespace llvm { +namespace MachO { + +// clang-format off + +/// Symbol flags. +enum class SymbolFlags : uint8_t { + /// No flags + None = 0, + + /// Thread-local value symbol + ThreadLocalValue = 1U << 0, + + /// Weak defined symbol + WeakDefined = 1U << 1, + + /// Weak referenced symbol + WeakReferenced = 1U << 2, + + /// Undefined + Undefined = 1U << 3, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Undefined), +}; + +// clang-format on + +enum class SymbolKind : uint8_t { + GlobalSymbol, + ObjectiveCClass, + ObjectiveCClassEHType, + ObjectiveCInstanceVariable, +}; + +class Symbol { +public: + constexpr Symbol(SymbolKind Kind, StringRef Name, + ArchitectureSet Architectures, SymbolFlags Flags) + : Name(Name), Architectures(Architectures), Kind(Kind), Flags(Flags) {} + + SymbolKind getKind() const { return Kind; } + StringRef getName() const { return Name; } + ArchitectureSet getArchitectures() const { return Architectures; } + void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; } + SymbolFlags getFlags() const { return Flags; } + + bool isWeakDefined() const { + return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; + } + + bool isWeakReferenced() const { + return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced; + } + + bool isThreadLocalValue() const { + return (Flags & SymbolFlags::ThreadLocalValue) == + SymbolFlags::ThreadLocalValue; + } + + bool isUndefined() const { + return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined; + } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump(raw_ostream &OS) const; + void dump() const { dump(llvm::errs()); } +#endif + +private: + StringRef Name; + ArchitectureSet Architectures; + SymbolKind Kind; + SymbolFlags Flags; +}; + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_SYMBOL_H diff --git a/include/llvm/TextAPI/MachO/TextAPIReader.h b/include/llvm/TextAPI/MachO/TextAPIReader.h new file mode 100644 index 000000000000..6d9c09de5294 --- /dev/null +++ b/include/llvm/TextAPI/MachO/TextAPIReader.h @@ -0,0 +1,34 @@ +//===--- TextAPIReader.h - Text API Reader ----------------------*- 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_TEXTAPI_MACHO_READER_H +#define LLVM_TEXTAPI_MACHO_READER_H + +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { +namespace MachO { + +class InterfaceFile; + +class TextAPIReader { +public: + static Expected<std::unique_ptr<InterfaceFile>> + get(std::unique_ptr<MemoryBuffer> InputBuffer); + + static Expected<std::unique_ptr<InterfaceFile>> + getUnmanaged(llvm::MemoryBuffer *InputBuffer); + + TextAPIReader() = delete; +}; + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_READER_H diff --git a/include/llvm/TextAPI/MachO/TextAPIWriter.h b/include/llvm/TextAPI/MachO/TextAPIWriter.h new file mode 100644 index 000000000000..2a45bb86a332 --- /dev/null +++ b/include/llvm/TextAPI/MachO/TextAPIWriter.h @@ -0,0 +1,29 @@ +//===--- TextAPIWriter.h - Text API Writer ----------------------*- 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_TEXTAPI_MACHO_WRITER_H +#define LLVM_TEXTAPI_MACHO_WRITER_H + +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { +namespace MachO { + +class InterfaceFile; + +class TextAPIWriter { +public: + TextAPIWriter() = delete; + + static Error writeToStream(raw_ostream &os, const InterfaceFile &); +}; + +} // end namespace MachO. +} // end namespace llvm. + +#endif // LLVM_TEXTAPI_MACHO_WRITER_H diff --git a/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h b/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h index 964b0f7620a2..d144f62f1cc1 100644 --- a/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h +++ b/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h @@ -1,9 +1,8 @@ //===- DlltoolDriver.h - dlltool.exe-compatible driver ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/ToolDrivers/llvm-lib/LibDriver.h b/include/llvm/ToolDrivers/llvm-lib/LibDriver.h index a4806ac4ad69..23a2fc348a89 100644 --- a/include/llvm/ToolDrivers/llvm-lib/LibDriver.h +++ b/include/llvm/ToolDrivers/llvm-lib/LibDriver.h @@ -1,9 +1,8 @@ //===- llvm-lib/LibDriver.h - lib.exe-compatible driver ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ namespace llvm { template <typename T> class ArrayRef; int libDriverMain(ArrayRef<const char *> ARgs); + } #endif diff --git a/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h b/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h index f970acdc741f..887c8807904e 100644 --- a/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h +++ b/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h @@ -1,9 +1,8 @@ //===- AggressiveInstCombine.h - AggressiveInstCombine pass -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Coroutines.h b/include/llvm/Transforms/Coroutines.h index 51beb44fdc56..9df3ec0f3ef4 100644 --- a/include/llvm/Transforms/Coroutines.h +++ b/include/llvm/Transforms/Coroutines.h @@ -1,9 +1,8 @@ //===-- Coroutines.h - Coroutine Transformations ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // Declare accessor functions for coroutine lowering passes. diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 11d363b1200b..de0c80f5b19a 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/IPO.h - Interprocedural Transformations --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -183,6 +182,10 @@ ModulePass *createBlockExtractorPass(); ModulePass * createBlockExtractorPass(const SmallVectorImpl<BasicBlock *> &BlocksToExtract, bool EraseFunctions); +ModulePass * +createBlockExtractorPass(const SmallVectorImpl<SmallVector<BasicBlock *, 16>> + &GroupsOfBlocksToExtract, + bool EraseFunctions); /// createStripDeadPrototypesPass - This pass removes any function declarations /// (prototypes) that are not used. diff --git a/include/llvm/Transforms/IPO/AlwaysInliner.h b/include/llvm/Transforms/IPO/AlwaysInliner.h index b52c0fdbd2c9..64e25230f6da 100644 --- a/include/llvm/Transforms/IPO/AlwaysInliner.h +++ b/include/llvm/Transforms/IPO/AlwaysInliner.h @@ -1,9 +1,8 @@ //===-- AlwaysInliner.h - Pass to inline "always_inline" functions --------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Transforms/IPO/ArgumentPromotion.h b/include/llvm/Transforms/IPO/ArgumentPromotion.h index 49ca6cc73393..c8afb7bdcd65 100644 --- a/include/llvm/Transforms/IPO/ArgumentPromotion.h +++ b/include/llvm/Transforms/IPO/ArgumentPromotion.h @@ -1,9 +1,8 @@ //===- ArgumentPromotion.h - Promote by-reference arguments -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/IPO/Attributor.h b/include/llvm/Transforms/IPO/Attributor.h new file mode 100644 index 000000000000..5dbe21ac5e4e --- /dev/null +++ b/include/llvm/Transforms/IPO/Attributor.h @@ -0,0 +1,789 @@ +//===- Attributor.h --- Module-wide attribute deduction ---------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Attributor: An inter procedural (abstract) "attribute" deduction framework. +// +// The Attributor framework is an inter procedural abstract analysis (fixpoint +// iteration analysis). The goal is to allow easy deduction of new attributes as +// well as information exchange between abstract attributes in-flight. +// +// The Attributor class is the driver and the link between the various abstract +// attributes. The Attributor will iterate until a fixpoint state is reached by +// all abstract attributes in-flight, or until it will enforce a pessimistic fix +// point because an iteration limit is reached. +// +// Abstract attributes, derived from the AbstractAttribute class, actually +// describe properties of the code. They can correspond to actual LLVM-IR +// attributes, or they can be more general, ultimately unrelated to LLVM-IR +// attributes. The latter is useful when an abstract attributes provides +// information to other abstract attributes in-flight but we might not want to +// manifest the information. The Attributor allows to query in-flight abstract +// attributes through the `Attributor::getAAFor` method (see the method +// description for an example). If the method is used by an abstract attribute +// P, and it results in an abstract attribute Q, the Attributor will +// automatically capture a potential dependence from Q to P. This dependence +// will cause P to be reevaluated whenever Q changes in the future. +// +// The Attributor will only reevaluated abstract attributes that might have +// changed since the last iteration. That means that the Attribute will not +// revisit all instructions/blocks/functions in the module but only query +// an update from a subset of the abstract attributes. +// +// The update method `AbstractAttribute::updateImpl` is implemented by the +// specific "abstract attribute" subclasses. The method is invoked whenever the +// currently assumed state (see the AbstractState class) might not be valid +// anymore. This can, for example, happen if the state was dependent on another +// abstract attribute that changed. In every invocation, the update method has +// to adjust the internal state of an abstract attribute to a point that is +// justifiable by the underlying IR and the current state of abstract attributes +// in-flight. Since the IR is given and assumed to be valid, the information +// derived from it can be assumed to hold. However, information derived from +// other abstract attributes is conditional on various things. If the justifying +// state changed, the `updateImpl` has to revisit the situation and potentially +// find another justification or limit the optimistic assumes made. +// +// Change is the key in this framework. Until a state of no-change, thus a +// fixpoint, is reached, the Attributor will query the abstract attributes +// in-flight to re-evaluate their state. If the (current) state is too +// optimistic, hence it cannot be justified anymore through other abstract +// attributes or the state of the IR, the state of the abstract attribute will +// have to change. Generally, we assume abstract attribute state to be a finite +// height lattice and the update function to be monotone. However, these +// conditions are not enforced because the iteration limit will guarantee +// termination. If an optimistic fixpoint is reached, or a pessimistic fix +// point is enforced after a timeout, the abstract attributes are tasked to +// manifest their result in the IR for passes to come. +// +// Attribute manifestation is not mandatory. If desired, there is support to +// generate a single LLVM-IR attribute already in the AbstractAttribute base +// class. In the simplest case, a subclass overloads +// `AbstractAttribute::getManifestPosition()` and +// `AbstractAttribute::getAttrKind()` to return the appropriate values. The +// Attributor manifestation framework will then create and place a new attribute +// if it is allowed to do so (based on the abstract state). Other use cases can +// be achieved by overloading other abstract attribute methods. +// +// +// The "mechanics" of adding a new "abstract attribute": +// - Define a class (transitively) inheriting from AbstractAttribute and one +// (which could be the same) that (transitively) inherits from AbstractState. +// For the latter, consider the already available BooleanState and +// IntegerState if they fit your needs, e.g., you require only a bit-encoding. +// - Implement all pure methods. Also use overloading if the attribute is not +// conforming with the "default" behavior: A (set of) LLVM-IR attribute(s) for +// an argument, call site argument, function return value, or function. See +// the class and method descriptions for more information on the two +// "Abstract" classes and their respective methods. +// - Register opportunities for the new abstract attribute in the +// `Attributor::identifyDefaultAbstractAttributes` method if it should be +// counted as a 'default' attribute. +// - Add sufficient tests. +// - Add a Statistics object for bookkeeping. If it is a simple (set of) +// attribute(s) manifested through the Attributor manifestation framework, see +// the bookkeeping function in Attributor.cpp. +// - If instructions with a certain opcode are interesting to the attribute, add +// that opcode to the switch in `Attributor::identifyAbstractAttributes`. This +// will make it possible to query all those instructions through the +// `InformationCache::getOpcodeInstMapForFunction` interface and eliminate the +// need to traverse the IR repeatedly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H +#define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H + +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct AbstractAttribute; +struct InformationCache; + +class Function; + +/// Simple enum class that forces the status to be spelled out explicitly. +/// +///{ +enum class ChangeStatus { + CHANGED, + UNCHANGED, +}; + +ChangeStatus operator|(ChangeStatus l, ChangeStatus r); +ChangeStatus operator&(ChangeStatus l, ChangeStatus r); +///} + +/// The fixpoint analysis framework that orchestrates the attribute deduction. +/// +/// The Attributor provides a general abstract analysis framework (guided +/// fixpoint iteration) as well as helper functions for the deduction of +/// (LLVM-IR) attributes. However, also other code properties can be deduced, +/// propagated, and ultimately manifested through the Attributor framework. This +/// is particularly useful if these properties interact with attributes and a +/// co-scheduled deduction allows to improve the solution. Even if not, thus if +/// attributes/properties are completely isolated, they should use the +/// Attributor framework to reduce the number of fixpoint iteration frameworks +/// in the code base. Note that the Attributor design makes sure that isolated +/// attributes are not impacted, in any way, by others derived at the same time +/// if there is no cross-reasoning performed. +/// +/// The public facing interface of the Attributor is kept simple and basically +/// allows abstract attributes to one thing, query abstract attributes +/// in-flight. There are two reasons to do this: +/// a) The optimistic state of one abstract attribute can justify an +/// optimistic state of another, allowing to framework to end up with an +/// optimistic (=best possible) fixpoint instead of one based solely on +/// information in the IR. +/// b) This avoids reimplementing various kinds of lookups, e.g., to check +/// for existing IR attributes, in favor of a single lookups interface +/// provided by an abstract attribute subclass. +/// +/// NOTE: The mechanics of adding a new "concrete" abstract attribute are +/// described in the file comment. +struct Attributor { + ~Attributor() { DeleteContainerPointers(AllAbstractAttributes); } + + /// Run the analyses until a fixpoint is reached or enforced (timeout). + /// + /// The attributes registered with this Attributor can be used after as long + /// as the Attributor is not destroyed (it owns the attributes now). + /// + /// \Returns CHANGED if the IR was changed, otherwise UNCHANGED. + ChangeStatus run(); + + /// Lookup an abstract attribute of type \p AAType anchored at value \p V and + /// argument number \p ArgNo. If no attribute is found and \p V is a call base + /// instruction, the called function is tried as a value next. Thus, the + /// returned abstract attribute might be anchored at the callee of \p V. + /// + /// This method is the only (supported) way an abstract attribute can retrieve + /// information from another abstract attribute. As an example, take an + /// abstract attribute that determines the memory access behavior for a + /// argument (readnone, readonly, ...). It should use `getAAFor` to get the + /// most optimistic information for other abstract attributes in-flight, e.g. + /// the one reasoning about the "captured" state for the argument or the one + /// reasoning on the memory access behavior of the function as a whole. + template <typename AAType> + const AAType *getAAFor(AbstractAttribute &QueryingAA, const Value &V, + int ArgNo = -1) { + static_assert(std::is_base_of<AbstractAttribute, AAType>::value, + "Cannot query an attribute with a type not derived from " + "'AbstractAttribute'!"); + assert(AAType::ID != Attribute::None && + "Cannot lookup generic abstract attributes!"); + + // Determine the argument number automatically for llvm::Arguments if none + // is set. Do not override a given one as it could be a use of the argument + // in a call site. + if (ArgNo == -1) + if (auto *Arg = dyn_cast<Argument>(&V)) + ArgNo = Arg->getArgNo(); + + // If a function was given together with an argument number, perform the + // lookup for the actual argument instead. Don't do it for variadic + // arguments. + if (ArgNo >= 0 && isa<Function>(&V) && + cast<Function>(&V)->arg_size() > (size_t)ArgNo) + return getAAFor<AAType>( + QueryingAA, *(cast<Function>(&V)->arg_begin() + ArgNo), ArgNo); + + // Lookup the abstract attribute of type AAType. If found, return it after + // registering a dependence of QueryingAA on the one returned attribute. + const auto &KindToAbstractAttributeMap = AAMap.lookup({&V, ArgNo}); + if (AAType *AA = static_cast<AAType *>( + KindToAbstractAttributeMap.lookup(AAType::ID))) { + // Do not return an attribute with an invalid state. This minimizes checks + // at the calls sites and allows the fallback below to kick in. + if (AA->getState().isValidState()) { + QueryMap[AA].insert(&QueryingAA); + return AA; + } + } + + // If no abstract attribute was found and we look for a call site argument, + // defer to the actual argument instead. + ImmutableCallSite ICS(&V); + if (ICS && ICS.getCalledValue()) + return getAAFor<AAType>(QueryingAA, *ICS.getCalledValue(), ArgNo); + + // No matching attribute found + return nullptr; + } + + /// Introduce a new abstract attribute into the fixpoint analysis. + /// + /// Note that ownership of the attribute is given to the Attributor. It will + /// invoke delete for the Attributor on destruction of the Attributor. + /// + /// Attributes are identified by + /// (1) their anchored value (see AA.getAnchoredValue()), + /// (2) their argument number (\p ArgNo, or Argument::getArgNo()), and + /// (3) their default attribute kind (see AAType::ID). + template <typename AAType> AAType ®isterAA(AAType &AA, int ArgNo = -1) { + static_assert(std::is_base_of<AbstractAttribute, AAType>::value, + "Cannot register an attribute with a type not derived from " + "'AbstractAttribute'!"); + + // Determine the anchor value and the argument number which are used to + // lookup the attribute together with AAType::ID. If passed an argument, + // use its argument number but do not override a given one as it could be a + // use of the argument at a call site. + Value &AnchoredVal = AA.getAnchoredValue(); + if (ArgNo == -1) + if (auto *Arg = dyn_cast<Argument>(&AnchoredVal)) + ArgNo = Arg->getArgNo(); + + // Put the attribute in the lookup map structure and the container we use to + // keep track of all attributes. + AAMap[{&AnchoredVal, ArgNo}][AAType::ID] = &AA; + AllAbstractAttributes.push_back(&AA); + return AA; + } + + /// Determine opportunities to derive 'default' attributes in \p F and create + /// abstract attribute objects for them. + /// + /// \param F The function that is checked for attribute opportunities. + /// \param InfoCache A cache for information queryable by the new attributes. + /// \param Whitelist If not null, a set limiting the attribute opportunities. + /// + /// Note that abstract attribute instances are generally created even if the + /// IR already contains the information they would deduce. The most important + /// reason for this is the single interface, the one of the abstract attribute + /// instance, which can be queried without the need to look at the IR in + /// various places. + void identifyDefaultAbstractAttributes( + Function &F, InformationCache &InfoCache, + DenseSet</* Attribute::AttrKind */ unsigned> *Whitelist = nullptr); + + /// Check \p Pred on all function call sites. + /// + /// This method will evaluate \p Pred on call sites and return + /// true if \p Pred holds in every call sites. However, this is only possible + /// all call sites are known, hence the function has internal linkage. + bool checkForAllCallSites(Function &F, std::function<bool(CallSite)> &Pred, + bool RequireAllCallSites); + +private: + /// The set of all abstract attributes. + ///{ + using AAVector = SmallVector<AbstractAttribute *, 64>; + AAVector AllAbstractAttributes; + ///} + + /// A nested map to lookup abstract attributes based on the anchored value and + /// an argument positions (or -1) on the outer level, and attribute kinds + /// (Attribute::AttrKind) on the inner level. + ///{ + using KindToAbstractAttributeMap = DenseMap<unsigned, AbstractAttribute *>; + DenseMap<std::pair<const Value *, int>, KindToAbstractAttributeMap> AAMap; + ///} + + /// A map from abstract attributes to the ones that queried them through calls + /// to the getAAFor<...>(...) method. + ///{ + using QueryMapTy = + DenseMap<AbstractAttribute *, SetVector<AbstractAttribute *>>; + QueryMapTy QueryMap; + ///} +}; + +/// Data structure to hold cached (LLVM-IR) information. +/// +/// All attributes are given an InformationCache object at creation time to +/// avoid inspection of the IR by all of them individually. This default +/// InformationCache will hold information required by 'default' attributes, +/// thus the ones deduced when Attributor::identifyDefaultAbstractAttributes(..) +/// is called. +/// +/// If custom abstract attributes, registered manually through +/// Attributor::registerAA(...), need more information, especially if it is not +/// reusable, it is advised to inherit from the InformationCache and cast the +/// instance down in the abstract attributes. +struct InformationCache { + /// A map type from opcodes to instructions with this opcode. + using OpcodeInstMapTy = DenseMap<unsigned, SmallVector<Instruction *, 32>>; + + /// Return the map that relates "interesting" opcodes with all instructions + /// with that opcode in \p F. + OpcodeInstMapTy &getOpcodeInstMapForFunction(Function &F) { + return FuncInstOpcodeMap[&F]; + } + + /// A vector type to hold instructions. + using InstructionVectorTy = std::vector<Instruction *>; + + /// Return the instructions in \p F that may read or write memory. + InstructionVectorTy &getReadOrWriteInstsForFunction(Function &F) { + return FuncRWInstsMap[&F]; + } + +private: + /// A map type from functions to opcode to instruction maps. + using FuncInstOpcodeMapTy = DenseMap<Function *, OpcodeInstMapTy>; + + /// A map type from functions to their read or write instructions. + using FuncRWInstsMapTy = DenseMap<Function *, InstructionVectorTy>; + + /// A nested map that remembers all instructions in a function with a certain + /// instruction opcode (Instruction::getOpcode()). + FuncInstOpcodeMapTy FuncInstOpcodeMap; + + /// A map from functions to their instructions that may read or write memory. + FuncRWInstsMapTy FuncRWInstsMap; + + /// Give the Attributor access to the members so + /// Attributor::identifyDefaultAbstractAttributes(...) can initialize them. + friend struct Attributor; +}; + +/// An interface to query the internal state of an abstract attribute. +/// +/// The abstract state is a minimal interface that allows the Attributor to +/// communicate with the abstract attributes about their internal state without +/// enforcing or exposing implementation details, e.g., the (existence of an) +/// underlying lattice. +/// +/// It is sufficient to be able to query if a state is (1) valid or invalid, (2) +/// at a fixpoint, and to indicate to the state that (3) an optimistic fixpoint +/// was reached or (4) a pessimistic fixpoint was enforced. +/// +/// All methods need to be implemented by the subclass. For the common use case, +/// a single boolean state or a bit-encoded state, the BooleanState and +/// IntegerState classes are already provided. An abstract attribute can inherit +/// from them to get the abstract state interface and additional methods to +/// directly modify the state based if needed. See the class comments for help. +struct AbstractState { + virtual ~AbstractState() {} + + /// Return if this abstract state is in a valid state. If false, no + /// information provided should be used. + virtual bool isValidState() const = 0; + + /// Return if this abstract state is fixed, thus does not need to be updated + /// if information changes as it cannot change itself. + virtual bool isAtFixpoint() const = 0; + + /// Indicate that the abstract state should converge to the optimistic state. + /// + /// This will usually make the optimistically assumed state the known to be + /// true state. + virtual void indicateOptimisticFixpoint() = 0; + + /// Indicate that the abstract state should converge to the pessimistic state. + /// + /// This will usually revert the optimistically assumed state to the known to + /// be true state. + virtual void indicatePessimisticFixpoint() = 0; +}; + +/// Simple state with integers encoding. +/// +/// The interface ensures that the assumed bits are always a subset of the known +/// bits. Users can only add known bits and, except through adding known bits, +/// they can only remove assumed bits. This should guarantee monotoniticy and +/// thereby the existence of a fixpoint (if used corretly). The fixpoint is +/// reached when the assumed and known state/bits are equal. Users can +/// force/inidicate a fixpoint. If an optimistic one is indicated, the known +/// state will catch up with the assumed one, for a pessimistic fixpoint it is +/// the other way around. +struct IntegerState : public AbstractState { + /// Underlying integer type, we assume 32 bits to be enough. + using base_t = uint32_t; + + /// Initialize the (best) state. + IntegerState(base_t BestState = ~0) : Assumed(BestState) {} + + /// Return the worst possible representable state. + static constexpr base_t getWorstState() { return 0; } + + /// See AbstractState::isValidState() + /// NOTE: For now we simply pretend that the worst possible state is invalid. + bool isValidState() const override { return Assumed != getWorstState(); } + + /// See AbstractState::isAtFixpoint() + bool isAtFixpoint() const override { return Assumed == Known; } + + /// See AbstractState::indicateOptimisticFixpoint(...) + void indicateOptimisticFixpoint() override { Known = Assumed; } + + /// See AbstractState::indicatePessimisticFixpoint(...) + void indicatePessimisticFixpoint() override { Assumed = Known; } + + /// Return the known state encoding + base_t getKnown() const { return Known; } + + /// Return the assumed state encoding. + base_t getAssumed() const { return Assumed; } + + /// Return true if the bits set in \p BitsEncoding are "known bits". + bool isKnown(base_t BitsEncoding) const { + return (Known & BitsEncoding) == BitsEncoding; + } + + /// Return true if the bits set in \p BitsEncoding are "assumed bits". + bool isAssumed(base_t BitsEncoding) const { + return (Assumed & BitsEncoding) == BitsEncoding; + } + + /// Add the bits in \p BitsEncoding to the "known bits". + IntegerState &addKnownBits(base_t Bits) { + // Make sure we never miss any "known bits". + Assumed |= Bits; + Known |= Bits; + return *this; + } + + /// Remove the bits in \p BitsEncoding from the "assumed bits" if not known. + IntegerState &removeAssumedBits(base_t BitsEncoding) { + // Make sure we never loose any "known bits". + Assumed = (Assumed & ~BitsEncoding) | Known; + return *this; + } + + /// Keep only "assumed bits" also set in \p BitsEncoding but all known ones. + IntegerState &intersectAssumedBits(base_t BitsEncoding) { + // Make sure we never loose any "known bits". + Assumed = (Assumed & BitsEncoding) | Known; + return *this; + } + +private: + /// The known state encoding in an integer of type base_t. + base_t Known = getWorstState(); + + /// The assumed state encoding in an integer of type base_t. + base_t Assumed; +}; + +/// Simple wrapper for a single bit (boolean) state. +struct BooleanState : public IntegerState { + BooleanState() : IntegerState(1){}; +}; + +/// Base struct for all "concrete attribute" deductions. +/// +/// The abstract attribute is a minimal interface that allows the Attributor to +/// orchestrate the abstract/fixpoint analysis. The design allows to hide away +/// implementation choices made for the subclasses but also to structure their +/// implementation and simplify the use of other abstract attributes in-flight. +/// +/// To allow easy creation of new attributes, most methods have default +/// implementations. The ones that do not are generally straight forward, except +/// `AbstractAttribute::updateImpl` which is the location of most reasoning +/// associated with the abstract attribute. The update is invoked by the +/// Attributor in case the situation used to justify the current optimistic +/// state might have changed. The Attributor determines this automatically +/// by monitoring the `Attributor::getAAFor` calls made by abstract attributes. +/// +/// The `updateImpl` method should inspect the IR and other abstract attributes +/// in-flight to justify the best possible (=optimistic) state. The actual +/// implementation is, similar to the underlying abstract state encoding, not +/// exposed. In the most common case, the `updateImpl` will go through a list of +/// reasons why its optimistic state is valid given the current information. If +/// any combination of them holds and is sufficient to justify the current +/// optimistic state, the method shall return UNCHAGED. If not, the optimistic +/// state is adjusted to the situation and the method shall return CHANGED. +/// +/// If the manifestation of the "concrete attribute" deduced by the subclass +/// differs from the "default" behavior, which is a (set of) LLVM-IR +/// attribute(s) for an argument, call site argument, function return value, or +/// function, the `AbstractAttribute::manifest` method should be overloaded. +/// +/// NOTE: If the state obtained via getState() is INVALID, thus if +/// AbstractAttribute::getState().isValidState() returns false, no +/// information provided by the methods of this class should be used. +/// NOTE: The Attributor currently has certain limitations to what we can do. +/// As a general rule of thumb, "concrete" abstract attributes should *for +/// now* only perform "backward" information propagation. That means +/// optimistic information obtained through abstract attributes should +/// only be used at positions that precede the origin of the information +/// with regards to the program flow. More practically, information can +/// *now* be propagated from instructions to their enclosing function, but +/// *not* from call sites to the called function. The mechanisms to allow +/// both directions will be added in the future. +/// NOTE: The mechanics of adding a new "concrete" abstract attribute are +/// described in the file comment. +struct AbstractAttribute { + + /// The positions attributes can be manifested in. + enum ManifestPosition { + MP_ARGUMENT, ///< An attribute for a function argument. + MP_CALL_SITE_ARGUMENT, ///< An attribute for a call site argument. + MP_FUNCTION, ///< An attribute for a function as a whole. + MP_RETURNED, ///< An attribute for the function return value. + }; + + /// An abstract attribute associated with \p AssociatedVal and anchored at + /// \p AnchoredVal. + /// + /// \param AssociatedVal The value this abstract attribute is associated with. + /// \param AnchoredVal The value this abstract attributes is anchored at. + /// \param InfoCache Cached information accessible to the abstract attribute. + AbstractAttribute(Value *AssociatedVal, Value &AnchoredVal, + InformationCache &InfoCache) + : AssociatedVal(AssociatedVal), AnchoredVal(AnchoredVal), + InfoCache(InfoCache) {} + + /// An abstract attribute associated with and anchored at \p V. + AbstractAttribute(Value &V, InformationCache &InfoCache) + : AbstractAttribute(&V, V, InfoCache) {} + + /// Virtual destructor. + virtual ~AbstractAttribute() {} + + /// Initialize the state with the information in the Attributor \p A. + /// + /// This function is called by the Attributor once all abstract attributes + /// have been identified. It can and shall be used for task like: + /// - identify existing knowledge in the IR and use it for the "known state" + /// - perform any work that is not going to change over time, e.g., determine + /// a subset of the IR, or attributes in-flight, that have to be looked at + /// in the `updateImpl` method. + virtual void initialize(Attributor &A) {} + + /// Return the internal abstract state for inspection. + virtual const AbstractState &getState() const = 0; + + /// Return the value this abstract attribute is anchored with. + /// + /// The anchored value might not be the associated value if the latter is not + /// sufficient to determine where arguments will be manifested. This is mostly + /// the case for call site arguments as the value is not sufficient to + /// pinpoint them. Instead, we can use the call site as an anchor. + /// + ///{ + Value &getAnchoredValue() { return AnchoredVal; } + const Value &getAnchoredValue() const { return AnchoredVal; } + ///} + + /// Return the llvm::Function surrounding the anchored value. + /// + ///{ + Function &getAnchorScope(); + const Function &getAnchorScope() const; + ///} + + /// Return the value this abstract attribute is associated with. + /// + /// The abstract state usually represents this value. + /// + ///{ + virtual Value *getAssociatedValue() { return AssociatedVal; } + virtual const Value *getAssociatedValue() const { return AssociatedVal; } + ///} + + /// Return the position this abstract state is manifested in. + virtual ManifestPosition getManifestPosition() const = 0; + + /// Return the kind that identifies the abstract attribute implementation. + virtual Attribute::AttrKind getAttrKind() const = 0; + + /// Return the deduced attributes in \p Attrs. + virtual void getDeducedAttributes(SmallVectorImpl<Attribute> &Attrs) const { + LLVMContext &Ctx = AnchoredVal.getContext(); + Attrs.emplace_back(Attribute::get(Ctx, getAttrKind())); + } + + /// Helper functions, for debug purposes only. + ///{ + virtual void print(raw_ostream &OS) const; + void dump() const { print(dbgs()); } + + /// This function should return the "summarized" assumed state as string. + virtual const std::string getAsStr() const = 0; + ///} + + /// Allow the Attributor access to the protected methods. + friend struct Attributor; + +protected: + /// Hook for the Attributor to trigger an update of the internal state. + /// + /// If this attribute is already fixed, this method will return UNCHANGED, + /// otherwise it delegates to `AbstractAttribute::updateImpl`. + /// + /// \Return CHANGED if the internal state changed, otherwise UNCHANGED. + ChangeStatus update(Attributor &A); + + /// Hook for the Attributor to trigger the manifestation of the information + /// represented by the abstract attribute in the LLVM-IR. + /// + /// \Return CHANGED if the IR was altered, otherwise UNCHANGED. + virtual ChangeStatus manifest(Attributor &A); + + /// Return the internal abstract state for careful modification. + virtual AbstractState &getState() = 0; + + /// The actual update/transfer function which has to be implemented by the + /// derived classes. + /// + /// If it is called, the environment has changed and we have to determine if + /// the current information is still valid or adjust it otherwise. + /// + /// \Return CHANGED if the internal state changed, otherwise UNCHANGED. + virtual ChangeStatus updateImpl(Attributor &A) = 0; + + /// The value this abstract attribute is associated with. + Value *AssociatedVal; + + /// The value this abstract attribute is anchored at. + Value &AnchoredVal; + + /// The information cache accessible to this abstract attribute. + InformationCache &InfoCache; +}; + +/// Forward declarations of output streams for debug purposes. +/// +///{ +raw_ostream &operator<<(raw_ostream &OS, const AbstractAttribute &AA); +raw_ostream &operator<<(raw_ostream &OS, ChangeStatus S); +raw_ostream &operator<<(raw_ostream &OS, AbstractAttribute::ManifestPosition); +raw_ostream &operator<<(raw_ostream &OS, const AbstractState &State); +///} + +struct AttributorPass : public PassInfoMixin<AttributorPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +Pass *createAttributorLegacyPass(); + +/// ---------------------------------------------------------------------------- +/// Abstract Attribute Classes +/// ---------------------------------------------------------------------------- + +/// An abstract attribute for the returned values of a function. +struct AAReturnedValues : public AbstractAttribute { + /// See AbstractAttribute::AbstractAttribute(...). + AAReturnedValues(Function &F, InformationCache &InfoCache) + : AbstractAttribute(F, InfoCache) {} + + /// Check \p Pred on all returned values. + /// + /// This method will evaluate \p Pred on returned values and return + /// true if (1) all returned values are known, and (2) \p Pred returned true + /// for all returned values. + virtual bool + checkForallReturnedValues(std::function<bool(Value &)> &Pred) const = 0; + + /// See AbstractAttribute::getAttrKind() + Attribute::AttrKind getAttrKind() const override { return ID; } + + /// The identifier used by the Attributor for this class of attributes. + static constexpr Attribute::AttrKind ID = Attribute::Returned; +}; + +struct AANoUnwind : public AbstractAttribute { + /// An abstract interface for all nosync attributes. + AANoUnwind(Value &V, InformationCache &InfoCache) + : AbstractAttribute(V, InfoCache) {} + + /// See AbstractAttribute::getAttrKind()/ + Attribute::AttrKind getAttrKind() const override { return ID; } + + static constexpr Attribute::AttrKind ID = Attribute::NoUnwind; + + /// Returns true if nounwind is assumed. + virtual bool isAssumedNoUnwind() const = 0; + + /// Returns true if nounwind is known. + virtual bool isKnownNoUnwind() const = 0; +}; + +struct AANoSync : public AbstractAttribute { + /// An abstract interface for all nosync attributes. + AANoSync(Value &V, InformationCache &InfoCache) + : AbstractAttribute(V, InfoCache) {} + + /// See AbstractAttribute::getAttrKind(). + Attribute::AttrKind getAttrKind() const override { return ID; } + + static constexpr Attribute::AttrKind ID = + Attribute::AttrKind(Attribute::NoSync); + + /// Returns true if "nosync" is assumed. + virtual bool isAssumedNoSync() const = 0; + + /// Returns true if "nosync" is known. + virtual bool isKnownNoSync() const = 0; +}; + +/// An abstract interface for all nonnull attributes. +struct AANonNull : public AbstractAttribute { + + /// See AbstractAttribute::AbstractAttribute(...). + AANonNull(Value &V, InformationCache &InfoCache) + : AbstractAttribute(V, InfoCache) {} + + /// See AbstractAttribute::AbstractAttribute(...). + AANonNull(Value *AssociatedVal, Value &AnchoredValue, + InformationCache &InfoCache) + : AbstractAttribute(AssociatedVal, AnchoredValue, InfoCache) {} + + /// Return true if we assume that the underlying value is nonnull. + virtual bool isAssumedNonNull() const = 0; + + /// Return true if we know that underlying value is nonnull. + virtual bool isKnownNonNull() const = 0; + + /// See AbastractState::getAttrKind(). + Attribute::AttrKind getAttrKind() const override { return ID; } + + /// The identifier used by the Attributor for this class of attributes. + static constexpr Attribute::AttrKind ID = Attribute::NonNull; +}; + +/// An abstract attribute for norecurse. +struct AANoRecurse : public AbstractAttribute { + + /// See AbstractAttribute::AbstractAttribute(...). + AANoRecurse(Value &V, InformationCache &InfoCache) + : AbstractAttribute(V, InfoCache) {} + + /// See AbstractAttribute::getAttrKind() + virtual Attribute::AttrKind getAttrKind() const override { + return Attribute::NoRecurse; + } + + /// Return true if "norecurse" is known. + virtual bool isKnownNoRecurse() const = 0; + + /// Return true if "norecurse" is assumed. + virtual bool isAssumedNoRecurse() const = 0; + + /// The identifier used by the Attributor for this class of attributes. + static constexpr Attribute::AttrKind ID = Attribute::NoRecurse; +}; + +/// An abstract attribute for willreturn. +struct AAWillReturn : public AbstractAttribute { + + /// See AbstractAttribute::AbstractAttribute(...). + AAWillReturn(Value &V, InformationCache &InfoCache) + : AbstractAttribute(V, InfoCache) {} + + /// See AbstractAttribute::getAttrKind() + virtual Attribute::AttrKind getAttrKind() const override { + return Attribute::WillReturn; + } + + /// Return true if "willreturn" is known. + virtual bool isKnownWillReturn() const = 0; + + /// Return true if "willreturn" is assumed. + virtual bool isAssumedWillReturn() const = 0; + + /// The identifier used by the Attributor for this class of attributes. + static constexpr Attribute::AttrKind ID = Attribute::WillReturn; +}; +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H diff --git a/include/llvm/Transforms/IPO/CalledValuePropagation.h b/include/llvm/Transforms/IPO/CalledValuePropagation.h index 352bdc7ac17f..c2626d0867b4 100644 --- a/include/llvm/Transforms/IPO/CalledValuePropagation.h +++ b/include/llvm/Transforms/IPO/CalledValuePropagation.h @@ -1,9 +1,8 @@ //===- CalledValuePropagation.h - Propagate called values -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/ConstantMerge.h b/include/llvm/Transforms/IPO/ConstantMerge.h index e04d3ae1a40e..12d38b5f58fa 100644 --- a/include/llvm/Transforms/IPO/ConstantMerge.h +++ b/include/llvm/Transforms/IPO/ConstantMerge.h @@ -1,9 +1,8 @@ //===- ConstantMerge.h - Merge duplicate global constants -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/CrossDSOCFI.h b/include/llvm/Transforms/IPO/CrossDSOCFI.h index 0979f5b79e86..8440df639729 100644 --- a/include/llvm/Transforms/IPO/CrossDSOCFI.h +++ b/include/llvm/Transforms/IPO/CrossDSOCFI.h @@ -1,9 +1,8 @@ //===-- CrossDSOCFI.cpp - Externalize this module's CFI checks --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/DeadArgumentElimination.h b/include/llvm/Transforms/IPO/DeadArgumentElimination.h index ba5666f20a9b..73797bc10017 100644 --- a/include/llvm/Transforms/IPO/DeadArgumentElimination.h +++ b/include/llvm/Transforms/IPO/DeadArgumentElimination.h @@ -1,9 +1,8 @@ //===- DeadArgumentElimination.h - Eliminate Dead Args ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/ElimAvailExtern.h b/include/llvm/Transforms/IPO/ElimAvailExtern.h index 94cb954fd2d5..92c319b3cce3 100644 --- a/include/llvm/Transforms/IPO/ElimAvailExtern.h +++ b/include/llvm/Transforms/IPO/ElimAvailExtern.h @@ -1,9 +1,8 @@ //===- ElimAvailExtern.h - Optimize Global Variables ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/ForceFunctionAttrs.h b/include/llvm/Transforms/IPO/ForceFunctionAttrs.h index ff8a6546f059..7379009b2592 100644 --- a/include/llvm/Transforms/IPO/ForceFunctionAttrs.h +++ b/include/llvm/Transforms/IPO/ForceFunctionAttrs.h @@ -1,9 +1,8 @@ //===-- ForceFunctionAttrs.h - Force function attrs for debugging ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/IPO/FunctionAttrs.h b/include/llvm/Transforms/IPO/FunctionAttrs.h index 901fed7a0fa4..ce61eea05c79 100644 --- a/include/llvm/Transforms/IPO/FunctionAttrs.h +++ b/include/llvm/Transforms/IPO/FunctionAttrs.h @@ -1,9 +1,8 @@ //===- FunctionAttrs.h - Compute function attributes ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/FunctionImport.h b/include/llvm/Transforms/IPO/FunctionImport.h index c2103b637266..bbf270c400af 100644 --- a/include/llvm/Transforms/IPO/FunctionImport.h +++ b/include/llvm/Transforms/IPO/FunctionImport.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/IPO/FunctionImport.h - ThinLTO importing -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/IPO/GlobalDCE.h b/include/llvm/Transforms/IPO/GlobalDCE.h index 7ca241f4645a..c434484d1ae3 100644 --- a/include/llvm/Transforms/IPO/GlobalDCE.h +++ b/include/llvm/Transforms/IPO/GlobalDCE.h @@ -1,9 +1,8 @@ //===-- GlobalDCE.h - DCE unreachable internal functions ------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/GlobalOpt.h b/include/llvm/Transforms/IPO/GlobalOpt.h index 5b4878604eab..48a861ff2cf8 100644 --- a/include/llvm/Transforms/IPO/GlobalOpt.h +++ b/include/llvm/Transforms/IPO/GlobalOpt.h @@ -1,9 +1,8 @@ //===- GlobalOpt.h - Optimize Global Variables ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/GlobalSplit.h b/include/llvm/Transforms/IPO/GlobalSplit.h index 56cefb7886fe..690b23a2d785 100644 --- a/include/llvm/Transforms/IPO/GlobalSplit.h +++ b/include/llvm/Transforms/IPO/GlobalSplit.h @@ -1,9 +1,8 @@ //===- GlobalSplit.h - global variable splitter -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/HotColdSplitting.h b/include/llvm/Transforms/IPO/HotColdSplitting.h index 57e9a9e69187..73668844590d 100644 --- a/include/llvm/Transforms/IPO/HotColdSplitting.h +++ b/include/llvm/Transforms/IPO/HotColdSplitting.h @@ -1,9 +1,8 @@ //===- HotColdSplitting.h ---- Outline Cold Regions -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 outlines cold regions to a separate function. diff --git a/include/llvm/Transforms/IPO/InferFunctionAttrs.h b/include/llvm/Transforms/IPO/InferFunctionAttrs.h index 54e1c243ae27..bb7907fb8ac8 100644 --- a/include/llvm/Transforms/IPO/InferFunctionAttrs.h +++ b/include/llvm/Transforms/IPO/InferFunctionAttrs.h @@ -1,9 +1,8 @@ //===-- InferFunctionAttrs.h - Infer implicit function attributes ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Transforms/IPO/Inliner.h b/include/llvm/Transforms/IPO/Inliner.h index 610e4500e4b1..8202b94d5a93 100644 --- a/include/llvm/Transforms/IPO/Inliner.h +++ b/include/llvm/Transforms/IPO/Inliner.h @@ -1,9 +1,8 @@ //===- Inliner.h - Inliner pass and infrastructure --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/IPO/Internalize.h b/include/llvm/Transforms/IPO/Internalize.h index 45d676d9f77b..6c1e19ef9fe4 100644 --- a/include/llvm/Transforms/IPO/Internalize.h +++ b/include/llvm/Transforms/IPO/Internalize.h @@ -1,9 +1,8 @@ //====- Internalize.h - Internalization API ---------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,11 +21,11 @@ #ifndef LLVM_TRANSFORMS_IPO_INTERNALIZE_H #define LLVM_TRANSFORMS_IPO_INTERNALIZE_H +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/PassManager.h" #include <functional> -#include <set> namespace llvm { class Module; @@ -45,11 +44,11 @@ class InternalizePass : public PassInfoMixin<InternalizePass> { /// Internalize GV if it is possible to do so, i.e. it is not externally /// visible and is not a member of an externally visible comdat. bool maybeInternalize(GlobalValue &GV, - const std::set<const Comdat *> &ExternalComdats); + const DenseSet<const Comdat *> &ExternalComdats); /// If GV is part of a comdat and is externally visible, keep track of its /// comdat so that we don't internalize any of its members. void checkComdatVisibility(GlobalValue &GV, - std::set<const Comdat *> &ExternalComdats); + DenseSet<const Comdat *> &ExternalComdats); public: InternalizePass(); diff --git a/include/llvm/Transforms/IPO/LowerTypeTests.h b/include/llvm/Transforms/IPO/LowerTypeTests.h index bc448386b63d..39b23f5957db 100644 --- a/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -1,9 +1,8 @@ //===- LowerTypeTests.h - type metadata lowering pass -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/PartialInlining.h b/include/llvm/Transforms/IPO/PartialInlining.h index ec6dd36dae06..3b8297d65987 100644 --- a/include/llvm/Transforms/IPO/PartialInlining.h +++ b/include/llvm/Transforms/IPO/PartialInlining.h @@ -1,9 +1,8 @@ //===- PartialInlining.h - Inline parts of functions ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 276306f686ff..63ff00afc2ae 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -1,9 +1,8 @@ // llvm/Transforms/IPO/PassManagerBuilder.h - Build Standard Pass -*- C++ -*-=// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -58,7 +57,7 @@ class PassManagerBase; /// ... class PassManagerBuilder { public: - /// Extensions are passed the builder itself (so they can see how it is + /// Extensions are passed to the builder itself (so they can see how it is /// configured) as well as the pass manager to add stuff to. typedef std::function<void(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM)> @@ -113,6 +112,16 @@ public: /// passes at the end of the main CallGraphSCC passes and before any /// function simplification passes run by CGPassManager. EP_CGSCCOptimizerLate, + + /// EP_FullLinkTimeOptimizationEarly - This extensions point allow adding + /// passes that + /// run at Link Time, before Full Link Time Optimization. + EP_FullLinkTimeOptimizationEarly, + + /// EP_FullLinkTimeOptimizationLast - This extensions point allow adding + /// passes that + /// run at Link Time, after Full Link Time Optimization. + EP_FullLinkTimeOptimizationLast, }; /// The Optimization Level - Specify the basic optimization level. @@ -143,13 +152,14 @@ public: const ModuleSummaryIndex *ImportSummary = nullptr; bool DisableTailCalls; - bool DisableUnitAtATime; bool DisableUnrollLoops; bool SLPVectorize; bool LoopVectorize; + bool LoopsInterleaved; bool RerollLoops; bool NewGVN; bool DisableGVNLoadPRE; + bool ForgetAllSCEVInLoopUnroll; bool VerifyInput; bool VerifyOutput; bool MergeFunctions; @@ -157,9 +167,15 @@ public: bool PrepareForThinLTO; bool PerformThinLTO; bool DivergentTarget; + unsigned LicmMssaOptCap; + unsigned LicmMssaNoAccForPromotionCap; /// Enable profile instrumentation pass. bool EnablePGOInstrGen; + /// Enable profile context sensitive instrumentation pass. + bool EnablePGOCSInstrGen; + /// Enable profile context sensitive profile use pass. + bool EnablePGOCSInstrUse; /// Profile data file name that the instrumentation will be written to. std::string PGOInstrGen; /// Path of the profile data file. @@ -186,7 +202,7 @@ private: void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const; void addLTOOptimizationPasses(legacy::PassManagerBase &PM); void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM); - void addPGOInstrPasses(legacy::PassManagerBase &MPM); + void addPGOInstrPasses(legacy::PassManagerBase &MPM, bool IsCS); void addFunctionSimplificationPasses(legacy::PassManagerBase &MPM); void addInstructionCombiningPass(legacy::PassManagerBase &MPM) const; diff --git a/include/llvm/Transforms/IPO/SCCP.h b/include/llvm/Transforms/IPO/SCCP.h index fdb7865fbac3..3c40d44ca9de 100644 --- a/include/llvm/Transforms/IPO/SCCP.h +++ b/include/llvm/Transforms/IPO/SCCP.h @@ -1,9 +1,8 @@ //===- SCCP.h - Sparse Conditional Constant Propagation ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/SampleProfile.h b/include/llvm/Transforms/IPO/SampleProfile.h index af4a933ec1f6..a5ad44551bf6 100644 --- a/include/llvm/Transforms/IPO/SampleProfile.h +++ b/include/llvm/Transforms/IPO/SampleProfile.h @@ -1,9 +1,8 @@ //===- SampleProfile.h - SamplePGO pass ---------- --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/StripDeadPrototypes.h b/include/llvm/Transforms/IPO/StripDeadPrototypes.h index 5a05cd75c9d5..f4a15c36afc9 100644 --- a/include/llvm/Transforms/IPO/StripDeadPrototypes.h +++ b/include/llvm/Transforms/IPO/StripDeadPrototypes.h @@ -1,9 +1,8 @@ //===-- StripDeadPrototypes.h - Remove unused function declarations -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h b/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h index bf04bbfe92d8..7acb922b37e1 100644 --- a/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h +++ b/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h @@ -1,9 +1,8 @@ //===- ThinLTOBitcodeWriter.h - Bitcode writing pass for ThinLTO ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/include/llvm/Transforms/IPO/WholeProgramDevirt.h index bf2c79b0751e..509fcc867060 100644 --- a/include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ b/include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -1,9 +1,8 @@ //===- WholeProgramDevirt.h - Whole-program devirt pass ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h index ab25fe08553a..8894d96e591f 100644 --- a/include/llvm/Transforms/InstCombine/InstCombine.h +++ b/include/llvm/Transforms/InstCombine/InstCombine.h @@ -1,9 +1,8 @@ //===- InstCombine.h - InstCombine pass -------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h index f860b4b86555..6c33bdbafbd2 100644 --- a/include/llvm/Transforms/InstCombine/InstCombineWorklist.h +++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h @@ -1,9 +1,8 @@ //===- InstCombineWorklist.h - Worklist for InstCombine pass ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 017cab0a7750..8b70d2926ae9 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation.h - Instrumentation passes ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -88,10 +87,14 @@ struct GCOVOptions { ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()); -// PGO Instrumention -ModulePass *createPGOInstrumentationGenLegacyPass(); +// PGO Instrumention. Parameter IsCS indicates if this is the context senstive +// instrumentation. +ModulePass *createPGOInstrumentationGenLegacyPass(bool IsCS = false); ModulePass * -createPGOInstrumentationUseLegacyPass(StringRef Filename = StringRef("")); +createPGOInstrumentationUseLegacyPass(StringRef Filename = StringRef(""), + bool IsCS = false); +ModulePass *createPGOInstrumentationGenCreateVarLegacyPass( + StringRef CSInstrName = StringRef("")); ModulePass *createPGOIndirectCallPromotionLegacyPass(bool InLTO = false, bool SamplePGO = false); FunctionPass *createPGOMemOPSizeOptLegacyPass(); @@ -133,48 +136,27 @@ struct InstrProfOptions { // Use atomic profile counter increments. bool Atomic = false; + // Use BFI to guide register promotion + bool UseBFIInPromotion = false; + // Name of the profile file to use as output std::string InstrProfileOutput; InstrProfOptions() = default; }; -/// Insert frontend instrumentation based profiling. +/// Insert frontend instrumentation based profiling. Parameter IsCS indicates if +// this is the context senstive instrumentation. ModulePass *createInstrProfilingLegacyPass( - const InstrProfOptions &Options = InstrProfOptions()); + const InstrProfOptions &Options = InstrProfOptions(), bool IsCS = false); -// Insert AddressSanitizer (address sanity checking) instrumentation -FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false, - bool Recover = false, - bool UseAfterScope = false); -ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false, - bool Recover = false, - bool UseGlobalsGC = true, - bool UseOdrIndicator = true); - -FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false, - bool Recover = false); +ModulePass *createInstrOrderFilePass(); // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation ModulePass *createDataFlowSanitizerPass( const std::vector<std::string> &ABIListFiles = std::vector<std::string>(), void *(*getArgTLS)() = nullptr, void *(*getRetValTLS)() = nullptr); -// Options for EfficiencySanitizer sub-tools. -struct EfficiencySanitizerOptions { - enum Type { - ESAN_None = 0, - ESAN_CacheFrag, - ESAN_WorkingSet, - } ToolType = ESAN_None; - - EfficiencySanitizerOptions() = default; -}; - -// Insert EfficiencySanitizer instrumentation. -ModulePass *createEfficiencySanitizerPass( - const EfficiencySanitizerOptions &Options = EfficiencySanitizerOptions()); - // Options for sanitizer coverage instrumentation. struct SanitizerCoverageOptions { enum Type { diff --git a/include/llvm/Transforms/Instrumentation/AddressSanitizer.h b/include/llvm/Transforms/Instrumentation/AddressSanitizer.h new file mode 100644 index 000000000000..40007a9b8c53 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation/AddressSanitizer.h @@ -0,0 +1,143 @@ +//===--------- Definition of the AddressSanitizer class ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AddressSanitizer class which is a port of the legacy +// AddressSanitizer pass to use the new PassManager infrastructure. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERPASS_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_ADDRESSSANITIZERPASS_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Frontend-provided metadata for source location. +struct LocationMetadata { + StringRef Filename; + int LineNo = 0; + int ColumnNo = 0; + + LocationMetadata() = default; + + bool empty() const { return Filename.empty(); } + void parse(MDNode *MDN); +}; + +/// Frontend-provided metadata for global variables. +class GlobalsMetadata { +public: + struct Entry { + LocationMetadata SourceLoc; + StringRef Name; + bool IsDynInit = false; + bool IsBlacklisted = false; + + Entry() = default; + }; + + /// Create a default uninitialized GlobalsMetadata instance. + GlobalsMetadata() = default; + + /// Create an initialized GlobalsMetadata instance. + GlobalsMetadata(Module &M); + + /// Returns metadata entry for a given global. + Entry get(GlobalVariable *G) const { + auto Pos = Entries.find(G); + return (Pos != Entries.end()) ? Pos->second : Entry(); + } + + /// Handle invalidation from the pass manager. + /// These results are never invalidated. + bool invalidate(Module &, const PreservedAnalyses &, + ModuleAnalysisManager::Invalidator &) { + return false; + } + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &) { + return false; + } + +private: + DenseMap<GlobalVariable *, Entry> Entries; +}; + +/// The ASanGlobalsMetadataAnalysis initializes and returns a GlobalsMetadata +/// object. More specifically, ASan requires looking at all globals registered +/// in 'llvm.asan.globals' before running, which only depends on reading module +/// level metadata. This analysis is required to run before running the +/// AddressSanitizerPass since it collects that metadata. +/// The legacy pass manager equivalent of this is ASanGlobalsMetadataLegacyPass. +class ASanGlobalsMetadataAnalysis + : public AnalysisInfoMixin<ASanGlobalsMetadataAnalysis> { +public: + using Result = GlobalsMetadata; + + Result run(Module &, ModuleAnalysisManager &); + +private: + friend AnalysisInfoMixin<ASanGlobalsMetadataAnalysis>; + static AnalysisKey Key; +}; + +/// Public interface to the address sanitizer pass for instrumenting code to +/// check for various memory errors at runtime. +/// +/// The sanitizer itself is a function pass that works by inserting various +/// calls to the ASan runtime library functions. The runtime library essentially +/// replaces malloc() and free() with custom implementations that allow regions +/// surrounding requested memory to be checked for invalid accesses. +class AddressSanitizerPass : public PassInfoMixin<AddressSanitizerPass> { +public: + explicit AddressSanitizerPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseAfterScope; +}; + +/// Public interface to the address sanitizer module pass for instrumenting code +/// to check for various memory errors. +/// +/// This adds 'asan.module_ctor' to 'llvm.global_ctors'. This pass may also +/// run intependently of the function address sanitizer. +class ModuleAddressSanitizerPass + : public PassInfoMixin<ModuleAddressSanitizerPass> { +public: + explicit ModuleAddressSanitizerPass(bool CompileKernel = false, + bool Recover = false, + bool UseGlobalGC = true, + bool UseOdrIndicator = false); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + bool CompileKernel; + bool Recover; + bool UseGlobalGC; + bool UseOdrIndicator; +}; + +// Insert AddressSanitizer (address sanity checking) instrumentation +FunctionPass *createAddressSanitizerFunctionPass(bool CompileKernel = false, + bool Recover = false, + bool UseAfterScope = false); +ModulePass *createModuleAddressSanitizerLegacyPassPass( + bool CompileKernel = false, bool Recover = false, bool UseGlobalsGC = true, + bool UseOdrIndicator = true); + +} // namespace llvm + +#endif diff --git a/include/llvm/Transforms/Instrumentation/BoundsChecking.h b/include/llvm/Transforms/Instrumentation/BoundsChecking.h index 3d4f62c121c2..120c6a8fb09f 100644 --- a/include/llvm/Transforms/Instrumentation/BoundsChecking.h +++ b/include/llvm/Transforms/Instrumentation/BoundsChecking.h @@ -1,9 +1,8 @@ //===- BoundsChecking.h - Bounds checking instrumentation -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Instrumentation/CGProfile.h b/include/llvm/Transforms/Instrumentation/CGProfile.h index c06c1a28715e..28fd3804dec9 100644 --- a/include/llvm/Transforms/Instrumentation/CGProfile.h +++ b/include/llvm/Transforms/Instrumentation/CGProfile.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation/CGProfile.h -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Instrumentation/ControlHeightReduction.h b/include/llvm/Transforms/Instrumentation/ControlHeightReduction.h index 460342d1631b..18b428582046 100644 --- a/include/llvm/Transforms/Instrumentation/ControlHeightReduction.h +++ b/include/llvm/Transforms/Instrumentation/ControlHeightReduction.h @@ -1,9 +1,8 @@ //===- ControlHeightReduction.h - Control Height Reduction ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Instrumentation/GCOVProfiler.h b/include/llvm/Transforms/Instrumentation/GCOVProfiler.h index dd55fbe29eed..b3971e49754e 100644 --- a/include/llvm/Transforms/Instrumentation/GCOVProfiler.h +++ b/include/llvm/Transforms/Instrumentation/GCOVProfiler.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation/GCOVProfiler.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h b/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h new file mode 100644 index 000000000000..e3104eeb1d36 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation/HWAddressSanitizer.h @@ -0,0 +1,41 @@ +//===--------- Definition of the HWAddressSanitizer class -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Hardware AddressSanitizer class which is a port of the +// legacy HWAddressSanitizer pass to use the new PassManager infrastructure. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZERPASS_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_HWADDRESSSANITIZERPASS_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// This is a public interface to the hardware address sanitizer pass for +/// instrumenting code to check for various memory errors at runtime, similar to +/// AddressSanitizer but based on partial hardware assistance. +class HWAddressSanitizerPass : public PassInfoMixin<HWAddressSanitizerPass> { +public: + explicit HWAddressSanitizerPass(bool CompileKernel = false, + bool Recover = false); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + +private: + bool CompileKernel; + bool Recover; +}; + +FunctionPass *createHWAddressSanitizerLegacyPassPass(bool CompileKernel = false, + bool Recover = false); + +} // namespace llvm + +#endif diff --git a/include/llvm/Transforms/Instrumentation/InstrOrderFile.h b/include/llvm/Transforms/Instrumentation/InstrOrderFile.h new file mode 100644 index 000000000000..f1245d8fd785 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation/InstrOrderFile.h @@ -0,0 +1,28 @@ +//===- InstrOrderFile.h ---- Late IR instrumentation for order file ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRORDERFILE_H +#define LLVM_TRANSFORMS_INSTRORDERFILE_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +class Module; + +/// The instrumentation pass for recording function order. +class InstrOrderFilePass : public PassInfoMixin<InstrOrderFilePass> { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_INSTRORDERFILE_H diff --git a/include/llvm/Transforms/Instrumentation/InstrProfiling.h b/include/llvm/Transforms/Instrumentation/InstrProfiling.h index 13fb3db4ae6f..8f76d4a1ce55 100644 --- a/include/llvm/Transforms/Instrumentation/InstrProfiling.h +++ b/include/llvm/Transforms/Instrumentation/InstrProfiling.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation/InstrProfiling.h --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -35,8 +34,9 @@ using LoadStorePair = std::pair<Instruction *, Instruction *>; /// instrumentation pass. class InstrProfiling : public PassInfoMixin<InstrProfiling> { public: - InstrProfiling() = default; - InstrProfiling(const InstrProfOptions &Options) : Options(Options) {} + InstrProfiling() : IsCS(false) {} + InstrProfiling(const InstrProfOptions &Options, bool IsCS = false) + : Options(Options), IsCS(IsCS) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); bool run(Module &M, const TargetLibraryInfo &TLI); @@ -61,6 +61,9 @@ private: GlobalVariable *NamesVar; size_t NamesSize; + // Is this lowering for the context-sensitive instrumentation. + bool IsCS; + // vector of counter load/store pairs to be register promoted. std::vector<LoadStorePair> PromotionCandidates; diff --git a/include/llvm/Transforms/Instrumentation/MemorySanitizer.h b/include/llvm/Transforms/Instrumentation/MemorySanitizer.h index 54f0e2f78230..0739d9e58a61 100644 --- a/include/llvm/Transforms/Instrumentation/MemorySanitizer.h +++ b/include/llvm/Transforms/Instrumentation/MemorySanitizer.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation/MemorySanitizer.h - MSan Pass -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -19,10 +18,18 @@ namespace llvm { +struct MemorySanitizerOptions { + MemorySanitizerOptions() = default; + MemorySanitizerOptions(int TrackOrigins, bool Recover, bool Kernel) + : TrackOrigins(TrackOrigins), Recover(Recover), Kernel(Kernel) {} + int TrackOrigins = 0; + bool Recover = false; + bool Kernel = false; +}; + // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0, - bool Recover = false, - bool EnableKmsan = false); +FunctionPass * +createMemorySanitizerLegacyPassPass(MemorySanitizerOptions Options = {}); /// A function pass for msan instrumentation. /// @@ -31,17 +38,12 @@ FunctionPass *createMemorySanitizerLegacyPassPass(int TrackOrigins = 0, /// yet, the pass inserts the declarations. Otherwise the existing globals are /// used. struct MemorySanitizerPass : public PassInfoMixin<MemorySanitizerPass> { - MemorySanitizerPass(int TrackOrigins = 0, bool Recover = false, - bool EnableKmsan = false) - : TrackOrigins(TrackOrigins), Recover(Recover), EnableKmsan(EnableKmsan) { - } + MemorySanitizerPass(MemorySanitizerOptions Options) : Options(Options) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); private: - int TrackOrigins; - bool Recover; - bool EnableKmsan; + MemorySanitizerOptions Options; }; } diff --git a/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h b/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h index fdc5df68a669..21cf291d82d1 100644 --- a/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h +++ b/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h @@ -1,9 +1,8 @@ //===- Transforms/Instrumentation/PGOInstrumentation.h ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -28,22 +27,46 @@ class Instruction; class Module; /// The instrumentation (profile-instr-gen) pass for IR based PGO. +// We use this pass to create COMDAT profile variables for context +// sensitive PGO (CSPGO). The reason to have a pass for this is CSPGO +// can be run after LTO/ThinLTO linking. Lld linker needs to see +// all the COMDAT variables before linking. So we have this pass +// always run before linking for CSPGO. +class PGOInstrumentationGenCreateVar + : public PassInfoMixin<PGOInstrumentationGenCreateVar> { +public: + PGOInstrumentationGenCreateVar(std::string CSInstrName = "") + : CSInstrName(CSInstrName) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + std::string CSInstrName; +}; + +/// The instrumentation (profile-instr-gen) pass for IR based PGO. class PGOInstrumentationGen : public PassInfoMixin<PGOInstrumentationGen> { public: + PGOInstrumentationGen(bool IsCS = false) : IsCS(IsCS) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + // If this is a context sensitive instrumentation. + bool IsCS; }; /// The profile annotation (profile-instr-use) pass for IR based PGO. class PGOInstrumentationUse : public PassInfoMixin<PGOInstrumentationUse> { public: PGOInstrumentationUse(std::string Filename = "", - std::string RemappingFilename = ""); + std::string RemappingFilename = "", bool IsCS = false); PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); private: std::string ProfileFileName; std::string ProfileRemappingFileName; + // If this is a context sensitive instrumentation. + bool IsCS; }; /// The indirect function call promotion pass. diff --git a/include/llvm/Transforms/Instrumentation/PoisonChecking.h b/include/llvm/Transforms/Instrumentation/PoisonChecking.h new file mode 100644 index 000000000000..606d3c255359 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation/PoisonChecking.h @@ -0,0 +1,25 @@ +//===- PoisonChecking.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_TRANSFORMS_INSTRUMENTATION_POISON_CHECKING_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_POISON_CHECKING_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct PoisonCheckingPass : public PassInfoMixin<PoisonCheckingPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} + + +#endif // LLVM_TRANSFORMS_INSTRUMENTATION_POISON_CHECKING_H diff --git a/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h b/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h index 701e2e6ec89e..b4e7d9924ff6 100644 --- a/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h +++ b/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h @@ -1,9 +1,8 @@ -//===- Transforms/Instrumentation/MemorySanitizer.h - TSan Pass -----------===// +//===- Transforms/Instrumentation/ThreadSanitizer.h - TSan Pass -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/ObjCARC.h b/include/llvm/Transforms/ObjCARC.h index 1897adc2ffbf..2f114c75e2e2 100644 --- a/include/llvm/Transforms/ObjCARC.h +++ b/include/llvm/Transforms/ObjCARC.h @@ -1,9 +1,8 @@ //===-- ObjCARC.h - ObjCARC Scalar Transformations --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 8fcf9296ba47..f9360b5ee2c8 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -1,9 +1,8 @@ //===-- Scalar.h - Scalar Transformations -----------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -138,6 +137,8 @@ Pass *createIndVarSimplifyPass(); // LICM - This pass is a loop invariant code motion and memory promotion pass. // Pass *createLICMPass(); +Pass *createLICMPass(unsigned LicmMssaOptCap, + unsigned LicmMssaNoAccForPromotionCap); //===----------------------------------------------------------------------===// // @@ -184,11 +185,13 @@ Pass *createLoopInstSimplifyPass(); // LoopUnroll - This pass is a simple loop unrolling pass. // Pass *createLoopUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, - int Threshold = -1, int Count = -1, - int AllowPartial = -1, int Runtime = -1, - int UpperBound = -1, int AllowPeeling = -1); + bool ForgetAllSCEV = false, int Threshold = -1, + int Count = -1, int AllowPartial = -1, + int Runtime = -1, int UpperBound = -1, + int AllowPeeling = -1); // Create an unrolling pass for full unrolling that uses exact trip count only. -Pass *createSimpleLoopUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false); +Pass *createSimpleLoopUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, + bool ForgetAllSCEV = false); //===----------------------------------------------------------------------===// // @@ -360,9 +363,15 @@ Pass *createLowerGuardIntrinsicPass(); //===----------------------------------------------------------------------===// // +// LowerWidenableCondition - Lower widenable condition to i1 true. +// +Pass *createLowerWidenableConditionPass(); + +//===----------------------------------------------------------------------===// +// // MergeICmps - Merge integer comparison chains into a memcmp // -Pass *createMergeICmpsPass(); +Pass *createMergeICmpsLegacyPass(); //===----------------------------------------------------------------------===// // @@ -374,9 +383,10 @@ Pass *createCorrelatedValuePropagationPass(); // // InferAddressSpaces - Modify users of addrspacecast instructions with values // in the source address space if using the destination address space is slower -// on the target. +// on the target. If AddressSpace is left to its default value, it will be +// obtained from the TargetTransformInfo. // -FunctionPass *createInferAddressSpacesPass(); +FunctionPass *createInferAddressSpacesPass(unsigned AddressSpace = ~0u); extern char &InferAddressSpacesID; //===----------------------------------------------------------------------===// @@ -453,6 +463,12 @@ FunctionPass *createLoopDistributePass(); //===----------------------------------------------------------------------===// // +// LoopFuse - Fuse loops. +// +FunctionPass *createLoopFusePass(); + +//===----------------------------------------------------------------------===// +// // LoopLoadElimination - Perform loop-aware load elimination. // FunctionPass *createLoopLoadEliminationPass(); diff --git a/include/llvm/Transforms/Scalar/ADCE.h b/include/llvm/Transforms/Scalar/ADCE.h index f98af62c1a76..7d8b7ae68c00 100644 --- a/include/llvm/Transforms/Scalar/ADCE.h +++ b/include/llvm/Transforms/Scalar/ADCE.h @@ -1,9 +1,8 @@ //===- ADCE.h - Aggressive dead code elimination ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h b/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h index 61975036e9ff..fb1687e1ac5d 100644 --- a/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h +++ b/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h @@ -1,9 +1,8 @@ //===---- AlignmentFromAssumptions.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/BDCE.h b/include/llvm/Transforms/Scalar/BDCE.h index d7d2730a8033..996622bccdba 100644 --- a/include/llvm/Transforms/Scalar/BDCE.h +++ b/include/llvm/Transforms/Scalar/BDCE.h @@ -1,9 +1,8 @@ //===---- BDCE.cpp - Bit-tracking dead code elimination ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/CallSiteSplitting.h b/include/llvm/Transforms/Scalar/CallSiteSplitting.h index b2ca2a1c09ae..b6055639e8a8 100644 --- a/include/llvm/Transforms/Scalar/CallSiteSplitting.h +++ b/include/llvm/Transforms/Scalar/CallSiteSplitting.h @@ -1,9 +1,8 @@ //===- CallSiteSplitting..h - Callsite Splitting ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/ConstantHoisting.h b/include/llvm/Transforms/Scalar/ConstantHoisting.h index ba32e122fa10..6b0fc9c1dd07 100644 --- a/include/llvm/Transforms/Scalar/ConstantHoisting.h +++ b/include/llvm/Transforms/Scalar/ConstantHoisting.h @@ -1,9 +1,8 @@ //==- ConstantHoisting.h - Prepare code for expensive constants --*- C++ -*-==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -56,6 +55,7 @@ class DominatorTree; class Function; class GlobalVariable; class Instruction; +class ProfileSummaryInfo; class TargetTransformInfo; /// A private "module" namespace for types and utilities used by @@ -125,9 +125,10 @@ public: // Glue for old PM. bool runImpl(Function &F, TargetTransformInfo &TTI, DominatorTree &DT, - BlockFrequencyInfo *BFI, BasicBlock &Entry); + BlockFrequencyInfo *BFI, BasicBlock &Entry, + ProfileSummaryInfo *PSI); - void releaseMemory() { + void cleanup() { ClonedCastMap.clear(); ConstIntCandVec.clear(); for (auto MapEntry : ConstGEPCandMap) @@ -149,6 +150,7 @@ private: LLVMContext *Ctx; const DataLayout *DL; BasicBlock *Entry; + ProfileSummaryInfo *PSI; /// Keeps track of constant candidates found in the function. using ConstCandVecType = std::vector<consthoist::ConstantCandidate>; diff --git a/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h b/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h index 20930699b557..25795de5d951 100644 --- a/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h +++ b/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h @@ -1,9 +1,8 @@ //===- CorrelatedValuePropagation.h -----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/DCE.h b/include/llvm/Transforms/Scalar/DCE.h index 273346cf81d9..974e4b20d152 100644 --- a/include/llvm/Transforms/Scalar/DCE.h +++ b/include/llvm/Transforms/Scalar/DCE.h @@ -1,9 +1,8 @@ //===- DCE.h - Dead code elimination ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/DeadStoreElimination.h b/include/llvm/Transforms/Scalar/DeadStoreElimination.h index cfeb21814232..b66b0de90c79 100644 --- a/include/llvm/Transforms/Scalar/DeadStoreElimination.h +++ b/include/llvm/Transforms/Scalar/DeadStoreElimination.h @@ -1,9 +1,8 @@ //===- DeadStoreElimination.h - Fast Dead Store Elimination -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/DivRemPairs.h b/include/llvm/Transforms/Scalar/DivRemPairs.h index 0a4346f33b12..7401e02cb4ab 100644 --- a/include/llvm/Transforms/Scalar/DivRemPairs.h +++ b/include/llvm/Transforms/Scalar/DivRemPairs.h @@ -1,9 +1,8 @@ //===- DivRemPairs.h - Hoist/decompose integer division and remainder -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/EarlyCSE.h b/include/llvm/Transforms/Scalar/EarlyCSE.h index faf03a4ec489..1e7fd71dcbf4 100644 --- a/include/llvm/Transforms/Scalar/EarlyCSE.h +++ b/include/llvm/Transforms/Scalar/EarlyCSE.h @@ -1,9 +1,8 @@ //===- EarlyCSE.h - Simple and fast CSE pass --------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/Float2Int.h b/include/llvm/Transforms/Scalar/Float2Int.h index 206ee980109b..06aeb8322527 100644 --- a/include/llvm/Transforms/Scalar/Float2Int.h +++ b/include/llvm/Transforms/Scalar/Float2Int.h @@ -1,9 +1,8 @@ //===-- Float2Int.h - Demote floating point ops to work on integers -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/GVN.h b/include/llvm/Transforms/Scalar/GVN.h index 9827678b89f2..9fe00a9e7f2d 100644 --- a/include/llvm/Transforms/Scalar/GVN.h +++ b/include/llvm/Transforms/Scalar/GVN.h @@ -1,9 +1,8 @@ //===- GVN.h - Eliminate redundant values and loads -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/GVNExpression.h b/include/llvm/Transforms/Scalar/GVNExpression.h index 8b346969b1e9..3dc4515f85a1 100644 --- a/include/llvm/Transforms/Scalar/GVNExpression.h +++ b/include/llvm/Transforms/Scalar/GVNExpression.h @@ -1,9 +1,8 @@ //===- GVNExpression.h - GVN Expression classes -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/GuardWidening.h b/include/llvm/Transforms/Scalar/GuardWidening.h index 2bc0940ac715..06dc9ac97bec 100644 --- a/include/llvm/Transforms/Scalar/GuardWidening.h +++ b/include/llvm/Transforms/Scalar/GuardWidening.h @@ -1,9 +1,8 @@ //===- GuardWidening.h - ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -17,7 +16,9 @@ #ifndef LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H #define LLVM_TRANSFORMS_SCALAR_GUARD_WIDENING_H +#include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { @@ -25,6 +26,8 @@ class Function; struct GuardWideningPass : public PassInfoMixin<GuardWideningPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } diff --git a/include/llvm/Transforms/Scalar/IVUsersPrinter.h b/include/llvm/Transforms/Scalar/IVUsersPrinter.h index fad00d86a95f..a1f20d9ca983 100644 --- a/include/llvm/Transforms/Scalar/IVUsersPrinter.h +++ b/include/llvm/Transforms/Scalar/IVUsersPrinter.h @@ -1,9 +1,8 @@ //===- IVUsersPrinter.h - Induction Variable Users Printing -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/IndVarSimplify.h b/include/llvm/Transforms/Scalar/IndVarSimplify.h index e321c8fc6e9c..3c20537ab76a 100644 --- a/include/llvm/Transforms/Scalar/IndVarSimplify.h +++ b/include/llvm/Transforms/Scalar/IndVarSimplify.h @@ -1,9 +1,8 @@ //===- IndVarSimplify.h - Induction Variable Simplification -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h b/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h index 311c549b8326..b1e700714e51 100644 --- a/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h +++ b/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h @@ -1,9 +1,8 @@ //===- InductiveRangeCheckElimination.h - IRCE ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/InstSimplifyPass.h b/include/llvm/Transforms/Scalar/InstSimplifyPass.h index da79a13eb7cf..0c30b6260536 100644 --- a/include/llvm/Transforms/Scalar/InstSimplifyPass.h +++ b/include/llvm/Transforms/Scalar/InstSimplifyPass.h @@ -1,9 +1,8 @@ //===- InstSimplifyPass.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/JumpThreading.h b/include/llvm/Transforms/Scalar/JumpThreading.h index 9894345645a1..0464d40c45e6 100644 --- a/include/llvm/Transforms/Scalar/JumpThreading.h +++ b/include/llvm/Transforms/Scalar/JumpThreading.h @@ -1,9 +1,8 @@ //===- JumpThreading.h - thread control through conditional BBs -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -23,7 +22,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/BranchProbabilityInfo.h" -#include "llvm/IR/DomTreeUpdater.h" +#include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/IR/ValueHandle.h" #include <memory> #include <utility> diff --git a/include/llvm/Transforms/Scalar/LICM.h b/include/llvm/Transforms/Scalar/LICM.h index 68ad190c7647..f0ea928abd49 100644 --- a/include/llvm/Transforms/Scalar/LICM.h +++ b/include/llvm/Transforms/Scalar/LICM.h @@ -1,9 +1,8 @@ //===- LICM.h - Loop Invariant Code Motion Pass -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -39,9 +38,21 @@ namespace llvm { +extern cl::opt<unsigned> SetLicmMssaOptCap; +extern cl::opt<unsigned> SetLicmMssaNoAccForPromotionCap; + /// Performs Loop Invariant Code Motion Pass. class LICMPass : public PassInfoMixin<LICMPass> { + unsigned LicmMssaOptCap; + unsigned LicmMssaNoAccForPromotionCap; + public: + LICMPass() + : LicmMssaOptCap(SetLicmMssaOptCap), + LicmMssaNoAccForPromotionCap(SetLicmMssaNoAccForPromotionCap) {} + LICMPass(unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap) + : LicmMssaOptCap(LicmMssaOptCap), + LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap) {} PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); }; diff --git a/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h b/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h index e1b33799578b..3f250fc1ce8c 100644 --- a/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h +++ b/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h @@ -1,9 +1,8 @@ //===- llvm/Analysis/LoopAccessAnalysisPrinter.h ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/LoopDataPrefetch.h b/include/llvm/Transforms/Scalar/LoopDataPrefetch.h index e1ad67ac6fff..9ebd5984cea9 100644 --- a/include/llvm/Transforms/Scalar/LoopDataPrefetch.h +++ b/include/llvm/Transforms/Scalar/LoopDataPrefetch.h @@ -1,10 +1,9 @@ //===-------- LoopDataPrefetch.h - Loop Data Prefetching Pass ---*- C++ -*-===// // // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/LoopDeletion.h b/include/llvm/Transforms/Scalar/LoopDeletion.h index 7b8cb1e115c9..557616e2e6ba 100644 --- a/include/llvm/Transforms/Scalar/LoopDeletion.h +++ b/include/llvm/Transforms/Scalar/LoopDeletion.h @@ -1,9 +1,8 @@ //===- LoopDeletion.h - Loop Deletion ---------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopDistribute.h b/include/llvm/Transforms/Scalar/LoopDistribute.h index 2bf1c9d696d5..1a82176490c5 100644 --- a/include/llvm/Transforms/Scalar/LoopDistribute.h +++ b/include/llvm/Transforms/Scalar/LoopDistribute.h @@ -1,9 +1,8 @@ //===- LoopDistribute.cpp - Loop Distribution Pass --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopFuse.h b/include/llvm/Transforms/Scalar/LoopFuse.h new file mode 100644 index 000000000000..d3a02db6bd28 --- /dev/null +++ b/include/llvm/Transforms/Scalar/LoopFuse.h @@ -0,0 +1,30 @@ +//===- LoopFuse.h - Loop Fusion Pass ----------------------------*- 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 the Loop Fusion pass. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOOPFUSE_H +#define LLVM_TRANSFORMS_SCALAR_LOOPFUSE_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Function; + +class LoopFusePass : public PassInfoMixin<LoopFusePass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_LOOPFUSE_H diff --git a/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h index 7added8d2c61..d2fff8bb5743 100644 --- a/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h +++ b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h @@ -1,9 +1,8 @@ //===- LoopIdiomRecognize.h - Loop Idiom Recognize Pass ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopInstSimplify.h b/include/llvm/Transforms/Scalar/LoopInstSimplify.h index 04dc79c3fa57..f6e86d11ed95 100644 --- a/include/llvm/Transforms/Scalar/LoopInstSimplify.h +++ b/include/llvm/Transforms/Scalar/LoopInstSimplify.h @@ -1,9 +1,8 @@ //===- LoopInstSimplify.h - Loop Inst Simplify Pass -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopLoadElimination.h b/include/llvm/Transforms/Scalar/LoopLoadElimination.h index b0514a4a7c98..65b9aabb8f51 100644 --- a/include/llvm/Transforms/Scalar/LoopLoadElimination.h +++ b/include/llvm/Transforms/Scalar/LoopLoadElimination.h @@ -1,9 +1,8 @@ //===- LoopLoadElimination.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopPassManager.h b/include/llvm/Transforms/Scalar/LoopPassManager.h index 46ebb74c413c..61ec58585fd0 100644 --- a/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -1,9 +1,8 @@ //===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/LoopPredication.h b/include/llvm/Transforms/Scalar/LoopPredication.h index 57398bdb6bd1..252daafab7a3 100644 --- a/include/llvm/Transforms/Scalar/LoopPredication.h +++ b/include/llvm/Transforms/Scalar/LoopPredication.h @@ -1,9 +1,8 @@ //===- LoopPredication.h - Guard based loop predication pass ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopRotation.h b/include/llvm/Transforms/Scalar/LoopRotation.h index ea8d5618e6f7..254e6072906a 100644 --- a/include/llvm/Transforms/Scalar/LoopRotation.h +++ b/include/llvm/Transforms/Scalar/LoopRotation.h @@ -1,9 +1,8 @@ //===- LoopRotation.h - Loop Rotation -------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h index 7628c7413eac..2d718592aef5 100644 --- a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h +++ b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h @@ -1,9 +1,8 @@ //===- LoopSimplifyCFG.cpp - Loop CFG Simplification Pass -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopSink.h b/include/llvm/Transforms/Scalar/LoopSink.h index 371a7c8d2c44..234c48cbebc5 100644 --- a/include/llvm/Transforms/Scalar/LoopSink.h +++ b/include/llvm/Transforms/Scalar/LoopSink.h @@ -1,9 +1,8 @@ //===- LoopSink.h - Loop Sink Pass ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopStrengthReduce.h b/include/llvm/Transforms/Scalar/LoopStrengthReduce.h index 62c038a3857d..5cf805bc4939 100644 --- a/include/llvm/Transforms/Scalar/LoopStrengthReduce.h +++ b/include/llvm/Transforms/Scalar/LoopStrengthReduce.h @@ -1,9 +1,8 @@ //===- LoopStrengthReduce.h - Loop Strength Reduce Pass ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h b/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h index fc69aa361059..7920269b0fb2 100644 --- a/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h +++ b/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h @@ -1,9 +1,8 @@ //===- LoopUnrollAndJamPass.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/LoopUnrollPass.h b/include/llvm/Transforms/Scalar/LoopUnrollPass.h index e38e983cc9eb..a84d889a83ad 100644 --- a/include/llvm/Transforms/Scalar/LoopUnrollPass.h +++ b/include/llvm/Transforms/Scalar/LoopUnrollPass.h @@ -1,9 +1,8 @@ //===- LoopUnrollPass.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// @@ -16,6 +15,8 @@ namespace llvm { +extern cl::opt<bool> ForgetSCEVInLoopUnroll; + class Function; class Loop; class LPMUpdater; @@ -29,9 +30,16 @@ class LoopFullUnrollPass : public PassInfoMixin<LoopFullUnrollPass> { /// metadata are considered. All other loops are skipped. const bool OnlyWhenForced; + /// If true, forget all loops when unrolling. If false, forget top-most loop + /// of the currently processed loops, which removes one entry at a time from + /// the internal SCEV records. For large loops, the former is faster. + const bool ForgetSCEV; + public: - explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false) - : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced) {} + explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, + bool ForgetSCEV = false) + : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), + ForgetSCEV(ForgetSCEV) {} PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); @@ -61,8 +69,15 @@ struct LoopUnrollOptions { /// metadata are considered. All other loops are skipped. bool OnlyWhenForced; - LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false) - : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced) {} + /// If true, forget all loops when unrolling. If false, forget top-most loop + /// of the currently processed loops, which removes one entry at a time from + /// the internal SCEV records. For large loops, the former is faster. + const bool ForgetSCEV; + + LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false, + bool ForgetSCEV = false) + : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), + ForgetSCEV(ForgetSCEV) {} /// Enables or disables partial unrolling. When disabled only full unrolling /// is allowed. diff --git a/include/llvm/Transforms/Scalar/LowerAtomic.h b/include/llvm/Transforms/Scalar/LowerAtomic.h index a4a2e7aafe44..40f8ca571f19 100644 --- a/include/llvm/Transforms/Scalar/LowerAtomic.h +++ b/include/llvm/Transforms/Scalar/LowerAtomic.h @@ -1,9 +1,8 @@ //===- LowerAtomic.cpp - Lower atomic intrinsics ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h index b6ee6523697c..4e47ff70d557 100644 --- a/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h +++ b/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h @@ -1,9 +1,8 @@ //===- LowerExpectIntrinsic.h - LowerExpectIntrinsic pass -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/LowerGuardIntrinsic.h b/include/llvm/Transforms/Scalar/LowerGuardIntrinsic.h index a9f19f6b84b4..ce97b9e4c386 100644 --- a/include/llvm/Transforms/Scalar/LowerGuardIntrinsic.h +++ b/include/llvm/Transforms/Scalar/LowerGuardIntrinsic.h @@ -1,9 +1,8 @@ //===--- LowerGuardIntrinsic.h - Lower the guard intrinsic ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/LowerWidenableCondition.h b/include/llvm/Transforms/Scalar/LowerWidenableCondition.h new file mode 100644 index 000000000000..7c1e64b8f3a9 --- /dev/null +++ b/include/llvm/Transforms/Scalar/LowerWidenableCondition.h @@ -0,0 +1,26 @@ +//===--- LowerWidenableCondition.h - Lower the guard intrinsic ---------------===// +// +// 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 lowers the llvm.widenable.condition intrinsic to default value +// which is i1 true. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H +#define LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct LowerWidenableConditionPass : PassInfoMixin<LowerWidenableConditionPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} + +#endif //LLVM_TRANSFORMS_SCALAR_LOWERWIDENABLECONDITION_H diff --git a/include/llvm/Transforms/Scalar/MakeGuardsExplicit.h b/include/llvm/Transforms/Scalar/MakeGuardsExplicit.h index 41b4aada2baa..525174734303 100644 --- a/include/llvm/Transforms/Scalar/MakeGuardsExplicit.h +++ b/include/llvm/Transforms/Scalar/MakeGuardsExplicit.h @@ -1,9 +1,8 @@ //===-- MakeGuardsExplicit.h - Turn guard intrinsics into guard branches --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/MemCpyOptimizer.h b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h index 046c808bd051..5386f58b2b82 100644 --- a/include/llvm/Transforms/Scalar/MemCpyOptimizer.h +++ b/include/llvm/Transforms/Scalar/MemCpyOptimizer.h @@ -1,9 +1,8 @@ //===- MemCpyOptimizer.h - memcpy optimization ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/MergeICmps.h b/include/llvm/Transforms/Scalar/MergeICmps.h new file mode 100644 index 000000000000..63bdbf8f4d09 --- /dev/null +++ b/include/llvm/Transforms/Scalar/MergeICmps.h @@ -0,0 +1,25 @@ +//===- MergeICmps.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_TRANSFORMS_SCALAR_MERGEICMPS_H +#define LLVM_TRANSFORMS_SCALAR_MERGEICMPS_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Function; + +struct MergeICmpsPass + : PassInfoMixin<MergeICmpsPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_MERGEICMPS_H diff --git a/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h b/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h index 48df09cdec9e..9071a56532f8 100644 --- a/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h +++ b/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h @@ -1,9 +1,8 @@ //===- MergedLoadStoreMotion.h - merge and hoist/sink load/stores ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/NaryReassociate.h b/include/llvm/Transforms/Scalar/NaryReassociate.h index e835bd5f0761..26f5fe185dd5 100644 --- a/include/llvm/Transforms/Scalar/NaryReassociate.h +++ b/include/llvm/Transforms/Scalar/NaryReassociate.h @@ -1,9 +1,8 @@ //===- NaryReassociate.h - Reassociate n-ary expressions --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/NewGVN.h b/include/llvm/Transforms/Scalar/NewGVN.h index 3f7541863a19..1f3680fec79c 100644 --- a/include/llvm/Transforms/Scalar/NewGVN.h +++ b/include/llvm/Transforms/Scalar/NewGVN.h @@ -1,9 +1,8 @@ //===- NewGVN.h - Global Value Numbering Pass -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h b/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h index 7f73831e0eb3..fd5a06c5051d 100644 --- a/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h +++ b/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h @@ -1,9 +1,8 @@ //===--- PartiallyInlineLibCalls.h - Partially inline libcalls --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/Reassociate.h b/include/llvm/Transforms/Scalar/Reassociate.h index ba7586dffd9d..2db8d8ce309c 100644 --- a/include/llvm/Transforms/Scalar/Reassociate.h +++ b/include/llvm/Transforms/Scalar/Reassociate.h @@ -1,9 +1,8 @@ //===- Reassociate.h - Reassociate binary expressions -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -83,7 +82,14 @@ protected: static const unsigned GlobalReassociateLimit = 10; static const unsigned NumBinaryOps = Instruction::BinaryOpsEnd - Instruction::BinaryOpsBegin; - DenseMap<std::pair<Value *, Value *>, unsigned> PairMap[NumBinaryOps]; + + struct PairMapValue { + WeakVH Value1; + WeakVH Value2; + unsigned Score; + bool isValid() const { return Value1 && Value2; } + }; + DenseMap<std::pair<Value *, Value *>, PairMapValue> PairMap[NumBinaryOps]; bool MadeChange; diff --git a/include/llvm/Transforms/Scalar/RewriteStatepointsForGC.h b/include/llvm/Transforms/Scalar/RewriteStatepointsForGC.h index 128f176f4420..12773c16dcc2 100644 --- a/include/llvm/Transforms/Scalar/RewriteStatepointsForGC.h +++ b/include/llvm/Transforms/Scalar/RewriteStatepointsForGC.h @@ -1,9 +1,8 @@ //===- RewriteStatepointsForGC.h - ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/SCCP.h b/include/llvm/Transforms/Scalar/SCCP.h index 0abbb32fde6a..0ffd983eb3e0 100644 --- a/include/llvm/Transforms/Scalar/SCCP.h +++ b/include/llvm/Transforms/Scalar/SCCP.h @@ -1,9 +1,8 @@ //===- SCCP.cpp - Sparse Conditional Constant Propagation -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/SROA.h b/include/llvm/Transforms/Scalar/SROA.h index b36c6f492be1..864a0cbd9db1 100644 --- a/include/llvm/Transforms/Scalar/SROA.h +++ b/include/llvm/Transforms/Scalar/SROA.h @@ -1,9 +1,8 @@ //===- SROA.h - Scalar Replacement Of Aggregates ----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -19,7 +18,6 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/PassManager.h" -#include "llvm/Support/Compiler.h" #include <vector> namespace llvm { diff --git a/include/llvm/Transforms/Scalar/Scalarizer.h b/include/llvm/Transforms/Scalar/Scalarizer.h index 1a0b9a2b638c..81363130e2e3 100644 --- a/include/llvm/Transforms/Scalar/Scalarizer.h +++ b/include/llvm/Transforms/Scalar/Scalarizer.h @@ -1,9 +1,8 @@ //===- Scalarizer.h --- Scalarize vector operations -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h index eed50ec96161..33c1faaeee0b 100644 --- a/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -1,9 +1,8 @@ //===- SimpleLoopUnswitch.h - Hoist loop-invariant control flow -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/SimplifyCFG.h b/include/llvm/Transforms/Scalar/SimplifyCFG.h index ce0a35fc06bd..f9792d38bbe6 100644 --- a/include/llvm/Transforms/Scalar/SimplifyCFG.h +++ b/include/llvm/Transforms/Scalar/SimplifyCFG.h @@ -1,9 +1,8 @@ //===- SimplifyCFG.h - Simplify and canonicalize the CFG --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 diff --git a/include/llvm/Transforms/Scalar/Sink.h b/include/llvm/Transforms/Scalar/Sink.h index f9b3cb0fae39..6cbe964d1580 100644 --- a/include/llvm/Transforms/Scalar/Sink.h +++ b/include/llvm/Transforms/Scalar/Sink.h @@ -1,9 +1,8 @@ //===-- Sink.h - Code Sinking -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h b/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h index 4a0bfd754723..3c7dafe71e8e 100644 --- a/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h +++ b/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h @@ -1,9 +1,8 @@ //===- SpeculateAroundPHIs.h - Speculate around PHIs ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Scalar/SpeculativeExecution.h b/include/llvm/Transforms/Scalar/SpeculativeExecution.h index d00e950222a0..14da86483213 100644 --- a/include/llvm/Transforms/Scalar/SpeculativeExecution.h +++ b/include/llvm/Transforms/Scalar/SpeculativeExecution.h @@ -1,9 +1,8 @@ //===- SpeculativeExecution.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/TailRecursionElimination.h b/include/llvm/Transforms/Scalar/TailRecursionElimination.h index 793f9bc152ed..906867644504 100644 --- a/include/llvm/Transforms/Scalar/TailRecursionElimination.h +++ b/include/llvm/Transforms/Scalar/TailRecursionElimination.h @@ -1,9 +1,8 @@ //===---- TailRecursionElimination.h ----------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Scalar/WarnMissedTransforms.h b/include/llvm/Transforms/Scalar/WarnMissedTransforms.h index 018b22a932e6..2d5942a3f569 100644 --- a/include/llvm/Transforms/Scalar/WarnMissedTransforms.h +++ b/include/llvm/Transforms/Scalar/WarnMissedTransforms.h @@ -1,9 +1,8 @@ //===- WarnMissedTransforms.h -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils.h b/include/llvm/Transforms/Utils.h index 378552775c77..6e03453babf1 100644 --- a/include/llvm/Transforms/Utils.h +++ b/include/llvm/Transforms/Utils.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils.h - Utility Transformations --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/ASanStackFrameLayout.h b/include/llvm/Transforms/Utils/ASanStackFrameLayout.h index eaad06a10819..0b570c0d1342 100644 --- a/include/llvm/Transforms/Utils/ASanStackFrameLayout.h +++ b/include/llvm/Transforms/Utils/ASanStackFrameLayout.h @@ -1,9 +1,8 @@ //===- ASanStackFrameLayout.h - ComputeASanStackFrameLayout -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/AddDiscriminators.h b/include/llvm/Transforms/Utils/AddDiscriminators.h index 4dad06e6c125..f512c6c06331 100644 --- a/include/llvm/Transforms/Utils/AddDiscriminators.h +++ b/include/llvm/Transforms/Utils/AddDiscriminators.h @@ -1,9 +1,8 @@ //===- AddDiscriminators.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 5b16a2c0d0b1..4d861ffe9a31 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -1,9 +1,8 @@ //===- Transform/Utils/BasicBlockUtils.h - BasicBlock Utils -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -18,9 +17,9 @@ // FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock #include "llvm/ADT/ArrayRef.h" +#include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" -#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/InstrTypes.h" #include <cassert> @@ -36,19 +35,38 @@ class LoopInfo; class MDNode; class MemoryDependenceResults; class MemorySSAUpdater; +class PostDominatorTree; class ReturnInst; class TargetLibraryInfo; class Value; +/// Replace contents of every block in \p BBs with single unreachable +/// instruction. If \p Updates is specified, collect all necessary DT updates +/// into this vector. If \p KeepOneInputPHIs is true, one-input Phis in +/// successors of blocks being deleted will be preserved. +void DetatchDeadBlocks(ArrayRef <BasicBlock *> BBs, + SmallVectorImpl<DominatorTree::UpdateType> *Updates, + bool KeepOneInputPHIs = false); + /// Delete the specified block, which must have no predecessors. -void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); +void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr, + bool KeepOneInputPHIs = false); /// Delete the specified blocks from \p BB. The set of deleted blocks must have /// no predecessors that are not being deleted themselves. \p BBs must have no /// duplicating blocks. If there are loops among this set of blocks, all /// relevant loop info updates should be done before this function is called. -void DeleteDeadBlocks(SmallVectorImpl <BasicBlock *> &BBs, - DomTreeUpdater *DTU = nullptr); +/// If \p KeepOneInputPHIs is true, one-input Phis in successors of blocks +/// being deleted will be preserved. +void DeleteDeadBlocks(ArrayRef <BasicBlock *> BBs, + DomTreeUpdater *DTU = nullptr, + bool KeepOneInputPHIs = false); + +/// Delete all basic blocks from \p F that are not reachable from its entry +/// node. If \p KeepOneInputPHIs is true, one-input Phis in successors of +/// blocks being deleted will be preserved. +bool EliminateUnreachableBlocks(Function &F, DomTreeUpdater *DTU = nullptr, + bool KeepOneInputPHIs = false); /// We know that BB has one predecessor. If there are any single-entry PHI nodes /// in it, fold them away. This handles the case when all entries to the PHI @@ -92,24 +110,27 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To); /// during critical edge splitting. struct CriticalEdgeSplittingOptions { DominatorTree *DT; + PostDominatorTree *PDT; LoopInfo *LI; MemorySSAUpdater *MSSAU; bool MergeIdenticalEdges = false; - bool DontDeleteUselessPHIs = false; + bool KeepOneInputPHIs = false; bool PreserveLCSSA = false; + bool IgnoreUnreachableDests = false; CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, - MemorySSAUpdater *MSSAU = nullptr) - : DT(DT), LI(LI), MSSAU(MSSAU) {} + MemorySSAUpdater *MSSAU = nullptr, + PostDominatorTree *PDT = nullptr) + : DT(DT), PDT(PDT), LI(LI), MSSAU(MSSAU) {} CriticalEdgeSplittingOptions &setMergeIdenticalEdges() { MergeIdenticalEdges = true; return *this; } - CriticalEdgeSplittingOptions &setDontDeleteUselessPHIs() { - DontDeleteUselessPHIs = true; + CriticalEdgeSplittingOptions &setKeepOneInputPHIs() { + KeepOneInputPHIs = true; return *this; } @@ -117,6 +138,11 @@ struct CriticalEdgeSplittingOptions { PreserveLCSSA = true; return *this; } + + CriticalEdgeSplittingOptions &setIgnoreUnreachableDests() { + IgnoreUnreachableDests = true; + return *this; + } }; /// If this edge is a critical edge, insert a new node to split the critical @@ -259,7 +285,8 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, /// SplitBefore /// Tail /// -/// If Unreachable is true, then ThenBlock ends with +/// If \p ThenBlock is not specified, a new block will be created for it. +/// If \p Unreachable is true, the newly created block will end with /// UnreachableInst, otherwise it branches to Tail. /// Returns the NewBasicBlock's terminator. /// @@ -268,7 +295,8 @@ Instruction *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights = nullptr, DominatorTree *DT = nullptr, - LoopInfo *LI = nullptr); + LoopInfo *LI = nullptr, + BasicBlock *ThenBlock = nullptr); /// SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, /// but also creates the ElseBlock. diff --git a/include/llvm/Transforms/Utils/BreakCriticalEdges.h b/include/llvm/Transforms/Utils/BreakCriticalEdges.h index 9cc81a176cb6..3644f1ed7a13 100644 --- a/include/llvm/Transforms/Utils/BreakCriticalEdges.h +++ b/include/llvm/Transforms/Utils/BreakCriticalEdges.h @@ -1,9 +1,8 @@ //===- BreakCriticalEdges.h - Critical Edge Elimination Pass --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 28efce6ac3fb..8421c31a36da 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -1,9 +1,8 @@ //===- BuildLibCalls.h - Utility builder for libcalls -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -71,12 +70,22 @@ namespace llvm { /// Emit a call to the strcpy function to the builder, for the specified /// pointer arguments. Value *emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, - const TargetLibraryInfo *TLI, StringRef Name = "strcpy"); + const TargetLibraryInfo *TLI); + + /// Emit a call to the stpcpy function to the builder, for the specified + /// pointer arguments. + Value *emitStpCpy(Value *Dst, Value *Src, IRBuilder<> &B, + const TargetLibraryInfo *TLI); /// Emit a call to the strncpy function to the builder, for the specified /// pointer arguments and length. Value *emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, - const TargetLibraryInfo *TLI, StringRef Name = "strncpy"); + const TargetLibraryInfo *TLI); + + /// Emit a call to the stpncpy function to the builder, for the specified + /// pointer arguments and length. + Value *emitStpNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + const TargetLibraryInfo *TLI); /// Emit a call to the __memcpy_chk function to the builder. This expects that /// the Len and ObjSize have type 'intptr_t' and Dst/Src are pointers. @@ -93,6 +102,47 @@ namespace llvm { Value *emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, const DataLayout &DL, const TargetLibraryInfo *TLI); + /// Emit a call to the bcmp function. + Value *emitBCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const DataLayout &DL, const TargetLibraryInfo *TLI); + + /// Emit a call to the memccpy function. + Value *emitMemCCpy(Value *Ptr1, Value *Ptr2, Value *Val, Value *Len, + IRBuilder<> &B, const TargetLibraryInfo *TLI); + + /// Emit a call to the snprintf function. + Value *emitSNPrintf(Value *Dest, Value *Size, Value *Fmt, + ArrayRef<Value *> Args, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the sprintf function. + Value *emitSPrintf(Value *Dest, Value *Fmt, ArrayRef<Value *> VariadicArgs, + IRBuilder<> &B, const TargetLibraryInfo *TLI); + + /// Emit a call to the strcat function. + Value *emitStrCat(Value *Dest, Value *Src, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the strlcpy function. + Value *emitStrLCpy(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the strlcat function. + Value *emitStrLCat(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the strncat function. + Value *emitStrNCat(Value *Dest, Value *Src, Value *Size, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the vsnprintf function. + Value *emitVSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *VAList, + IRBuilder<> &B, const TargetLibraryInfo *TLI); + + /// Emit a call to the vsprintf function. + Value *emitVSPrintf(Value *Dest, Value *Fmt, Value *VAList, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + /// Emit a call to the unary function named 'Name' (e.g. 'floor'). This /// function is known to take a single of type matching 'Op' and returns one /// value with the same type. If 'Op' is a long double, 'l' is added as the diff --git a/include/llvm/Transforms/Utils/BypassSlowDivision.h b/include/llvm/Transforms/Utils/BypassSlowDivision.h index 6eca5ed2154e..471055921fa8 100644 --- a/include/llvm/Transforms/Utils/BypassSlowDivision.h +++ b/include/llvm/Transforms/Utils/BypassSlowDivision.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils/BypassSlowDivision.h ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/CallPromotionUtils.h b/include/llvm/Transforms/Utils/CallPromotionUtils.h index 6e8ece723638..d9d171c6d8bd 100644 --- a/include/llvm/Transforms/Utils/CallPromotionUtils.h +++ b/include/llvm/Transforms/Utils/CallPromotionUtils.h @@ -1,9 +1,8 @@ //===- CallPromotionUtils.h - Utilities for call promotion ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/CanonicalizeAliases.h b/include/llvm/Transforms/Utils/CanonicalizeAliases.h index f23263783fec..8f23a041a24e 100644 --- a/include/llvm/Transforms/Utils/CanonicalizeAliases.h +++ b/include/llvm/Transforms/Utils/CanonicalizeAliases.h @@ -1,9 +1,8 @@ //===-- CanonicalizeAliases.h - Alias Canonicalization Pass -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index f5e997324fc8..872ab9cab85c 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -1,9 +1,8 @@ //===- Cloning.h - Clone various parts of LLVM programs ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -230,10 +229,7 @@ public: /// and all varargs at the callsite will be passed to any calls to /// ForwardVarArgsTo. The caller of InlineFunction has to make sure any varargs /// are only used by ForwardVarArgsTo. -InlineResult InlineFunction(CallInst *C, InlineFunctionInfo &IFI, - AAResults *CalleeAAR = nullptr, - bool InsertLifetime = true); -InlineResult InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, +InlineResult InlineFunction(CallBase *CB, InlineFunctionInfo &IFI, AAResults *CalleeAAR = nullptr, bool InsertLifetime = true); InlineResult InlineFunction(CallSite CS, InlineFunctionInfo &IFI, @@ -269,6 +265,13 @@ BasicBlock *DuplicateInstructionsInSplitBetween(BasicBlock *BB, ValueToValueMapTy &ValueMapping, DomTreeUpdater &DTU); +/// Updates profile information by adjusting the entry count by adding +/// entryDelta then scaling callsite information by the new count divided by the +/// old count. VMap is used during inlinng to also update the new clone +void updateProfileCallee( + Function *Callee, int64_t entryDelta, + const ValueMap<const Value *, WeakTrackingVH> *VMap = nullptr); + } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_CLONING_H diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index fee79fdc3bff..9d79ee1633f6 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -1,9 +1,8 @@ //===- Transform/Utils/CodeExtractor.h - Code extraction util ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -27,6 +26,7 @@ class BasicBlock; class BlockFrequency; class BlockFrequencyInfo; class BranchProbabilityInfo; +class AssumptionCache; class CallInst; class DominatorTree; class Function; @@ -57,6 +57,7 @@ class Value; const bool AggregateArgs; BlockFrequencyInfo *BFI; BranchProbabilityInfo *BPI; + AssumptionCache *AC; // If true, varargs functions can be extracted. bool AllowVarArgs; @@ -85,6 +86,7 @@ class Value; CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = nullptr, bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr, BranchProbabilityInfo *BPI = nullptr, + AssumptionCache *AC = nullptr, bool AllowVarArgs = false, bool AllowAlloca = false, std::string Suffix = ""); @@ -95,6 +97,7 @@ class Value; CodeExtractor(DominatorTree &DT, Loop &L, bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr, BranchProbabilityInfo *BPI = nullptr, + AssumptionCache *AC = nullptr, std::string Suffix = ""); /// Perform the extraction, returning the new function. @@ -148,6 +151,16 @@ class Value; BasicBlock *findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock); private: + struct LifetimeMarkerInfo { + bool SinkLifeStart = false; + bool HoistLifeEnd = false; + Instruction *LifeStart = nullptr; + Instruction *LifeEnd = nullptr; + }; + + LifetimeMarkerInfo getLifetimeMarkers(Instruction *Addr, + BasicBlock *ExitBlock) const; + void severSplitPHINodesOfEntry(BasicBlock *&Header); void severSplitPHINodesOfExits(const SmallPtrSetImpl<BasicBlock *> &Exits); void splitReturnBlocks(); diff --git a/include/llvm/Transforms/Utils/CtorUtils.h b/include/llvm/Transforms/Utils/CtorUtils.h index 63e564dcb87a..3625ee662b1c 100644 --- a/include/llvm/Transforms/Utils/CtorUtils.h +++ b/include/llvm/Transforms/Utils/CtorUtils.h @@ -1,9 +1,8 @@ //===- CtorUtils.h - Helpers for working with global_ctors ------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/EntryExitInstrumenter.h b/include/llvm/Transforms/Utils/EntryExitInstrumenter.h index f50c5c922081..3913693af359 100644 --- a/include/llvm/Transforms/Utils/EntryExitInstrumenter.h +++ b/include/llvm/Transforms/Utils/EntryExitInstrumenter.h @@ -1,9 +1,8 @@ //===- EntryExitInstrumenter.h - Function Entry/Exit Instrumentation ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/EscapeEnumerator.h b/include/llvm/Transforms/Utils/EscapeEnumerator.h index 1256dfdaca17..e667796c841b 100644 --- a/include/llvm/Transforms/Utils/EscapeEnumerator.h +++ b/include/llvm/Transforms/Utils/EscapeEnumerator.h @@ -1,9 +1,8 @@ //===-- EscapeEnumerator.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/Evaluator.h b/include/llvm/Transforms/Utils/Evaluator.h index 9908ae6fd393..bffd65f71b2e 100644 --- a/include/llvm/Transforms/Utils/Evaluator.h +++ b/include/llvm/Transforms/Utils/Evaluator.h @@ -1,9 +1,8 @@ //===- Evaluator.h - LLVM IR evaluator --------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/FunctionComparator.h b/include/llvm/Transforms/Utils/FunctionComparator.h index 35ba0950343c..4e2571b1d0b6 100644 --- a/include/llvm/Transforms/Utils/FunctionComparator.h +++ b/include/llvm/Transforms/Utils/FunctionComparator.h @@ -1,9 +1,8 @@ //===- FunctionComparator.h - Function Comparator ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/FunctionImportUtils.h b/include/llvm/Transforms/Utils/FunctionImportUtils.h index e24398b90012..9c2a9ea531ea 100644 --- a/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -1,9 +1,8 @@ //===- FunctionImportUtils.h - Importing support utilities -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -44,6 +43,11 @@ class FunctionImportGlobalProcessing { /// to promote any non-renamable values. SmallPtrSet<GlobalValue *, 8> Used; + /// Keep track of any COMDATs that require renaming (because COMDAT + /// leader was promoted and renamed). Maps from original COMDAT to one + /// with new name. + DenseMap<const Comdat *, Comdat *> RenamedComdats; + /// Check if we should promote the given local value to global scope. bool shouldPromoteLocalToGlobal(const GlobalValue *SGV); diff --git a/include/llvm/Transforms/Utils/GlobalStatus.h b/include/llvm/Transforms/Utils/GlobalStatus.h index 8cc265bdf81d..519593c96766 100644 --- a/include/llvm/Transforms/Utils/GlobalStatus.h +++ b/include/llvm/Transforms/Utils/GlobalStatus.h @@ -1,9 +1,8 @@ //===- GlobalStatus.h - Compute status info for globals ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Utils/GuardUtils.h b/include/llvm/Transforms/Utils/GuardUtils.h index 537045edafe4..3b365c56a5c0 100644 --- a/include/llvm/Transforms/Utils/GuardUtils.h +++ b/include/llvm/Transforms/Utils/GuardUtils.h @@ -1,9 +1,8 @@ //===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 transformations related to guards and their diff --git a/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h b/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h index b55a9893bcf7..033ea05b77fa 100644 --- a/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h +++ b/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h @@ -1,9 +1,8 @@ -//===-- ImportedFunctionsInliningStats.h ------------------------*- C++ -*-===// +//===-- ImportedFunctionsInliningStatistics.h -------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // Generating inliner statistics for imported functions, mostly useful for diff --git a/include/llvm/Transforms/Utils/IntegerDivision.h b/include/llvm/Transforms/Utils/IntegerDivision.h index 5d9927eb51b2..35cae9aa2269 100644 --- a/include/llvm/Transforms/Utils/IntegerDivision.h +++ b/include/llvm/Transforms/Utils/IntegerDivision.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils/IntegerDivision.h ------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/LCSSA.h b/include/llvm/Transforms/Utils/LCSSA.h index fe717e5f6635..b01c8022a65b 100644 --- a/include/llvm/Transforms/Utils/LCSSA.h +++ b/include/llvm/Transforms/Utils/LCSSA.h @@ -1,9 +1,8 @@ //===- LCSSA.h - Loop-closed SSA transform Pass -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/LibCallsShrinkWrap.h b/include/llvm/Transforms/Utils/LibCallsShrinkWrap.h index c9df532e5794..ff1537ace329 100644 --- a/include/llvm/Transforms/Utils/LibCallsShrinkWrap.h +++ b/include/llvm/Transforms/Utils/LibCallsShrinkWrap.h @@ -1,9 +1,8 @@ //===- LibCallsShrinkWrap.h - Shrink Wrap Library Calls -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index ec8b0eda3641..ff516f230979 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -1,9 +1,8 @@ //===- Local.h - Functions to perform local transformations -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,12 +20,11 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/Utils/Local.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Operator.h" @@ -233,7 +231,8 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// If this basic block is ONLY a setcc and a branch, and if a predecessor /// branches to us and one of our successors, fold the setcc into the /// predecessor and use logical operations to pick the right destination. -bool FoldBranchToCommonDest(BranchInst *BI, unsigned BonusInstThreshold = 1); +bool FoldBranchToCommonDest(BranchInst *BI, MemorySSAUpdater *MSSAU = nullptr, + unsigned BonusInstThreshold = 1); /// This function takes a virtual register computed by an Instruction and /// replaces it with a slot in the stack frame, allocated via alloca. @@ -317,7 +316,7 @@ void findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V); /// (between the optional Deref operations). Offset can be negative. bool replaceDbgDeclare(Value *Address, Value *NewAddress, Instruction *InsertBefore, DIBuilder &Builder, - bool DerefBefore, int Offset, bool DerefAfter); + uint8_t DIExprFlags, int Offset); /// Replaces llvm.dbg.declare instruction when the alloca it describes /// is replaced with a new value. If Deref is true, an additional @@ -326,8 +325,8 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress, /// optional Deref operations). Offset can be negative. The new /// llvm.dbg.declare is inserted immediately after AI. bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, - DIBuilder &Builder, bool DerefBefore, - int Offset, bool DerefAfter); + DIBuilder &Builder, uint8_t DIExprFlags, + int Offset); /// Replaces multiple llvm.dbg.value instructions when the alloca it describes /// is replaced with a new value. If Offset is non-zero, a constant displacement @@ -337,11 +336,27 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DIBuilder &Builder, int Offset = 0); +/// Finds alloca where the value comes from. +AllocaInst *findAllocaForValue(Value *V, + DenseMap<Value *, AllocaInst *> &AllocaForValue); + /// Assuming the instruction \p I is going to be deleted, attempt to salvage /// debug users of \p I by writing the effect of \p I in a DIExpression. /// Returns true if any debug users were updated. bool salvageDebugInfo(Instruction &I); +/// Implementation of salvageDebugInfo, applying only to instructions in +/// \p Insns, rather than all debug users of \p I. +bool salvageDebugInfoForDbgValues(Instruction &I, + ArrayRef<DbgVariableIntrinsic *> Insns); + +/// Given an instruction \p I and DIExpression \p DIExpr operating on it, write +/// the effects of \p I into the returned DIExpression, or return nullptr if +/// it cannot be salvaged. \p StackVal: whether DW_OP_stack_value should be +/// appended to the expression. +DIExpression *salvageDebugInfoImpl(Instruction &I, DIExpression *DIExpr, + bool StackVal); + /// Point debug users of \p From to \p To or salvage them. Use this function /// only when replacing all uses of \p From with \p To, with a guarantee that /// \p From is going to be deleted. @@ -367,7 +382,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB); /// instruction, making it and the rest of the code in the block dead. unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, bool PreserveLCSSA = false, - DomTreeUpdater *DTU = nullptr); + DomTreeUpdater *DTU = nullptr, + MemorySSAUpdater *MSSAU = nullptr); /// Convert the CallInst to InvokeInst with the specified unwind edge basic /// block. This also splits the basic block where CI is located, because @@ -426,7 +442,7 @@ unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, const BasicBlock *BB); -/// Return true if the CallSite CS calls a gc leaf function. +/// Return true if this call calls a gc leaf function. /// /// A leaf function is a function that does not safepoint the thread during its /// execution. During a call or invoke to such a function, the callers stack @@ -434,7 +450,7 @@ unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT, /// /// Most passes can and should ignore this information, and it is only used /// during lowering by the GC infrastructure. -bool callsGCLeafFunction(ImmutableCallSite CS, const TargetLibraryInfo &TLI); +bool callsGCLeafFunction(const CallBase *Call, const TargetLibraryInfo &TLI); /// Copy a nonnull metadata node to a new load instruction. /// @@ -456,8 +472,7 @@ void dropDebugUsers(Instruction &I); /// \p DomBlock, by moving its instructions to the insertion point \p InsertPt. /// /// The moved instructions receive the insertion point debug location values -/// (DILocations) and their debug intrinsic instructions (dbg.values) are -/// removed. +/// (DILocations) and their debug intrinsic instructions are removed. void hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt, BasicBlock *BB); diff --git a/include/llvm/Transforms/Utils/LoopRotationUtils.h b/include/llvm/Transforms/Utils/LoopRotationUtils.h index cd5bc4301018..1e80722ed8b8 100644 --- a/include/llvm/Transforms/Utils/LoopRotationUtils.h +++ b/include/llvm/Transforms/Utils/LoopRotationUtils.h @@ -1,9 +1,8 @@ //===- LoopRotationUtils.h - Utilities to perform loop rotation -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/LoopSimplify.h b/include/llvm/Transforms/Utils/LoopSimplify.h index 166da2738ffd..2c1df7942f63 100644 --- a/include/llvm/Transforms/Utils/LoopSimplify.h +++ b/include/llvm/Transforms/Utils/LoopSimplify.h @@ -1,9 +1,8 @@ //===- LoopSimplify.h - Loop Canonicalization Pass --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -46,6 +45,8 @@ namespace llvm { +class MemorySSAUpdater; + /// This pass is responsible for loop canonicalization. class LoopSimplifyPass : public PassInfoMixin<LoopSimplifyPass> { public: @@ -56,9 +57,11 @@ public: /// /// This takes a potentially un-simplified loop L (and its children) and turns /// it into a simplified loop nest with preheaders and single backedges. It will -/// update \c AliasAnalysis and \c ScalarEvolution analyses if they're non-null. +/// update \c DominatorTree, \c LoopInfo, \c ScalarEvolution and \c MemorySSA +/// analyses if they're non-null, and LCSSA if \c PreserveLCSSA is true. bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE, - AssumptionCache *AC, bool PreserveLCSSA); + AssumptionCache *AC, MemorySSAUpdater *MSSAU, + bool PreserveLCSSA); } // end namespace llvm diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 8c2527b6ae68..68bdded5cf93 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils/LoopUtils.h - Loop utilities -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -41,6 +40,7 @@ class BasicBlock; class DataLayout; class Loop; class LoopInfo; +class MemoryAccess; class MemorySSAUpdater; class OptimizationRemarkEmitter; class PredicatedScalarEvolution; @@ -51,7 +51,7 @@ class TargetLibraryInfo; class TargetTransformInfo; BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, - bool PreserveLCSSA); + MemorySSAUpdater *MSSAU, bool PreserveLCSSA); /// Ensure that all exit blocks of the loop are dedicated exits. /// @@ -59,7 +59,7 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, /// predecessors to use a dedicated loop exit block. We update the dominator /// tree and loop info if provided, and will preserve LCSSA if requested. bool formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI, - bool PreserveLCSSA); + MemorySSAUpdater *MSSAU, bool PreserveLCSSA); /// Ensures LCSSA form for every instruction from the Worklist in the scope of /// innermost containing loop. @@ -79,7 +79,8 @@ bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, /// /// Looks at all instructions in the loop which have uses outside of the /// current loop. For each, an LCSSA PHI node is inserted and the uses outside -/// the loop are rewritten to use this node. +/// the loop are rewritten to use this node. Sub-loops must be in LCSSA form +/// already. /// /// LoopInfo and DominatorTree are required and preserved. /// @@ -100,6 +101,14 @@ bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE); bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE); +struct SinkAndHoistLICMFlags { + bool NoOfMemAccTooLarge; + unsigned LicmMssaOptCounter; + unsigned LicmMssaOptCap; + unsigned LicmMssaNoAccForPromotionCap; + bool IsSink; +}; + /// Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in /// reverse depth first order w.r.t the DominatorTree. This allows us to visit @@ -111,7 +120,7 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, TargetTransformInfo *, Loop *, AliasSetTracker *, MemorySSAUpdater *, ICFLoopSafetyInfo *, - OptimizationRemarkEmitter *ORE); + SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *); /// Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in depth @@ -124,7 +133,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, Loop *, AliasSetTracker *, MemorySSAUpdater *, ICFLoopSafetyInfo *, - OptimizationRemarkEmitter *ORE); + SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *); /// This function deletes dead loops. The caller of this function needs to /// guarantee that the loop is infact dead. @@ -148,14 +157,12 @@ void deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, /// LoopInfo, DominatorTree, Loop, AliasSet information for all instructions /// of the loop and loop safety information as arguments. /// Diagnostics is emitted via \p ORE. It returns changed status. -bool promoteLoopAccessesToScalars(const SmallSetVector<Value *, 8> &, - SmallVectorImpl<BasicBlock *> &, - SmallVectorImpl<Instruction *> &, - PredIteratorCache &, LoopInfo *, - DominatorTree *, const TargetLibraryInfo *, - Loop *, AliasSetTracker *, - ICFLoopSafetyInfo *, - OptimizationRemarkEmitter *); +bool promoteLoopAccessesToScalars( + const SmallSetVector<Value *, 8> &, SmallVectorImpl<BasicBlock *> &, + SmallVectorImpl<Instruction *> &, SmallVectorImpl<MemoryAccess *> &, + PredIteratorCache &, LoopInfo *, DominatorTree *, const TargetLibraryInfo *, + Loop *, AliasSetTracker *, MemorySSAUpdater *, ICFLoopSafetyInfo *, + OptimizationRemarkEmitter *); /// Does a BFS from a given node to all of its children inside a given loop. /// The returned vector of nodes includes the starting point. @@ -277,6 +284,7 @@ void getLoopAnalysisUsage(AnalysisUsage &AU); bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, Loop *CurLoop, AliasSetTracker *CurAST, MemorySSAUpdater *MSSAU, bool TargetExecutesOncePerLoop, + SinkAndHoistLICMFlags *LICMFlags = nullptr, OptimizationRemarkEmitter *ORE = nullptr); /// Returns a Min/Max operation corresponding to MinMaxRecurrenceKind. @@ -292,6 +300,7 @@ getOrderedReduction(IRBuilder<> &Builder, Value *Acc, Value *Src, unsigned Op, ArrayRef<Value *> RedOps = None); /// Generates a vector reduction using shufflevectors to reduce the value. +/// Fast-math-flags are propagated using the IRBuilder's setting. Value *getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op, RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind = RecurrenceDescriptor::MRK_Invalid, @@ -302,6 +311,7 @@ Value *getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op, /// additional information supplied in \p Flags. /// The target is queried to determine if intrinsics or shuffle sequences are /// required to implement the reduction. +/// Fast-math-flags are propagated using the IRBuilder's setting. Value *createSimpleTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI, unsigned Opcode, Value *Src, @@ -312,6 +322,7 @@ Value *createSimpleTargetReduction(IRBuilder<> &B, /// Create a generic target reduction using a recurrence descriptor \p Desc /// The target is queried to determine if intrinsics or shuffle sequences are /// required to implement the reduction. +/// Fast-math-flags are propagated using the RecurrenceDescriptor. Value *createTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI, RecurrenceDescriptor &Desc, Value *Src, bool NoNaN = false); diff --git a/include/llvm/Transforms/Utils/LoopVersioning.h b/include/llvm/Transforms/Utils/LoopVersioning.h index fcd734b37a1f..355c4d7dc6d8 100644 --- a/include/llvm/Transforms/Utils/LoopVersioning.h +++ b/include/llvm/Transforms/Utils/LoopVersioning.h @@ -1,9 +1,8 @@ //===- LoopVersioning.h - Utility to version a loop -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/LowerInvoke.h b/include/llvm/Transforms/Utils/LowerInvoke.h index 12774c7fd1f7..c1198b08d3de 100644 --- a/include/llvm/Transforms/Utils/LowerInvoke.h +++ b/include/llvm/Transforms/Utils/LowerInvoke.h @@ -1,9 +1,8 @@ //===- LowerInvoke.h - Eliminate Invoke instructions ----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/LowerMemIntrinsics.h b/include/llvm/Transforms/Utils/LowerMemIntrinsics.h index 2b7d0f67a324..8e9d7b522c78 100644 --- a/include/llvm/Transforms/Utils/LowerMemIntrinsics.h +++ b/include/llvm/Transforms/Utils/LowerMemIntrinsics.h @@ -1,9 +1,8 @@ -//===- llvm/Transforms/Utils/LowerMemintrinsics.h ---------------*- C++ -*-===// +//===- llvm/Transforms/Utils/LowerMemIntrinsics.h ---------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/Mem2Reg.h b/include/llvm/Transforms/Utils/Mem2Reg.h index 407684338a3b..76c1c2c5bffe 100644 --- a/include/llvm/Transforms/Utils/Mem2Reg.h +++ b/include/llvm/Transforms/Utils/Mem2Reg.h @@ -1,9 +1,8 @@ //===- Mem2Reg.h - The -mem2reg pass, a wrapper around the Utils lib ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index fee492be2a90..c69af5588741 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -1,9 +1,8 @@ //===-- ModuleUtils.h - Functions to manipulate Modules ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -22,6 +21,7 @@ namespace llvm { template <typename T> class ArrayRef; class Module; class Function; +class FunctionCallee; class GlobalValue; class GlobalVariable; class Constant; @@ -40,20 +40,14 @@ void appendToGlobalCtors(Module &M, Function *F, int Priority, void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data = nullptr); -// Validate the result of Module::getOrInsertFunction called for an interface -// function of given sanitizer. If the instrumented module defines a function -// with the same name, their prototypes must match, otherwise -// getOrInsertFunction returns a bitcast. -Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast); - -Function *declareSanitizerInitFunction(Module &M, StringRef InitName, - ArrayRef<Type *> InitArgTypes); +FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, + ArrayRef<Type *> InitArgTypes); /// Creates sanitizer constructor function, and calls sanitizer's init /// function from it. /// \return Returns pair of pointers to constructor, and init functions /// respectively. -std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions( +std::pair<Function *, FunctionCallee> createSanitizerCtorAndInitFunctions( Module &M, StringRef CtorName, StringRef InitName, ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, StringRef VersionCheckName = StringRef()); @@ -65,10 +59,10 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions( /// /// \return Returns pair of pointers to constructor, and init functions /// respectively. -std::pair<Function *, Function *> getOrCreateSanitizerCtorAndInitFunctions( +std::pair<Function *, FunctionCallee> getOrCreateSanitizerCtorAndInitFunctions( Module &M, StringRef CtorName, StringRef InitName, ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, - function_ref<void(Function *, Function *)> FunctionsCreatedCallback, + function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName = StringRef()); // Creates and returns a sanitizer init function without argument if it doesn't diff --git a/include/llvm/Transforms/Utils/NameAnonGlobals.h b/include/llvm/Transforms/Utils/NameAnonGlobals.h index 17fc902eebf8..659ebe33ffa6 100644 --- a/include/llvm/Transforms/Utils/NameAnonGlobals.h +++ b/include/llvm/Transforms/Utils/NameAnonGlobals.h @@ -1,9 +1,8 @@ //===-- NameAnonGlobals.h - Anonymous Global Naming Pass --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/PredicateInfo.h b/include/llvm/Transforms/Utils/PredicateInfo.h index 2fc38089f3f1..da4a5dcc28c0 100644 --- a/include/llvm/Transforms/Utils/PredicateInfo.h +++ b/include/llvm/Transforms/Utils/PredicateInfo.h @@ -1,9 +1,8 @@ //===- PredicateInfo.h - Build PredicateInfo ----------------------*-C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// /// diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 5ddfbe2bf058..b2b4507bbc74 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -1,9 +1,8 @@ //===- PromoteMemToReg.h - Promote Allocas to Scalars -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index d02607acbbb5..22b2295cc9d7 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -1,9 +1,8 @@ //===- SSAUpdater.h - Unstructured SSA Update Tool --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -148,7 +147,7 @@ public: /// Insts is a list of loads and stores to promote, and Name is the basename /// for the PHIs to insert. After this is complete, the loads and stores are /// removed from the code. - void run(const SmallVectorImpl<Instruction *> &Insts) const; + void run(const SmallVectorImpl<Instruction *> &Insts); /// Return true if the specified instruction is in the Inst list. /// @@ -159,7 +158,7 @@ public: /// This hook is invoked after all the stores are found and inserted as /// available values. - virtual void doExtraRewritesBeforeFinalDeletion() const {} + virtual void doExtraRewritesBeforeFinalDeletion() {} /// Clients can choose to implement this to get notified right before /// a load is RAUW'd another value. diff --git a/include/llvm/Transforms/Utils/SSAUpdaterBulk.h b/include/llvm/Transforms/Utils/SSAUpdaterBulk.h index 53a608f01804..5d17d6f3d285 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterBulk.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterBulk.h @@ -1,9 +1,8 @@ //===- SSAUpdaterBulk.h - Unstructured SSA Update Tool ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index cab0f3e71575..ee06893ca660 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -1,9 +1,8 @@ //===- SSAUpdaterImpl.h - SSA Updater Implementation ------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SanitizerStats.h b/include/llvm/Transforms/Utils/SanitizerStats.h index d36e34258a3f..14e8ae045cdd 100644 --- a/include/llvm/Transforms/Utils/SanitizerStats.h +++ b/include/llvm/Transforms/Utils/SanitizerStats.h @@ -1,9 +1,8 @@ //===- SanitizerStats.h - Sanitizer statistics gathering -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h index a1dfed29a22d..dec73ef057e8 100644 --- a/include/llvm/Transforms/Utils/SimplifyIndVar.h +++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -1,9 +1,8 @@ //===-- llvm/Transforms/Utils/SimplifyIndVar.h - Indvar Utils ---*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 025bcd44e310..2572094ddac8 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -1,9 +1,8 @@ //===- SimplifyLibCalls.h - Library call simplifier -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -29,6 +28,8 @@ class TargetLibraryInfo; class BasicBlock; class Function; class OptimizationRemarkEmitter; +class BlockFrequencyInfo; +class ProfileSummaryInfo; /// This class implements simplifications for calls to fortified library /// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to, @@ -56,14 +57,41 @@ private: Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B); Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B); - // Str/Stp cpy are similar enough to be handled in the same functions. + /// Str/Stp cpy are similar enough to be handled in the same functions. Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); + Value *optimizeMemCCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeSNPrintfChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeSPrintfChk(CallInst *CI,IRBuilder<> &B); + Value *optimizeStrCatChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrLCat(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCatChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrLCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeVSNPrintfChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeVSPrintfChk(CallInst *CI, IRBuilder<> &B); /// Checks whether the call \p CI to a fortified libcall is foldable /// to the non-fortified version. + /// + /// \param CI the call to the fortified libcall. + /// + /// \param ObjSizeOp the index of the object size parameter of this chk + /// function. Not optional since this is mandatory. + /// + /// \param SizeOp optionally set to the parameter index of an explicit buffer + /// size argument. For instance, set to '2' for __strncpy_chk. + /// + /// \param StrOp optionally set to the parameter index of the source string + /// parameter to strcpy-like functions, where only the strlen of the source + /// will be writtin into the destination. + /// + /// \param FlagsOp optionally set to the parameter index of a 'flags' + /// parameter. These are used by an implementation to opt-into stricter + /// checking. bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp, - unsigned SizeOp, bool isString); + Optional<unsigned> SizeOp = None, + Optional<unsigned> StrOp = None, + Optional<unsigned> FlagsOp = None); }; /// LibCallSimplifier - This class implements a collection of optimizations @@ -75,6 +103,8 @@ private: const DataLayout &DL; const TargetLibraryInfo *TLI; OptimizationRemarkEmitter &ORE; + BlockFrequencyInfo *BFI; + ProfileSummaryInfo *PSI; bool UnsafeFPShrink; function_ref<void(Instruction *, Value *)> Replacer; function_ref<void(Instruction *)> Eraser; @@ -102,6 +132,7 @@ public: LibCallSimplifier( const DataLayout &DL, const TargetLibraryInfo *TLI, OptimizationRemarkEmitter &ORE, + BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, function_ref<void(Instruction *, Value *)> Replacer = &replaceAllUsesWithDefault, function_ref<void(Instruction *)> Eraser = &eraseFromParentDefault); @@ -134,6 +165,8 @@ private: Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeBCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCmpBCmpCommon(CallInst *CI, IRBuilder<> &B); Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); diff --git a/include/llvm/Transforms/Utils/SizeOpts.h b/include/llvm/Transforms/Utils/SizeOpts.h new file mode 100644 index 000000000000..1a052c694e6d --- /dev/null +++ b/include/llvm/Transforms/Utils/SizeOpts.h @@ -0,0 +1,34 @@ +//===- llvm/Transforms/Utils/SizeOpts.h - size optimization -----*- 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 shared code size optimization related code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SIZEOPTS_H +#define LLVM_TRANSFORMS_UTILS_SIZEOPTS_H + +namespace llvm { + +class BasicBlock; +class BlockFrequencyInfo; +class Function; +class ProfileSummaryInfo; + +/// Returns true if function \p F is suggested to be size-optimized base on the +/// profile. +bool shouldOptimizeForSize(Function *F, ProfileSummaryInfo *PSI, + BlockFrequencyInfo *BFI); +/// Returns true if basic block \p BB is suggested to be size-optimized base +/// on the profile. +bool shouldOptimizeForSize(BasicBlock *BB, ProfileSummaryInfo *PSI, + BlockFrequencyInfo *BFI); + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_SIZEOPTS_H diff --git a/include/llvm/Transforms/Utils/SplitModule.h b/include/llvm/Transforms/Utils/SplitModule.h index d2c31f2701ac..7839c5d9a589 100644 --- a/include/llvm/Transforms/Utils/SplitModule.h +++ b/include/llvm/Transforms/Utils/SplitModule.h @@ -1,9 +1,8 @@ //===- SplitModule.h - Split a module into partitions -----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h index 5f6488e08b5a..ce9dcaf2b74f 100644 --- a/include/llvm/Transforms/Utils/SymbolRewriter.h +++ b/include/llvm/Transforms/Utils/SymbolRewriter.h @@ -1,9 +1,8 @@ //===- SymbolRewriter.h - Symbol Rewriting Pass -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 222c601ad608..f68534ecd2eb 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -1,9 +1,8 @@ //===-- UnifyFunctionExitNodes.h - Ensure fn's have one return --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index 70e936d75008..593ca26feb98 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Utils/UnrollLoop.h - Unrolling utilities -*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -25,11 +24,13 @@ namespace llvm { class AssumptionCache; class BasicBlock; +class BlockFrequencyInfo; class DependenceInfo; class DominatorTree; class Loop; class LoopInfo; class MDNode; +class ProfileSummaryInfo; class OptimizationRemarkEmitter; class ScalarEvolution; @@ -63,22 +64,31 @@ enum class LoopUnrollResult { FullyUnrolled }; -LoopUnrollResult UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, - bool Force, bool AllowRuntime, - bool AllowExpensiveTripCount, bool PreserveCondBr, - bool PreserveOnlyFirst, unsigned TripMultiple, - unsigned PeelCount, bool UnrollRemainder, - LoopInfo *LI, ScalarEvolution *SE, - DominatorTree *DT, AssumptionCache *AC, - OptimizationRemarkEmitter *ORE, bool PreserveLCSSA, - Loop **RemainderLoop = nullptr); +struct UnrollLoopOptions { + unsigned Count; + unsigned TripCount; + bool Force; + bool AllowRuntime; + bool AllowExpensiveTripCount; + bool PreserveCondBr; + bool PreserveOnlyFirst; + unsigned TripMultiple; + unsigned PeelCount; + bool UnrollRemainder; + bool ForgetAllSCEV; +}; + +LoopUnrollResult UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, + ScalarEvolution *SE, DominatorTree *DT, + AssumptionCache *AC, OptimizationRemarkEmitter *ORE, + bool PreserveLCSSA, Loop **RemainderLoop = nullptr); bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count, bool AllowExpensiveTripCount, bool UseEpilogRemainder, bool UnrollRemainder, - LoopInfo *LI, ScalarEvolution *SE, - DominatorTree *DT, AssumptionCache *AC, - bool PreserveLCSSA, + bool ForgetAllSCEV, LoopInfo *LI, + ScalarEvolution *SE, DominatorTree *DT, + AssumptionCache *AC, bool PreserveLCSSA, Loop **ResultLoop = nullptr); void computePeelCount(Loop *L, unsigned LoopSize, @@ -109,9 +119,6 @@ bool computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, TargetTransformInfo::UnrollingPreferences &UP, bool &UseUpperBound); -BasicBlock *foldBlockIntoPredecessor(BasicBlock *BB, LoopInfo *LI, - ScalarEvolution *SE, DominatorTree *DT); - void remapInstruction(Instruction *I, ValueToValueMapTy &VMap); void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI, @@ -121,7 +128,8 @@ void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI, MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name); TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences( - Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, int OptLevel, + Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, + BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, int OptLevel, Optional<unsigned> UserThreshold, Optional<unsigned> UserCount, Optional<bool> UserAllowPartial, Optional<bool> UserRuntime, Optional<bool> UserUpperBound, Optional<bool> UserAllowPeeling); diff --git a/include/llvm/Transforms/Utils/VNCoercion.h b/include/llvm/Transforms/Utils/VNCoercion.h index 1baa9b66e491..f67b9ed0afdd 100644 --- a/include/llvm/Transforms/Utils/VNCoercion.h +++ b/include/llvm/Transforms/Utils/VNCoercion.h @@ -1,9 +1,8 @@ //===- VNCoercion.h - Value Numbering Coercion Utilities --------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 routines used by LLVM's value numbering passes to diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index 4ecb23ea1951..1952a210291e 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -1,9 +1,8 @@ //===- ValueMapper.h - Remapping for constants and metadata -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 70f9a2e0741b..88a0e49d0fae 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -1,9 +1,8 @@ //===-- Vectorize.h - Vectorization Transformations -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -110,8 +109,9 @@ struct VectorizeConfig { // // LoopVectorize - Create a loop vectorization pass. // -Pass *createLoopVectorizePass(bool InterleaveOnlyWhenForced = false, - bool VectorizeOnlyWhenForced = false); +Pass *createLoopVectorizePass(); +Pass *createLoopVectorizePass(bool InterleaveOnlyWhenForced, + bool VectorizeOnlyWhenForced); //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Vectorize/LoadStoreVectorizer.h b/include/llvm/Transforms/Vectorize/LoadStoreVectorizer.h index 6b37d7093c44..f72c76c6f0f2 100644 --- a/include/llvm/Transforms/Vectorize/LoadStoreVectorizer.h +++ b/include/llvm/Transforms/Vectorize/LoadStoreVectorizer.h @@ -1,9 +1,8 @@ //===- LoadStoreVectorizer.cpp - GPU Load & Store Vectorizer --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// diff --git a/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h index 5c7bba048607..b144006e2628 100644 --- a/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h +++ b/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h @@ -1,9 +1,8 @@ //===- llvm/Transforms/Vectorize/LoopVectorizationLegality.h ----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -99,11 +98,7 @@ public: OptimizationRemarkEmitter &ORE); /// Mark the loop L as already vectorized by setting the width to 1. - void setAlreadyVectorized() { - IsVectorized.Value = 1; - Hint Hints[] = {IsVectorized}; - writeHintsToMetadata(Hints); - } + void setAlreadyVectorized(); bool allowVectorization(Function *F, Loop *L, bool VectorizeOnlyWhenForced) const; @@ -152,15 +147,6 @@ private: /// Checks string hint with one operand and set value if valid. void setHint(StringRef Name, Metadata *Arg); - /// Create a new hint from name / value pair. - MDNode *createHintMetadata(StringRef Name, unsigned V) const; - - /// Matches metadata with hint name. - bool matchesHintMetadataName(MDNode *Node, ArrayRef<Hint> HintTypes); - - /// Sets current hints into loop metadata, keeping other values intact. - void writeHintsToMetadata(ArrayRef<Hint> HintTypes); - /// The loop these hints belong to. const Loop *TheLoop; @@ -219,12 +205,13 @@ class LoopVectorizationLegality { public: LoopVectorizationLegality( Loop *L, PredicatedScalarEvolution &PSE, DominatorTree *DT, - TargetLibraryInfo *TLI, AliasAnalysis *AA, Function *F, - std::function<const LoopAccessInfo &(Loop &)> *GetLAA, LoopInfo *LI, - OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R, - LoopVectorizeHints *H, DemandedBits *DB, AssumptionCache *AC) - : TheLoop(L), LI(LI), PSE(PSE), TLI(TLI), DT(DT), GetLAA(GetLAA), - ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC) {} + TargetTransformInfo *TTI, TargetLibraryInfo *TLI, AliasAnalysis *AA, + Function *F, std::function<const LoopAccessInfo &(Loop &)> *GetLAA, + LoopInfo *LI, OptimizationRemarkEmitter *ORE, + LoopVectorizationRequirements *R, LoopVectorizeHints *H, DemandedBits *DB, + AssumptionCache *AC) + : TheLoop(L), LI(LI), PSE(PSE), TTI(TTI), TLI(TLI), DT(DT), + GetLAA(GetLAA), ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC) {} /// ReductionList contains the reduction descriptors for all /// of the reductions that were found in the loop. @@ -385,18 +372,6 @@ private: void addInductionPhi(PHINode *Phi, const InductionDescriptor &ID, SmallPtrSetImpl<Value *> &AllowedExit); - /// Create an analysis remark that explains why vectorization failed - /// - /// \p RemarkName is the identifier for the remark. If \p I is passed it is - /// an instruction that prevents vectorization. Otherwise the loop is used - /// for the location of the remark. \return the remark object that can be - /// streamed to. - OptimizationRemarkAnalysis - createMissedAnalysis(StringRef RemarkName, Instruction *I = nullptr) const { - return createLVMissedAnalysis(Hints->vectorizeAnalysisPassName(), - RemarkName, TheLoop, I); - } - /// If an access has a symbolic strides, this maps the pointer value to /// the stride symbol. const ValueToValueMap *getSymbolicStrides() { @@ -407,6 +382,14 @@ private: return LAI ? &LAI->getSymbolicStrides() : nullptr; } + /// Reports a vectorization illegality: print \p DebugMsg for debugging + /// purposes along with the corresponding optimization remark \p RemarkName. + /// If \p I is passed it is an instruction that prevents vectorization. + /// Otherwise the loop is used for the location of the remark. + void reportVectorizationFailure(const StringRef DebugMsg, + const StringRef OREMsg, const StringRef ORETag, + Instruction *I = nullptr) const; + /// The loop that we evaluate. Loop *TheLoop; @@ -420,6 +403,9 @@ private: /// unrolling. PredicatedScalarEvolution &PSE; + /// Target Transform Info. + TargetTransformInfo *TTI; + /// Target Library Info. TargetLibraryInfo *TLI; @@ -479,7 +465,7 @@ private: /// Used to emit an analysis of any legality issues. LoopVectorizeHints *Hints; - /// The demanded bits analsyis is used to compute the minimum type size in + /// The demanded bits analysis is used to compute the minimum type size in /// which a reduction can be computed. DemandedBits *DB; diff --git a/include/llvm/Transforms/Vectorize/LoopVectorize.h b/include/llvm/Transforms/Vectorize/LoopVectorize.h index d9c4f7b023c1..d1ec06afb02a 100644 --- a/include/llvm/Transforms/Vectorize/LoopVectorize.h +++ b/include/llvm/Transforms/Vectorize/LoopVectorize.h @@ -1,9 +1,8 @@ //===- LoopVectorize.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -72,19 +71,63 @@ class Loop; class LoopAccessInfo; class LoopInfo; class OptimizationRemarkEmitter; +class ProfileSummaryInfo; class ScalarEvolution; class TargetLibraryInfo; class TargetTransformInfo; +extern cl::opt<bool> EnableLoopInterleaving; +extern cl::opt<bool> EnableLoopVectorization; + +struct LoopVectorizeOptions { + /// If false, consider all loops for interleaving. + /// If true, only loops that explicitly request interleaving are considered. + bool InterleaveOnlyWhenForced; + + /// If false, consider all loops for vectorization. + /// If true, only loops that explicitly request vectorization are considered. + bool VectorizeOnlyWhenForced; + + /// The current defaults when creating the pass with no arguments are: + /// EnableLoopInterleaving = true and EnableLoopVectorization = true. This + /// means that interleaving default is consistent with the cl::opt flag, while + /// vectorization is not. + /// FIXME: The default for EnableLoopVectorization in the cl::opt should be + /// set to true, and the corresponding change to account for this be made in + /// opt.cpp. The initializations below will become: + /// InterleaveOnlyWhenForced(!EnableLoopInterleaving) + /// VectorizeOnlyWhenForced(!EnableLoopVectorization). + LoopVectorizeOptions() + : InterleaveOnlyWhenForced(false), VectorizeOnlyWhenForced(false) {} + LoopVectorizeOptions(bool InterleaveOnlyWhenForced, + bool VectorizeOnlyWhenForced) + : InterleaveOnlyWhenForced(InterleaveOnlyWhenForced), + VectorizeOnlyWhenForced(VectorizeOnlyWhenForced) {} + + LoopVectorizeOptions &setInterleaveOnlyWhenForced(bool Value) { + InterleaveOnlyWhenForced = Value; + return *this; + } + + LoopVectorizeOptions &setVectorizeOnlyWhenForced(bool Value) { + VectorizeOnlyWhenForced = Value; + return *this; + } +}; + /// The LoopVectorize Pass. struct LoopVectorizePass : public PassInfoMixin<LoopVectorizePass> { /// If false, consider all loops for interleaving. /// If true, only loops that explicitly request interleaving are considered. - bool InterleaveOnlyWhenForced = false; + bool InterleaveOnlyWhenForced; /// If false, consider all loops for vectorization. /// If true, only loops that explicitly request vectorization are considered. - bool VectorizeOnlyWhenForced = false; + bool VectorizeOnlyWhenForced; + + LoopVectorizePass(LoopVectorizeOptions Opts = {}) + : InterleaveOnlyWhenForced(Opts.InterleaveOnlyWhenForced), + VectorizeOnlyWhenForced(Opts.VectorizeOnlyWhenForced) {} ScalarEvolution *SE; LoopInfo *LI; @@ -97,6 +140,7 @@ struct LoopVectorizePass : public PassInfoMixin<LoopVectorizePass> { AssumptionCache *AC; std::function<const LoopAccessInfo &(Loop &)> *GetLAA; OptimizationRemarkEmitter *ORE; + ProfileSummaryInfo *PSI; PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); @@ -106,7 +150,7 @@ struct LoopVectorizePass : public PassInfoMixin<LoopVectorizePass> { BlockFrequencyInfo &BFI_, TargetLibraryInfo *TLI_, DemandedBits &DB_, AliasAnalysis &AA_, AssumptionCache &AC_, std::function<const LoopAccessInfo &(Loop &)> &GetLAA_, - OptimizationRemarkEmitter &ORE); + OptimizationRemarkEmitter &ORE_, ProfileSummaryInfo *PSI_); bool processLoop(Loop *L); }; diff --git a/include/llvm/Transforms/Vectorize/SLPVectorizer.h b/include/llvm/Transforms/Vectorize/SLPVectorizer.h index 3152e8192fc5..ac6afb761d4d 100644 --- a/include/llvm/Transforms/Vectorize/SLPVectorizer.h +++ b/include/llvm/Transforms/Vectorize/SLPVectorizer.h @@ -1,9 +1,8 @@ //===- SLPVectorizer.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 the Bottom Up SLP vectorizer. It detects consecutive @@ -56,6 +55,8 @@ class BoUpSLP; } // end namespace slpvectorizer +extern cl::opt<bool> RunSLPVectorization; + struct SLPVectorizerPass : public PassInfoMixin<SLPVectorizerPass> { using StoreList = SmallVector<StoreInst *, 8>; using StoreListMap = MapVector<Value *, StoreList>; diff --git a/include/llvm/WindowsManifest/WindowsManifestMerger.h b/include/llvm/WindowsManifest/WindowsManifestMerger.h index 302d3705887b..935c930ad91d 100644 --- a/include/llvm/WindowsManifest/WindowsManifestMerger.h +++ b/include/llvm/WindowsManifest/WindowsManifestMerger.h @@ -1,9 +1,8 @@ //===-- WindowsManifestMerger.h ---------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// // diff --git a/include/llvm/WindowsResource/ResourceProcessor.h b/include/llvm/WindowsResource/ResourceProcessor.h index 4ca0a4b05bd0..4e99c05f4cd9 100644 --- a/include/llvm/WindowsResource/ResourceProcessor.h +++ b/include/llvm/WindowsResource/ResourceProcessor.h @@ -1,9 +1,8 @@ //===-- ResourceProcessor.h -------------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// diff --git a/include/llvm/WindowsResource/ResourceScriptToken.h b/include/llvm/WindowsResource/ResourceScriptToken.h index 494ae3222a4b..254121cd318a 100644 --- a/include/llvm/WindowsResource/ResourceScriptToken.h +++ b/include/llvm/WindowsResource/ResourceScriptToken.h @@ -1,9 +1,8 @@ //===-- ResourceScriptToken.h -----------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// // diff --git a/include/llvm/WindowsResource/ResourceScriptTokenList.h b/include/llvm/WindowsResource/ResourceScriptTokenList.h index 0beed117c3e7..6b44dccaa35f 100644 --- a/include/llvm/WindowsResource/ResourceScriptTokenList.h +++ b/include/llvm/WindowsResource/ResourceScriptTokenList.h @@ -1,9 +1,8 @@ //===-- ResourceScriptTokenList.h -------------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===---------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/BlockIndexer.h b/include/llvm/XRay/BlockIndexer.h index b42fa17f3fb7..dafd2b5a5230 100644 --- a/include/llvm/XRay/BlockIndexer.h +++ b/include/llvm/XRay/BlockIndexer.h @@ -1,9 +1,8 @@ //===- BlockIndexer.h - FDR Block Indexing Visitor ------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/BlockPrinter.h b/include/llvm/XRay/BlockPrinter.h index bfb21e239517..949258085332 100644 --- a/include/llvm/XRay/BlockPrinter.h +++ b/include/llvm/XRay/BlockPrinter.h @@ -1,9 +1,8 @@ //===- BlockPrinter.h - FDR Block Pretty Printer -------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/BlockVerifier.h b/include/llvm/XRay/BlockVerifier.h index 46371c13891a..c848fdf084bc 100644 --- a/include/llvm/XRay/BlockVerifier.h +++ b/include/llvm/XRay/BlockVerifier.h @@ -1,9 +1,8 @@ //===- BlockVerifier.h - FDR Block Verifier -------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/FDRLogBuilder.h b/include/llvm/XRay/FDRLogBuilder.h index b5e9ed5c406b..3f49dc6dcb9d 100644 --- a/include/llvm/XRay/FDRLogBuilder.h +++ b/include/llvm/XRay/FDRLogBuilder.h @@ -1,9 +1,8 @@ //===- FDRLogBuilder.h - XRay FDR Log Building Utility --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_INCLUDE_LLVM_XRAY_FDRLOGBUILDER_H_ diff --git a/include/llvm/XRay/FDRRecordConsumer.h b/include/llvm/XRay/FDRRecordConsumer.h index e856e1540558..4fbb1d41d0da 100644 --- a/include/llvm/XRay/FDRRecordConsumer.h +++ b/include/llvm/XRay/FDRRecordConsumer.h @@ -1,9 +1,8 @@ //===- FDRRecordConsumer.h - XRay Flight Data Recorder Mode Records -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_INCLUDE_LLVM_XRAY_FDRRECORDCONSUMER_H_ diff --git a/include/llvm/XRay/FDRRecordProducer.h b/include/llvm/XRay/FDRRecordProducer.h index efdba2a67b7b..b530a85bc7e1 100644 --- a/include/llvm/XRay/FDRRecordProducer.h +++ b/include/llvm/XRay/FDRRecordProducer.h @@ -1,9 +1,8 @@ //===- FDRRecordProducer.h - XRay FDR Mode Record Producer ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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_INCLUDE_LLVM_XRAY_FDRRECORDPRODUCER_H_ diff --git a/include/llvm/XRay/FDRRecords.h b/include/llvm/XRay/FDRRecords.h index 8a84f4d0c1fb..a8ce74bd88fb 100644 --- a/include/llvm/XRay/FDRRecords.h +++ b/include/llvm/XRay/FDRRecords.h @@ -1,9 +1,8 @@ //===- FDRRecords.h - XRay Flight Data Recorder Mode Records --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/FDRTraceExpander.h b/include/llvm/XRay/FDRTraceExpander.h index 02a21bed5ce9..f3c36cf4cf66 100644 --- a/include/llvm/XRay/FDRTraceExpander.h +++ b/include/llvm/XRay/FDRTraceExpander.h @@ -1,9 +1,8 @@ //===- FDRTraceExpander.h - XRay FDR Mode Log Expander --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/FDRTraceWriter.h b/include/llvm/XRay/FDRTraceWriter.h index 7b3b5fa25eff..2498877e27c1 100644 --- a/include/llvm/XRay/FDRTraceWriter.h +++ b/include/llvm/XRay/FDRTraceWriter.h @@ -1,9 +1,8 @@ //===- FDRTraceWriter.h - XRay FDR Trace Writer -----------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/FileHeaderReader.h b/include/llvm/XRay/FileHeaderReader.h index 3b8809bdbb34..1c9681cfd9af 100644 --- a/include/llvm/XRay/FileHeaderReader.h +++ b/include/llvm/XRay/FileHeaderReader.h @@ -1,9 +1,8 @@ //===- FileHeaderReader.h - XRay Trace File Header Reading Function -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/Graph.h b/include/llvm/XRay/Graph.h index a4d34a8a4be3..004681512800 100644 --- a/include/llvm/XRay/Graph.h +++ b/include/llvm/XRay/Graph.h @@ -1,9 +1,8 @@ //===-- Graph.h - XRay Graph Class ------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/InstrumentationMap.h b/include/llvm/XRay/InstrumentationMap.h index 42bfca36a20b..5cbe5c44893b 100644 --- a/include/llvm/XRay/InstrumentationMap.h +++ b/include/llvm/XRay/InstrumentationMap.h @@ -1,9 +1,8 @@ //===- InstrumentationMap.h - XRay Instrumentation Map ----------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/Profile.h b/include/llvm/XRay/Profile.h index 9365630358e8..79d9b53387f3 100644 --- a/include/llvm/XRay/Profile.h +++ b/include/llvm/XRay/Profile.h @@ -1,9 +1,8 @@ //===- Profile.h - XRay Profile Abstraction -------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/RecordPrinter.h b/include/llvm/XRay/RecordPrinter.h index 649c64ab6f5c..7c7b7a32c56d 100644 --- a/include/llvm/XRay/RecordPrinter.h +++ b/include/llvm/XRay/RecordPrinter.h @@ -1,9 +1,8 @@ //===- RecordPrinter.h - FDR Record Printer -------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/Trace.h b/include/llvm/XRay/Trace.h index 924addd1560d..eb1f03b2a0d4 100644 --- a/include/llvm/XRay/Trace.h +++ b/include/llvm/XRay/Trace.h @@ -1,9 +1,8 @@ //===- Trace.h - XRay Trace Abstraction -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/XRayRecord.h b/include/llvm/XRay/XRayRecord.h index 7685ec95838a..546b02303b6a 100644 --- a/include/llvm/XRay/XRayRecord.h +++ b/include/llvm/XRay/XRayRecord.h @@ -1,9 +1,8 @@ //===- XRayRecord.h - XRay Trace Record -----------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/XRay/YAMLXRayRecord.h b/include/llvm/XRay/YAMLXRayRecord.h index 6150196ed98d..bc8b03548d6e 100644 --- a/include/llvm/XRay/YAMLXRayRecord.h +++ b/include/llvm/XRay/YAMLXRayRecord.h @@ -1,9 +1,8 @@ //===- YAMLXRayRecord.h - XRay Record YAML Support Definitions ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap index bcc12534ec85..9c4668e1473c 100644 --- a/include/llvm/module.modulemap +++ b/include/llvm/module.modulemap @@ -5,6 +5,7 @@ module LLVM_Analysis { // This is intended for (repeated) textual inclusion. textual header "Analysis/TargetLibraryInfo.def" + textual header "Analysis/VecFuncs.def" } module LLVM_AsmParser { @@ -53,6 +54,7 @@ module LLVM_BinaryFormat { textual header "BinaryFormat/Dwarf.def" textual header "BinaryFormat/DynamicTags.def" textual header "BinaryFormat/MachO.def" + textual header "BinaryFormat/MinidumpConstants.def" textual header "BinaryFormat/ELFRelocs/AArch64.def" textual header "BinaryFormat/ELFRelocs/AMDGPU.def" textual header "BinaryFormat/ELFRelocs/ARM.def" @@ -220,7 +222,7 @@ module LLVM_intrinsic_gen { module IR_ConstantRange { header "IR/ConstantRange.h" export * } module IR_Dominators { header "IR/Dominators.h" export * } module Analysis_PostDominators { header "Analysis/PostDominators.h" export * } - module IR_DomTreeUpdater { header "IR/DomTreeUpdater.h" export * } + module Analysis_DomTreeUpdater { header "Analysis/DomTreeUpdater.h" export * } module IR_IRBuilder { header "IR/IRBuilder.h" export * } module IR_PassManager { header "IR/PassManager.h" export * } module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * } @@ -235,6 +237,7 @@ module LLVM_intrinsic_gen { } module IR_IntrinsicInst { header "IR/IntrinsicInst.h" export * } module IR_PatternMatch { header "IR/PatternMatch.h" export * } + module IR_SafepointIRVerifier { header "IR/SafepointIRVerifier.h" export * } module IR_Statepoint { header "IR/Statepoint.h" export * } export * |