From 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Jun 16 2017 21:03:24 +0000 Subject: Vendor import of llvm trunk r305575: https://llvm.org/svn/llvm-project/llvm/trunk@305575 --- diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake index 17ae1c9..21421e4 100644 --- a/cmake/modules/TableGen.cmake +++ b/cmake/modules/TableGen.cmake @@ -35,38 +35,24 @@ function(tablegen project ofn) # a tablegen change, as cmake does not propagate file-level dependencies # of custom targets. See the following ticket for more information: # https://cmake.org/Bug/view.php?id=15858 - # We could always have just one dependency on both the target and - # the file, but these 2 cases would produce cleaner cmake files. - if (${${project}_TABLEGEN_TARGET} STREQUAL ${${project}_TABLEGEN_EXE}) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - # Generate tablegen output in a temporary file. - COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} - ${LLVM_TABLEGEN_FLAGS} - ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} - -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - # The file in LLVM_TARGET_DEFINITIONS may be not in the current - # directory and local_tds may not contain it, so we must - # explicitly list it here: - DEPENDS ${${project}_TABLEGEN_TARGET} ${local_tds} ${global_tds} - ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} - COMMENT "Building ${ofn}..." - ) - else() - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - # Generate tablegen output in a temporary file. - COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} - ${LLVM_TABLEGEN_FLAGS} - ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} - -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp - # The file in LLVM_TARGET_DEFINITIONS may be not in the current - # directory and local_tds may not contain it, so we must - # explicitly list it here: - DEPENDS ${${project}_TABLEGEN_TARGET} ${${project}_TABLEGEN_EXE} - ${local_tds} ${global_tds} - ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} - COMMENT "Building ${ofn}..." - ) - endif() + # The dependency on both, the target and the file, produces the same + # dependency twice in the result file when + # ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}") + # but lets us having smaller and cleaner code here. + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # Generate tablegen output in a temporary file. + COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} + ${LLVM_TABLEGEN_FLAGS} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # The file in LLVM_TARGET_DEFINITIONS may be not in the current + # directory and local_tds may not contain it, so we must + # explicitly list it here: + DEPENDS ${${project}_TABLEGEN_TARGET} ${${project}_TABLEGEN_EXE} + ${local_tds} ${global_tds} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + COMMENT "Building ${ofn}..." + ) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} # Only update the real output file if there are any differences. # This prevents recompilation of all the files depending on it if there diff --git a/docs/BranchWeightMetadata.rst b/docs/BranchWeightMetadata.rst index b941d0d..9bd8bd4 100644 --- a/docs/BranchWeightMetadata.rst +++ b/docs/BranchWeightMetadata.rst @@ -64,6 +64,20 @@ Branch weights are assigned to every destination. [ , i32 ... ] } +``CallInst`` +^^^^^^^^^^^^^^^^^^ + +Calls may have branch weight metadata, containing the execution count of +the call. It is currently used in SamplePGO mode only, to augment the +block and entry counts which may not be accurate with sampling. + +.. code-block:: none + + !0 = metadata !{ + metadata !"branch_weights", + i32 + } + Other ^^^^^ diff --git a/docs/LangRef.rst b/docs/LangRef.rst index e063f6b..68aa500 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -4033,26 +4033,26 @@ DICompileUnit """"""""""""" ``DICompileUnit`` nodes represent a compile unit. The ``enums:``, -``retainedTypes:``, ``subprograms:``, ``globals:``, ``imports:`` and ``macros:`` -fields are tuples containing the debug info to be emitted along with the compile -unit, regardless of code optimizations (some nodes are only emitted if there are -references to them from instructions). The ``debugInfoForProfiling:`` field is a -boolean indicating whether or not line-table discriminators are updated to -provide more-accurate debug info for profiling results. +``retainedTypes:``, ``globals:``, ``imports:`` and ``macros:`` fields are tuples +containing the debug info to be emitted along with the compile unit, regardless +of code optimizations (some nodes are only emitted if there are references to +them from instructions). The ``debugInfoForProfiling:`` field is a boolean +indicating whether or not line-table discriminators are updated to provide +more-accurate debug info for profiling results. .. code-block:: text !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, flags: "-O2", runtimeVersion: 2, splitDebugFilename: "abc.debug", emissionKind: FullDebug, - enums: !2, retainedTypes: !3, subprograms: !4, - globals: !5, imports: !6, macros: !7, dwoId: 0x0abcd) + enums: !2, retainedTypes: !3, globals: !4, imports: !5, + macros: !6, dwoId: 0x0abcd) Compile unit descriptors provide the root scope for objects declared in a -specific compilation unit. File descriptors are defined using this scope. -These descriptors are collected by a named metadata ``!llvm.dbg.cu``. They -keep track of subprograms, global variables, type information, and imported -entities (declarations and namespaces). +specific compilation unit. File descriptors are defined using this scope. These +descriptors are collected by a named metadata node ``!llvm.dbg.cu``. They keep +track of global variables, type information, and imported entities (declarations +and namespaces). .. _DIFile: @@ -4326,8 +4326,8 @@ and ``scope:``. containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, flags: DIFlagPrototyped, - isOptimized: true, templateParams: !5, - declaration: !6, variables: !7) + isOptimized: true, unit: !5, templateParams: !6, + declaration: !7, variables: !8, thrownTypes: !9) .. _DILexicalBlock: @@ -4404,7 +4404,12 @@ referenced LLVM variable relates to the source language variable. The current supported vocabulary is limited: - ``DW_OP_deref`` dereferences the top of the expression stack. -- ``DW_OP_plus, 93`` adds ``93`` to the working expression. +- ``DW_OP_plus`` pops the last two entries from the expression stack, adds + them together and appends the result to the expression stack. +- ``DW_OP_minus`` pops the last two entries from the expression stack, subtracts + the last entry from the second last entry and appends the result to the + expression stack. +- ``DW_OP_plus_uconst, 93`` adds ``93`` to the working expression. - ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8`` here, respectively) of the variable fragment from the working expression. Note that contrary to DW_OP_bit_piece, the offset is describing the the location @@ -4426,9 +4431,10 @@ combined with a concrete location. .. code-block:: llvm !0 = !DIExpression(DW_OP_deref) - !1 = !DIExpression(DW_OP_plus, 3) + !1 = !DIExpression(DW_OP_plus_uconst, 3) + !1 = !DIExpression(DW_OP_constu, 3, DW_OP_plus) !2 = !DIExpression(DW_OP_bit_piece, 3, 7) - !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) + !3 = !DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_fragment, 3, 7) !4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) !5 = !DIExpression(DW_OP_constu, 42, DW_OP_stack_value) @@ -5186,6 +5192,72 @@ Example: !0 = !{i32* @a} +'``prof``' Metadata +^^^^^^^^^^^^^^^^^^^ + +The ``prof`` metadata is used to record profile data in the IR. +The first operand of the metadata node indicates the profile metadata +type. There are currently 3 types: +:ref:`branch_weights`, +:ref:`function_entry_count`, and +:ref:`VP`. + +.. _prof_node_branch_weights: + +branch_weights +"""""""""""""" + +Branch weight metadata attached to a branch, select, switch or call instruction +represents the likeliness of the associated branch being taken. +For more information, see :doc:`BranchWeightMetadata`. + +.. _prof_node_function_entry_count: + +function_entry_count +"""""""""""""""""""" + +Function entry count metadata can be attached to function definitions +to record the number of times the function is called. Used with BFI +information, it is also used to derive the basic block profile count. +For more information, see :doc:`BranchWeightMetadata`. + +.. _prof_node_VP: + +VP +"" + +VP (value profile) metadata can be attached to instructions that have +value profile information. Currently this is indirect calls (where it +records the hottest callees) and calls to memory intrinsics such as memcpy, +memmove, and memset (where it records the hottest byte lengths). + +Each VP metadata node contains "VP" string, then a uint32_t value for the value +profiling kind, a uint64_t value for the total number of times the instruction +is executed, followed by uint64_t value and execution count pairs. +The value profiling kind is 0 for indirect call targets and 1 for memory +operations. For indirect call targets, each profile value is a hash +of the callee function name, and for memory operations each value is the +byte length. + +Note that the value counts do not need to add up to the total count +listed in the third operand (in practice only the top hottest values +are tracked and reported). + +Indirect call example: + +.. code-block:: llvm + + call void %f(), !prof !1 + !1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410} + +Note that the VP type is 0 (the second operand), which indicates this is +an indirect call value profile data. The third operand indicates that the +indirect call executed 1600 times. The 4th and 6th operands give the +hashes of the 2 hottest target functions' names (this is the same hash used +to represent function names in the profile database), and the 5th and 7th +operands give the execution count that each of the respective prior target +functions was called. + Module Flags Metadata ===================== @@ -5352,40 +5424,6 @@ Some important flag interactions: - A module with ``Objective-C Garbage Collection`` set to 0 cannot be merged with a module with ``Objective-C GC Only`` set to 6. -Automatic Linker Flags Module Flags Metadata --------------------------------------------- - -Some targets support embedding flags to the linker inside individual object -files. Typically this is used in conjunction with language extensions which -allow source files to explicitly declare the libraries they depend on, and have -these automatically be transmitted to the linker via object files. - -These flags are encoded in the IR using metadata in the module flags section, -using the ``Linker Options`` key. The merge behavior for this flag is required -to be ``AppendUnique``, and the value for the key is expected to be a metadata -node which should be a list of other metadata nodes, each of which should be a -list of metadata strings defining linker options. - -For example, the following metadata section specifies two separate sets of -linker options, presumably to link against ``libz`` and the ``Cocoa`` -framework:: - - !0 = !{ i32 6, !"Linker Options", - !{ - !{ !"-lz" }, - !{ !"-framework", !"Cocoa" } } } - !llvm.module.flags = !{ !0 } - -The metadata encoding as lists of lists of options, as opposed to a collapsed -list of options, is chosen so that the IR encoding can use multiple option -strings to specify e.g., a single library, while still having that specifier be -preserved as an atomic element that can be recognized by a target specific -assembly writer or object file emitter. - -Each individual option is required to be either a valid option for the target's -linker, or an option that is reserved by the target specific assembly writer or -object file emitter. No other aspect of these options is defined by the IR. - C type width Module Flags Metadata ---------------------------------- @@ -5422,6 +5460,37 @@ enum is the smallest type which can represent all of its values:: !0 = !{i32 1, !"short_wchar", i32 1} !1 = !{i32 1, !"short_enum", i32 0} +Automatic Linker Flags Named Metadata +===================================== + +Some targets support embedding flags to the linker inside individual object +files. Typically this is used in conjunction with language extensions which +allow source files to explicitly declare the libraries they depend on, and have +these automatically be transmitted to the linker via object files. + +These flags are encoded in the IR using named metadata with the name +``!llvm.linker.options``. Each operand is expected to be a metadata node +which should be a list of other metadata nodes, each of which should be a +list of metadata strings defining linker options. + +For example, the following metadata section specifies two separate sets of +linker options, presumably to link against ``libz`` and the ``Cocoa`` +framework:: + + !0 = !{ !"-lz" }, + !1 = !{ !"-framework", !"Cocoa" } } } + !llvm.linker.options = !{ !0, !1 } + +The metadata encoding as lists of lists of options, as opposed to a collapsed +list of options, is chosen so that the IR encoding can use multiple option +strings to specify e.g., a single library, while still having that specifier be +preserved as an atomic element that can be recognized by a target specific +assembly writer or object file emitter. + +Each individual option is required to be either a valid option for the target's +linker, or an option that is reserved by the target specific assembly writer or +object file emitter. No other aspect of these options is defined by the IR. + .. _intrinsicglobalvariables: Intrinsic Global Variables @@ -13999,62 +14068,66 @@ Element Wise Atomic Memory Intrinsics These intrinsics are similar to the standard library memory intrinsics except that they perform memory transfer as a sequence of atomic memory accesses. -.. _int_memcpy_element_atomic: +.. _int_memcpy_element_unordered_atomic: -'``llvm.memcpy.element.atomic``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'``llvm.memcpy.element.unordered.atomic``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" -This is an overloaded intrinsic. You can use ``llvm.memcpy.element.atomic`` on +This is an overloaded intrinsic. You can use ``llvm.memcpy.element.unordered.atomic`` on any integer bit width and for different address spaces. Not all targets support all bit widths however. :: - declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* , i8* , - i64 , i32 ) + declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* , + i8* , + i32 , + i32 ) + declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* , + i8* , + i64 , + i32 ) Overview: """"""""" -The '``llvm.memcpy.element.atomic.*``' intrinsic performs copy of a block of -memory from the source location to the destination location as a sequence of -unordered atomic memory accesses where each access is a multiple of -``element_size`` bytes wide and aligned at an element size boundary. For example -each element is accessed atomically in source and destination buffers. +The '``llvm.memcpy.element.unordered.atomic.*``' intrinsic is a specialization of the +'``llvm.memcpy.*``' intrinsic. It differs in that the ``dest`` and ``src`` are treated +as arrays with elements that are exactly ``element_size`` bytes, and the copy between +buffers uses a sequence of :ref:`unordered atomic ` load/store operations +that are a positive integer multiple of the ``element_size`` in size. Arguments: """""""""" -The first argument is a pointer to the destination, the second is a -pointer to the source. The third argument is an integer argument -specifying the number of elements to copy, the fourth argument is size of -the single element in bytes. +The first three arguments are the same as they are in the :ref:`@llvm.memcpy ` +intrinsic, with the added constraint that ``len`` is required to be a positive integer +multiple of the ``element_size``. If ``len`` is not a positive integer multiple of +``element_size``, then the behaviour of the intrinsic is undefined. -``element_size`` should be a power of two, greater than zero and less than -a target-specific atomic access size limit. +``element_size`` must be a compile-time constant positive power of two no greater than +target-specific atomic access size limit. -For each of the input pointers ``align`` parameter attribute must be specified. -It must be a power of two and greater than or equal to the ``element_size``. -Caller guarantees that both the source and destination pointers are aligned to -that boundary. +For each of the input pointers ``align`` parameter attribute must be specified. It +must be a power of two no less than the ``element_size``. Caller guarantees that +both the source and destination pointers are aligned to that boundary. Semantics: """""""""" -The '``llvm.memcpy.element.atomic.*``' intrinsic copies -'``num_elements`` * ``element_size``' bytes of memory from the source location to -the destination location. These locations are not allowed to overlap. Memory copy -is performed as a sequence of unordered atomic memory accesses where each access -is guaranteed to be a multiple of ``element_size`` bytes wide and aligned at an -element size boundary. +The '``llvm.memcpy.element.unordered.atomic.*``' intrinsic copies ``len`` bytes of +memory from the source location to the destination location. These locations are not +allowed to overlap. The memory copy is performed as a sequence of load/store operations +where each access is guaranteed to be a multiple of ``element_size`` bytes wide and +aligned at an ``element_size`` boundary. The order of the copy is unspecified. The same value may be read from the source buffer many times, but only one write is issued to the destination buffer per -element. It is well defined to have concurrent reads and writes to both source -and destination provided those reads and writes are at least unordered atomic. +element. It is well defined to have concurrent reads and writes to both source and +destination provided those reads and writes are unordered atomic when specified. This intrinsic does not provide any additional ordering guarantees over those provided by a set of unordered loads from the source location and stores to the @@ -14063,8 +14136,8 @@ destination. Lowering: """"""""" -In the most general case call to the '``llvm.memcpy.element.atomic.*``' is lowered -to a call to the symbol ``__llvm_memcpy_element_atomic_*``. Where '*' is replaced -with an actual element size. +In the most general case call to the '``llvm.memcpy.element.unordered.atomic.*``' is +lowered to a call to the symbol ``__llvm_memcpy_element_unordered_atomic_*``. Where '*' +is replaced with an actual element size. -Optimizer is allowed to inline memory copy when it's profitable to do so. +The optimizer is allowed to inline the memory copy when it's profitable to do so. diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst index ebc3fb7..ce7ed31 100644 --- a/docs/Lexicon.rst +++ b/docs/Lexicon.rst @@ -109,6 +109,13 @@ G Garbage Collection. The practice of using reachability analysis instead of explicit memory management to reclaim unused memory. +**GVN** + Global Value Numbering. GVN is a pass that partitions values computed by a + function into congruence classes. Values ending up in the same congruence + class are guaranteed to be the same for every execution of the program. + In that respect, congruency is a compile-time approximation of equivalence + of values at runtime. + H - diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst index 8d1984b..cc8484c 100644 --- a/docs/Phabricator.rst +++ b/docs/Phabricator.rst @@ -54,7 +54,8 @@ reviewer understand your code. To get a full diff, use one of the following commands (or just use Arcanist to upload your patch): -* ``git diff -U999999 other-branch`` +* ``git show HEAD -U999999 > mypatch.patch`` +* ``git format-patch -U999999 @{u}`` * ``svn diff --diff-cmd=diff -x -U999999`` To upload a new patch: diff --git a/include/llvm/ADT/AllocatorList.h b/include/llvm/ADT/AllocatorList.h index 05a549f..178c674 100644 --- a/include/llvm/ADT/AllocatorList.h +++ b/include/llvm/ADT/AllocatorList.h @@ -10,10 +10,16 @@ #ifndef LLVM_ADT_ALLOCATORLIST_H #define LLVM_ADT_ALLOCATORLIST_H +#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/simple_ilist.h" #include "llvm/Support/Allocator.h" +#include +#include +#include +#include #include +#include namespace llvm { @@ -39,7 +45,8 @@ template class AllocatorList : AllocatorT { T V; }; - typedef simple_ilist list_type; + using list_type = simple_ilist; + list_type List; AllocatorT &getAlloc() { return *this; } @@ -51,13 +58,17 @@ template class AllocatorList : AllocatorT { struct Cloner { AllocatorList &AL; + Cloner(AllocatorList &AL) : AL(AL) {} + Node *operator()(const Node &N) const { return AL.create(N.V); } }; struct Disposer { AllocatorList &AL; + Disposer(AllocatorList &AL) : AL(AL) {} + void operator()(Node *N) const { N->~Node(); AL.getAlloc().Deallocate(N); @@ -65,13 +76,13 @@ template class AllocatorList : AllocatorT { }; public: - typedef T value_type; - typedef T *pointer; - typedef T &reference; - typedef const T *const_pointer; - typedef const T &const_reference; - typedef typename list_type::size_type size_type; - typedef typename list_type::difference_type difference_type; + using value_type = T; + using pointer = T *; + using reference = T &; + using const_pointer = const T *; + using const_reference = const T &; + using size_type = typename list_type::size_type; + using difference_type = typename list_type::difference_type; private: template @@ -83,20 +94,18 @@ private: friend class IteratorImpl; friend AllocatorList; - typedef iterator_adaptor_base, - IteratorBase, std::bidirectional_iterator_tag, - ValueT> - base_type; + using base_type = + iterator_adaptor_base, IteratorBase, + std::bidirectional_iterator_tag, ValueT>; public: - typedef ValueT value_type; - typedef ValueT *pointer; - typedef ValueT &reference; + using value_type = ValueT; + using pointer = ValueT *; + using reference = ValueT &; IteratorImpl() = default; IteratorImpl(const IteratorImpl &) = default; IteratorImpl &operator=(const IteratorImpl &) = default; - ~IteratorImpl() = default; explicit IteratorImpl(const IteratorBase &I) : base_type(I) {} @@ -106,6 +115,8 @@ private: OtherIteratorBase, IteratorBase>::value>::type * = nullptr) : base_type(X.wrapped()) {} + ~IteratorImpl() = default; + reference operator*() const { return base_type::wrapped()->V; } pointer operator->() const { return &operator*(); } @@ -118,30 +129,34 @@ private: }; public: - typedef IteratorImpl iterator; - typedef IteratorImpl - reverse_iterator; - typedef IteratorImpl - const_iterator; - typedef IteratorImpl - const_reverse_iterator; + using iterator = IteratorImpl; + using reverse_iterator = + IteratorImpl; + using const_iterator = + IteratorImpl; + using const_reverse_iterator = + IteratorImpl; AllocatorList() = default; AllocatorList(AllocatorList &&X) : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {} + AllocatorList(const AllocatorList &X) { List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); } + AllocatorList &operator=(AllocatorList &&X) { clear(); // Dispose of current nodes explicitly. List = std::move(X.List); getAlloc() = std::move(X.getAlloc()); return *this; } + AllocatorList &operator=(const AllocatorList &X) { List.cloneFrom(X.List, Cloner(*this), Disposer(*this)); return *this; } + ~AllocatorList() { clear(); } void swap(AllocatorList &RHS) { diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 6b35d0a..925ebaf 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -1,4 +1,4 @@ -//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// +//===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,12 +12,21 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compiler.h" +#include #include +#include +#include +#include +#include +#include +#include #include namespace llvm { + /// ArrayRef - Represent a constant reference to an array (0 or more elements /// consecutively in memory), i.e. a start pointer and a length. It allows /// various APIs to take consecutive elements easily and conveniently. @@ -32,28 +41,27 @@ namespace llvm { template class LLVM_NODISCARD ArrayRef { public: - typedef const T *iterator; - typedef const T *const_iterator; - typedef size_t size_type; - - typedef std::reverse_iterator reverse_iterator; + using iterator = const T *; + using const_iterator = const T *; + using size_type = size_t; + using reverse_iterator = std::reverse_iterator; private: /// The start of the array, in an external buffer. - const T *Data; + const T *Data = nullptr; /// The number of elements. - size_type Length; + size_type Length = 0; public: /// @name Constructors /// @{ /// Construct an empty ArrayRef. - /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} + /*implicit*/ ArrayRef() = default; /// Construct an empty ArrayRef from None. - /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} + /*implicit*/ ArrayRef(NoneType) {} /// Construct an ArrayRef from a single element. /*implicit*/ ArrayRef(const T &OneElt) @@ -282,9 +290,8 @@ namespace llvm { template class LLVM_NODISCARD MutableArrayRef : public ArrayRef { public: - typedef T *iterator; - - typedef std::reverse_iterator reverse_iterator; + using iterator = T *; + using reverse_iterator = std::reverse_iterator; /// Construct an empty MutableArrayRef. /*implicit*/ MutableArrayRef() : ArrayRef() {} @@ -416,19 +423,23 @@ namespace llvm { /// This is a MutableArrayRef that owns its array. template class OwningArrayRef : public MutableArrayRef { public: - OwningArrayRef() {} + OwningArrayRef() = default; OwningArrayRef(size_t Size) : MutableArrayRef(new T[Size], Size) {} + OwningArrayRef(ArrayRef Data) : MutableArrayRef(new T[Data.size()], Data.size()) { std::copy(Data.begin(), Data.end(), this->begin()); } + OwningArrayRef(OwningArrayRef &&Other) { *this = Other; } + OwningArrayRef &operator=(OwningArrayRef &&Other) { delete[] this->data(); this->MutableArrayRef::operator=(Other); Other.MutableArrayRef::operator=(MutableArrayRef()); return *this; } + ~OwningArrayRef() { delete[] this->data(); } }; @@ -517,13 +528,14 @@ namespace llvm { // ArrayRefs can be treated like a POD type. template struct isPodLike; - template struct isPodLike > { + template struct isPodLike> { static const bool value = true; }; template hash_code hash_value(ArrayRef S) { return hash_combine_range(S.begin(), S.end()); } + } // end namespace llvm #endif // LLVM_ADT_ARRAYREF_H diff --git a/include/llvm/ADT/BreadthFirstIterator.h b/include/llvm/ADT/BreadthFirstIterator.h index eaeecb6..6bc63c2 100644 --- a/include/llvm/ADT/BreadthFirstIterator.h +++ b/include/llvm/ADT/BreadthFirstIterator.h @@ -25,7 +25,6 @@ #include "llvm/ADT/iterator_range.h" #include #include -#include #include namespace llvm { @@ -49,13 +48,13 @@ template , public bf_iterator_storage { - typedef std::iterator super; + using super = std::iterator; - typedef typename GT::NodeRef NodeRef; - typedef typename GT::ChildIteratorType ChildItTy; + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; // First element is the node reference, second is the next child to visit. - typedef std::pair> QueueElement; + using QueueElement = std::pair>; // Visit queue - used to maintain BFS ordering. // Optional<> because we need markers for levels. @@ -109,7 +108,7 @@ private: } public: - typedef typename super::pointer pointer; + using pointer = typename super::pointer; // Provide static begin and end methods as our public "constructors" static bf_iterator begin(const GraphT &G) { diff --git a/include/llvm/ADT/DAGDeltaAlgorithm.h b/include/llvm/ADT/DAGDeltaAlgorithm.h index 5ea0fe8..41fdd43 100644 --- a/include/llvm/ADT/DAGDeltaAlgorithm.h +++ b/include/llvm/ADT/DAGDeltaAlgorithm.h @@ -1,4 +1,4 @@ -//===--- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ----*- C++ -*--===// +//===- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -40,12 +40,12 @@ class DAGDeltaAlgorithm { virtual void anchor(); public: - typedef unsigned change_ty; - typedef std::pair edge_ty; + using change_ty = unsigned; + using edge_ty = std::pair; // FIXME: Use a decent data structure. - typedef std::set changeset_ty; - typedef std::vector changesetlist_ty; + using changeset_ty = std::set; + using changesetlist_ty = std::vector; public: virtual ~DAGDeltaAlgorithm() = default; diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h index a26f37d..6becb2a 100644 --- a/include/llvm/ADT/DeltaAlgorithm.h +++ b/include/llvm/ADT/DeltaAlgorithm.h @@ -1,4 +1,4 @@ -//===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- C++ -*--===// +//===- DeltaAlgorithm.h - A Set Minimization Algorithm ---------*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -35,10 +35,10 @@ namespace llvm { /// predicate. class DeltaAlgorithm { public: - typedef unsigned change_ty; + using change_ty = unsigned; // FIXME: Use a decent data structure. - typedef std::set changeset_ty; - typedef std::vector changesetlist_ty; + using changeset_ty = std::set; + using changesetlist_ty = std::vector; private: /// Cache of failed test results. Successful test results are never cached @@ -90,4 +90,4 @@ public: } // end namespace llvm -#endif +#endif // LLVM_ADT_DELTAALGORITHM_H diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index fd8d3bf..b311e69 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -25,8 +25,8 @@ #include #include #include -#include #include +#include #include namespace llvm { @@ -57,14 +57,15 @@ class DenseMapBase : public DebugEpochBase { using const_arg_type_t = typename const_pointer_or_const_ref::type; public: - typedef unsigned size_type; - typedef KeyT key_type; - typedef ValueT mapped_type; - typedef BucketT value_type; - - typedef DenseMapIterator iterator; - typedef DenseMapIterator - const_iterator; + using size_type = unsigned; + using key_type = KeyT; + using mapped_type = ValueT; + using value_type = BucketT; + + using iterator = DenseMapIterator; + using const_iterator = + DenseMapIterator; + inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this); @@ -387,15 +388,18 @@ protected: static unsigned getHashValue(const KeyT &Val) { return KeyInfoT::getHashValue(Val); } + template static unsigned getHashValue(const LookupKeyT &Val) { return KeyInfoT::getHashValue(Val); } + static const KeyT getEmptyKey() { static_assert(std::is_base_of::value, "Must pass the derived type to this template!"); return KeyInfoT::getEmptyKey(); } + static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); } @@ -404,39 +408,51 @@ private: unsigned getNumEntries() const { return static_cast(this)->getNumEntries(); } + void setNumEntries(unsigned Num) { static_cast(this)->setNumEntries(Num); } + void incrementNumEntries() { setNumEntries(getNumEntries() + 1); } + void decrementNumEntries() { setNumEntries(getNumEntries() - 1); } + unsigned getNumTombstones() const { return static_cast(this)->getNumTombstones(); } + void setNumTombstones(unsigned Num) { static_cast(this)->setNumTombstones(Num); } + void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); } + void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); } + const BucketT *getBuckets() const { return static_cast(this)->getBuckets(); } + BucketT *getBuckets() { return static_cast(this)->getBuckets(); } + unsigned getNumBuckets() const { return static_cast(this)->getNumBuckets(); } + BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); } + const BucketT *getBucketsEnd() const { return getBuckets() + getNumBuckets(); } @@ -587,10 +603,11 @@ template > class DenseMap : public DenseMapBase, KeyT, ValueT, KeyInfoT, BucketT> { + friend class DenseMapBase; + // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - friend class DenseMapBase; + using BaseT = DenseMapBase; BucketT *Buckets; unsigned NumEntries; @@ -705,6 +722,7 @@ private: unsigned getNumEntries() const { return NumEntries; } + void setNumEntries(unsigned Num) { NumEntries = Num; } @@ -712,6 +730,7 @@ private: unsigned getNumTombstones() const { return NumTombstones; } + void setNumTombstones(unsigned Num) { NumTombstones = Num; } @@ -743,10 +762,12 @@ class SmallDenseMap : public DenseMapBase< SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> { + friend class DenseMapBase; + // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - friend class DenseMapBase; + using BaseT = DenseMapBase; + static_assert(isPowerOf2_64(InlineBuckets), "InlineBuckets must be a power of 2."); @@ -972,6 +993,7 @@ private: unsigned getNumEntries() const { return NumEntries; } + void setNumEntries(unsigned Num) { // NumEntries is hardcoded to be 31 bits wide. assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries"); @@ -981,6 +1003,7 @@ private: unsigned getNumTombstones() const { return NumTombstones; } + void setNumTombstones(unsigned Num) { NumTombstones = Num; } @@ -992,15 +1015,18 @@ private: // 'storage.buffer' static type is 'char *'. return reinterpret_cast(storage.buffer); } + BucketT *getInlineBuckets() { return const_cast( const_cast(this)->getInlineBuckets()); } + const LargeRep *getLargeRep() const { assert(!Small); // Note, same rule about aliasing as with getInlineBuckets. return reinterpret_cast(storage.buffer); } + LargeRep *getLargeRep() { return const_cast( const_cast(this)->getLargeRep()); @@ -1009,10 +1035,12 @@ private: const BucketT *getBuckets() const { return Small ? getInlineBuckets() : getLargeRep()->Buckets; } + BucketT *getBuckets() { return const_cast( const_cast(this)->getBuckets()); } + unsigned getNumBuckets() const { return Small ? InlineBuckets : getLargeRep()->NumBuckets; } @@ -1037,23 +1065,25 @@ private: template class DenseMapIterator : DebugEpochBase::HandleBase { - typedef DenseMapIterator ConstIterator; friend class DenseMapIterator; friend class DenseMapIterator; + using ConstIterator = DenseMapIterator; + public: - typedef ptrdiff_t difference_type; - typedef typename std::conditional::type - value_type; - typedef value_type *pointer; - typedef value_type &reference; - typedef std::forward_iterator_tag iterator_category; + using difference_type = ptrdiff_t; + using value_type = + typename std::conditional::type; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::forward_iterator_tag; private: - pointer Ptr, End; + pointer Ptr = nullptr; + pointer End = nullptr; public: - DenseMapIterator() : Ptr(nullptr), End(nullptr) {} + DenseMapIterator() = default; DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, bool NoAdvance = false) diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h index bb973ac..a96904c 100644 --- a/include/llvm/ADT/DenseMapInfo.h +++ b/include/llvm/ADT/DenseMapInfo.h @@ -18,7 +18,10 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" -#include "llvm/Support/type_traits.h" +#include +#include +#include +#include namespace llvm { @@ -38,15 +41,18 @@ struct DenseMapInfo { Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; return reinterpret_cast(Val); } + static inline T* getTombstoneKey() { uintptr_t Val = static_cast(-2); Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; return reinterpret_cast(Val); } + static unsigned getHashValue(const T *PtrVal) { return (unsigned((uintptr_t)PtrVal) >> 4) ^ (unsigned((uintptr_t)PtrVal) >> 9); } + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } }; @@ -55,6 +61,7 @@ template<> struct DenseMapInfo { static inline char getEmptyKey() { return ~0; } static inline char getTombstoneKey() { return ~0 - 1; } static unsigned getHashValue(const char& Val) { return Val * 37U; } + static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; } @@ -65,6 +72,7 @@ template <> struct DenseMapInfo { static inline unsigned short getEmptyKey() { return 0xFFFF; } static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; } static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; } + static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) { return LHS == RHS; } @@ -75,6 +83,7 @@ template<> struct DenseMapInfo { static inline unsigned getEmptyKey() { return ~0U; } static inline unsigned getTombstoneKey() { return ~0U - 1; } static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { return LHS == RHS; } @@ -84,9 +93,11 @@ template<> struct DenseMapInfo { template<> struct DenseMapInfo { static inline unsigned long getEmptyKey() { return ~0UL; } static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + static unsigned getHashValue(const unsigned long& Val) { return (unsigned)(Val * 37UL); } + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { return LHS == RHS; } @@ -96,9 +107,11 @@ template<> struct DenseMapInfo { template<> struct DenseMapInfo { static inline unsigned long long getEmptyKey() { return ~0ULL; } static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + static unsigned getHashValue(const unsigned long long& Val) { return (unsigned)(Val * 37ULL); } + static bool isEqual(const unsigned long long& LHS, const unsigned long long& RHS) { return LHS == RHS; @@ -118,6 +131,7 @@ template<> struct DenseMapInfo { static inline int getEmptyKey() { return 0x7fffffff; } static inline int getTombstoneKey() { return -0x7fffffff - 1; } static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); } + static bool isEqual(const int& LHS, const int& RHS) { return LHS == RHS; } @@ -128,10 +142,13 @@ template<> struct DenseMapInfo { static inline long getEmptyKey() { return (1UL << (sizeof(long) * 8 - 1)) - 1UL; } + static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + static unsigned getHashValue(const long& Val) { return (unsigned)(Val * 37UL); } + static bool isEqual(const long& LHS, const long& RHS) { return LHS == RHS; } @@ -141,9 +158,11 @@ template<> struct DenseMapInfo { template<> struct DenseMapInfo { static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + static unsigned getHashValue(const long long& Val) { return (unsigned)(Val * 37ULL); } + static bool isEqual(const long long& LHS, const long long& RHS) { return LHS == RHS; @@ -152,19 +171,21 @@ template<> struct DenseMapInfo { // Provide DenseMapInfo for all pairs whose members have info. template -struct DenseMapInfo > { - typedef std::pair Pair; - typedef DenseMapInfo FirstInfo; - typedef DenseMapInfo SecondInfo; +struct DenseMapInfo> { + using Pair = std::pair; + using FirstInfo = DenseMapInfo; + using SecondInfo = DenseMapInfo; static inline Pair getEmptyKey() { return std::make_pair(FirstInfo::getEmptyKey(), SecondInfo::getEmptyKey()); } + static inline Pair getTombstoneKey() { return std::make_pair(FirstInfo::getTombstoneKey(), SecondInfo::getTombstoneKey()); } + static unsigned getHashValue(const Pair& PairVal) { uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 | (uint64_t)SecondInfo::getHashValue(PairVal.second); @@ -178,6 +199,7 @@ struct DenseMapInfo > { key ^= (key >> 31); return (unsigned)key; } + static bool isEqual(const Pair &LHS, const Pair &RHS) { return FirstInfo::isEqual(LHS.first, RHS.first) && SecondInfo::isEqual(LHS.second, RHS.second); @@ -190,16 +212,19 @@ template <> struct DenseMapInfo { return StringRef(reinterpret_cast(~static_cast(0)), 0); } + static inline StringRef getTombstoneKey() { return StringRef(reinterpret_cast(~static_cast(1)), 0); } + static unsigned getHashValue(StringRef Val) { assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); assert(Val.data() != getTombstoneKey().data() && "Cannot hash the tombstone key!"); return (unsigned)(hash_value(Val)); } + static bool isEqual(StringRef LHS, StringRef RHS) { if (RHS.data() == getEmptyKey().data()) return LHS.data() == getEmptyKey().data(); @@ -215,16 +240,19 @@ template struct DenseMapInfo> { return ArrayRef(reinterpret_cast(~static_cast(0)), size_t(0)); } + static inline ArrayRef getTombstoneKey() { return ArrayRef(reinterpret_cast(~static_cast(1)), size_t(0)); } + static unsigned getHashValue(ArrayRef Val) { assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); assert(Val.data() != getTombstoneKey().data() && "Cannot hash the tombstone key!"); return (unsigned)(hash_value(Val)); } + static bool isEqual(ArrayRef LHS, ArrayRef RHS) { if (RHS.data() == getEmptyKey().data()) return LHS.data() == getEmptyKey().data(); @@ -236,4 +264,4 @@ template struct DenseMapInfo> { } // end namespace llvm -#endif +#endif // LLVM_ADT_DENSEMAPINFO_H diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index fcf304c..7e5171c 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -15,11 +15,18 @@ #define LLVM_ADT_DENSESET_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/type_traits.h" +#include +#include #include +#include +#include namespace llvm { namespace detail { + struct DenseSetEmpty {}; // Use the empty base class trick so we can create a DenseMap where the buckets @@ -48,13 +55,14 @@ class DenseSetImpl { static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), "DenseMap buckets unexpectedly large!"); MapTy TheMap; + template using const_arg_type_t = typename const_pointer_or_const_ref::type; public: - typedef ValueT key_type; - typedef ValueT value_type; - typedef unsigned size_type; + using key_type = ValueT; + using value_type = ValueT; + using size_type = unsigned; explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {} @@ -100,11 +108,11 @@ public: friend class ConstIterator; public: - typedef typename MapTy::iterator::difference_type difference_type; - typedef ValueT value_type; - typedef value_type *pointer; - typedef value_type &reference; - typedef std::forward_iterator_tag iterator_category; + using difference_type = typename MapTy::iterator::difference_type; + using value_type = ValueT; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::forward_iterator_tag; Iterator() = default; Iterator(const typename MapTy::iterator &i) : I(i) {} @@ -126,16 +134,14 @@ public: friend class Iterator; public: - typedef typename MapTy::const_iterator::difference_type difference_type; - typedef ValueT value_type; - typedef value_type *pointer; - typedef value_type &reference; - typedef std::forward_iterator_tag iterator_category; - - ConstIterator(const Iterator &B) : I(B.I) {} + using difference_type = typename MapTy::const_iterator::difference_type; + using value_type = ValueT; + using pointer = value_type *; + using reference = value_type &; + using iterator_category = std::forward_iterator_tag; ConstIterator() = default; - + ConstIterator(const Iterator &B) : I(B.I) {} ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} const ValueT &operator*() const { return I->getFirst(); } @@ -147,8 +153,8 @@ public: bool operator!=(const ConstIterator& X) const { return I != X.I; } }; - typedef Iterator iterator; - typedef ConstIterator const_iterator; + using iterator = Iterator; + using const_iterator = ConstIterator; iterator begin() { return Iterator(TheMap.begin()); } iterator end() { return Iterator(TheMap.end()); } @@ -208,7 +214,7 @@ public: } }; -} // namespace detail +} // end namespace detail /// Implements a dense probed hash-table based set. template > @@ -246,4 +252,4 @@ public: } // end namespace llvm -#endif +#endif // LLVM_ADT_DENSESET_H diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index b020d48..e964d7f 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -68,13 +68,14 @@ public: // cross edges in the spanning tree but is not used in the common case. template struct df_iterator_default_set : public SmallPtrSet { - typedef SmallPtrSet BaseSet; - typedef typename BaseSet::iterator iterator; - std::pair insert(NodeRef N) { return BaseSet::insert(N) ; } + using BaseSet = SmallPtrSet; + using iterator = typename BaseSet::iterator; + + std::pair insert(NodeRef N) { return BaseSet::insert(N); } template void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); } - void completed(NodeRef) { } + void completed(NodeRef) {} }; // Generic Depth First Iterator @@ -85,15 +86,14 @@ template , public df_iterator_storage { - typedef std::iterator super; - - typedef typename GT::NodeRef NodeRef; - typedef typename GT::ChildIteratorType ChildItTy; + using super = std::iterator; + using NodeRef = typename GT::NodeRef; + using ChildItTy = typename GT::ChildIteratorType; // First element is node reference, second is the 'next child' to visit. // The second child is initialized lazily to pick up graph changes during the // DFS. - typedef std::pair> StackElement; + using StackElement = std::pair>; // VisitStack - Used to maintain the ordering. Top = current block std::vector VisitStack; @@ -103,12 +103,15 @@ private: this->Visited.insert(Node); VisitStack.push_back(StackElement(Node, None)); } + inline df_iterator() = default; // End is when stack is empty + inline df_iterator(NodeRef Node, SetType &S) : df_iterator_storage(S) { if (this->Visited.insert(Node).second) VisitStack.push_back(StackElement(Node, None)); } + inline df_iterator(SetType &S) : df_iterator_storage(S) { // End is when stack is empty @@ -142,7 +145,7 @@ private: } public: - typedef typename super::pointer pointer; + using pointer = typename super::pointer; // Provide static begin and end methods as our public "constructors" static df_iterator begin(const GraphT &G) { diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 8fcac17..af293d4 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -1,4 +1,4 @@ -//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// +//===- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -69,6 +69,7 @@ class EquivalenceClasses { /// leader is determined by a bit stolen from one of the pointers. class ECValue { friend class EquivalenceClasses; + mutable const ECValue *Leader, *Next; ElemTy Data; @@ -141,14 +142,14 @@ public: // /// iterator* - Provides a way to iterate over all values in the set. - typedef typename std::set::const_iterator iterator; + using iterator = typename std::set::const_iterator; + iterator begin() const { return TheMapping.begin(); } iterator end() const { return TheMapping.end(); } bool empty() const { return TheMapping.empty(); } /// member_* Iterate over the members of an equivalence class. - /// class member_iterator; member_iterator member_begin(iterator I) const { // Only leaders provide anything to iterate over. @@ -204,7 +205,6 @@ public: /// equivalence class it is in. This does the path-compression part that /// makes union-find "union findy". This returns an end iterator if the value /// is not in the equivalence class. - /// member_iterator findLeader(iterator I) const { if (I == TheMapping.end()) return member_end(); return member_iterator(I->getLeader()); @@ -241,15 +241,17 @@ public: class member_iterator : public std::iterator { - typedef std::iterator super; - const ECValue *Node; friend class EquivalenceClasses; + using super = std::iterator; + + const ECValue *Node; + public: - typedef size_t size_type; - typedef typename super::pointer pointer; - typedef typename super::reference reference; + using size_type = size_t; + using pointer = typename super::pointer; + using reference = typename super::reference; explicit member_iterator() = default; explicit member_iterator(const ECValue *N) : Node(N) {} diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index dab1829..c5987a9 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -40,7 +40,7 @@ namespace llvm { /// FoldingSetNode. The node class must also define a Profile method used to /// establish the unique bits of data for the node. The Profile method is /// passed a FoldingSetNodeID object which is used to gather the bits. Just -/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// call one of the Add* functions defined in the FoldingSetBase::NodeID class. /// NOTE: That the folding set does not own the nodes and it is the /// responsibility of the user to dispose of the nodes. /// @@ -104,13 +104,13 @@ class FoldingSetNodeID; class StringRef; //===----------------------------------------------------------------------===// -/// FoldingSetImpl - Implements the folding set functionality. The main +/// FoldingSetBase - Implements the folding set functionality. The main /// structure is an array of buckets. Each bucket is indexed by the hash of /// the nodes it contains. The bucket itself points to the nodes contained /// in the bucket via a singly linked list. The last node in the list points /// back to the bucket to facilitate node removal. /// -class FoldingSetImpl { +class FoldingSetBase { virtual void anchor(); // Out of line virtual method. protected: @@ -126,10 +126,10 @@ protected: /// is greater than twice the number of buckets. unsigned NumNodes; - explicit FoldingSetImpl(unsigned Log2InitSize = 6); - FoldingSetImpl(FoldingSetImpl &&Arg); - FoldingSetImpl &operator=(FoldingSetImpl &&RHS); - ~FoldingSetImpl(); + explicit FoldingSetBase(unsigned Log2InitSize = 6); + FoldingSetBase(FoldingSetBase &&Arg); + FoldingSetBase &operator=(FoldingSetBase &&RHS); + ~FoldingSetBase(); public: //===--------------------------------------------------------------------===// @@ -152,33 +152,6 @@ public: /// clear - Remove all nodes from the folding set. void clear(); - /// RemoveNode - Remove a node from the folding set, returning true if one - /// was removed or false if the node was not in the folding set. - bool RemoveNode(Node *N); - - /// GetOrInsertNode - If there is an existing simple Node exactly - /// equal to the specified node, return it. Otherwise, insert 'N' and return - /// it instead. - Node *GetOrInsertNode(Node *N); - - /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, - /// return it. If not, return the insertion token that will make insertion - /// faster. - Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); - - /// InsertNode - Insert the specified node into the folding set, knowing that - /// it is not already in the folding set. InsertPos must be obtained from - /// FindNodeOrInsertPos. - void InsertNode(Node *N, void *InsertPos); - - /// InsertNode - Insert the specified node into the folding set, knowing that - /// it is not already in the folding set. - void InsertNode(Node *N) { - Node *Inserted = GetOrInsertNode(N); - (void)Inserted; - assert(Inserted == N && "Node already inserted!"); - } - /// size - Returns the number of nodes in the folding set. unsigned size() const { return NumNodes; } @@ -220,6 +193,28 @@ protected: /// ComputeNodeHash - Instantiations of the FoldingSet template implement /// this function to compute a hash value for the given node. virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0; + + // The below methods are protected to encourage subclasses to provide a more + // type-safe API. + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); }; //===----------------------------------------------------------------------===// @@ -293,7 +288,7 @@ public: FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, - /// used to lookup the node in the FoldingSetImpl. + /// used to lookup the node in the FoldingSetBase. unsigned ComputeHash() const; bool operator==(FoldingSetNodeIDRef) const; @@ -345,7 +340,7 @@ public: inline void clear() { Bits.clear(); } /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used - /// to lookup the node in the FoldingSetImpl. + /// to lookup the node in the FoldingSetBase. unsigned ComputeHash() const; /// operator== - Used to compare two nodes to each other. @@ -368,7 +363,7 @@ public: }; // Convenience type to hide the implementation of the folding set. -typedef FoldingSetImpl::Node FoldingSetNode; +typedef FoldingSetBase::Node FoldingSetNode; template class FoldingSetIterator; template class FoldingSetBucketIterator; @@ -408,6 +403,71 @@ DefaultContextualFoldingSetTrait::ComputeHash(T &X, } //===----------------------------------------------------------------------===// +/// FoldingSetImpl - An implementation detail that lets us share code between +/// FoldingSet and ContextualFoldingSet. +template class FoldingSetImpl : public FoldingSetBase { +protected: + explicit FoldingSetImpl(unsigned Log2InitSize) + : FoldingSetBase(Log2InitSize) {} + + FoldingSetImpl(FoldingSetImpl &&Arg) = default; + FoldingSetImpl &operator=(FoldingSetImpl &&RHS) = default; + ~FoldingSetImpl() = default; + +public: + typedef FoldingSetIterator iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(T *N) { + return static_cast(FoldingSetBase::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetBase::FindNodeOrInsertPos(ID, InsertPos)); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(T *N, void *InsertPos) { + FoldingSetBase::InsertNode(N, InsertPos); + } + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(T *N) { + T *Inserted = GetOrInsertNode(N); + (void)Inserted; + assert(Inserted == N && "Node already inserted!"); + } +}; + +//===----------------------------------------------------------------------===// /// FoldingSet - This template class is used to instantiate a specialized /// implementation of the folding set to the node class T. T must be a /// subclass of FoldingSetNode and implement a Profile function. @@ -416,8 +476,10 @@ DefaultContextualFoldingSetTrait::ComputeHash(T &X, /// moved-from state is not a valid state for anything other than /// move-assigning and destroying. This is primarily to enable movable APIs /// that incorporate these objects. -template class FoldingSet final : public FoldingSetImpl { -private: +template class FoldingSet final : public FoldingSetImpl { + using Super = FoldingSetImpl; + using Node = typename Super::Node; + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a /// way to convert nodes into a unique specifier. void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { @@ -442,45 +504,10 @@ private: public: explicit FoldingSet(unsigned Log2InitSize = 6) - : FoldingSetImpl(Log2InitSize) {} - - FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {} - FoldingSet &operator=(FoldingSet &&RHS) { - (void)FoldingSetImpl::operator=(std::move(RHS)); - return *this; - } - - typedef FoldingSetIterator iterator; - iterator begin() { return iterator(Buckets); } - iterator end() { return iterator(Buckets+NumBuckets); } - - typedef FoldingSetIterator const_iterator; - const_iterator begin() const { return const_iterator(Buckets); } - const_iterator end() const { return const_iterator(Buckets+NumBuckets); } - - typedef FoldingSetBucketIterator bucket_iterator; - - bucket_iterator bucket_begin(unsigned hash) { - return bucket_iterator(Buckets + (hash & (NumBuckets-1))); - } - - bucket_iterator bucket_end(unsigned hash) { - return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); - } + : Super(Log2InitSize) {} - /// GetOrInsertNode - If there is an existing simple Node exactly - /// equal to the specified node, return it. Otherwise, insert 'N' and - /// return it instead. - T *GetOrInsertNode(Node *N) { - return static_cast(FoldingSetImpl::GetOrInsertNode(N)); - } - - /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, - /// return it. If not, return the insertion token that will make insertion - /// faster. - T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { - return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); - } + FoldingSet(FoldingSet &&Arg) = default; + FoldingSet &operator=(FoldingSet &&RHS) = default; }; //===----------------------------------------------------------------------===// @@ -493,74 +520,42 @@ public: /// function with signature /// void Profile(FoldingSetNodeID &, Ctx); template -class ContextualFoldingSet final : public FoldingSetImpl { +class ContextualFoldingSet final : public FoldingSetImpl { // Unfortunately, this can't derive from FoldingSet because the - // construction vtable for FoldingSet requires + // construction of the vtable for FoldingSet requires // FoldingSet::GetNodeProfile to be instantiated, which in turn // requires a single-argument T::Profile(). -private: + using Super = FoldingSetImpl; + using Node = typename Super::Node; + Ctx Context; /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a /// way to convert nodes into a unique specifier. - void GetNodeProfile(FoldingSetImpl::Node *N, - FoldingSetNodeID &ID) const override { + void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { T *TN = static_cast(N); ContextualFoldingSetTrait::Profile(*TN, ID, Context); } - bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) const override { + bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const override { T *TN = static_cast(N); return ContextualFoldingSetTrait::Equals(*TN, ID, IDHash, TempID, Context); } - unsigned ComputeNodeHash(FoldingSetImpl::Node *N, - FoldingSetNodeID &TempID) const override { + unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { T *TN = static_cast(N); return ContextualFoldingSetTrait::ComputeHash(*TN, TempID, Context); } public: explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6) - : FoldingSetImpl(Log2InitSize), Context(Context) + : Super(Log2InitSize), Context(Context) {} Ctx getContext() const { return Context; } - - typedef FoldingSetIterator iterator; - iterator begin() { return iterator(Buckets); } - iterator end() { return iterator(Buckets+NumBuckets); } - - typedef FoldingSetIterator const_iterator; - const_iterator begin() const { return const_iterator(Buckets); } - const_iterator end() const { return const_iterator(Buckets+NumBuckets); } - - typedef FoldingSetBucketIterator bucket_iterator; - - bucket_iterator bucket_begin(unsigned hash) { - return bucket_iterator(Buckets + (hash & (NumBuckets-1))); - } - - bucket_iterator bucket_end(unsigned hash) { - return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); - } - - /// GetOrInsertNode - If there is an existing simple Node exactly - /// equal to the specified node, return it. Otherwise, insert 'N' - /// and return it instead. - T *GetOrInsertNode(Node *N) { - return static_cast(FoldingSetImpl::GetOrInsertNode(N)); - } - - /// FindNodeOrInsertPos - Look up the node specified by ID. If it - /// exists, return it. If not, return the insertion token that will - /// make insertion faster. - T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { - return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); - } }; //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h index 68149d9..225d9eb 100644 --- a/include/llvm/ADT/GraphTraits.h +++ b/include/llvm/ADT/GraphTraits.h @@ -1,4 +1,4 @@ -//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- C++ -*-===// +//===- llvm/ADT/GraphTraits.h - Graph traits template -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -41,7 +41,6 @@ struct GraphTraits { // static ChildIteratorType child_end (NodeRef) // Return iterators that point to the beginning and ending of the child // node list for the specified node. - // // typedef ...iterator nodes_iterator; - dereference to a NodeRef // static nodes_iterator nodes_begin(GraphType *G) @@ -50,7 +49,6 @@ struct GraphTraits { // static unsigned size (GraphType *G) // Return total number of nodes in the graph - // // If anyone tries to use this class without having an appropriate // specialization, make an error. If you get this error, it's because you @@ -58,11 +56,9 @@ struct GraphTraits { // graph, or you need to define it for a new graph type. Either that or // your argument to XXX_begin(...) is unknown or needs to have the proper .h // file #include'd. - // - typedef typename GraphType::UnknownGraphTypeError NodeRef; + using NodeRef = typename GraphType::UnknownGraphTypeError; }; - // Inverse - This class is used as a little marker class to tell the graph // iterator to iterate over the graph in a graph defined "Inverse" ordering. // Not all graphs define an inverse ordering, and if they do, it depends on @@ -73,7 +69,7 @@ struct GraphTraits { // for (; I != E; ++I) { ... } // // Which is equivalent to: -// df_iterator > I = idf_begin(M), E = idf_end(M); +// df_iterator> I = idf_begin(M), E = idf_end(M); // for (; I != E; ++I) { ... } // template @@ -114,6 +110,7 @@ inverse_children(const typename GraphTraits::NodeRef &G) { return make_range(GraphTraits>::child_begin(G), GraphTraits>::child_end(G)); } -} // End llvm namespace -#endif +} // end namespace llvm + +#endif // LLVM_ADT_GRAPHTRAITS_H diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h index e5f51ba..60d63e0 100644 --- a/include/llvm/ADT/ImmutableList.h +++ b/include/llvm/ADT/ImmutableList.h @@ -63,8 +63,8 @@ public: template class ImmutableList { public: - typedef T value_type; - typedef ImmutableListFactory Factory; + using value_type = T; + using Factory = ImmutableListFactory; private: const ImmutableListImpl* X; @@ -141,8 +141,8 @@ public: template class ImmutableListFactory { - typedef ImmutableListImpl ListTy; - typedef FoldingSet CacheTy; + using ListTy = ImmutableListImpl; + using CacheTy = FoldingSet; CacheTy Cache; uintptr_t Allocator; diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index f197d40..10d1e1f 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -26,12 +26,12 @@ namespace llvm { /// only the first element (the key) is used by isEqual and isLess. template struct ImutKeyValueInfo { - typedef const std::pair value_type; - typedef const value_type& value_type_ref; - typedef const T key_type; - typedef const T& key_type_ref; - typedef const S data_type; - typedef const S& data_type_ref; + using value_type = const std::pair; + using value_type_ref = const value_type&; + using key_type = const T; + using key_type_ref = const T&; + using data_type = const S; + using data_type_ref = const S&; static inline key_type_ref KeyOfValue(value_type_ref V) { return V.first; @@ -62,13 +62,13 @@ template > class ImmutableMap { public: - typedef typename ValInfo::value_type value_type; - typedef typename ValInfo::value_type_ref value_type_ref; - typedef typename ValInfo::key_type key_type; - typedef typename ValInfo::key_type_ref key_type_ref; - typedef typename ValInfo::data_type data_type; - typedef typename ValInfo::data_type_ref data_type_ref; - typedef ImutAVLTree TreeTy; + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using key_type = typename ValInfo::key_type; + using key_type_ref = typename ValInfo::key_type_ref; + using data_type = typename ValInfo::data_type; + using data_type_ref = typename ValInfo::data_type_ref; + using TreeTy = ImutAVLTree; protected: TreeTy* Root; @@ -86,6 +86,10 @@ public: if (Root) { Root->retain(); } } + ~ImmutableMap() { + if (Root) { Root->release(); } + } + ImmutableMap &operator=(const ImmutableMap &X) { if (Root != X.Root) { if (X.Root) { X.Root->retain(); } @@ -95,10 +99,6 @@ public: return *this; } - ~ImmutableMap() { - if (Root) { Root->release(); } - } - class Factory { typename TreeTy::Factory F; const bool Canonicalize; @@ -166,12 +166,14 @@ private: template struct CBWrapper { Callback C; + void operator()(value_type_ref V) { C(V.first,V.second); } }; template struct CBWrapperRef { Callback &C; + CBWrapperRef(Callback& c) : C(c) {} void operator()(value_type_ref V) { C(V.first,V.second); } @@ -254,14 +256,14 @@ template > class ImmutableMapRef { public: - typedef typename ValInfo::value_type value_type; - typedef typename ValInfo::value_type_ref value_type_ref; - typedef typename ValInfo::key_type key_type; - typedef typename ValInfo::key_type_ref key_type_ref; - typedef typename ValInfo::data_type data_type; - typedef typename ValInfo::data_type_ref data_type_ref; - typedef ImutAVLTree TreeTy; - typedef typename TreeTy::Factory FactoryTy; + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using key_type = typename ValInfo::key_type; + using key_type_ref = typename ValInfo::key_type_ref; + using data_type = typename ValInfo::data_type; + using data_type_ref = typename ValInfo::data_type_ref; + using TreeTy = ImutAVLTree; + using FactoryTy = typename TreeTy::Factory; protected: TreeTy *Root; @@ -292,6 +294,11 @@ public: } } + ~ImmutableMapRef() { + if (Root) + Root->release(); + } + ImmutableMapRef &operator=(const ImmutableMapRef &X) { if (Root != X.Root) { if (X.Root) @@ -306,11 +313,6 @@ public: return *this; } - ~ImmutableMapRef() { - if (Root) - Root->release(); - } - static inline ImmutableMapRef getEmptyMap(FactoryTy *F) { return ImmutableMapRef(0, F); } diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index 9c9bcb8..9d580c5 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -41,18 +41,16 @@ template class ImutAVLTreeGenericIterator; template class ImutAVLTree { public: - typedef typename ImutInfo::key_type_ref key_type_ref; - typedef typename ImutInfo::value_type value_type; - typedef typename ImutInfo::value_type_ref value_type_ref; + using key_type_ref = typename ImutInfo::key_type_ref; + using value_type = typename ImutInfo::value_type; + using value_type_ref = typename ImutInfo::value_type_ref; + using Factory = ImutAVLFactory; + using iterator = ImutAVLTreeInOrderIterator; - typedef ImutAVLFactory Factory; friend class ImutAVLFactory; friend class ImutIntervalAVLFactory; - friend class ImutAVLTreeGenericIterator; - typedef ImutAVLTreeInOrderIterator iterator; - //===----------------------------------------------------===// // Public Interface. //===----------------------------------------------------===// @@ -225,17 +223,17 @@ private: Factory *factory; ImutAVLTree *left; ImutAVLTree *right; - ImutAVLTree *prev; - ImutAVLTree *next; + ImutAVLTree *prev = nullptr; + ImutAVLTree *next = nullptr; - unsigned height : 28; - unsigned IsMutable : 1; - unsigned IsDigestCached : 1; - unsigned IsCanonicalized : 1; + unsigned height : 28; + bool IsMutable : 1; + bool IsDigestCached : 1; + bool IsCanonicalized : 1; value_type value; - uint32_t digest; - uint32_t refCount; + uint32_t digest = 0; + uint32_t refCount = 0; //===----------------------------------------------------===// // Internal methods (node manipulation; used by Factory). @@ -246,9 +244,8 @@ private: /// ImutAVLFactory. ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) - : factory(f), left(l), right(r), prev(nullptr), next(nullptr), - height(height), IsMutable(true), IsDigestCached(false), - IsCanonicalized(0), value(v), digest(0), refCount(0) + : factory(f), left(l), right(r), height(height), IsMutable(true), + IsDigestCached(false), IsCanonicalized(false), value(v) { if (left) left->retain(); if (right) right->retain(); @@ -369,11 +366,11 @@ public: template class ImutAVLFactory { friend class ImutAVLTree; - typedef ImutAVLTree TreeTy; - typedef typename TreeTy::value_type_ref value_type_ref; - typedef typename TreeTy::key_type_ref key_type_ref; - typedef DenseMap CacheTy; + using TreeTy = ImutAVLTree; + using value_type_ref = typename TreeTy::value_type_ref; + using key_type_ref = typename TreeTy::key_type_ref; + using CacheTy = DenseMap; CacheTy Cache; uintptr_t Allocator; @@ -659,7 +656,7 @@ public: enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, Flags=0x3 }; - typedef ImutAVLTree TreeTy; + using TreeTy = ImutAVLTree; ImutAVLTreeGenericIterator() = default; ImutAVLTreeGenericIterator(const TreeTy *Root) { @@ -764,11 +761,12 @@ template class ImutAVLTreeInOrderIterator : public std::iterator> { - typedef ImutAVLTreeGenericIterator InternalIteratorTy; + using InternalIteratorTy = ImutAVLTreeGenericIterator; + InternalIteratorTy InternalItr; public: - typedef ImutAVLTree TreeTy; + using TreeTy = ImutAVLTree; ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { if (Root) @@ -840,8 +838,8 @@ struct ImutAVLValueIterator /// and generic handling of pointers is done below. template struct ImutProfileInfo { - typedef const T value_type; - typedef const T& value_type_ref; + using value_type = const T; + using value_type_ref = const T&; static void Profile(FoldingSetNodeID &ID, value_type_ref X) { FoldingSetTrait::Profile(X,ID); @@ -851,8 +849,8 @@ struct ImutProfileInfo { /// Profile traits for integers. template struct ImutProfileInteger { - typedef const T value_type; - typedef const T& value_type_ref; + using value_type = const T; + using value_type_ref = const T&; static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddInteger(X); @@ -878,8 +876,8 @@ PROFILE_INTEGER_INFO(unsigned long long) /// Profile traits for booleans. template <> struct ImutProfileInfo { - typedef const bool value_type; - typedef const bool& value_type_ref; + using value_type = const bool; + using value_type_ref = const bool&; static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddBoolean(X); @@ -890,8 +888,8 @@ struct ImutProfileInfo { /// references to unique objects. template struct ImutProfileInfo { - typedef const T* value_type; - typedef value_type value_type_ref; + using value_type = const T*; + using value_type_ref = value_type; static void Profile(FoldingSetNodeID &ID, value_type_ref X) { ID.AddPointer(X); @@ -910,12 +908,12 @@ struct ImutProfileInfo { /// std::equal_to<> and std::less<> to perform comparison of elements. template struct ImutContainerInfo : public ImutProfileInfo { - typedef typename ImutProfileInfo::value_type value_type; - typedef typename ImutProfileInfo::value_type_ref value_type_ref; - typedef value_type key_type; - typedef value_type_ref key_type_ref; - typedef bool data_type; - typedef bool data_type_ref; + using value_type = typename ImutProfileInfo::value_type; + using value_type_ref = typename ImutProfileInfo::value_type_ref; + using key_type = value_type; + using key_type_ref = value_type_ref; + using data_type = bool; + using data_type_ref = bool; static key_type_ref KeyOfValue(value_type_ref D) { return D; } static data_type_ref DataOfValue(value_type_ref) { return true; } @@ -936,12 +934,12 @@ struct ImutContainerInfo : public ImutProfileInfo { /// their addresses. template struct ImutContainerInfo : public ImutProfileInfo { - typedef typename ImutProfileInfo::value_type value_type; - typedef typename ImutProfileInfo::value_type_ref value_type_ref; - typedef value_type key_type; - typedef value_type_ref key_type_ref; - typedef bool data_type; - typedef bool data_type_ref; + using value_type = typename ImutProfileInfo::value_type; + using value_type_ref = typename ImutProfileInfo::value_type_ref; + using key_type = value_type; + using key_type_ref = value_type_ref; + using data_type = bool; + using data_type_ref = bool; static key_type_ref KeyOfValue(value_type_ref D) { return D; } static data_type_ref DataOfValue(value_type_ref) { return true; } @@ -960,9 +958,9 @@ struct ImutContainerInfo : public ImutProfileInfo { template > class ImmutableSet { public: - typedef typename ValInfo::value_type value_type; - typedef typename ValInfo::value_type_ref value_type_ref; - typedef ImutAVLTree TreeTy; + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using TreeTy = ImutAVLTree; private: TreeTy *Root; @@ -980,6 +978,10 @@ public: if (Root) { Root->retain(); } } + ~ImmutableSet() { + if (Root) { Root->release(); } + } + ImmutableSet &operator=(const ImmutableSet &X) { if (Root != X.Root) { if (X.Root) { X.Root->retain(); } @@ -989,10 +991,6 @@ public: return *this; } - ~ImmutableSet() { - if (Root) { Root->release(); } - } - class Factory { typename TreeTy::Factory F; const bool Canonicalize; @@ -1084,7 +1082,7 @@ public: // Iterators. //===--------------------------------------------------===// - typedef ImutAVLValueIterator iterator; + using iterator = ImutAVLValueIterator; iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } @@ -1112,10 +1110,10 @@ public: template > class ImmutableSetRef { public: - typedef typename ValInfo::value_type value_type; - typedef typename ValInfo::value_type_ref value_type_ref; - typedef ImutAVLTree TreeTy; - typedef typename TreeTy::Factory FactoryTy; + using value_type = typename ValInfo::value_type; + using value_type_ref = typename ValInfo::value_type_ref; + using TreeTy = ImutAVLTree; + using FactoryTy = typename TreeTy::Factory; private: TreeTy *Root; @@ -1138,6 +1136,10 @@ public: if (Root) { Root->retain(); } } + ~ImmutableSetRef() { + if (Root) { Root->release(); } + } + ImmutableSetRef &operator=(const ImmutableSetRef &X) { if (Root != X.Root) { if (X.Root) { X.Root->retain(); } @@ -1147,9 +1149,6 @@ public: } return *this; } - ~ImmutableSetRef() { - if (Root) { Root->release(); } - } static ImmutableSetRef getEmptySet(FactoryTy *F) { return ImmutableSetRef(0, F); @@ -1196,7 +1195,7 @@ public: // Iterators. //===--------------------------------------------------===// - typedef ImutAVLValueIterator iterator; + using iterator = ImutAVLValueIterator; iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h index 5ba85c0..2ee80d2 100644 --- a/include/llvm/ADT/IndexedMap.h +++ b/include/llvm/ADT/IndexedMap.h @@ -20,28 +20,28 @@ #ifndef LLVM_ADT_INDEXEDMAP_H #define LLVM_ADT_INDEXEDMAP_H -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include -#include namespace llvm { -template > +template > class IndexedMap { - typedef typename ToIndexT::argument_type IndexT; + using IndexT = typename ToIndexT::argument_type; // Prefer SmallVector with zero inline storage over std::vector. IndexedMaps // can grow very large and SmallVector grows more efficiently as long as T // is trivially copyable. - typedef SmallVector StorageT; + using StorageT = SmallVector; + StorageT storage_; T nullVal_; ToIndexT toIndex_; public: - IndexedMap() : nullVal_(T()) { } + IndexedMap() : nullVal_(T()) {} - explicit IndexedMap(const T& val) : nullVal_(val) { } + explicit IndexedMap(const T& val) : nullVal_(val) {} typename StorageT::reference operator[](IndexT n) { assert(toIndex_(n) < storage_.size() && "index out of bounds!"); @@ -80,6 +80,6 @@ template > } }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_INDEXEDMAP_H diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 430b967..f713668 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -106,6 +106,7 @@ #include "llvm/Support/RecyclingAllocator.h" #include #include +#include #include #include #include @@ -186,7 +187,7 @@ struct IntervalMapHalfOpenInfo { /// It should be considered private to the implementation. namespace IntervalMapImpl { -typedef std::pair IdxPair; +using IdxPair = std::pair; //===----------------------------------------------------------------------===// //--- IntervalMapImpl::NodeBase ---// @@ -445,7 +446,7 @@ struct NodeSizer { LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize }; - typedef NodeBase, ValT, LeafSize> LeafBase; + using LeafBase = NodeBase, ValT, LeafSize>; enum { // Now that we have the leaf branching factor, compute the actual allocation @@ -461,8 +462,8 @@ struct NodeSizer { /// This typedef is very likely to be identical for all IntervalMaps with /// reasonably sized entries, so the same allocator can be shared among /// different kinds of maps. - typedef RecyclingAllocator Allocator; + using Allocator = + RecyclingAllocator; }; //===----------------------------------------------------------------------===// @@ -930,12 +931,12 @@ template ::LeafSize, typename Traits = IntervalMapInfo> class IntervalMap { - typedef IntervalMapImpl::NodeSizer Sizer; - typedef IntervalMapImpl::LeafNode Leaf; - typedef IntervalMapImpl::BranchNode - Branch; - typedef IntervalMapImpl::LeafNode RootLeaf; - typedef IntervalMapImpl::IdxPair IdxPair; + using Sizer = IntervalMapImpl::NodeSizer; + using Leaf = IntervalMapImpl::LeafNode; + using Branch = + IntervalMapImpl::BranchNode; + using RootLeaf = IntervalMapImpl::LeafNode; + using IdxPair = IntervalMapImpl::IdxPair; // The RootLeaf capacity is given as a template parameter. We must compute the // corresponding RootBranch capacity. @@ -945,8 +946,8 @@ class IntervalMap { RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 }; - typedef IntervalMapImpl::BranchNode - RootBranch; + using RootBranch = + IntervalMapImpl::BranchNode; // When branched, we store a global start key as well as the branch node. struct RootBranchData { @@ -955,10 +956,10 @@ class IntervalMap { }; public: - typedef typename Sizer::Allocator Allocator; - typedef KeyT KeyType; - typedef ValT ValueType; - typedef Traits KeyTraits; + using Allocator = typename Sizer::Allocator; + using KeyType = KeyT; + using ValueType = ValT; + using KeyTraits = Traits; private: // The root data is either a RootLeaf or a RootBranchData instance. @@ -1290,7 +1291,7 @@ protected: friend class IntervalMap; // The map referred to. - IntervalMap *map; + IntervalMap *map = nullptr; // We store a full path from the root to the current position. // The path may be partially filled, but never between iterator calls. @@ -1338,7 +1339,7 @@ protected: public: /// const_iterator - Create an iterator that isn't pointing anywhere. - const_iterator() : map(nullptr) {} + const_iterator() = default; /// setMap - Change the map iterated over. This call must be followed by a /// call to goToBegin(), goToEnd(), or find() @@ -1509,7 +1510,8 @@ const_iterator::treeAdvanceTo(KeyT x) { template class IntervalMap::iterator : public const_iterator { friend class IntervalMap; - typedef IntervalMapImpl::IdxPair IdxPair; + + using IdxPair = IntervalMapImpl::IdxPair; explicit iterator(IntervalMap &map) : const_iterator(map) {} @@ -2003,7 +2005,7 @@ iterator::overflow(unsigned Level) { // Elements have been rearranged, now update node sizes and stops. bool SplitRoot = false; unsigned Pos = 0; - for (;;) { + while (true) { KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); if (NewNode && Pos == NewNode) { SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); @@ -2045,8 +2047,9 @@ iterator::overflow(unsigned Level) { /// template class IntervalMapOverlaps { - typedef typename MapA::KeyType KeyType; - typedef typename MapA::KeyTraits Traits; + using KeyType = typename MapA::KeyType; + using Traits = typename MapA::KeyTraits; + typename MapA::const_iterator posA; typename MapB::const_iterator posB; @@ -2071,7 +2074,7 @@ class IntervalMapOverlaps { // Already overlapping. return; - for (;;) { + while (true) { // Make a.end > b.start. posA.advanceTo(posB.start()); if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index a77cf04..430ef86 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -1,4 +1,4 @@ -//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==// +//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -73,9 +73,10 @@ template class RefCountedBase { public: RefCountedBase() = default; - RefCountedBase(const RefCountedBase &) : RefCount(0) {} + RefCountedBase(const RefCountedBase &) {} void Retain() const { ++RefCount; } + void Release() const { assert(RefCount > 0 && "Reference count is already zero."); if (--RefCount == 0) @@ -136,7 +137,7 @@ template class IntrusiveRefCntPtr { T *Obj = nullptr; public: - typedef T element_type; + using element_type = T; explicit IntrusiveRefCntPtr() = default; IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } @@ -153,13 +154,13 @@ public: retain(); } + ~IntrusiveRefCntPtr() { release(); } + IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { swap(S); return *this; } - ~IntrusiveRefCntPtr() { release(); } - T &operator*() const { return *Obj; } T *operator->() const { return Obj; } T *get() const { return Obj; } @@ -183,6 +184,7 @@ private: if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } + void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); @@ -248,14 +250,16 @@ bool operator!=(const IntrusiveRefCntPtr &A, std::nullptr_t B) { template struct simplify_type; template struct simplify_type> { - typedef T *SimpleType; + using SimpleType = T *; + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr &Val) { return Val.get(); } }; template struct simplify_type> { - typedef /*const*/ T *SimpleType; + using SimpleType = /*const*/ T *; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr &Val) { return Val.get(); } diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index ac18857..26a555e 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -19,6 +19,12 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include +#include +#include +#include +#include +#include #include namespace llvm { @@ -27,20 +33,20 @@ namespace llvm { /// in a deterministic order. The values are kept in a std::vector and the /// mapping is done with DenseMap from Keys to indexes in that vector. template, - typename VectorType = std::vector > > + typename MapType = DenseMap, + typename VectorType = std::vector>> class MapVector { - typedef typename VectorType::value_type value_type; - typedef typename VectorType::size_type size_type; + using value_type = typename VectorType::value_type; + using size_type = typename VectorType::size_type; MapType Map; VectorType Vector; public: - typedef typename VectorType::iterator iterator; - typedef typename VectorType::const_iterator const_iterator; - typedef typename VectorType::reverse_iterator reverse_iterator; - typedef typename VectorType::const_reverse_iterator const_reverse_iterator; + using iterator = typename VectorType::iterator; + using const_iterator = typename VectorType::const_iterator; + using reverse_iterator = typename VectorType::reverse_iterator; + using const_reverse_iterator = typename VectorType::const_reverse_iterator; /// Clear the MapVector and return the underlying vector. VectorType takeVector() { @@ -220,4 +226,4 @@ struct SmallMapVector } // end namespace llvm -#endif +#endif // LLVM_ADT_MAPVECTOR_H diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 701872c..b782d9d 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -1,4 +1,4 @@ -//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=// +//===- Optional.h - Simple variant for passing optional values --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,6 +19,8 @@ #include "llvm/ADT/None.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" +#include #include #include #include @@ -28,15 +30,18 @@ namespace llvm { template class Optional { AlignedCharArrayUnion storage; - bool hasVal; + bool hasVal = false; + public: - typedef T value_type; + using value_type = T; + + Optional(NoneType) {} + explicit Optional() {} - Optional(NoneType) : hasVal(false) {} - explicit Optional() : hasVal(false) {} Optional(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + Optional(const Optional &O) : hasVal(O.hasVal) { if (hasVal) new (storage.buffer) T(*O); @@ -45,12 +50,18 @@ public: Optional(T &&y) : hasVal(true) { new (storage.buffer) T(std::forward(y)); } + Optional(Optional &&O) : hasVal(O) { if (O) { new (storage.buffer) T(std::move(*O)); O.reset(); } } + + ~Optional() { + reset(); + } + Optional &operator=(T &&y) { if (hasVal) **this = std::move(y); @@ -60,6 +71,7 @@ public: } return *this; } + Optional &operator=(Optional &&O) { if (!O) reset(); @@ -112,10 +124,6 @@ public: } } - ~Optional() { - reset(); - } - const T* getPointer() const { assert(hasVal); return reinterpret_cast(storage.buffer); } T* getPointer() { assert(hasVal); return reinterpret_cast(storage.buffer); } const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } @@ -144,8 +152,7 @@ public: #endif }; -template struct isPodLike; -template struct isPodLike > { +template struct isPodLike> { // An Optional is pod-like if T is. static const bool value = isPodLike::value; }; @@ -284,6 +291,6 @@ template bool operator>=(const T &X, const Optional &Y) { return !(X < Y); } -} // end llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_OPTIONAL_H diff --git a/include/llvm/ADT/PackedVector.h b/include/llvm/ADT/PackedVector.h index 8f925f1..95adc29 100644 --- a/include/llvm/ADT/PackedVector.h +++ b/include/llvm/ADT/PackedVector.h @@ -76,8 +76,8 @@ template class PackedVector : public PackedVectorBase::is_signed> { BitVectorTy Bits; - typedef PackedVectorBase::is_signed> base; + using base = PackedVectorBase::is_signed>; public: class reference { @@ -99,7 +99,7 @@ public: }; PackedVector() = default; - explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) { } + explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) {} bool empty() const { return Bits.empty(); } diff --git a/include/llvm/ADT/PointerEmbeddedInt.h b/include/llvm/ADT/PointerEmbeddedInt.h index 2279d43..34323b5 100644 --- a/include/llvm/ADT/PointerEmbeddedInt.h +++ b/include/llvm/ADT/PointerEmbeddedInt.h @@ -13,7 +13,10 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/PointerLikeTypeTraits.h" +#include #include +#include +#include namespace llvm { @@ -29,7 +32,7 @@ namespace llvm { /// Also, the default constructed value zero initializes the integer. template class PointerEmbeddedInt { - uintptr_t Value; + uintptr_t Value = 0; // Note: This '<' is correct; using '<=' would result in some shifts // overflowing their storage types. @@ -54,15 +57,12 @@ class PointerEmbeddedInt { explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {} public: - PointerEmbeddedInt() : Value(0) {} + PointerEmbeddedInt() = default; - PointerEmbeddedInt(IntT I) { - *this = I; - } + PointerEmbeddedInt(IntT I) { *this = I; } PointerEmbeddedInt &operator=(IntT I) { - assert((std::is_signed::value ? llvm::isInt(I) - : llvm::isUInt(I)) && + assert((std::is_signed::value ? isInt(I) : isUInt(I)) && "Integer has bits outside those preserved!"); Value = static_cast(I) << Shift; return *this; @@ -81,15 +81,17 @@ public: // types. template class PointerLikeTypeTraits> { - typedef PointerEmbeddedInt T; + using T = PointerEmbeddedInt; public: static inline void *getAsVoidPointer(const T &P) { return reinterpret_cast(P.Value); } + static inline T getFromVoidPointer(void *P) { return T(reinterpret_cast(P), typename T::RawValueTag()); } + static inline T getFromVoidPointer(const void *P) { return T(reinterpret_cast(P), typename T::RawValueTag()); } @@ -101,17 +103,19 @@ public: // itself can be a key. template struct DenseMapInfo> { - typedef PointerEmbeddedInt T; - - typedef DenseMapInfo IntInfo; + using T = PointerEmbeddedInt; + using IntInfo = DenseMapInfo; static inline T getEmptyKey() { return IntInfo::getEmptyKey(); } static inline T getTombstoneKey() { return IntInfo::getTombstoneKey(); } + static unsigned getHashValue(const T &Arg) { return IntInfo::getHashValue(Arg); } + static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; } }; -} -#endif +} // end namespace llvm + +#endif // LLVM_ADT_POINTEREMBEDDEDINT_H diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 7ce70eb..aeab641 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -158,7 +158,7 @@ public: assert( get() == Val.getPointer() && "Can't get the address because PointerLikeTypeTraits changes the ptr"); - return (PT1 *)Val.getAddrOfPointer(); + return const_cast(reinterpret_cast(Val.getAddrOfPointer())); } /// Assignment from nullptr which just clears the union. diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index d52128e..22b0c1b 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -109,6 +109,7 @@ private: ScopedHashTableVal *getLastValInScope() { return LastValInScope; } + void setLastValInScope(ScopedHashTableVal *Val) { LastValInScope = Val; } @@ -151,13 +152,14 @@ class ScopedHashTable { public: /// ScopeTy - This is a helpful typedef that allows clients to get easy access /// to the name of the scope for this hash table. - typedef ScopedHashTableScope ScopeTy; - typedef unsigned size_type; + using ScopeTy = ScopedHashTableScope; + using size_type = unsigned; private: friend class ScopedHashTableScope; - typedef ScopedHashTableVal ValTy; + using ValTy = ScopedHashTableVal; + DenseMap TopLevelMap; ScopeTy *CurScope = nullptr; @@ -165,7 +167,7 @@ private: public: ScopedHashTable() = default; - ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} + ScopedHashTable(AllocatorTy A) : Allocator(A) {} ScopedHashTable(const ScopedHashTable &) = delete; ScopedHashTable &operator=(const ScopedHashTable &) = delete; @@ -194,7 +196,7 @@ public: insertIntoScope(CurScope, Key, Val); } - typedef ScopedHashTableIterator iterator; + using iterator = ScopedHashTableIterator; iterator end() { return iterator(0); } diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 0ff4270..b639174 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -15,8 +15,15 @@ #define LLVM_ADT_SMALLBITVECTOR_H #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/MathExtras.h" +#include #include +#include +#include +#include +#include +#include namespace llvm { @@ -29,7 +36,7 @@ class SmallBitVector { // TODO: In "large" mode, a pointer to a BitVector is used, leading to an // unnecessary level of indirection. It would be more efficient to use a // pointer to memory containing size, allocation size, and the array of bits. - uintptr_t X; + uintptr_t X = 1; enum { // The number of bits in this class. @@ -54,7 +61,8 @@ class SmallBitVector { "Unsupported word size"); public: - typedef unsigned size_type; + using size_type = unsigned; + // Encapsulation of a single bit. class reference { SmallBitVector &TheVector; @@ -134,21 +142,8 @@ private: } public: - typedef const_set_bits_iterator_impl const_set_bits_iterator; - typedef const_set_bits_iterator set_iterator; - - const_set_bits_iterator set_bits_begin() const { - return const_set_bits_iterator(*this); - } - const_set_bits_iterator set_bits_end() const { - return const_set_bits_iterator(*this, -1); - } - iterator_range set_bits() const { - return make_range(set_bits_begin(), set_bits_end()); - } - /// Creates an empty bitvector. - SmallBitVector() : X(1) {} + SmallBitVector() = default; /// Creates a bitvector of specified number of bits. All bits are initialized /// to the specified value. @@ -176,6 +171,21 @@ public: delete getPointer(); } + using const_set_bits_iterator = const_set_bits_iterator_impl; + using set_iterator = const_set_bits_iterator; + + const_set_bits_iterator set_bits_begin() const { + return const_set_bits_iterator(*this); + } + + const_set_bits_iterator set_bits_end() const { + return const_set_bits_iterator(*this, -1); + } + + iterator_range set_bits() const { + return make_range(set_bits_begin(), set_bits_end()); + } + /// Tests whether there are no bits in this bitvector. bool empty() const { return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); @@ -677,14 +687,16 @@ operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { return Result; } -} // End llvm namespace +} // end namespace llvm namespace std { - /// Implement std::swap in terms of BitVector swap. - inline void - swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { - LHS.swap(RHS); - } + +/// Implement std::swap in terms of BitVector swap. +inline void +swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { + LHS.swap(RHS); } -#endif +} // end namespace std + +#endif // LLVM_ADT_SMALLBITVECTOR_H diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index 6dac167..d52d0f0 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -39,8 +39,9 @@ class SmallSet { /// we will never use. SmallVector Vector; std::set Set; - typedef typename SmallVector::const_iterator VIterator; - typedef typename SmallVector::iterator mutable_iterator; + + using VIterator = typename SmallVector::const_iterator; + using mutable_iterator = typename SmallVector::iterator; // In small mode SmallPtrSet uses linear search for the elements, so it is // not a good idea to choose this value too high. You may consider using a @@ -48,7 +49,7 @@ class SmallSet { static_assert(N <= 32, "N should be small"); public: - typedef size_t size_type; + using size_type = size_t; SmallSet() = default; diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index bbea861..ffcf998 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include #include @@ -40,6 +41,11 @@ static inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); } +/// Construct a string ref from an array ref of unsigned chars. +static inline StringRef toStringRef(ArrayRef Input) { + return StringRef(reinterpret_cast(Input.begin()), Input.size()); +} + /// Interpret the given character \p C as a hexadecimal digit and return its /// value. /// @@ -68,7 +74,7 @@ static inline std::string utohexstr(uint64_t X, bool LowerCase = false) { /// Convert buffer \p Input to its hexadecimal representation. /// The returned string is double the size of \p Input. -static inline std::string toHex(StringRef Input) { +inline std::string toHex(StringRef Input) { static const char *const LUT = "0123456789ABCDEF"; size_t Length = Input.size(); @@ -82,6 +88,10 @@ static inline std::string toHex(StringRef Input) { return Output; } +inline std::string toHex(ArrayRef Input) { + return toHex(toStringRef(Input)); +} + static inline uint8_t hexFromNibbles(char MSB, char LSB) { unsigned U1 = hexDigitValue(MSB); unsigned U2 = hexDigitValue(LSB); diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 0762698..26a9918 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -239,7 +239,9 @@ public: /// Default constructor is the same as an empty string and leaves all /// triple fields unknown. - Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {} + Triple() + : Data(), Arch(), SubArch(), Vendor(), OS(), Environment(), + ObjectFormat() {} explicit Triple(const Twine &Str); Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr); diff --git a/include/llvm/ADT/ilist_base.h b/include/llvm/ADT/ilist_base.h index 1ffc864..3d818a4 100644 --- a/include/llvm/ADT/ilist_base.h +++ b/include/llvm/ADT/ilist_base.h @@ -1,4 +1,4 @@ -//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==// +//===- llvm/ADT/ilist_base.h - Intrusive List Base --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,13 @@ #include "llvm/ADT/ilist_node_base.h" #include -#include -#include namespace llvm { /// Implementations of list algorithms using ilist_node_base. template class ilist_base { public: - typedef ilist_node_base node_base_type; + using node_base_type = ilist_node_base; static void insertBeforeImpl(node_base_type &Next, node_base_type &N) { node_base_type &Prev = *Next.getPrev(); diff --git a/include/llvm/ADT/ilist_iterator.h b/include/llvm/ADT/ilist_iterator.h index c848d1a..671e644 100644 --- a/include/llvm/ADT/ilist_iterator.h +++ b/include/llvm/ADT/ilist_iterator.h @@ -1,4 +1,4 @@ -//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==// +//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,28 +23,30 @@ namespace ilist_detail { /// Find const-correct node types. template struct IteratorTraits; template struct IteratorTraits { - typedef typename OptionsT::value_type value_type; - typedef typename OptionsT::pointer pointer; - typedef typename OptionsT::reference reference; - typedef ilist_node_impl *node_pointer; - typedef ilist_node_impl &node_reference; + using value_type = typename OptionsT::value_type; + using pointer = typename OptionsT::pointer; + using reference = typename OptionsT::reference; + using node_pointer = ilist_node_impl *; + using node_reference = ilist_node_impl &; }; template struct IteratorTraits { - typedef const typename OptionsT::value_type value_type; - typedef typename OptionsT::const_pointer pointer; - typedef typename OptionsT::const_reference reference; - typedef const ilist_node_impl *node_pointer; - typedef const ilist_node_impl &node_reference; + using value_type = const typename OptionsT::value_type; + using pointer = typename OptionsT::const_pointer; + using reference = typename OptionsT::const_reference; + using node_pointer = const ilist_node_impl *; + using node_reference = const ilist_node_impl &; }; template struct IteratorHelper; template <> struct IteratorHelper : ilist_detail::NodeAccess { - typedef ilist_detail::NodeAccess Access; + using Access = ilist_detail::NodeAccess; + template static void increment(T *&I) { I = Access::getNext(*I); } template static void decrement(T *&I) { I = Access::getPrev(*I); } }; template <> struct IteratorHelper : ilist_detail::NodeAccess { - typedef ilist_detail::NodeAccess Access; + using Access = ilist_detail::NodeAccess; + template static void increment(T *&I) { I = Access::getPrev(*I); } template static void decrement(T *&I) { I = Access::getNext(*I); } }; @@ -58,24 +60,23 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess { friend ilist_iterator; friend ilist_iterator; - typedef ilist_detail::IteratorTraits Traits; - typedef ilist_detail::SpecificNodeAccess Access; + using Traits = ilist_detail::IteratorTraits; + using Access = ilist_detail::SpecificNodeAccess; public: - typedef typename Traits::value_type value_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - typedef typename OptionsT::const_pointer const_pointer; - typedef typename OptionsT::const_reference const_reference; + using value_type = typename Traits::value_type; + using pointer = typename Traits::pointer; + using reference = typename Traits::reference; + using difference_type = ptrdiff_t; + using iterator_category = std::bidirectional_iterator_tag; + using const_pointer = typename OptionsT::const_pointer; + using const_reference = typename OptionsT::const_reference; private: - typedef typename Traits::node_pointer node_pointer; - typedef typename Traits::node_reference node_reference; + using node_pointer = typename Traits::node_pointer; + using node_reference = typename Traits::node_reference; - node_pointer NodePtr; + node_pointer NodePtr = nullptr; public: /// Create from an ilist_node. @@ -83,7 +84,7 @@ public: explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {} explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {} - ilist_iterator() : NodePtr(nullptr) {} + ilist_iterator() = default; // This is templated so that we can allow constructing a const iterator from // a nonconst iterator... @@ -184,8 +185,8 @@ template struct simplify_type; /// FIXME: remove this, since there is no implicit conversion to NodeTy. template struct simplify_type> { - typedef ilist_iterator iterator; - typedef typename iterator::pointer SimpleType; + using iterator = ilist_iterator; + using SimpleType = typename iterator::pointer; static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; } }; diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index 7244d0f..3362611 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -1,4 +1,4 @@ -//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==// +//===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,11 +21,10 @@ namespace llvm { namespace ilist_detail { + struct NodeAccess; -} // end namespace ilist_detail -template -struct ilist_traits; +} // end namespace ilist_detail template class ilist_iterator; template class ilist_sentinel; @@ -39,9 +38,9 @@ template class ilist_sentinel; /// provide type safety: you can't insert nodes of \a ilist_node_impl into the /// wrong \a simple_ilist or \a iplist. template class ilist_node_impl : OptionsT::node_base_type { - typedef typename OptionsT::value_type value_type; - typedef typename OptionsT::node_base_type node_base_type; - typedef typename OptionsT::list_base_type list_base_type; + using value_type = typename OptionsT::value_type; + using node_base_type = typename OptionsT::node_base_type; + using list_base_type = typename OptionsT::list_base_type; friend typename OptionsT::list_base_type; friend struct ilist_detail::NodeAccess; @@ -52,17 +51,18 @@ template class ilist_node_impl : OptionsT::node_base_type { friend class ilist_iterator; protected: - ilist_node_impl() = default; + using self_iterator = ilist_iterator; + using const_self_iterator = ilist_iterator; + using reverse_self_iterator = ilist_iterator; + using const_reverse_self_iterator = ilist_iterator; - typedef ilist_iterator self_iterator; - typedef ilist_iterator const_self_iterator; - typedef ilist_iterator reverse_self_iterator; - typedef ilist_iterator const_reverse_self_iterator; + ilist_node_impl() = default; private: ilist_node_impl *getPrev() { return static_cast(node_base_type::getPrev()); } + ilist_node_impl *getNext() { return static_cast(node_base_type::getNext()); } @@ -70,6 +70,7 @@ private: const ilist_node_impl *getPrev() const { return static_cast(node_base_type::getPrev()); } + const ilist_node_impl *getNext() const { return static_cast(node_base_type::getNext()); } @@ -80,9 +81,11 @@ private: public: self_iterator getIterator() { return self_iterator(*this); } const_self_iterator getIterator() const { return const_self_iterator(*this); } + reverse_self_iterator getReverseIterator() { return reverse_self_iterator(*this); } + const_reverse_self_iterator getReverseIterator() const { return const_reverse_self_iterator(*this); } @@ -151,6 +154,7 @@ class ilist_node }; namespace ilist_detail { + /// An access class for ilist_node private API. /// /// This gives access to the private parts of ilist nodes. Nodes for an ilist @@ -163,15 +167,18 @@ protected: static ilist_node_impl *getNodePtr(typename OptionsT::pointer N) { return N; } + template static const ilist_node_impl * getNodePtr(typename OptionsT::const_pointer N) { return N; } + template static typename OptionsT::pointer getValuePtr(ilist_node_impl *N) { return static_cast(N); } + template static typename OptionsT::const_pointer getValuePtr(const ilist_node_impl *N) { @@ -182,15 +189,18 @@ protected: static ilist_node_impl *getPrev(ilist_node_impl &N) { return N.getPrev(); } + template static ilist_node_impl *getNext(ilist_node_impl &N) { return N.getNext(); } + template static const ilist_node_impl * getPrev(const ilist_node_impl &N) { return N.getPrev(); } + template static const ilist_node_impl * getNext(const ilist_node_impl &N) { @@ -200,23 +210,27 @@ protected: template struct SpecificNodeAccess : NodeAccess { protected: - typedef typename OptionsT::pointer pointer; - typedef typename OptionsT::const_pointer const_pointer; - typedef ilist_node_impl node_type; + using pointer = typename OptionsT::pointer; + using const_pointer = typename OptionsT::const_pointer; + using node_type = ilist_node_impl; static node_type *getNodePtr(pointer N) { return NodeAccess::getNodePtr(N); } + static const node_type *getNodePtr(const_pointer N) { return NodeAccess::getNodePtr(N); } + static pointer getValuePtr(node_type *N) { return NodeAccess::getValuePtr(N); } + static const_pointer getValuePtr(const node_type *N) { return NodeAccess::getValuePtr(N); } }; + } // end namespace ilist_detail template @@ -265,6 +279,7 @@ public: getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); return List.getPrevNode(*static_cast(this)); } + /// \brief Get the previous node, or \c nullptr for the list head. const NodeTy *getPrevNode() const { return const_cast(this)->getPrevNode(); @@ -278,6 +293,7 @@ public: getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr)); return List.getNextNode(*static_cast(this)); } + /// \brief Get the next node, or \c nullptr for the list tail. const NodeTy *getNextNode() const { return const_cast(this)->getNextNode(); @@ -285,6 +301,6 @@ public: /// @} }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_ADT_ILIST_NODE_H diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 28dcdf9..15720a6 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -11,9 +11,11 @@ #define LLVM_ADT_ITERATOR_H #include "llvm/ADT/iterator_range.h" +#include #include #include #include +#include namespace llvm { @@ -206,7 +208,7 @@ template < class iterator_adaptor_base : public iterator_facade_base { - typedef typename iterator_adaptor_base::iterator_facade_base BaseT; + using BaseT = typename iterator_adaptor_base::iterator_facade_base; protected: WrappedIteratorT I; @@ -221,7 +223,7 @@ protected: const WrappedIteratorT &wrapped() const { return I; } public: - typedef DifferenceTypeT difference_type; + using difference_type = DifferenceTypeT; DerivedT &operator+=(difference_type n) { static_assert( @@ -279,7 +281,7 @@ public: /// which is implemented with some iterator over T*s: /// /// \code -/// typedef pointee_iterator::iterator> iterator; +/// using iterator = pointee_iterator::iterator>; /// \endcode template #include #include +#include +#include +#include namespace llvm { @@ -77,23 +82,23 @@ class simple_ilist typename ilist_detail::compute_node_options::type> { static_assert(ilist_detail::check_options::value, "Unrecognized node option!"); - typedef - typename ilist_detail::compute_node_options::type OptionsT; - typedef typename OptionsT::list_base_type list_base_type; + using OptionsT = + typename ilist_detail::compute_node_options::type; + using list_base_type = typename OptionsT::list_base_type; ilist_sentinel Sentinel; public: - typedef typename OptionsT::value_type value_type; - typedef typename OptionsT::pointer pointer; - typedef typename OptionsT::reference reference; - typedef typename OptionsT::const_pointer const_pointer; - typedef typename OptionsT::const_reference const_reference; - typedef ilist_iterator iterator; - typedef ilist_iterator const_iterator; - typedef ilist_iterator reverse_iterator; - typedef ilist_iterator const_reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; + using value_type = typename OptionsT::value_type; + using pointer = typename OptionsT::pointer; + using reference = typename OptionsT::reference; + using const_pointer = typename OptionsT::const_pointer; + using const_reference = typename OptionsT::const_reference; + using iterator = ilist_iterator; + using const_iterator = ilist_iterator; + using reverse_iterator = ilist_iterator; + using const_reverse_iterator = ilist_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; simple_ilist() = default; ~simple_ilist() = default; diff --git a/include/llvm/Analysis/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h index f0bba8c..462e459 100644 --- a/include/llvm/Analysis/MemorySSA.h +++ b/include/llvm/Analysis/MemorySSA.h @@ -147,7 +147,6 @@ public: MemoryAccess(const MemoryAccess &) = delete; MemoryAccess &operator=(const MemoryAccess &) = delete; - void *operator new(size_t, unsigned) = delete; void *operator new(size_t) = delete; BasicBlock *getBlock() const { return Block; } @@ -232,7 +231,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) { /// MemoryDef instead. class MemoryUseOrDef : public MemoryAccess { public: - void *operator new(size_t, unsigned) = delete; void *operator new(size_t) = delete; DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); @@ -298,7 +296,6 @@ public: // allocate space for exactly one operand void *operator new(size_t s) { return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; static inline bool classof(const Value *MA) { return MA->getValueID() == MemoryUseVal; @@ -355,7 +352,6 @@ public: // allocate space for exactly one operand void *operator new(size_t s) { return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; static inline bool classof(const Value *MA) { return MA->getValueID() == MemoryDefVal; @@ -438,8 +434,6 @@ public: allocHungoffUses(ReservedSpace); } - void *operator new(size_t, unsigned) = delete; - // Block iterator interface. This provides access to the list of incoming // basic blocks, which parallels the list of incoming values. typedef BasicBlock **block_iterator; diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 8ee9712..2a4b768 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -1214,26 +1214,31 @@ public: SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, unsigned Depth = 0); const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { SmallVector Ops = {LHS, RHS}; - return getAddExpr(Ops, Flags); + return getAddExpr(Ops, Flags, Depth); } const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { SmallVector Ops = {Op0, Op1, Op2}; - return getAddExpr(Ops, Flags); + return getAddExpr(Ops, Flags, Depth); } const SCEV *getMulExpr(SmallVectorImpl &Ops, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0); const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { SmallVector Ops = {LHS, RHS}; - return getMulExpr(Ops, Flags); + return getMulExpr(Ops, Flags, Depth); } const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) { + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0) { SmallVector Ops = {Op0, Op1, Op2}; - return getMulExpr(Ops, Flags); + return getMulExpr(Ops, Flags, Depth); } const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS); @@ -1287,7 +1292,8 @@ public: /// Return LHS-RHS. Minus is represented in SCEV as A+B*-1. const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, - SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); + SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap, + unsigned Depth = 0); /// Return a SCEV corresponding to a conversion of the input value to the /// specified type. If the type must be extended, it is zero extended. @@ -1693,10 +1699,14 @@ private: bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned, bool NoWrap); - /// Get add expr already created or create a new one + /// Get add expr already created or create a new one. const SCEV *getOrCreateAddExpr(SmallVectorImpl &Ops, SCEV::NoWrapFlags Flags); + /// Get mul expr already created or create a new one. + const SCEV *getOrCreateMulExpr(SmallVectorImpl &Ops, + SCEV::NoWrapFlags Flags); + private: FoldingSet UniqueSCEVs; FoldingSet UniquePreds; diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index cd8c2cd..af2ebb7 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -235,6 +235,11 @@ public: /// starting with the sources of divergence. bool isSourceOfDivergence(const Value *V) const; + // \brief Returns true for the target specific + // set of operations which produce uniform result + // even taking non-unform arguments + bool isAlwaysUniform(const Value *V) const; + /// Returns the address space ID for a target's 'flat' address space. Note /// this is not necessarily the same as addrspace(0), which LLVM sometimes /// refers to as the generic address space. The flat address space is a @@ -821,6 +826,7 @@ public: virtual int getUserCost(const User *U) = 0; virtual bool hasBranchDivergence() = 0; virtual bool isSourceOfDivergence(const Value *V) = 0; + virtual bool isAlwaysUniform(const Value *V) = 0; virtual unsigned getFlatAddressSpace() = 0; virtual bool isLoweredToCall(const Function *F) = 0; virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; @@ -873,7 +879,7 @@ public: virtual int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty) = 0; virtual unsigned getNumberOfRegisters(bool Vector) = 0; - virtual unsigned getRegisterBitWidth(bool Vector) = 0; + virtual unsigned getRegisterBitWidth(bool Vector) const = 0; virtual unsigned getMinVectorRegisterBitWidth() = 0; virtual bool shouldConsiderAddressTypePromotion( const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0; @@ -998,6 +1004,10 @@ public: return Impl.isSourceOfDivergence(V); } + bool isAlwaysUniform(const Value *V) override { + return Impl.isAlwaysUniform(V); + } + unsigned getFlatAddressSpace() override { return Impl.getFlatAddressSpace(); } @@ -1119,7 +1129,7 @@ public: unsigned getNumberOfRegisters(bool Vector) override { return Impl.getNumberOfRegisters(Vector); } - unsigned getRegisterBitWidth(bool Vector) override { + unsigned getRegisterBitWidth(bool Vector) const override { return Impl.getRegisterBitWidth(Vector); } unsigned getMinVectorRegisterBitWidth() override { diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 72de7c1..24ac3b1 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -177,6 +177,8 @@ public: bool isSourceOfDivergence(const Value *V) { return false; } + bool isAlwaysUniform(const Value *V) { return false; } + unsigned getFlatAddressSpace () { return -1; } @@ -320,7 +322,7 @@ public: unsigned getNumberOfRegisters(bool Vector) { return 8; } - unsigned getRegisterBitWidth(bool Vector) { return 32; } + unsigned getRegisterBitWidth(bool Vector) const { return 32; } unsigned getMinVectorRegisterBitWidth() { return 128; } diff --git a/include/llvm/Analysis/TypeMetadataUtils.h b/include/llvm/Analysis/TypeMetadataUtils.h index 17906ba..422e153 100644 --- a/include/llvm/Analysis/TypeMetadataUtils.h +++ b/include/llvm/Analysis/TypeMetadataUtils.h @@ -20,6 +20,13 @@ namespace llvm { +/// The type of CFI jumptable needed for a function. +enum CfiFunctionLinkage { + CFL_Definition = 0, + CFL_Declaration = 1, + CFL_WeakDeclaration = 2 +}; + /// A call site that could be devirtualized. struct DevirtCallSite { /// The offset from the address point to the virtual function. diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 612779b..e953ec8 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -249,8 +249,8 @@ template class ArrayRef; }; /// Returns true if the value \p V is a pointer into a ContantDataArray. - /// If successfull \p Index will point to a ConstantDataArray info object - /// with an apropriate offset. + /// If successful \p Index will point to a ConstantDataArray info object + /// with an appropriate offset. bool getConstantDataArrayInfo(const Value *V, ConstantDataArraySlice &Slice, unsigned ElementSize, uint64_t Offset = 0); diff --git a/include/llvm/BinaryFormat/ELF.h b/include/llvm/BinaryFormat/ELF.h index 3724f55..a4450ee 100644 --- a/include/llvm/BinaryFormat/ELF.h +++ b/include/llvm/BinaryFormat/ELF.h @@ -1,4 +1,4 @@ -//===-- llvm/BinaryFormat/ELF.h - ELF constants and structures --*- C++ -*-===// +//===- llvm/BinaryFormat/ELF.h - ELF constants and structures ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -20,27 +20,25 @@ #ifndef LLVM_BINARYFORMAT_ELF_H #define LLVM_BINARYFORMAT_ELF_H -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" +#include #include namespace llvm { - namespace ELF { -typedef uint32_t Elf32_Addr; // Program address -typedef uint32_t Elf32_Off; // File offset -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; +using Elf32_Addr = uint32_t; // Program address +using Elf32_Off = uint32_t; // File offset +using Elf32_Half = uint16_t; +using Elf32_Word = uint32_t; +using Elf32_Sword = int32_t; -typedef uint64_t Elf64_Addr; -typedef uint64_t Elf64_Off; -typedef uint16_t Elf64_Half; -typedef uint32_t Elf64_Word; -typedef int32_t Elf64_Sword; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; +using Elf64_Addr = uint64_t; +using Elf64_Off = uint64_t; +using Elf64_Half = uint16_t; +using Elf64_Word = uint32_t; +using Elf64_Sword = int32_t; +using Elf64_Xword = uint64_t; +using Elf64_Sxword = int64_t; // Object file magic string. static const char ElfMagic[] = {0x7f, 'E', 'L', 'F', '\0'}; @@ -75,9 +73,11 @@ struct Elf32_Ehdr { Elf32_Half e_shentsize; // Size of an entry in the section header table Elf32_Half e_shnum; // Number of entries in the section header table Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic() const { return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } }; @@ -99,9 +99,11 @@ struct Elf64_Ehdr { Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; + bool checkMagic() const { return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } }; @@ -683,6 +685,7 @@ enum : unsigned { SHT_GROUP = 17, // Section group. SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. @@ -1356,7 +1359,6 @@ enum { }; } // end namespace ELF - } // end namespace llvm -#endif +#endif // LLVM_BINARYFORMAT_ELF_H diff --git a/include/llvm/Bitcode/BitcodeReader.h b/include/llvm/Bitcode/BitcodeReader.h index 61e4f63..0e17e9a 100644 --- a/include/llvm/Bitcode/BitcodeReader.h +++ b/include/llvm/Bitcode/BitcodeReader.h @@ -42,6 +42,12 @@ namespace llvm { struct BitcodeFileContents; + /// Basic information extracted from a bitcode module to be used for LTO. + struct BitcodeLTOInfo { + bool IsThinLTO; + bool HasSummary; + }; + /// Represents a module in a bitcode file. class BitcodeModule { // This covers the identification (if present) and module blocks. @@ -90,15 +96,17 @@ namespace llvm { /// Read the entire bitcode module and return it. Expected> parseModule(LLVMContext &Context); - /// Check if the given bitcode buffer contains a summary block. - Expected hasSummary(); + /// Returns information about the module to be used for LTO: whether to + /// compile with ThinLTO, and whether it has a summary. + Expected getLTOInfo(); /// Parse the specified bitcode buffer, returning the module summary index. Expected> getSummary(); /// Parse the specified bitcode buffer and merge its module summary index /// into CombinedIndex. - Error readSummary(ModuleSummaryIndex &CombinedIndex, unsigned ModuleId); + Error readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath, + uint64_t ModuleId); }; struct BitcodeFileContents { @@ -147,8 +155,8 @@ namespace llvm { Expected> parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context); - /// Check if the given bitcode buffer contains a summary block. - Expected hasGlobalValueSummary(MemoryBufferRef Buffer); + /// Returns LTO information for the specified bitcode file. + Expected getBitcodeLTOInfo(MemoryBufferRef Buffer); /// Parse the specified bitcode buffer, returning the module summary index. Expected> @@ -157,7 +165,7 @@ namespace llvm { /// Parse the specified bitcode buffer and merge the index into CombinedIndex. Error readModuleSummaryIndex(MemoryBufferRef Buffer, ModuleSummaryIndex &CombinedIndex, - unsigned ModuleId); + uint64_t ModuleId); /// Parse the module summary index out of an IR file and return the module /// summary index object if found, or an empty summary if not. If Path refers diff --git a/include/llvm/Bitcode/BitcodeWriter.h b/include/llvm/Bitcode/BitcodeWriter.h index 23b5ae8..7c3c4b2 100644 --- a/include/llvm/Bitcode/BitcodeWriter.h +++ b/include/llvm/Bitcode/BitcodeWriter.h @@ -67,6 +67,10 @@ namespace llvm { void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false, const ModuleSummaryIndex *Index = nullptr, bool GenerateHash = false, ModuleHash *ModHash = nullptr); + + void writeIndex( + const ModuleSummaryIndex *Index, + const std::map *ModuleToSummariesForIndex); }; /// \brief Write the specified module to the specified raw output stream. diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index a643bfd..4e3e177 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -240,6 +240,14 @@ enum GlobalValueSummarySymtabCodes { // summaries, but it can also appear in per-module summaries for PGO data. // [valueid, guid] FS_VALUE_GUID = 16, + // The list of local functions with CFI jump tables. Function names are + // strings in strtab. + // [n * name] + FS_CFI_FUNCTION_DEFS = 17, + // The list of external functions with CFI jump tables. Function names are + // strings in strtab. + // [n * name] + FS_CFI_FUNCTION_DECLS = 18, }; enum MetadataCodes { diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index 9e33df6..5eb7a0f 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -93,6 +93,8 @@ public: bool isSourceOfDivergence(const Value *V) { return false; } + bool isAlwaysUniform(const Value *V) { return false; } + unsigned getFlatAddressSpace() { // Return an invalid address space. return -1; @@ -346,7 +348,7 @@ public: unsigned getNumberOfRegisters(bool Vector) { return Vector ? 0 : 1; } - unsigned getRegisterBitWidth(bool Vector) { return 32; } + unsigned getRegisterBitWidth(bool Vector) const { return 32; } /// Estimate the overhead of scalarizing an instruction. Insert and Extract /// are set if the result needs to be inserted and/or extracted from vectors. diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 7d7c3e8..f32a589 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -82,6 +82,11 @@ public: DenseMap, unsigned> SwiftErrorVRegUpwardsUse; + /// A map from instructions that define/use a swifterror value to the virtual + /// register that represents that def/use. + llvm::DenseMap, unsigned> + SwiftErrorVRegDefUses; + /// The swifterror argument of the current function. const Value *SwiftErrorArg; @@ -101,6 +106,13 @@ public: 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 getOrCreateSwiftErrorVRegDefAt(const Instruction *); + std::pair + 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. diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 3148e70..5197ba8 100644 --- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -21,9 +21,11 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H #define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H +#include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" namespace llvm { // Forward declarations. @@ -99,6 +101,12 @@ private: const LegalizerInfo &LI; }; +/// Helper function that replaces \p MI with a libcall. +LegalizerHelper::LegalizeResult +replaceWithLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, + RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result, + ArrayRef Args); + } // End namespace llvm. #endif diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index db72f78..4e7b835 100644 --- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -40,8 +40,8 @@ class MachineIRBuilder { MachineFunction *MF; /// Information used to access the description of the opcodes. const TargetInstrInfo *TII; - /// Information used to verify types are consistent. - const MachineRegisterInfo *MRI; + /// Information used to verify types are consistent and to create virtual registers. + MachineRegisterInfo *MRI; /// Debug location to be set to any instruction we create. DebugLoc DL; @@ -229,6 +229,26 @@ public: MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0, unsigned Op1); + /// Materialize and insert \p Res = G_GEP \p Op0, (G_CONSTANT \p Value) + /// + /// G_GEP adds \p Value bytes to the pointer specified by \p Op0, + /// storing the resulting pointer in \p Res. If \p Value is zero then no + /// G_GEP or G_CONSTANT will be created and \pre Op0 will be assigned to + /// \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Op0 must be a generic virtual register with pointer type. + /// \pre \p ValueTy must be a scalar type. + /// \pre \p Res must be 0. This is to detect confusion between + /// materializeGEP() and buildGEP(). + /// \post \p Res will either be a new generic virtual register of the same + /// type as \p Op0 or \p Op0 itself. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + Optional materializeGEP(unsigned &Res, unsigned Op0, + const LLT &ValueTy, + uint64_t Value); + /// Build and insert \p Res = G_PTR_MASK \p Op0, \p NumBits /// /// G_PTR_MASK clears the low bits of a pointer operand without destroying its diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index ddfabb0..8c3aaca 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -333,12 +333,12 @@ namespace RTLIB { MEMSET, MEMMOVE, - // ELEMENT-WISE ATOMIC MEMORY - MEMCPY_ELEMENT_ATOMIC_1, - MEMCPY_ELEMENT_ATOMIC_2, - MEMCPY_ELEMENT_ATOMIC_4, - MEMCPY_ELEMENT_ATOMIC_8, - MEMCPY_ELEMENT_ATOMIC_16, + // ELEMENT-WISE UNORDERED-ATOMIC MEMORY of different element sizes + MEMCPY_ELEMENT_UNORDERED_ATOMIC_1, + MEMCPY_ELEMENT_UNORDERED_ATOMIC_2, + MEMCPY_ELEMENT_UNORDERED_ATOMIC_4, + MEMCPY_ELEMENT_UNORDERED_ATOMIC_8, + MEMCPY_ELEMENT_UNORDERED_ATOMIC_16, // EXCEPTION HANDLING UNWIND_RESUME, @@ -511,9 +511,10 @@ namespace RTLIB { /// UNKNOWN_LIBCALL if there is none. Libcall getSYNC(unsigned Opc, MVT VT); - /// getMEMCPY_ELEMENT_ATOMIC - Return MEMCPY_ELEMENT_ATOMIC_* value for the - /// given element size or UNKNOW_LIBCALL if there is none. - Libcall getMEMCPY_ELEMENT_ATOMIC(uint64_t ElementSize); + /// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return + /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or + /// UNKNOW_LIBCALL if there is none. + Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize); } } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 2ef7796..f3f3003 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -1217,6 +1217,12 @@ public: void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, unsigned Num); + /// If an existing load has uses of its chain, create a token factor node with + /// that chain and the new memory node's chain and update users of the old + /// chain to the token factor. This ensures that the new memory node will have + /// the same relative memory dependency position as the old load. + void makeEquivalentMemoryOrdering(LoadSDNode *Old, SDValue New); + /// Topological-sort the AllNodes list and a /// assign a unique node id for each node in the DAG based on their /// topological order. Returns the number of nodes. diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 106a084..e4d3cc9 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -42,9 +42,8 @@ public: ~TargetLoweringObjectFileELF() override = default; /// Emit Obj-C garbage collection and linker options. - void emitModuleFlags(MCStreamer &Streamer, - ArrayRef ModuleFlags, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M, + const TargetMachine &TM) const override; void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, const MCSymbol *Sym) const override; @@ -99,9 +98,8 @@ public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; /// Emit the module flags that specify the garbage collection information. - void emitModuleFlags(MCStreamer &Streamer, - ArrayRef ModuleFlags, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M, + const TargetMachine &TM) const override; MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override; @@ -155,9 +153,8 @@ public: const TargetMachine &TM) const override; /// Emit Obj-C garbage collection and linker options. - void emitModuleFlags(MCStreamer &Streamer, - ArrayRef ModuleFlags, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M, + const TargetMachine &TM) const override; MCSection *getStaticCtorSection(unsigned Priority, const MCSymbol *KeySym) const override; diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h index 251c9d1..6820e26 100644 --- a/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/include/llvm/DebugInfo/CodeView/CodeView.h @@ -418,6 +418,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags) /// Corresponds to COMPILESYM2::Flags bitfield. enum class CompileSym2Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, EC = 1 << 8, NoDbgInfo = 1 << 9, LTCG = 1 << 10, @@ -432,6 +434,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags) /// Corresponds to COMPILESYM3::Flags bitfield. enum class CompileSym3Flags : uint32_t { + None = 0, + SourceLanguageMask = 0xFF, EC = 1 << 8, NoDbgInfo = 1 << 9, LTCG = 1 << 10, @@ -448,6 +452,7 @@ enum class CompileSym3Flags : uint32_t { CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags) enum class ExportFlags : uint16_t { + None = 0, IsConstant = 1 << 0, IsData = 1 << 1, IsPrivate = 1 << 2, diff --git a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h index 686b5c4..1e329c7 100644 --- a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h @@ -49,6 +49,7 @@ public: Error commit(BinaryStreamWriter &Writer) const override; void addFrameData(const FrameData &Frame); + void setFrames(ArrayRef Frames); private: std::vector Frames; diff --git a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h index c9b0627..7484af6 100644 --- a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h @@ -19,7 +19,7 @@ namespace llvm { namespace codeview { -class DebugInlineeLinesSubsectionsRef; +class DebugInlineeLinesSubsectionRef; class DebugChecksumsSubsection; enum class InlineeLinesSignature : uint32_t { diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index 49a269d..6947317 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -49,13 +49,13 @@ private: class DebugSubsectionRecordBuilder { public: - DebugSubsectionRecordBuilder(std::unique_ptr Subsection, + DebugSubsectionRecordBuilder(std::shared_ptr Subsection, CodeViewContainer Container); uint32_t calculateSerializedLength(); Error commit(BinaryStreamWriter &Writer) const; private: - std::unique_ptr Subsection; + std::shared_ptr Subsection; CodeViewContainer Container; }; @@ -64,6 +64,9 @@ private: template <> struct VarStreamArrayExtractor { Error operator()(BinaryStreamRef Stream, uint32_t &Length, codeview::DebugSubsectionRecord &Info) { + // FIXME: We need to pass the container type through to this function. In + // practice this isn't super important since the subsection header describes + // its length and we can just skip it. It's more important when writing. if (auto EC = codeview::DebugSubsectionRecord::initialize( Stream, Info, codeview::CodeViewContainer::Pdb)) return EC; diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index d4a3d91..75f749d 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/Support/Error.h" #include @@ -30,56 +31,7 @@ class DebugStringTableSubsectionRef; class DebugSymbolRVASubsectionRef; class DebugSymbolsSubsectionRef; class DebugUnknownSubsectionRef; - -struct DebugSubsectionState { -public: - // If no subsections are known about initially, we find as much as we can. - DebugSubsectionState(); - - // If only a string table subsection is given, we find a checksums subsection. - explicit DebugSubsectionState(const DebugStringTableSubsectionRef &Strings); - - // If both subsections are given, we don't need to find anything. - DebugSubsectionState(const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums); - - template void initialize(T &&FragmentRange) { - for (const DebugSubsectionRecord &R : FragmentRange) { - if (Strings && Checksums) - return; - if (R.kind() == DebugSubsectionKind::FileChecksums) { - initializeChecksums(R); - continue; - } - if (R.kind() == DebugSubsectionKind::StringTable && !Strings) { - // While in practice we should never encounter a string table even - // though the string table is already initialized, in theory it's - // possible. PDBs are supposed to have one global string table and - // then this subsection should not appear. Whereas object files are - // supposed to have this subsection appear exactly once. However, - // for testing purposes it's nice to be able to test this subsection - // independently of one format or the other, so for some tests we - // manually construct a PDB that contains this subsection in addition - // to a global string table. - initializeStrings(R); - continue; - } - } - } - - const DebugStringTableSubsectionRef &strings() const { return *Strings; } - const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; } - -private: - void initializeStrings(const DebugSubsectionRecord &SR); - void initializeChecksums(const DebugSubsectionRecord &FCR); - - std::unique_ptr OwnedStrings; - std::unique_ptr OwnedChecksums; - - const DebugStringTableSubsectionRef *Strings = nullptr; - const DebugChecksumsSubsectionRef *Checksums = nullptr; -}; +class StringsAndChecksumsRef; class DebugSubsectionVisitor { public: @@ -89,38 +41,38 @@ public: return Error::success(); } virtual Error visitLines(DebugLinesSubsectionRef &Lines, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitStringTable(DebugStringTableSubsectionRef &ST, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs, - const DebugSubsectionState &State) = 0; + const StringsAndChecksumsRef &State) = 0; }; Error visitDebugSubsection(const DebugSubsectionRecord &R, DebugSubsectionVisitor &V, - const DebugSubsectionState &State); + const StringsAndChecksumsRef &State); namespace detail { template Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, - DebugSubsectionState &State) { + StringsAndChecksumsRef &State) { State.initialize(std::forward(FragmentRange)); for (const DebugSubsectionRecord &L : FragmentRange) { @@ -133,7 +85,7 @@ Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, template Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { - DebugSubsectionState State; + StringsAndChecksumsRef State; return detail::visitDebugSubsections(std::forward(FragmentRange), V, State); } @@ -141,7 +93,7 @@ Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { template Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, const DebugStringTableSubsectionRef &Strings) { - DebugSubsectionState State(Strings); + StringsAndChecksumsRef State(Strings); return detail::visitDebugSubsections(std::forward(FragmentRange), V, State); } @@ -150,7 +102,7 @@ template Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums) { - DebugSubsectionState State(Strings, Checksums); + StringsAndChecksumsRef State(Strings, Checksums); return detail::visitDebugSubsections(std::forward(FragmentRange), V, State); } diff --git a/include/llvm/DebugInfo/CodeView/Formatters.h b/include/llvm/DebugInfo/CodeView/Formatters.h index 37a9109..1fbb0dd 100644 --- a/include/llvm/DebugInfo/CodeView/Formatters.h +++ b/include/llvm/DebugInfo/CodeView/Formatters.h @@ -12,7 +12,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatProviders.h" +#include "llvm/Support/FormatVariadic.h" namespace llvm { namespace codeview { @@ -35,6 +38,20 @@ inline detail::GuidAdapter fmt_guid(ArrayRef Item) { return detail::GuidAdapter(Item); } } + +template <> struct format_provider { +public: + static void format(const codeview::TypeIndex &V, llvm::raw_ostream &Stream, + StringRef Style) { + if (V.isNoneType()) + Stream << ""; + else { + Stream << formatv("{0:X+4}", V.getIndex()); + if (V.isSimple()) + Stream << " (" << codeview::TypeIndex::simpleTypeName(V) << ")"; + } + } +}; } #endif diff --git a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h new file mode 100644 index 0000000..708b317 --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h @@ -0,0 +1,106 @@ +//===- StringsAndChecksums.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_CODEVIEW_STRINGS_AND_CHECKSUMS_H +#define LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" + +#include + +namespace llvm { +namespace codeview { + +class DebugSubsectionRecord; +class DebugChecksumsSubsectionRef; +class DebugStringTableSubsectionRef; +class DebugChecksumsSubsection; +class DebugStringTableSubsection; + +class StringsAndChecksumsRef { +public: + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksumsRef(); + + // If only a string table subsection is given, we find a checksums subsection. + explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings); + + // If both subsections are given, we don't need to find anything. + StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums); + + void setChecksums(const DebugChecksumsSubsectionRef &CS); + + template void initialize(T &&FragmentRange) { + for (const DebugSubsectionRecord &R : FragmentRange) { + if (Strings && Checksums) + return; + if (R.kind() == DebugSubsectionKind::FileChecksums) { + initializeChecksums(R); + continue; + } + if (R.kind() == DebugSubsectionKind::StringTable && !Strings) { + // While in practice we should never encounter a string table even + // though the string table is already initialized, in theory it's + // possible. PDBs are supposed to have one global string table and + // then this subsection should not appear. Whereas object files are + // supposed to have this subsection appear exactly once. However, + // for testing purposes it's nice to be able to test this subsection + // independently of one format or the other, so for some tests we + // manually construct a PDB that contains this subsection in addition + // to a global string table. + initializeStrings(R); + continue; + } + } + } + + const DebugStringTableSubsectionRef &strings() const { return *Strings; } + const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + void initializeStrings(const DebugSubsectionRecord &SR); + void initializeChecksums(const DebugSubsectionRecord &FCR); + + std::unique_ptr OwnedStrings; + std::unique_ptr OwnedChecksums; + + const DebugStringTableSubsectionRef *Strings = nullptr; + const DebugChecksumsSubsectionRef *Checksums = nullptr; +}; + +class StringsAndChecksums { +public: + using StringsPtr = std::shared_ptr; + using ChecksumsPtr = std::shared_ptr; + // If no subsections are known about initially, we find as much as we can. + StringsAndChecksums() {} + + void setStrings(const StringsPtr &SP) { Strings = SP; } + void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; } + + const StringsPtr &strings() const { return Strings; } + const ChecksumsPtr &checksums() const { return Checksums; } + + bool hasStrings() const { return Strings != nullptr; } + bool hasChecksums() const { return Checksums != nullptr; } + +private: + StringsPtr Strings; + ChecksumsPtr Checksums; +}; + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index a3e4dff..5f85ed2 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -363,7 +363,7 @@ public: : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset) {} - uint32_t Index; + TypeIndex Index; uint32_t Offset; uint16_t Segment; StringRef Name; @@ -379,7 +379,7 @@ public: : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset) {} - uint32_t Index; + TypeIndex Index; RegisterId Register; StringRef Name; @@ -679,7 +679,7 @@ public: : SymbolRecord(SymbolRecordKind::FileStaticSym), RecordOffset(RecordOffset) {} - uint32_t Index; + TypeIndex Index; uint32_t ModFilenameOffset; LocalSymFlags Flags; StringRef Name; @@ -814,7 +814,7 @@ public: uint32_t CodeOffset; uint16_t Register; - uint8_t CookieKind; + FrameCookieKind CookieKind; uint8_t Flags; uint32_t RecordOffset; @@ -871,7 +871,7 @@ public: uint32_t Offset; TypeIndex Type; - uint16_t Register; + RegisterId Register; StringRef Name; uint32_t RecordOffset; diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h index 31eed7d..10d51c2 100644 --- a/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -248,6 +248,8 @@ public: return A.toArrayIndex() - B.toArrayIndex(); } + static StringRef simpleTypeName(TypeIndex TI); + private: support::ulittle32_t Index; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 72793e9..3012b39 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -50,6 +50,10 @@ public: : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} bool extract(); + uint32_t getNumBuckets(); + uint32_t getNumHashes(); + uint32_t getSizeHdr(); + uint32_t getHeaderDataLength(); void dump(raw_ostream &OS) const; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index b9f14be..9eb5c45 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -20,6 +20,7 @@ struct DWARFAttribute; class DWARFContext; class DWARFDie; class DWARFUnit; +class DWARFAcceleratorTable; /// A class that verifies DWARF debug information given a DWARF Context. class DWARFVerifier { @@ -29,8 +30,9 @@ class DWARFVerifier { /// can verify each reference points to a valid DIE and not an offset that /// lies between to valid DIEs. std::map> ReferenceToDIEOffsets; - uint32_t NumDebugInfoErrors; - uint32_t NumDebugLineErrors; + uint32_t NumDebugInfoErrors = 0; + uint32_t NumDebugLineErrors = 0; + uint32_t NumAppleNamesErrors = 0; /// Verifies the attribute's DWARF attribute and its value. /// @@ -38,8 +40,8 @@ class DWARFVerifier { /// - DW_AT_ranges values is a valid .debug_ranges offset /// - DW_AT_stmt_list is a valid .debug_line offset /// - /// @param Die The DWARF DIE that owns the attribute value - /// @param AttrValue The DWARF attribute value to check + /// \param Die The DWARF DIE that owns the attribute value + /// \param AttrValue The DWARF attribute value to check void verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue); /// Verifies the attribute's DWARF form. @@ -49,8 +51,8 @@ class DWARFVerifier { /// - All DW_FORM_ref_addr values have valid .debug_info offsets /// - All DW_FORM_strp values have valid .debug_str offsets /// - /// @param Die The DWARF DIE that owns the attribute value - /// @param AttrValue The DWARF attribute value to check + /// \param Die The DWARF DIE that owns the attribute value + /// \param AttrValue The DWARF attribute value to check void verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); /// Verifies the all valid references that were found when iterating through @@ -75,13 +77,13 @@ class DWARFVerifier { public: DWARFVerifier(raw_ostream &S, DWARFContext &D) - : OS(S), DCtx(D), NumDebugInfoErrors(0), NumDebugLineErrors(0) {} + : OS(S), DCtx(D) {} /// Verify the information in the .debug_info section. /// /// Any errors are reported to the stream that was this object was /// constructed with. /// - /// @return True if the .debug_info verifies successfully, false otherwise. + /// \returns true if the .debug_info verifies successfully, false otherwise. bool handleDebugInfo(); /// Verify the information in the .debug_line section. @@ -89,8 +91,16 @@ public: /// Any errors are reported to the stream that was this object was /// constructed with. /// - /// @return True if the .debug_line verifies successfully, false otherwise. + /// \returns true if the .debug_line verifies successfully, false otherwise. bool handleDebugLine(); + + /// Verify the information in the .apple_names accelerator table. + /// + /// Any errors are reported to the stream that was this object was + /// constructed with. + /// + /// \returns true if the .apple_names verifies successfully, false otherwise. + bool handleAppleNames(); }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index 2ff166b..a89e26a 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -50,12 +50,14 @@ public: void addSymbol(codeview::CVSymbol Symbol); void - addDebugSubsection(std::unique_ptr Subsection); + addDebugSubsection(std::shared_ptr Subsection); uint16_t getStreamIndex() const; StringRef getModuleName() const { return ModuleName; } StringRef getObjFileName() const { return ObjFileName; } + unsigned getModuleIndex() const { return Layout.Mod; } + ArrayRef source_files() const { return makeArrayRef(SourceFiles); } diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h index bcf1cff..2885081 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamRef.h" @@ -21,6 +22,7 @@ #include namespace llvm { +namespace codeview {} namespace pdb { class DbiModuleList; diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index e116f31..aeb2e2a 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -49,7 +49,6 @@ public: void setPdbDllRbld(uint16_t R); void setFlags(uint16_t F); void setMachineType(PDB_Machine M); - void setSectionContribs(ArrayRef SecMap); void setSectionMap(ArrayRef SecMap); // Add given bytes as a new stream. @@ -65,10 +64,8 @@ public: Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer); - // A helper function to create Section Contributions from COFF input - // section headers. - static std::vector - createSectionContribs(ArrayRef SecHdrs); + void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi, + const llvm::object::coff_section *SecHdr); // A helper function to create a Section Map from a COFF section header. static std::vector @@ -112,7 +109,7 @@ private: WritableBinaryStreamRef NamesBuffer; MutableBinaryByteStream FileInfoBuffer; - ArrayRef SectionContribs; + std::vector SectionContribs; ArrayRef SectionMap; llvm::SmallVector DbgStreams; }; diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h index 1c38c2b..fc91fc7 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStream.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -35,6 +35,7 @@ public: uint32_t getStreamSize() const; + bool containsIdStream() const; PdbRaw_ImplVer getVersion() const; uint32_t getSignature() const; uint32_t getAge() const; diff --git a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h index a812197..c744696 100644 --- a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -31,6 +31,7 @@ class ModuleDebugStreamRef { public: ModuleDebugStreamRef(const DbiModuleDescriptor &Module, std::unique_ptr Stream); + ModuleDebugStreamRef(ModuleDebugStreamRef &&Other) = default; ~ModuleDebugStreamRef(); Error reload(); @@ -40,6 +41,12 @@ public: iterator_range symbols(bool *HadError) const; + const codeview::CVSymbolArray &getSymbolArray() const { + return SymbolsSubstream; + } + + ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = default; + llvm::iterator_range subsections() const; bool hasDebugSubsections() const; @@ -54,7 +61,7 @@ private: uint32_t Signature; - std::unique_ptr Stream; + std::shared_ptr Stream; codeview::CVSymbolArray SymbolsSubstream; BinaryStreamRef C11LinesSubstream; diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h index 3bed671..4d3c569 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -108,6 +108,8 @@ public: bool hasPDBTpiStream() const; bool hasPDBStringTable(); + uint32_t getPointerSize(); + private: Expected> safelyCreateIndexedStream(const msf::MSFLayout &Layout, diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index 28a14d7..86ef113 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -45,7 +45,7 @@ public: FixedStreamArray name_ids() const; - codeview::DebugStringTableSubsectionRef getStringTable() const; + const codeview::DebugStringTableSubsectionRef &getStringTable() const; private: Error readHeader(BinaryStreamReader &Reader); diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h index 0faa02d..b57707e 100644 --- a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -41,10 +41,7 @@ public: uint32_t calculateSerializedSize() const; Error commit(BinaryStreamWriter &Writer) const; - codeview::DebugStringTableSubsection &getStrings() { return Strings; } - const codeview::DebugStringTableSubsection &getStrings() const { - return Strings; - } + void setStrings(const codeview::DebugStringTableSubsection &Strings); private: uint32_t calculateHashTableSize() const; diff --git a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h index 4a541ed..4570c80 100644 --- a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h +++ b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h @@ -35,6 +35,7 @@ public: uint32_t getSymHash() const; uint32_t getAddrMap() const; uint32_t getNumBuckets() const { return NumBuckets; } + Expected getSymbolArray() const; iterator_range getSymbols(bool *HadError) const; FixedStreamArray getHashBuckets() const { diff --git a/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/include/llvm/DebugInfo/PDB/Native/RawConstants.h index e1bd86b..bb1d097 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawConstants.h +++ b/include/llvm/DebugInfo/PDB/Native/RawConstants.h @@ -98,15 +98,19 @@ enum class DbgHeaderType : uint16_t { }; enum class OMFSegDescFlags : uint16_t { + None = 0, Read = 1 << 0, // Segment is readable. Write = 1 << 1, // Segment is writable. Execute = 1 << 2, // Segment is executable. AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address. IsSelector = 1 << 8, // Frame represents a selector. IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address. - IsGroup = 1 << 10 // If set, descriptor represents a group. + IsGroup = 1 << 10, // If set, descriptor represents a group. + LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IsGroup) }; +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + } // end namespace pdb } // end namespace llvm diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h index 41d5e6a..17695f5 100644 --- a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h +++ b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h @@ -27,6 +27,10 @@ public: ~SymbolStream(); Error reload(); + const codeview::CVSymbolArray &getSymbolArray() const { + return SymbolRecords; + } + iterator_range getSymbols(bool *HadError) const; diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h index 21cfa83..411720d 100644 --- a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h @@ -58,6 +58,8 @@ public: Error finalizeMsfLayout(); + uint32_t getRecordCount() const { return TypeRecords.size(); } + Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer); uint32_t calculateSerializedLength(); diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index bb5e193..003a6d5 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -68,11 +68,8 @@ protected: void *operator new(size_t s) { return User::operator new(s, 0); } public: - ConstantData() = delete; ConstantData(const ConstantData &) = delete; - void *operator new(size_t, unsigned) = delete; - /// Methods to support type inquiry through isa, cast, and dyn_cast. static bool classof(const Value *V) { return V->getValueID() >= ConstantDataFirstVal && @@ -691,8 +688,6 @@ class ConstantDataArray final : public ConstantDataSequential { public: ConstantDataArray(const ConstantDataArray &) = delete; - void *operator new(size_t, unsigned) = delete; - /// get() constructors - Return a constant with array type with an element /// count and element type matching the ArrayRef passed in. Note that this /// can return a ConstantAggregateZero object. @@ -752,8 +747,6 @@ class ConstantDataVector final : public ConstantDataSequential { public: ConstantDataVector(const ConstantDataVector &) = delete; - void *operator new(size_t, unsigned) = delete; - /// get() constructors - Return a constant with vector type with an element /// count and element type matching the ArrayRef passed in. Note that this /// can return a ConstantAggregateZero object. @@ -830,8 +823,6 @@ class BlockAddress final : public Constant { Value *handleOperandChangeImpl(Value *From, Value *To); public: - void *operator new(size_t, unsigned) = delete; - /// Return a BlockAddress for the specified function and basic block. static BlockAddress *get(Function *F, BasicBlock *BB); diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 2174e1f..9374fe4 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -2117,9 +2117,6 @@ public: /// variable, or the location of a single piece of a variable, or (when using /// DW_OP_stack_value) is the constant variable value. /// -/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const -/// and have DW_OP_plus consume the topmost elements on the stack. -/// /// TODO: Co-allocate the expression elements. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 4544927..8255a4f 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -78,8 +78,6 @@ public: return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; - /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 5ddaf2b..ec33f82 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -435,27 +435,25 @@ public: MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - /// \brief Create and insert an atomic memcpy between the specified - /// pointers. + /// \brief Create and insert an element unordered-atomic memcpy between the + /// specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. Likewise with alias.scope /// and noalias tags. - CallInst *CreateElementAtomicMemCpy( - Value *Dst, Value *Src, uint64_t NumElements, uint32_t ElementSize, + CallInst *CreateElementUnorderedAtomicMemCpy( + Value *Dst, Value *Src, uint64_t Size, uint32_t ElementSize, MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr) { - return CreateElementAtomicMemCpy(Dst, Src, getInt64(NumElements), - ElementSize, TBAATag, TBAAStructTag, - ScopeTag, NoAliasTag); + return CreateElementUnorderedAtomicMemCpy( + Dst, Src, getInt64(Size), ElementSize, TBAATag, TBAAStructTag, ScopeTag, + NoAliasTag); } - CallInst *CreateElementAtomicMemCpy(Value *Dst, Value *Src, - Value *NumElements, uint32_t ElementSize, - MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr, - MDNode *ScopeTag = nullptr, - MDNode *NoAliasTag = nullptr); + CallInst *CreateElementUnorderedAtomicMemCpy( + Value *Dst, Value *Src, Value *Size, uint32_t ElementSize, + MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memmove between the specified /// pointers. diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index ff63da5..b3c6644 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -294,8 +294,6 @@ public: return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -343,8 +341,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -907,15 +903,11 @@ protected: BasicBlock *InsertAtEnd); public: - CmpInst() = delete; - // allocate space for exactly two operands void *operator new(size_t s) { return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Construct a compare instruction, given the opcode, the predicate and /// the two operands. Optionally (if InstBefore is specified) insert the /// instruction into a BasicBlock right before the specified instruction. diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 6029b0a..b3032f5 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -337,8 +337,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Return true if this is a store to a volatile memory location. bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } @@ -460,8 +458,6 @@ public: return User::operator new(s, 0); } - void *operator new(size_t, unsigned) = delete; - /// Returns the ordering effect of this fence. AtomicOrdering getOrdering() const { return AtomicOrdering(getSubclassDataFromInstruction() >> 1); @@ -538,8 +534,6 @@ public: return User::operator new(s, 3); } - void *operator new(size_t, unsigned) = delete; - /// Return true if this is a cmpxchg from a volatile memory /// location. /// @@ -728,8 +722,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - BinOp getOperation() const { return static_cast(getSubclassDataFromInstruction() >> 5); } @@ -2234,8 +2226,6 @@ public: return User::operator new(s, 3); } - void *operator new(size_t, unsigned) = delete; - /// Return true if a shufflevector instruction can be /// formed with the specified operands. static bool isValidOperands(const Value *V1, const Value *V2, @@ -2467,8 +2457,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - static InsertValueInst *Create(Value *Agg, Value *Val, ArrayRef Idxs, const Twine &NameStr = "", @@ -2596,11 +2584,6 @@ class PHINode : public Instruction { allocHungoffUses(ReservedSpace); } - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s); - } - protected: // Note: Instruction needs to be a friend here to call cloneImpl. friend class Instruction; @@ -2615,8 +2598,6 @@ protected: } public: - void *operator new(size_t, unsigned) = delete; - /// Constructors - NumReservedValues is a hint for the number of incoming /// edges that this phi node will have (use 0 if you really have no idea). static PHINode *Create(Type *Ty, unsigned NumReservedValues, @@ -2834,8 +2815,6 @@ protected: LandingPadInst *cloneImpl() const; public: - void *operator new(size_t, unsigned) = delete; - /// Constructors - NumReservedClauses is a hint for the number of incoming /// clauses that this landingpad will have (use 0 if you really have no idea). static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses, @@ -3134,8 +3113,6 @@ protected: SwitchInst *cloneImpl() const; public: - void *operator new(size_t, unsigned) = delete; - // -2 static const unsigned DefaultPseudoIndex = static_cast(~0L-1); @@ -3489,8 +3466,6 @@ protected: IndirectBrInst *cloneImpl() const; public: - void *operator new(size_t, unsigned) = delete; - static IndirectBrInst *Create(Value *Address, unsigned NumDests, Instruction *InsertBefore = nullptr) { return new IndirectBrInst(Address, NumDests, InsertBefore); @@ -4173,8 +4148,6 @@ protected: CatchSwitchInst *cloneImpl() const; public: - void *operator new(size_t, unsigned) = delete; - static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumHandlers, const Twine &NameStr = "", @@ -4609,8 +4582,6 @@ public: return User::operator new(s, 0); } - void *operator new(size_t, unsigned) = delete; - unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 2ae98d9..e0dd3ca 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -205,25 +205,91 @@ namespace llvm { }; /// This class represents atomic memcpy intrinsic - /// TODO: Integrate this class into MemIntrinsic hierarchy. - class ElementAtomicMemCpyInst : public IntrinsicInst { + /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is + /// C&P of all methods from that hierarchy + class ElementUnorderedAtomicMemCpyInst : public IntrinsicInst { + private: + enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 }; + public: - Value *getRawDest() const { return getArgOperand(0); } - Value *getRawSource() const { return getArgOperand(1); } + Value *getRawDest() const { + return const_cast(getArgOperand(ARG_DEST)); + } + const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } + Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } + + /// Return the arguments to the instruction. + Value *getRawSource() const { + return const_cast(getArgOperand(ARG_SOURCE)); + } + const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } + Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } + + Value *getLength() const { + return const_cast(getArgOperand(ARG_LENGTH)); + } + const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } + Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } + + bool isVolatile() const { return false; } + + Value *getRawElementSizeInBytes() const { + return const_cast(getArgOperand(ARG_ELEMENTSIZE)); + } + + ConstantInt *getElementSizeInBytesCst() const { + return cast(getRawElementSizeInBytes()); + } + + uint32_t getElementSizeInBytes() const { + return getElementSizeInBytesCst()->getZExtValue(); + } + + /// This is just like getRawDest, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getDest() const { return getRawDest()->stripPointerCasts(); } + + /// This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return getRawSource()->stripPointerCasts(); } + + unsigned getDestAddressSpace() const { + return cast(getRawDest()->getType())->getAddressSpace(); + } - Value *getNumElements() const { return getArgOperand(2); } - void setNumElements(Value *V) { setArgOperand(2, V); } + unsigned getSourceAddressSpace() const { + return cast(getRawSource()->getType())->getAddressSpace(); + } - uint64_t getSrcAlignment() const { return getParamAlignment(0); } - uint64_t getDstAlignment() const { return getParamAlignment(1); } + /// Set the specified arguments of the instruction. + void setDest(Value *Ptr) { + assert(getRawDest()->getType() == Ptr->getType() && + "setDest called with pointer of wrong type!"); + setArgOperand(ARG_DEST, Ptr); + } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setArgOperand(ARG_SOURCE, Ptr); + } + + void setLength(Value *L) { + assert(getLength()->getType() == L->getType() && + "setLength called with value of wrong type!"); + setArgOperand(ARG_LENGTH, L); + } - uint64_t getElementSizeInBytes() const { - Value *Arg = getArgOperand(3); - return cast(Arg)->getZExtValue(); + void setElementSizeInBytes(Constant *V) { + assert(V->getType() == Type::getInt8Ty(getContext()) && + "setElementSizeInBytes called with value of wrong type!"); + setArgOperand(ARG_ELEMENTSIZE, V); } static inline bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::memcpy_element_atomic; + return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; } static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 291d16f..45936a6 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -862,11 +862,16 @@ def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], //===------ Memory intrinsics with element-wise atomicity guarantees ------===// // -def int_memcpy_element_atomic : Intrinsic<[], - [llvm_anyptr_ty, llvm_anyptr_ty, - llvm_i64_ty, llvm_i32_ty], - [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, - WriteOnly<0>, ReadOnly<1>]>; +// @llvm.memcpy.element.unordered.atomic.*(dest, src, length, elementsize) +def int_memcpy_element_unordered_atomic + : Intrinsic<[], + [ + llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty + ], + [ + IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, + ReadOnly<1> + ]>; //===------------------------ Reduction Intrinsics ------------------------===// // diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index 144e45f..b43d588 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -542,6 +543,9 @@ private: /// considered live. bool WithGlobalValueDeadStripping = false; + std::set CfiFunctionDefs; + std::set CfiFunctionDecls; + // YAML I/O support. friend yaml::MappingTraits; @@ -567,6 +571,7 @@ public: bool isGlobalValueLive(const GlobalValueSummary *GVS) const { return !WithGlobalValueDeadStripping || GVS->isLive(); } + bool isGUIDLive(GlobalValue::GUID GUID) const; /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo(). ValueInfo getValueInfo(GlobalValue::GUID GUID) const { @@ -592,6 +597,12 @@ public: return I == OidGuidMap.end() ? 0 : I->second; } + std::set &cfiFunctionDefs() { return CfiFunctionDefs; } + const std::set &cfiFunctionDefs() const { return CfiFunctionDefs; } + + std::set &cfiFunctionDecls() { return CfiFunctionDecls; } + const std::set &cfiFunctionDecls() const { return CfiFunctionDecls; } + /// Add a global value summary for a value of the given name. void addGlobalValueSummary(StringRef ValueName, std::unique_ptr Summary) { @@ -691,14 +702,13 @@ public: return Pair.first; } - /// Add a new module path with the given \p Hash, mapped to the given \p - /// ModID, and return an iterator to the entry in the index. - ModulePathStringTableTy::iterator - addModulePath(StringRef ModPath, uint64_t ModId, - ModuleHash Hash = ModuleHash{{0}}) { - return ModulePathStringTable.insert(std::make_pair( - ModPath, - std::make_pair(ModId, Hash))).first; + typedef ModulePathStringTableTy::value_type ModuleInfo; + + /// Add a new module with the given \p Hash, mapped to the given \p + /// ModID, and return a reference to the module. + ModuleInfo *addModule(StringRef ModPath, uint64_t ModId, + ModuleHash Hash = ModuleHash{{0}}) { + return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first; } /// Check if the given Module has any functions available for exporting diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h index 891d84c..8950c52 100644 --- a/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -188,6 +188,7 @@ template <> struct MappingTraits { LLVM_YAML_IS_STRING_MAP(TypeIdSummary) LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml) +LLVM_YAML_IS_SEQUENCE_VECTOR(std::string) namespace llvm { namespace yaml { @@ -240,6 +241,23 @@ template <> struct MappingTraits { io.mapOptional("TypeIdMap", index.TypeIdMap); io.mapOptional("WithGlobalValueDeadStripping", index.WithGlobalValueDeadStripping); + + if (io.outputting()) { + std::vector CfiFunctionDefs(index.CfiFunctionDefs.begin(), + index.CfiFunctionDefs.end()); + io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); + std::vector CfiFunctionDecls(index.CfiFunctionDecls.begin(), + index.CfiFunctionDecls.end()); + io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); + } else { + std::vector CfiFunctionDefs; + io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); + index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()}; + std::vector CfiFunctionDecls; + io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); + index.CfiFunctionDecls = {CfiFunctionDecls.begin(), + CfiFunctionDecls.end()}; + } } }; diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 49fa6a6..6eb5998 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -35,7 +35,6 @@ public: Operator() = delete; ~Operator() = delete; - void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) = delete; /// Return the opcode for this Instruction or ConstantExpr. diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 542570a..015a17e 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -1027,7 +1027,7 @@ struct MaxMin_match { (TrueVal != RHS || FalseVal != LHS)) return false; typename CmpInst_t::Predicate Pred = - LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getInversePredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -1138,7 +1138,7 @@ inline MaxMin_match m_OrdFMax(const LHS &L, /// semantics. In the presence of 'NaN' we have to preserve the original /// select(fcmp(olt/le, L, R), L, R) semantics matched by this predicate. /// -/// max(L, R) iff L and R are not NaN +/// min(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN template inline MaxMin_match m_OrdFMin(const LHS &L, @@ -1154,13 +1154,28 @@ inline MaxMin_match m_OrdFMin(const LHS &L, /// select(fcmp(ugt/ge, L, R), L, R) semantics matched by this predicate. /// /// max(L, R) iff L and R are not NaN -/// m_UnordFMin(L, R) = L iff L or R are NaN +/// m_UnordFMax(L, R) = L iff L or R are NaN template inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(L, R); } +/// \brief Match an 'unordered' floating point minimum function. +/// Floating point has one special value 'NaN'. Therefore, there is no total +/// order. However, if we can ignore the 'NaN' value (for example, because of a +/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' +/// semantics. In the presence of 'NaN' we have to preserve the original +/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate. +/// +/// min(L, R) iff L and R are not NaN +/// m_UnordFMin(L, R) = L iff L or R are NaN +template +inline MaxMin_match +m_UnordFMin(const LHS &L, const RHS &R) { + return MaxMin_match(L, R); +} + //===----------------------------------------------------------------------===// // Matchers for overflow check patterns: e.g. (a + b) u< a // @@ -1207,21 +1222,6 @@ m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { return UAddWithOverflow_match(L, R, S); } -/// \brief Match an 'unordered' floating point minimum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_UnordFMin(L, R) = L iff L or R are NaN -template -inline MaxMin_match -m_UnordFMin(const LHS &L, const RHS &R) { - return MaxMin_match(L, R); -} - template struct Argument_match { unsigned OpI; Opnd_t Val; diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h index 774e144..d678a68 100644 --- a/include/llvm/LTO/LTO.h +++ b/include/llvm/LTO/LTO.h @@ -281,6 +281,16 @@ private: bool HasModule = false; std::unique_ptr CombinedModule; std::unique_ptr Mover; + + // This stores the information about a regular LTO module that we have added + // to the link. It will either be linked immediately (for modules without + // summaries) or after summary-based dead stripping (for modules with + // summaries). + struct AddedModule { + std::unique_ptr M; + std::vector Keep; + }; + std::vector ModsWithSummaries; } RegularLTO; struct ThinLTOState { @@ -303,9 +313,10 @@ private: /// The unmangled name of the global. std::string IRName; - /// Keep track if the symbol is visible outside of ThinLTO (i.e. in - /// either a regular object or the regular LTO partition). - bool VisibleOutsideThinLTO = false; + /// Keep track if the symbol is visible outside of a module with a summary + /// (i.e. in either a regular object or a regular LTO module without a + /// summary). + bool VisibleOutsideSummary = false; bool UnnamedAddr = true; @@ -339,8 +350,9 @@ private: // Global mapping from mangled symbol names to resolutions. StringMap GlobalResolutions; - void addSymbolToGlobalRes(const InputFile::Symbol &Sym, SymbolResolution Res, - unsigned Partition); + void addModuleToGlobalRes(ArrayRef Syms, + ArrayRef Res, unsigned Partition, + bool InSummary); // These functions take a range of symbol resolutions [ResI, ResE) and consume // the resolutions used by a single input module by incrementing ResI. After @@ -348,10 +360,13 @@ private: // the remaining modules in the InputFile. Error addModule(InputFile &Input, unsigned ModI, const SymbolResolution *&ResI, const SymbolResolution *ResE); - Error addRegularLTO(BitcodeModule BM, - ArrayRef Syms, - const SymbolResolution *&ResI, - const SymbolResolution *ResE); + + Expected + addRegularLTO(BitcodeModule BM, ArrayRef Syms, + const SymbolResolution *&ResI, const SymbolResolution *ResE); + Error linkRegularLTO(RegularLTOState::AddedModule Mod, + bool LivenessFromIndex); + Error addThinLTO(BitcodeModule BM, ArrayRef Syms, const SymbolResolution *&ResI, const SymbolResolution *ResE); diff --git a/include/llvm/LTO/legacy/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h index 2a87585..017e223 100644 --- a/include/llvm/LTO/legacy/LTOModule.h +++ b/include/llvm/LTO/legacy/LTOModule.h @@ -158,7 +158,7 @@ public: private: /// Parse metadata from the module - // FIXME: it only parses "Linker Options" metadata at the moment + // FIXME: it only parses "llvm.linker.options" metadata at the moment void parseMetadata(); /// Parse the symbols from the module and model-level ASM and add them to diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h index 7d661cc..1b87095 100644 --- a/include/llvm/MC/MCSymbolWasm.h +++ b/include/llvm/MC/MCSymbolWasm.h @@ -13,6 +13,7 @@ #include "llvm/MC/MCSymbol.h" namespace llvm { + class MCSymbolWasm : public MCSymbol { private: bool IsFunction = false; @@ -52,6 +53,7 @@ public: Params = std::move(Pars); } }; -} -#endif +} // end namespace llvm + +#endif // LLVM_MC_MCSYMBOLWASM_H diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h index c250d3b..bebc0a8 100644 --- a/include/llvm/MC/MCWasmObjectWriter.h +++ b/include/llvm/MC/MCWasmObjectWriter.h @@ -12,20 +12,12 @@ #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/Wasm.h" -#include "llvm/MC/MCValue.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/raw_ostream.h" -#include namespace llvm { -class MCAssembler; -class MCContext; + class MCFixup; -class MCFragment; class MCObjectWriter; -class MCSectionWasm; -class MCSymbol; -class MCSymbolWasm; class MCValue; class raw_pwrite_stream; @@ -38,8 +30,8 @@ protected: public: virtual ~MCWasmObjectTargetWriter(); - virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const = 0; + virtual unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup) const = 0; /// \name Accessors /// @{ @@ -54,6 +46,7 @@ public: /// \returns The constructed object writer. MCObjectWriter *createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS); + } // End llvm namespace #endif diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 3e84a58..1ed758d 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -22,6 +22,7 @@ namespace llvm { struct NewArchiveMember { std::unique_ptr Buf; + StringRef MemberName; sys::TimePoint ModTime; unsigned UID = 0, GID = 0, Perms = 0644; diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h index c518932..4839013 100644 --- a/include/llvm/Object/WindowsResource.h +++ b/include/llvm/Object/WindowsResource.h @@ -118,7 +118,7 @@ public: class TreeNode; WindowsResourceParser(); Error parse(WindowsResource *WR); - void printTree() const; + void printTree(raw_ostream &OS) const; const TreeNode &getTree() const { return Root; } const ArrayRef> getData() const { return Data; } const ArrayRef> getStringTable() const { @@ -159,14 +159,16 @@ public: TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, uint32_t Characteristics); - void addEntry(const ResourceEntryRef &Entry); - TreeNode &addTypeNode(const ResourceEntryRef &Entry); - TreeNode &addNameNode(const ResourceEntryRef &Entry); + void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString, + bool &IsNewNameString); + 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 NameRef); + TreeNode &addChild(ArrayRef NameRef, bool &IsNewString); + bool IsDataNode = false; uint32_t StringIndex; uint32_t DataIndex; diff --git a/include/llvm/ObjectYAML/COFFYAML.h b/include/llvm/ObjectYAML/COFFYAML.h index 1b5f7b0..719cb1a 100644 --- a/include/llvm/ObjectYAML/COFFYAML.h +++ b/include/llvm/ObjectYAML/COFFYAML.h @@ -16,6 +16,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" +#include "llvm/ObjectYAML/CodeViewYAMLTypes.h" #include "llvm/ObjectYAML/YAML.h" namespace llvm { @@ -56,6 +58,8 @@ namespace COFFYAML { COFF::section Header; unsigned Alignment = 0; yaml::BinaryRef SectionData; + std::vector DebugS; + std::vector DebugT; std::vector Relocations; StringRef Name; Section(); diff --git a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h index faa3ed8..8180e0f 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h @@ -28,6 +28,8 @@ class DebugStringTableSubsectionRef; class DebugChecksumsSubsectionRef; class DebugStringTableSubsection; class DebugChecksumsSubsection; +class StringsAndChecksums; +class StringsAndChecksumsRef; } namespace CodeViewYAML { @@ -103,25 +105,24 @@ struct InlineeInfo { struct YAMLDebugSubsection { static Expected - fromCodeViewSubection(const codeview::DebugStringTableSubsectionRef &Strings, - const codeview::DebugChecksumsSubsectionRef &Checksums, + fromCodeViewSubection(const codeview::StringsAndChecksumsRef &SC, const codeview::DebugSubsectionRecord &SS); std::shared_ptr Subsection; }; -Expected>> +struct DebugSubsectionState {}; + +Expected>> toCodeViewSubsectionList(BumpPtrAllocator &Allocator, ArrayRef Subsections, - codeview::DebugStringTableSubsection &Strings); -Expected>> -toCodeViewSubsectionList( - BumpPtrAllocator &Allocator, ArrayRef Subsections, - std::unique_ptr &TakeStrings, - codeview::DebugStringTableSubsection *StringsRef); - -std::unique_ptr -findStringTable(ArrayRef Sections); + const codeview::StringsAndChecksums &SC); + +std::vector +fromDebugS(ArrayRef Data, const codeview::StringsAndChecksumsRef &SC); + +void initializeStringsAndChecksums(ArrayRef Sections, + codeview::StringsAndChecksums &SC); } // namespace CodeViewYAML } // namespace llvm diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h index 91b75aa..e97d5f9 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h @@ -41,6 +41,9 @@ struct LeafRecord { codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const; static Expected fromCodeViewRecord(codeview::CVType Type); }; + +std::vector fromDebugT(ArrayRef DebugT); +ArrayRef toDebugT(ArrayRef, BumpPtrAllocator &Alloc); } // namespace CodeViewYAML } // namespace llvm diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index 99d3296..c519a4a 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -1,4 +1,4 @@ -//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===// +//===- Arg.h - Parsed Argument Classes --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,7 +21,11 @@ #include namespace llvm { + +class raw_ostream; + namespace opt { + class ArgList; /// \brief A concrete instance of a particular driver option. @@ -29,9 +33,6 @@ class ArgList; /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. class Arg { - Arg(const Arg &) = delete; - void operator=(const Arg &) = delete; - private: /// \brief The option this argument is an instance of. const Option Opt; @@ -65,6 +66,8 @@ public: const char *Value0, const Arg *BaseArg = nullptr); Arg(const Option Opt, StringRef Spelling, unsigned Index, const char *Value0, const char *Value1, const Arg *BaseArg = nullptr); + Arg(const Arg &) = delete; + Arg &operator=(const Arg &) = delete; ~Arg(); const Option &getOption() const { return Opt; } @@ -89,6 +92,7 @@ public: void claim() const { getBaseArg().Claimed = true; } unsigned getNumValues() const { return Values.size(); } + const char *getValue(unsigned N = 0) const { return Values[N]; } @@ -122,6 +126,7 @@ public: }; } // end namespace opt + } // end namespace llvm -#endif +#endif // LLVM_OPTION_ARG_H diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 6a92dd0..aaea68b 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -1,4 +1,4 @@ -//===--- ArgList.h - Argument List Management -------------------*- C++ -*-===// +//===- ArgList.h - Argument List Management ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,7 +10,9 @@ #ifndef LLVM_OPTION_ARGLIST_H #define LLVM_OPTION_ARGLIST_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -18,15 +20,21 @@ #include "llvm/Option/Arg.h" #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" +#include +#include +#include +#include #include #include #include +#include #include namespace llvm { + +class raw_ostream; + namespace opt { -class ArgList; -class Option; /// arg_iterator - Iterates through arguments stored inside an ArgList. template @@ -59,14 +67,14 @@ class arg_iterator { } } - typedef std::iterator_traits Traits; + using Traits = std::iterator_traits; public: - typedef typename Traits::value_type value_type; - typedef typename Traits::reference reference; - typedef typename Traits::pointer pointer; - typedef std::forward_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + using value_type = typename Traits::value_type; + using reference = typename Traits::reference; + using pointer = typename Traits::pointer; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; arg_iterator( BaseIter Current, BaseIter End, @@ -111,12 +119,12 @@ public: /// and to iterate over groups of arguments. class ArgList { public: - typedef SmallVector arglist_type; - typedef arg_iterator iterator; - typedef arg_iterator const_iterator; - typedef arg_iterator reverse_iterator; - typedef arg_iterator - const_reverse_iterator; + using arglist_type = SmallVector; + using iterator = arg_iterator; + using const_iterator = arg_iterator; + using reverse_iterator = arg_iterator; + using const_reverse_iterator = + arg_iterator; template using filtered_iterator = arg_iterator; @@ -127,7 +135,7 @@ private: /// The internal list of arguments. arglist_type Args; - typedef std::pair OptRange; + using OptRange = std::pair; static OptRange emptyRange() { return {-1u, 0u}; } /// The first and last index of each different OptSpecifier ID. @@ -142,6 +150,7 @@ protected: // derived objects, but can still be used by derived objects to implement // their own special members. ArgList() = default; + // Explicit move operations to ensure the container is cleared post-move // otherwise it could lead to a double-delete in the case of moving of an // InputArgList which deletes the contents of the container. If we could fix @@ -152,6 +161,7 @@ protected: RHS.Args.clear(); RHS.OptRanges.clear(); } + ArgList &operator=(ArgList &&RHS) { Args = std::move(RHS.Args); RHS.Args.clear(); @@ -159,6 +169,7 @@ protected: RHS.OptRanges.clear(); return *this; } + // Protect the dtor to ensure this type is never destroyed polymorphically. ~ArgList() = default; @@ -380,10 +391,12 @@ private: public: InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); + InputArgList(InputArgList &&RHS) : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)), SynthesizedStrings(std::move(RHS.SynthesizedStrings)), NumInputArgStrings(RHS.NumInputArgStrings) {} + InputArgList &operator=(InputArgList &&RHS) { releaseMemory(); ArgList::operator=(std::move(RHS)); @@ -392,6 +405,7 @@ public: NumInputArgStrings = RHS.NumInputArgStrings; return *this; } + ~InputArgList() { releaseMemory(); } const char *getArgString(unsigned Index) const override { @@ -464,7 +478,6 @@ public: append(MakePositionalArg(BaseArg, Opt, Value)); } - /// AddSeparateArg - Construct a new Positional arg for the given option /// \p Id, with the provided \p Value and append it to the argument /// list. @@ -473,7 +486,6 @@ public: append(MakeSeparateArg(BaseArg, Opt, Value)); } - /// AddJoinedArg - Construct a new Positional arg for the given option /// \p Id, with the provided \p Value and append it to the argument list. void AddJoinedArg(const Arg *BaseArg, const Option Opt, @@ -481,7 +493,6 @@ public: append(MakeJoinedArg(BaseArg, Opt, Value)); } - /// MakeFlagArg - Construct a new FlagArg for the given option \p Id. Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const; @@ -504,6 +515,7 @@ public: }; } // end namespace opt + } // end namespace llvm -#endif +#endif // LLVM_OPTION_ARGLIST_H diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index 0b2aaae..84c3cf8 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -1,4 +1,4 @@ -//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===// +//===- OptSpecifier.h - Option Specifiers -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,32 +10,30 @@ #ifndef LLVM_OPTION_OPTSPECIFIER_H #define LLVM_OPTION_OPTSPECIFIER_H -#include "llvm/Support/Compiler.h" - namespace llvm { namespace opt { - class Option; - /// OptSpecifier - Wrapper class for abstracting references to option IDs. - class OptSpecifier { - unsigned ID; +class Option; + +/// OptSpecifier - Wrapper class for abstracting references to option IDs. +class OptSpecifier { + unsigned ID = 0; - private: - explicit OptSpecifier(bool) = delete; +public: + OptSpecifier() = default; + explicit OptSpecifier(bool) = delete; + /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {} + /*implicit*/ OptSpecifier(const Option *Opt); - public: - OptSpecifier() : ID(0) {} - /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {} - /*implicit*/ OptSpecifier(const Option *Opt); + bool isValid() const { return ID != 0; } - bool isValid() const { return ID != 0; } + unsigned getID() const { return ID; } - unsigned getID() const { return ID; } + bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } + bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); } +}; - bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); } - bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); } - }; -} -} +} // end namespace opt +} // end namespace llvm -#endif +#endif // LLVM_OPTION_OPTSPECIFIER_H diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index 8a323a2..e0169b9 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -1,4 +1,4 @@ -//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===// +//===- OptTable.h - Option Table --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,12 +11,19 @@ #define LLVM_OPTION_OPTTABLE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" +#include +#include +#include namespace llvm { + class raw_ostream; + namespace opt { + class Arg; class ArgList; class InputArgList; @@ -53,12 +60,12 @@ private: ArrayRef OptionInfos; bool IgnoreCase; - unsigned TheInputOptionID; - unsigned TheUnknownOptionID; + unsigned TheInputOptionID = 0; + unsigned TheUnknownOptionID = 0; /// The index of the first option which can be parsed (i.e., is not a /// special option like 'input' or 'unknown', and is not an option group). - unsigned FirstSearchableIndex; + unsigned FirstSearchableIndex = 0; /// The union of all option prefixes. If an argument does not begin with /// one of these, it is an input. @@ -176,7 +183,9 @@ public: void PrintHelp(raw_ostream &OS, const char *Name, const char *Title, bool ShowHidden = false) const; }; + } // end namespace opt + } // end namespace llvm -#endif +#endif // LLVM_OPTION_OPTTABLE_H diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index 139f281..c08834f 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -1,4 +1,4 @@ -//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===// +//===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,23 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Option/OptSpecifier.h" #include "llvm/Option/OptTable.h" #include "llvm/Support/ErrorHandling.h" +#include +#include namespace llvm { + +class raw_ostream; + namespace opt { + class Arg; class ArgList; + /// ArgStringList - Type used for constructing argv lists for subprocesses. -typedef SmallVector ArgStringList; +using ArgStringList = SmallVector; /// Base flags for all options. Custom flags may be added after. enum DriverFlag { @@ -202,6 +210,7 @@ public: }; } // end namespace opt + } // end namespace llvm -#endif +#endif // LLVM_OPTION_OPTION_H diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h index 65ec15f..3f5562b 100644 --- a/include/llvm/Support/BinaryStreamArray.h +++ b/include/llvm/Support/BinaryStreamArray.h @@ -290,6 +290,12 @@ public: return FixedStreamArrayIterator(*this, size()); } + const T &front() const { return *begin(); } + const T &back() const { + FixedStreamArrayIterator I = end(); + return *(--I); + } + BinaryStreamRef getUnderlyingStream() const { return Stream; } private: diff --git a/include/llvm/Support/DebugCounter.h b/include/llvm/Support/DebugCounter.h index 9687cb7..a533fea 100644 --- a/include/llvm/Support/DebugCounter.h +++ b/include/llvm/Support/DebugCounter.h @@ -121,10 +121,10 @@ public: Us.Counters[ID] = Val; } - // Dump or print the current counter set. - LLVM_DUMP_METHOD void dump() { print(dbgs()); } + // Dump or print the current counter set into llvm::dbgs(). + LLVM_DUMP_METHOD void dump() const; - void print(raw_ostream &OS); + void print(raw_ostream &OS) const; // Get the counter ID for a given named counter, or return 0 if none is found. unsigned getCounterId(const std::string &Name) const { diff --git a/include/llvm/Support/FormatAdapters.h b/include/llvm/Support/FormatAdapters.h index 698e134..197beb7 100644 --- a/include/llvm/Support/FormatAdapters.h +++ b/include/llvm/Support/FormatAdapters.h @@ -28,14 +28,16 @@ namespace detail { template class AlignAdapter final : public FormatAdapter { AlignStyle Where; size_t Amount; + char Fill; public: - AlignAdapter(T &&Item, AlignStyle Where, size_t Amount) - : FormatAdapter(std::forward(Item)), Where(Where), Amount(Amount) {} + AlignAdapter(T &&Item, AlignStyle Where, size_t Amount, char Fill) + : FormatAdapter(std::forward(Item)), Where(Where), Amount(Amount), + Fill(Fill) {} void format(llvm::raw_ostream &Stream, StringRef Style) { auto Adapter = detail::build_format_adapter(std::forward(this->Item)); - FmtAlign(Adapter, Where, Amount).format(Stream, Style); + FmtAlign(Adapter, Where, Amount, Fill).format(Stream, Style); } }; @@ -72,8 +74,9 @@ public: } template -detail::AlignAdapter fmt_align(T &&Item, AlignStyle Where, size_t Amount) { - return detail::AlignAdapter(std::forward(Item), Where, Amount); +detail::AlignAdapter fmt_align(T &&Item, AlignStyle Where, size_t Amount, + char Fill = ' ') { + return detail::AlignAdapter(std::forward(Item), Where, Amount, Fill); } template diff --git a/include/llvm/Support/FormatCommon.h b/include/llvm/Support/FormatCommon.h index a8c5fde..36fbad2 100644 --- a/include/llvm/Support/FormatCommon.h +++ b/include/llvm/Support/FormatCommon.h @@ -21,9 +21,11 @@ struct FmtAlign { detail::format_adapter &Adapter; AlignStyle Where; size_t Amount; + char Fill; - FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount) - : Adapter(Adapter), Where(Where), Amount(Amount) {} + FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount, + char Fill = ' ') + : Adapter(Adapter), Where(Where), Amount(Amount), Fill(Fill) {} void format(raw_ostream &S, StringRef Options) { // If we don't need to align, we can format straight into the underlying @@ -48,21 +50,27 @@ struct FmtAlign { switch (Where) { case AlignStyle::Left: S << Item; - S.indent(PadAmount); + fill(S, PadAmount); break; case AlignStyle::Center: { size_t X = PadAmount / 2; - S.indent(X); + fill(S, X); S << Item; - S.indent(PadAmount - X); + fill(S, PadAmount - X); break; } default: - S.indent(PadAmount); + fill(S, PadAmount); S << Item; break; } } + +private: + void fill(llvm::raw_ostream &S, uint32_t Count) { + for (uint32_t I = 0; I < Count; ++I) + S << Fill; + } }; } diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index bb84038..fd29865 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -272,23 +272,22 @@ T reverseBits(T Val) { // type overloading so that signed and unsigned integers can be used without // ambiguity. -/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +/// Return the high 32 bits of a 64 bit value. constexpr inline uint32_t Hi_32(uint64_t Value) { return static_cast(Value >> 32); } -/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +/// Return the low 32 bits of a 64 bit value. constexpr inline uint32_t Lo_32(uint64_t Value) { return static_cast(Value); } -/// Make_64 - This functions makes a 64-bit integer from a high / low pair of -/// 32-bit integers. +/// Make a 64-bit integer from a high / low pair of 32-bit integers. constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { return ((uint64_t)High << 32) | (uint64_t)Low; } -/// isInt - Checks if an integer fits into the given bit width. +/// Checks if an integer fits into the given bit width. template constexpr inline bool isInt(int64_t x) { return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); } @@ -303,8 +302,7 @@ template <> constexpr inline bool isInt<32>(int64_t x) { return static_cast(x) == x; } -/// isShiftedInt - Checks if a signed integer is an N bit number shifted -/// left by S. +/// Checks if a signed integer is an N bit number shifted left by S. template constexpr inline bool isShiftedInt(int64_t x) { static_assert( @@ -313,7 +311,7 @@ constexpr inline bool isShiftedInt(int64_t x) { return isInt(x) && (x % (UINT64_C(1) << S) == 0); } -/// isUInt - Checks if an unsigned integer fits into the given bit width. +/// Checks if an unsigned integer fits into the given bit width. /// /// This is written as two functions rather than as simply /// @@ -383,71 +381,63 @@ inline int64_t maxIntN(int64_t N) { return (UINT64_C(1) << (N - 1)) - 1; } -/// isUIntN - Checks if an unsigned integer fits into the given (dynamic) -/// bit width. +/// Checks if an unsigned integer fits into the given (dynamic) bit width. inline bool isUIntN(unsigned N, uint64_t x) { return N >= 64 || x <= maxUIntN(N); } -/// isIntN - Checks if an signed integer fits into the given (dynamic) -/// bit width. +/// Checks if an signed integer fits into the given (dynamic) bit width. inline bool isIntN(unsigned N, int64_t x) { return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); } -/// isMask_32 - This function returns true if the argument is a non-empty -/// sequence of ones starting at the least significant bit with the remainder -/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. +/// Return true if the argument is a non-empty sequence of ones starting at the +/// least significant bit with the remainder zero (32 bit version). +/// Ex. isMask_32(0x0000FFFFU) == true. constexpr inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; } -/// isMask_64 - This function returns true if the argument is a non-empty -/// sequence of ones starting at the least significant bit with the remainder -/// zero (64 bit version). +/// Return true if the argument is a non-empty sequence of ones starting at the +/// least significant bit with the remainder zero (64 bit version). constexpr inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } -/// isShiftedMask_32 - This function returns true if the argument contains a -/// non-empty sequence of ones with the remainder zero (32 bit version.) -/// Ex. isShiftedMask_32(0x0000FF00U) == true. +/// Return true if the argument contains a non-empty sequence of ones with the +/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true. constexpr inline bool isShiftedMask_32(uint32_t Value) { return Value && isMask_32((Value - 1) | Value); } -/// isShiftedMask_64 - This function returns true if the argument contains a -/// non-empty sequence of ones with the remainder zero (64 bit version.) +/// Return true if the argument contains a non-empty sequence of ones with the +/// remainder zero (64 bit version.) constexpr inline bool isShiftedMask_64(uint64_t Value) { return Value && isMask_64((Value - 1) | Value); } -/// isPowerOf2_32 - This function returns true if the argument is a power of -/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) +/// Return true if the argument is a power of two > 0. +/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) constexpr inline bool isPowerOf2_32(uint32_t Value) { return Value && !(Value & (Value - 1)); } -/// isPowerOf2_64 - This function returns true if the argument is a power of two -/// > 0 (64 bit edition.) +/// Return true if the argument is a power of two > 0 (64 bit edition.) constexpr inline bool isPowerOf2_64(uint64_t Value) { return Value && !(Value & (Value - int64_t(1L))); } -/// ByteSwap_16 - This function returns a byte-swapped representation of the -/// 16-bit argument, Value. +/// Return a byte-swapped representation of the 16-bit argument. inline uint16_t ByteSwap_16(uint16_t Value) { return sys::SwapByteOrder_16(Value); } -/// ByteSwap_32 - This function returns a byte-swapped representation of the -/// 32-bit argument, Value. +/// Return a byte-swapped representation of the 32-bit argument. inline uint32_t ByteSwap_32(uint32_t Value) { return sys::SwapByteOrder_32(Value); } -/// ByteSwap_64 - This function returns a byte-swapped representation of the -/// 64-bit argument, Value. +/// Return a byte-swapped representation of the 64-bit argument. inline uint64_t ByteSwap_64(uint64_t Value) { return sys::SwapByteOrder_64(Value); } @@ -455,7 +445,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) { /// \brief Count the number of ones from the most significant bit to the first /// zero bit. /// -/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. +/// Ex. countLeadingOnes(0xFF0FFF00) == 8. /// Only unsigned integral types are allowed. /// /// \param ZB the behavior on an input of all ones. Only ZB_Width and @@ -526,7 +516,7 @@ inline unsigned countPopulation(T Value) { return detail::PopulationCounter::count(Value); } -/// Log2 - This function returns the log base 2 of the specified value +/// Return the log base 2 of the specified value. inline double Log2(double Value) { #if defined(__ANDROID_API__) && __ANDROID_API__ < 18 return __builtin_log(Value) / __builtin_log(2.0); @@ -535,34 +525,33 @@ inline double Log2(double Value) { #endif } -/// Log2_32 - This function returns the floor log base 2 of the specified value, -/// -1 if the value is zero. (32 bit edition.) +/// Return the floor log base 2 of the specified value, -1 if the value is zero. +/// (32 bit edition.) /// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 inline unsigned Log2_32(uint32_t Value) { return 31 - countLeadingZeros(Value); } -/// Log2_64 - This function returns the floor log base 2 of the specified value, -/// -1 if the value is zero. (64 bit edition.) +/// Return the floor log base 2 of the specified value, -1 if the value is zero. +/// (64 bit edition.) inline unsigned Log2_64(uint64_t Value) { return 63 - countLeadingZeros(Value); } -/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified -/// value, 32 if the value is zero. (32 bit edition). +/// Return the ceil log base 2 of the specified value, 32 if the value is zero. +/// (32 bit edition). /// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 inline unsigned Log2_32_Ceil(uint32_t Value) { return 32 - countLeadingZeros(Value - 1); } -/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified -/// value, 64 if the value is zero. (64 bit edition.) +/// Return the ceil log base 2 of the specified value, 64 if the value is zero. +/// (64 bit edition.) inline unsigned Log2_64_Ceil(uint64_t Value) { return 64 - countLeadingZeros(Value - 1); } -/// GreatestCommonDivisor64 - Return the greatest common divisor of the two -/// values using Euclid's algorithm. +/// Return the greatest common divisor of the values using Euclid's algorithm. inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { while (B) { uint64_t T = B; @@ -572,8 +561,7 @@ inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { return A; } -/// BitsToDouble - This function takes a 64-bit integer and returns the bit -/// equivalent double. +/// This function takes a 64-bit integer and returns the bit equivalent double. inline double BitsToDouble(uint64_t Bits) { double D; static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes"); @@ -581,8 +569,7 @@ inline double BitsToDouble(uint64_t Bits) { return D; } -/// BitsToFloat - This function takes a 32-bit integer and returns the bit -/// equivalent float. +/// This function takes a 32-bit integer and returns the bit equivalent float. inline float BitsToFloat(uint32_t Bits) { float F; static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes"); @@ -590,10 +577,9 @@ inline float BitsToFloat(uint32_t Bits) { return F; } -/// DoubleToBits - This function takes a double and returns the bit -/// equivalent 64-bit integer. Note that copying doubles around -/// changes the bits of NaNs on some hosts, notably x86, so this -/// routine cannot be used if these bits are needed. +/// This function takes a double and returns the bit equivalent 64-bit integer. +/// Note that copying doubles around changes the bits of NaNs on some hosts, +/// notably x86, so this routine cannot be used if these bits are needed. inline uint64_t DoubleToBits(double Double) { uint64_t Bits; static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes"); @@ -601,10 +587,9 @@ inline uint64_t DoubleToBits(double Double) { return Bits; } -/// FloatToBits - This function takes a float and returns the bit -/// equivalent 32-bit integer. Note that copying floats around -/// changes the bits of NaNs on some hosts, notably x86, so this -/// routine cannot be used if these bits are needed. +/// This function takes a float and returns the bit equivalent 32-bit integer. +/// Note that copying floats around changes the bits of NaNs on some hosts, +/// notably x86, so this routine cannot be used if these bits are needed. inline uint32_t FloatToBits(float Float) { uint32_t Bits; static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes"); @@ -612,8 +597,8 @@ inline uint32_t FloatToBits(float Float) { return Bits; } -/// MinAlign - A and B are either alignments or offsets. Return the minimum -/// alignment that may be assumed after adding the two together. +/// A and B are either alignments or offsets. Return the minimum alignment that +/// may be assumed after adding the two together. constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) { // The largest power of 2 that divides both A and B. // @@ -642,8 +627,8 @@ inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) { return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; } -/// NextPowerOf2 - Returns the next power of two (in 64-bits) -/// that is strictly greater than A. Returns zero on overflow. +/// Returns the next power of two (in 64-bits) that is strictly greater than A. +/// Returns zero on overflow. inline uint64_t NextPowerOf2(uint64_t A) { A |= (A >> 1); A |= (A >> 2); diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h index f0e3ffa..9ada946 100644 --- a/include/llvm/Support/ThreadPool.h +++ b/include/llvm/Support/ThreadPool.h @@ -35,17 +35,8 @@ namespace llvm { /// for some work to become available. class ThreadPool { public: -#ifndef _MSC_VER - using VoidTy = void; using TaskTy = std::function; using PackagedTaskTy = std::packaged_task; -#else - // MSVC 2013 has a bug and can't use std::packaged_task; - // We force it to use bool(bool) instead. - using VoidTy = bool; - using TaskTy = std::function; - using PackagedTaskTy = std::packaged_task; -#endif /// Construct a pool with the number of core available on the system (or /// whatever the value returned by std::thread::hardware_concurrency() is). @@ -60,30 +51,17 @@ public: /// Asynchronous submission of a task to the pool. The returned future can be /// used to wait for the task to finish and is *non-blocking* on destruction. template - inline std::shared_future async(Function &&F, Args &&... ArgList) { + inline std::shared_future async(Function &&F, Args &&... ArgList) { auto Task = std::bind(std::forward(F), std::forward(ArgList)...); -#ifndef _MSC_VER return asyncImpl(std::move(Task)); -#else - // This lambda has to be marked mutable because MSVC 2013's std::bind call - // operator isn't const qualified. - return asyncImpl([Task](VoidTy) mutable -> VoidTy { - Task(); - return VoidTy(); - }); -#endif } /// Asynchronous submission of a task to the pool. The returned future can be /// used to wait for the task to finish and is *non-blocking* on destruction. template - inline std::shared_future async(Function &&F) { -#ifndef _MSC_VER + inline std::shared_future async(Function &&F) { return asyncImpl(std::forward(F)); -#else - return asyncImpl([F] (VoidTy) -> VoidTy { F(); return VoidTy(); }); -#endif } /// Blocking wait for all the threads to complete and the queue to be empty. @@ -93,7 +71,7 @@ public: private: /// Asynchronous submission of a task to the pool. The returned future can be /// used to wait for the task to finish and is *non-blocking* on destruction. - std::shared_future asyncImpl(TaskTy F); + std::shared_future asyncImpl(TaskTy F); /// Threads in flight std::vector Threads; diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h index 866b986..ca8c95c 100644 --- a/include/llvm/TableGen/Main.h +++ b/include/llvm/TableGen/Main.h @@ -16,13 +16,15 @@ namespace llvm { -class RecordKeeper; class raw_ostream; +class RecordKeeper; + /// \brief Perform the action using Records, and write output to OS. /// \returns true on error, false otherwise -typedef bool TableGenMainFn(raw_ostream &OS, RecordKeeper &Records); +using TableGenMainFn = bool (raw_ostream &OS, RecordKeeper &Records); int TableGenMain(char *argv0, TableGenMainFn *MainFn); -} -#endif +} // end namespace llvm + +#endif // LLVM_TABLEGEN_MAIN_H diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 5c3bf88..fa9ca28 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -38,11 +38,11 @@ namespace llvm { class ListRecTy; +struct MultiClass; class Record; class RecordKeeper; class RecordVal; class StringInit; -struct MultiClass; //===----------------------------------------------------------------------===// // Type Classes @@ -90,7 +90,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { } /// 'bit' - Represent a single bit -/// class BitRecTy : public RecTy { static BitRecTy Shared; @@ -109,7 +108,6 @@ public: }; /// 'bits' - Represent a fixed number of bits -/// class BitsRecTy : public RecTy { unsigned Size; @@ -130,7 +128,6 @@ public: }; /// 'code' - Represent a code fragment -/// class CodeRecTy : public RecTy { static CodeRecTy Shared; @@ -147,7 +144,6 @@ public: }; /// 'int' - Represent an integer value of no particular size -/// class IntRecTy : public RecTy { static IntRecTy Shared; @@ -166,7 +162,6 @@ public: }; /// 'string' - Represent an string value -/// class StringRecTy : public RecTy { static StringRecTy Shared; @@ -185,14 +180,13 @@ public: /// 'list' - Represent a list of values, all of which must be of /// the specified type. -/// class ListRecTy : public RecTy { + friend ListRecTy *RecTy::getListTy(); + RecTy *Ty; explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {} - friend ListRecTy *RecTy::getListTy(); - public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == ListRecTyKind; @@ -207,7 +201,6 @@ public: }; /// 'dag' - Represent a dag fragment -/// class DagRecTy : public RecTy { static DagRecTy Shared; @@ -225,14 +218,13 @@ public: /// '[classname]' - Represent an instance of a class, such as: /// (R32 X = EAX). -/// class RecordRecTy : public RecTy { + friend class Record; + Record *Rec; explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {} - friend class Record; - public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == RecordRecTyKind; @@ -249,7 +241,6 @@ public: /// Find a common type that T1 and T2 convert to. /// Return 0 if no such type exists. -/// RecTy *resolveTypes(RecTy *T1, RecTy *T2); //===----------------------------------------------------------------------===// @@ -341,7 +332,6 @@ public: /// selection operator. Given an initializer, it selects the specified bits /// out, returning them as a new init of bits type. If it is not legal to use /// the bit subscript operator on this initializer, return null. - /// virtual Init *convertInitializerBitRange(ArrayRef Bits) const { return nullptr; } @@ -350,7 +340,6 @@ public: /// selection operator. Given an initializer, it selects the specified list /// elements, returning them as a new init of list type. If it is not legal /// to take a slice of this, return null. - /// virtual Init *convertInitListSlice(ArrayRef Elements) const { return nullptr; } @@ -358,7 +347,6 @@ public: /// This method is used to implement the FieldInit class. /// Implementors of this method should return the type of the named field if /// they are of record type. - /// virtual RecTy *getFieldType(StringInit *FieldName) const { return nullptr; } @@ -366,7 +354,6 @@ public: /// This method complements getFieldType to return the /// initializer for the specified field. If getFieldType returns non-null /// this method should return non-null, otherwise it returns null. - /// virtual Init *getFieldInit(Record &R, const RecordVal *RV, StringInit *FieldName) const { return nullptr; @@ -376,7 +363,6 @@ public: /// variables which may not be defined at the time the expression is formed. /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. - /// virtual Init *resolveReferences(Record &R, const RecordVal *RV) const { return const_cast(this); } @@ -400,7 +386,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { /// This is the common super-class of types that have a specific, /// explicit, type. -/// class TypedInit : public Init { RecTy *Ty; @@ -409,8 +394,8 @@ protected: : Init(K, Opc), Ty(T) {} public: - TypedInit(const TypedInit &Other) = delete; - TypedInit &operator=(const TypedInit &Other) = delete; + TypedInit(const TypedInit &) = delete; + TypedInit &operator=(const TypedInit &) = delete; static bool classof(const Init *I) { return I->getKind() >= IK_FirstTypedInit && @@ -438,13 +423,12 @@ public: }; /// '?' - Represents an uninitialized value -/// class UnsetInit : public Init { UnsetInit() : Init(IK_UnsetInit) {} public: UnsetInit(const UnsetInit &) = delete; - UnsetInit &operator=(const UnsetInit &Other) = delete; + UnsetInit &operator=(const UnsetInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_UnsetInit; @@ -463,15 +447,14 @@ public: }; /// 'true'/'false' - Represent a concrete initializer for a bit. -/// class BitInit : public Init { bool Value; explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} public: - BitInit(const BitInit &Other) = delete; - BitInit &operator=(BitInit &Other) = delete; + BitInit(const BitInit &) = delete; + BitInit &operator=(BitInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_BitInit; @@ -493,7 +476,6 @@ public: /// '{ a, b, c }' - Represents an initializer for a BitsRecTy value. /// It contains a vector of bits, whose size is determined by the type. -/// class BitsInit final : public TypedInit, public FoldingSetNode, public TrailingObjects { unsigned NumBits; @@ -502,8 +484,8 @@ class BitsInit final : public TypedInit, public FoldingSetNode, : TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {} public: - BitsInit(const BitsInit &Other) = delete; - BitsInit &operator=(const BitsInit &Other) = delete; + BitsInit(const BitsInit &) = delete; + BitsInit &operator=(const BitsInit &) = delete; // Do not use sized deallocation due to trailing objects. void operator delete(void *p) { ::operator delete(p); } @@ -552,7 +534,6 @@ public: }; /// '7' - Represent an initialization by a literal integer value. -/// class IntInit : public TypedInit { int64_t Value; @@ -560,8 +541,8 @@ class IntInit : public TypedInit { : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {} public: - IntInit(const IntInit &Other) = delete; - IntInit &operator=(const IntInit &Other) = delete; + IntInit(const IntInit &) = delete; + IntInit &operator=(const IntInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_IntInit; @@ -590,7 +571,6 @@ public: }; /// "foo" - Represent an initialization by a string value. -/// class StringInit : public TypedInit { StringRef Value; @@ -598,8 +578,8 @@ class StringInit : public TypedInit { : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {} public: - StringInit(const StringInit &Other) = delete; - StringInit &operator=(const StringInit &Other) = delete; + StringInit(const StringInit &) = delete; + StringInit &operator=(const StringInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_StringInit; @@ -636,8 +616,8 @@ class CodeInit : public TypedInit { Value(V) {} public: - CodeInit(const StringInit &Other) = delete; - CodeInit &operator=(const StringInit &Other) = delete; + CodeInit(const StringInit &) = delete; + CodeInit &operator=(const StringInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_CodeInit; @@ -675,15 +655,15 @@ class ListInit final : public TypedInit, public FoldingSetNode, unsigned NumValues; public: - typedef Init *const *const_iterator; + using const_iterator = Init *const *; private: explicit ListInit(unsigned N, RecTy *EltTy) : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {} public: - ListInit(const ListInit &Other) = delete; - ListInit &operator=(const ListInit &Other) = delete; + ListInit(const ListInit &) = delete; + ListInit &operator=(const ListInit &) = delete; // Do not use sized deallocation due to trailing objects. void operator delete(void *p) { ::operator delete(p); } @@ -744,8 +724,8 @@ protected: : TypedInit(K, Type, Opc) {} public: - OpInit(const OpInit &Other) = delete; - OpInit &operator=(OpInit &Other) = delete; + OpInit(const OpInit &) = delete; + OpInit &operator=(OpInit &) = delete; static bool classof(const Init *I) { return I->getKind() >= IK_FirstOpInit && @@ -781,8 +761,8 @@ private: : OpInit(IK_UnOpInit, Type, opc), LHS(lhs) {} public: - UnOpInit(const UnOpInit &Other) = delete; - UnOpInit &operator=(const UnOpInit &Other) = delete; + UnOpInit(const UnOpInit &) = delete; + UnOpInit &operator=(const UnOpInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_UnOpInit; @@ -819,7 +799,6 @@ 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, @@ -832,8 +811,8 @@ private: OpInit(IK_BinOpInit, Type, opc), LHS(lhs), RHS(rhs) {} public: - BinOpInit(const BinOpInit &Other) = delete; - BinOpInit &operator=(const BinOpInit &Other) = delete; + BinOpInit(const BinOpInit &) = delete; + BinOpInit &operator=(const BinOpInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_BinOpInit; @@ -874,7 +853,6 @@ public: }; /// !op (X, Y, Z) - Combine two inits. -/// class TernOpInit : public OpInit, public FoldingSetNode { public: enum TernaryOp : uint8_t { SUBST, FOREACH, IF }; @@ -887,8 +865,8 @@ private: OpInit(IK_TernOpInit, Type, opc), LHS(lhs), MHS(mhs), RHS(rhs) {} public: - TernOpInit(const TernOpInit &Other) = delete; - TernOpInit &operator=(const TernOpInit &Other) = delete; + TernOpInit(const TernOpInit &) = delete; + TernOpInit &operator=(const TernOpInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_TernOpInit; @@ -935,7 +913,6 @@ public: }; /// 'Opcode' - Represent a reference to an entire variable object. -/// class VarInit : public TypedInit { Init *VarName; @@ -943,8 +920,8 @@ class VarInit : public TypedInit { : TypedInit(IK_VarInit, T), VarName(VN) {} public: - VarInit(const VarInit &Other) = delete; - VarInit &operator=(const VarInit &Other) = delete; + VarInit(const VarInit &) = delete; + VarInit &operator=(const VarInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_VarInit; @@ -980,7 +957,6 @@ public: }; /// Opcode{0} - Represent access to one bit of a variable or field. -/// class VarBitInit : public Init { TypedInit *TI; unsigned Bit; @@ -994,8 +970,8 @@ class VarBitInit : public Init { } public: - VarBitInit(const VarBitInit &Other) = delete; - VarBitInit &operator=(const VarBitInit &Other) = delete; + VarBitInit(const VarBitInit &) = delete; + VarBitInit &operator=(const VarBitInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_VarBitInit; @@ -1032,8 +1008,8 @@ class VarListElementInit : public TypedInit { } public: - VarListElementInit(const VarListElementInit &Other) = delete; - void operator=(const VarListElementInit &Other) = delete; + VarListElementInit(const VarListElementInit &) = delete; + VarListElementInit &operator=(const VarListElementInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_VarListElementInit; @@ -1057,17 +1033,16 @@ public: }; /// AL - Represent a reference to a 'def' in the description -/// class DefInit : public TypedInit { + friend class Record; + Record *Def; DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {} - friend class Record; - public: - DefInit(const DefInit &Other) = delete; - DefInit &operator=(const DefInit &Other) = delete; + DefInit(const DefInit &) = delete; + DefInit &operator=(const DefInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_DefInit; @@ -1101,7 +1076,6 @@ public: }; /// X.Y - Represent a reference to a subfield of a variable -/// class FieldInit : public TypedInit { Init *Rec; // Record we are referring to StringInit *FieldName; // Field we are accessing @@ -1112,8 +1086,8 @@ class FieldInit : public TypedInit { } public: - FieldInit(const FieldInit &Other) = delete; - FieldInit &operator=(const FieldInit &Other) = delete; + FieldInit(const FieldInit &) = delete; + FieldInit &operator=(const FieldInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_FieldInit; @@ -1136,9 +1110,10 @@ public: /// (v a, b) - Represent a DAG tree value. DAG inits are required /// to have at least one value then a (possibly empty) list of arguments. Each /// argument can have a name associated with it. -/// class DagInit final : public TypedInit, public FoldingSetNode, public TrailingObjects { + friend TrailingObjects; + Init *Val; StringInit *ValName; unsigned NumArgs; @@ -1148,12 +1123,11 @@ class DagInit final : public TypedInit, public FoldingSetNode, : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN), NumArgs(NumArgs), NumArgNames(NumArgNames) {} - friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { return NumArgs; } public: - DagInit(const DagInit &Other) = delete; - DagInit &operator=(const DagInit &Other) = delete; + DagInit(const DagInit &) = delete; + DagInit &operator=(const DagInit &) = delete; static bool classof(const Init *I) { return I->getKind() == IK_DagInit; @@ -1171,19 +1145,23 @@ public: Init *getOperator() const { return Val; } StringInit *getName() const { return ValName; } + StringRef getNameStr() const { return ValName ? ValName->getValue() : StringRef(); } unsigned getNumArgs() const { return NumArgs; } + Init *getArg(unsigned Num) const { assert(Num < NumArgs && "Arg number out of range!"); return getTrailingObjects()[Num]; } + StringInit *getArgName(unsigned Num) const { assert(Num < NumArgNames && "Arg number out of range!"); return getTrailingObjects()[Num]; } + StringRef getArgNameStr(unsigned Num) const { StringInit *Init = getArgName(Num); return Init ? Init->getValue() : StringRef(); @@ -1192,6 +1170,7 @@ public: ArrayRef getArgs() const { return makeArrayRef(getTrailingObjects(), NumArgs); } + ArrayRef getArgNames() const { return makeArrayRef(getTrailingObjects(), NumArgNames); } @@ -1200,8 +1179,8 @@ public: std::string getAsString() const override; - typedef SmallVectorImpl::const_iterator const_arg_iterator; - typedef SmallVectorImpl::const_iterator const_name_iterator; + using const_arg_iterator = SmallVectorImpl::const_iterator; + using const_name_iterator = SmallVectorImpl::const_iterator; inline const_arg_iterator arg_begin() const { return getArgs().begin(); } inline const_arg_iterator arg_end () const { return getArgs().end(); } @@ -1231,6 +1210,7 @@ public: class RecordVal { friend class Record; + Init *Name; PointerIntPair TyAndPrefix; Init *Value; @@ -1298,7 +1278,7 @@ class Record { // definitions that use them (e.g. Def). However, inside a multiclass they // can't be immediately resolved so we mark them ResolveFirst to fully // resolve them later as soon as the multiclass is instantiated. - bool ResolveFirst; + bool ResolveFirst = false; void init(); void checkName(); @@ -1308,7 +1288,7 @@ public: explicit Record(Init *N, ArrayRef locs, RecordKeeper &records, bool Anonymous = false) : Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records), - ID(LastID++), IsAnonymous(Anonymous), ResolveFirst(false) { + ID(LastID++), IsAnonymous(Anonymous) { init(); } @@ -1330,6 +1310,7 @@ public: unsigned getID() const { return ID; } StringRef getName() const; + Init *getNameInit() const { return Name; } @@ -1435,7 +1416,6 @@ public: /// If there are any field references that refer to fields /// that have been filled in, we can propagate the values now. - /// void resolveReferences() { resolveReferencesTo(nullptr); } /// If anything in this record refers to RV, replace the @@ -1468,7 +1448,6 @@ public: /// Return the initializer for a value with the specified name, /// or throw an exception if the field does not exist. - /// Init *getValueInit(StringRef FieldName) const; /// Return true if the named field is unset. @@ -1479,67 +1458,56 @@ public: /// This method looks up the specified field and returns /// its value as a string, throwing an exception if the field does not exist /// or if the value is not a string. - /// StringRef getValueAsString(StringRef FieldName) const; /// This method looks up the specified field and returns /// its value as a BitsInit, throwing an exception if the field does not exist /// or if the value is not the right type. - /// BitsInit *getValueAsBitsInit(StringRef FieldName) const; /// This method looks up the specified field and returns /// its value as a ListInit, throwing an exception if the field does not exist /// or if the value is not the right type. - /// ListInit *getValueAsListInit(StringRef FieldName) const; /// This method looks up the specified field and /// returns its value as a vector of records, throwing an exception if the /// field does not exist or if the value is not the right type. - /// std::vector getValueAsListOfDefs(StringRef FieldName) const; /// This method looks up the specified field and /// returns its value as a vector of integers, throwing an exception if the /// field does not exist or if the value is not the right type. - /// std::vector getValueAsListOfInts(StringRef FieldName) const; /// This method looks up the specified field and /// returns its value as a vector of strings, throwing an exception if the /// field does not exist or if the value is not the right type. - /// std::vector getValueAsListOfStrings(StringRef FieldName) const; /// This method looks up the specified field and returns its /// value as a Record, throwing an exception if the field does not exist or if /// the value is not the right type. - /// Record *getValueAsDef(StringRef FieldName) const; /// This method looks up the specified field and returns its /// value as a bit, throwing an exception if the field does not exist or if /// the value is not the right type. - /// bool getValueAsBit(StringRef FieldName) const; /// This method looks up the specified field and /// returns its value as a bit. If the field is unset, sets Unset to true and /// returns false. - /// bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const; /// This method looks up the specified field and returns its /// value as an int64_t, throwing an exception if the field does not exist or /// if the value is not the right type. - /// int64_t getValueAsInt(StringRef FieldName) const; /// This method looks up the specified field and returns its /// value as an Dag, throwing an exception if the field does not exist or if /// the value is not the right type. - /// DagInit *getValueAsDag(StringRef FieldName) const; }; @@ -1547,7 +1515,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Record &R); struct MultiClass { Record Rec; // Placeholder for template args and Name. - typedef std::vector> RecordVector; + using RecordVector = std::vector>; RecordVector DefPrototypes; void dump() const; @@ -1557,7 +1525,7 @@ struct MultiClass { }; class RecordKeeper { - typedef std::map> RecordMap; + using RecordMap = std::map>; RecordMap Classes, Defs; public: @@ -1600,7 +1568,6 @@ public: }; /// Sorting predicate to sort record pointers by name. -/// struct LessRecord { bool operator()(const Record *Rec1, const Record *Rec2) const { return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0; @@ -1619,7 +1586,6 @@ struct LessRecordByID { /// Sorting predicate to sort record pointers by their /// name field. -/// struct LessRecordFieldName { bool operator()(const Record *Rec1, const Record *Rec2) const { return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name"); diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h index 818b054..4b32f9e 100644 --- a/include/llvm/TableGen/SetTheory.h +++ b/include/llvm/TableGen/SetTheory.h @@ -64,8 +64,8 @@ class Record; class SetTheory { public: - typedef std::vector RecVec; - typedef SmallSetVector RecSet; + using RecVec = std::vector; + using RecSet = SmallSetVector; /// Operator - A callback representing a DAG operator. class Operator { @@ -95,7 +95,7 @@ public: private: // Map set defs to their fully expanded contents. This serves as a memoization // cache and it makes it possible to return const references on queries. - typedef std::map ExpandMap; + using ExpandMap = std::map; ExpandMap Expansions; // Known DAG operators by name. diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h index 11a8ad8..7c919ff 100644 --- a/include/llvm/TableGen/StringMatcher.h +++ b/include/llvm/TableGen/StringMatcher.h @@ -20,7 +20,8 @@ #include namespace llvm { - class raw_ostream; + +class raw_ostream; /// StringMatcher - Given a list of strings and code to execute when they match, /// output a simple switch tree to classify the input string. @@ -30,7 +31,7 @@ namespace llvm { /// class StringMatcher { public: - typedef std::pair StringPair; + using StringPair = std::pair; private: StringRef StrVariableName; @@ -49,6 +50,6 @@ private: unsigned CharNo, unsigned IndentCount) const; }; -} // end llvm namespace. +} // end namespace llvm -#endif +#endif // LLVM_TABLEGEN_STRINGMATCHER_H diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 0ffd4b7..80d4d8e 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -70,10 +70,9 @@ public: virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, const MCSymbol *Sym) const; - /// Emit the module flags that the platform cares about. - virtual void emitModuleFlags(MCStreamer &Streamer, - ArrayRef Flags, - const TargetMachine &TM) const {} + /// Emit the module-level metadata that the platform cares about. + virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M, + const TargetMachine &TM) const {} /// Given a constant with the SectionKind, return a section that it should be /// placed in. diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 4ce6d2f..86ad8ad 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -497,6 +497,16 @@ public: /// function. Used by MachineRegisterInfo::isConstantPhysReg(). virtual bool isConstantPhysReg(unsigned PhysReg) 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 + /// prior to a call and is guaranteed to be restored (also by the caller) + /// after the call. + virtual bool isCallerPreservedPhysReg(unsigned PhysReg, + const MachineFunction &MF) const { + return false; + } + /// Prior to adding the live-out mask to a stackmap or patchpoint /// instruction, provide the target the opportunity to adjust it (mainly to /// remove pseudo-registers that should be ignored). diff --git a/include/llvm/Testing/Support/Error.h b/include/llvm/Testing/Support/Error.h new file mode 100644 index 0000000..d527529 --- /dev/null +++ b/include/llvm/Testing/Support/Error.h @@ -0,0 +1,69 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TESTING_SUPPORT_ERROR_H +#define LLVM_TESTING_SUPPORT_ERROR_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/Error.h" +#include "llvm/Testing/Support/SupportHelpers.h" + +#include "gmock/gmock.h" +#include + +namespace llvm { +namespace detail { +ErrorHolder TakeError(Error Err); + +template ExpectedHolder TakeExpected(Expected &Exp) { + llvm::detail::ExpectedHolder Result; + auto &EH = static_cast(Result); + EH = TakeError(Exp.takeError()); + if (Result.Success) + Result.Value = &(*Exp); + return Result; +} + +template ExpectedHolder TakeExpected(const Expected &Exp) { + return TakeExpected(const_cast &>(Exp)); +} +} // namespace detail + +#define EXPECT_THAT_ERROR(Err, Matcher) \ + EXPECT_THAT(llvm::detail::TakeError(Err), Matcher) +#define ASSERT_THAT_ERROR(Err, Matcher) \ + ASSERT_THAT(llvm::detail::TakeError(Err), Matcher) + +#define EXPECT_THAT_EXPECTED(Err, Matcher) \ + EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher) +#define ASSERT_THAT_EXPECTED(Err, Matcher) \ + ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher) + +MATCHER(Succeeded, "") { return arg.Success; } +MATCHER(Failed, "") { return !arg.Success; } + +MATCHER_P(HasValue, value, + "succeeded with value " + testing::PrintToString(value)) { + if (!arg.Success) { + *result_listener << "operation failed"; + return false; + } + + assert(arg.Value.hasValue()); + if (**arg.Value != value) { + *result_listener << "but \"" + testing::PrintToString(**arg.Value) + + "\" != " + testing::PrintToString(value); + return false; + } + + return true; +} +} // namespace llvm + +#endif diff --git a/include/llvm/Testing/Support/SupportHelpers.h b/include/llvm/Testing/Support/SupportHelpers.h new file mode 100644 index 0000000..c4dd414 --- /dev/null +++ b/include/llvm/Testing/Support/SupportHelpers.h @@ -0,0 +1,47 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H +#define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "gtest/gtest-printers.h" + +namespace llvm { +namespace detail { +struct ErrorHolder { + bool Success; + std::string Message; +}; + +template struct ExpectedHolder : public ErrorHolder { + Optional Value; +}; + +inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) { + *Out << (Err.Success ? "succeeded" : "failed"); + if (!Err.Success) { + *Out << " (" << StringRef(Err.Message).trim().str() << ")"; + } +} + +template +void PrintTo(const ExpectedHolder &Item, std::ostream *Out) { + if (Item.Success) { + *Out << "succeeded with value \"" << ::testing::PrintToString(**Item.Value) + << "\""; + } else { + PrintTo(static_cast(Item), Out); + } +} +} // namespace detail +} // namespace llvm + +#endif diff --git a/include/llvm/Transforms/Scalar/GVNExpression.h b/include/llvm/Transforms/Scalar/GVNExpression.h index 0083413..f603ebc 100644 --- a/include/llvm/Transforms/Scalar/GVNExpression.h +++ b/include/llvm/Transforms/Scalar/GVNExpression.h @@ -121,10 +121,7 @@ public: OS << "}"; } - LLVM_DUMP_METHOD void dump() const { - print(dbgs()); - dbgs() << "\n"; - } + LLVM_DUMP_METHOD void dump() const; }; inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) { diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index 7e23544..682b353 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -106,15 +106,32 @@ template class ArrayRef; /// significant impact on the cost however. void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs, const ValueSet &Allocas) const; + + /// Check if life time marker nodes can be hoisted/sunk into the outline + /// region. + /// + /// Returns true if it is safe to do the code motion. + bool isLegalToShrinkwrapLifetimeMarkers(Instruction *AllocaAddr) const; /// Find the set of allocas whose life ranges are contained within the /// outlined region. /// /// Allocas which have life_time markers contained in the outlined region /// should be pushed to the outlined function. The address bitcasts that /// are used by the lifetime markers are also candidates for shrink- - /// wrapping. The instructions that need to be sinked are collected in + /// wrapping. The instructions that need to be sunk are collected in /// 'Allocas'. - void findAllocas(ValueSet &Allocas) const; + void findAllocas(ValueSet &SinkCands, ValueSet &HoistCands, + BasicBlock *&ExitBlock) const; + + /// Find or create a block within the outline region for placing hoisted + /// code. + /// + /// CommonExitBlock is block outside the outline region. It is the common + /// successor of blocks inside the region. If there exists a single block + /// inside the region that is the predecessor of CommonExitBlock, that block + /// will be returned. Otherwise CommonExitBlock will be split and the + /// original block will be added to the outline region. + BasicBlock *findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock); private: void severSplitPHINodes(BasicBlock *&Header); diff --git a/include/llvm/Transforms/Utils/Mem2Reg.h b/include/llvm/Transforms/Utils/Mem2Reg.h index 456876b..1fe186d 100644 --- a/include/llvm/Transforms/Utils/Mem2Reg.h +++ b/include/llvm/Transforms/Utils/Mem2Reg.h @@ -25,4 +25,4 @@ public: }; } -#endif // LLVM_TRANSFORMS_UTILS_MEM2REG_H \ No newline at end of file +#endif // LLVM_TRANSFORMS_UTILS_MEM2REG_H diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index f743cb2..dbb1b01 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -1011,10 +1011,24 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1, // equal each other so we can exit early. if (C1 && C2) return NoAlias; - if (isKnownNonEqual(GEP1->getOperand(GEP1->getNumOperands() - 1), - GEP2->getOperand(GEP2->getNumOperands() - 1), - DL)) - return NoAlias; + { + Value *GEP1LastIdx = GEP1->getOperand(GEP1->getNumOperands() - 1); + Value *GEP2LastIdx = GEP2->getOperand(GEP2->getNumOperands() - 1); + if (isa(GEP1LastIdx) || isa(GEP2LastIdx)) { + // If one of the indices is a PHI node, be safe and only use + // computeKnownBits so we don't make any assumptions about the + // relationships between the two indices. This is important if we're + // asking about values from different loop iterations. See PR32314. + // TODO: We may be able to change the check so we only do this when + // we definitely looked through a PHINode. + KnownBits Known1 = computeKnownBits(GEP1LastIdx, DL); + KnownBits Known2 = computeKnownBits(GEP2LastIdx, DL); + if (Known1.Zero.intersects(Known2.One) || + Known1.One.intersects(Known2.Zero)) + return NoAlias; + } else if (isKnownNonEqual(GEP1LastIdx, GEP2LastIdx, DL)) + return NoAlias; + } return MayAlias; } else if (!LastIndexedStruct || !C1 || !C2) { return MayAlias; diff --git a/lib/Analysis/CallGraphSCCPass.cpp b/lib/Analysis/CallGraphSCCPass.cpp index 5896e6e..facda24 100644 --- a/lib/Analysis/CallGraphSCCPass.cpp +++ b/lib/Analysis/CallGraphSCCPass.cpp @@ -608,18 +608,18 @@ namespace { } bool runOnSCC(CallGraphSCC &SCC) override { + bool BannerPrinted = false; auto PrintBannerOnce = [&] () { - static bool BannerPrinted = false; if (BannerPrinted) return; Out << Banner; BannerPrinted = true; }; for (CallGraphNode *CGN : SCC) { - if (CGN->getFunction()) { - if (isFunctionInPrintList(CGN->getFunction()->getName())) { + if (Function *F = CGN->getFunction()) { + if (!F->isDeclaration() && isFunctionInPrintList(F->getName())) { PrintBannerOnce(); - CGN->getFunction()->print(Out); + F->print(Out); } } else if (llvm::isFunctionInPrintList("*")) { PrintBannerOnce(); diff --git a/lib/Analysis/DivergenceAnalysis.cpp b/lib/Analysis/DivergenceAnalysis.cpp index 1b36569..2d39a0b 100644 --- a/lib/Analysis/DivergenceAnalysis.cpp +++ b/lib/Analysis/DivergenceAnalysis.cpp @@ -241,7 +241,7 @@ void DivergencePropagator::exploreDataDependency(Value *V) { // Follow def-use chains of V. for (User *U : V->users()) { Instruction *UserInst = cast(U); - if (DV.insert(UserInst).second) + if (!TTI.isAlwaysUniform(U) && DV.insert(UserInst).second) Worklist.push_back(UserInst); } } diff --git a/lib/Analysis/MemorySSA.cpp b/lib/Analysis/MemorySSA.cpp index e0e04a9..86d0d92 100644 --- a/lib/Analysis/MemorySSA.cpp +++ b/lib/Analysis/MemorySSA.cpp @@ -1872,7 +1872,6 @@ MemorySSAPrinterLegacyPass::MemorySSAPrinterLegacyPass() : FunctionPass(ID) { void MemorySSAPrinterLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); - AU.addPreserved(); } bool MemorySSAPrinterLegacyPass::runOnFunction(Function &F) { @@ -1957,6 +1956,7 @@ MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess( #ifdef EXPENSIVE_CHECKS MemoryAccess *NewNoCache = Walker.findClobber(StartingAccess, Q); assert(NewNoCache == New && "Cache made us hand back a different result?"); + (void)NewNoCache; #endif if (AutoResetWalker) resetClobberWalker(); diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index b9c4716..aebc80a 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -149,9 +149,9 @@ static cl::opt MaxValueCompareDepth( cl::init(2)); static cl::opt - MaxAddExprDepth("scalar-evolution-max-addexpr-depth", cl::Hidden, - cl::desc("Maximum depth of recursive AddExpr"), - cl::init(32)); + MaxArithDepth("scalar-evolution-max-arith-depth", cl::Hidden, + cl::desc("Maximum depth of recursive arithmetics"), + cl::init(32)); static cl::opt MaxConstantEvolvingDepth( "scalar-evolution-max-constant-evolving-depth", cl::Hidden, @@ -2276,8 +2276,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, if (Ops.size() == 1) return Ops[0]; } - // Limit recursion calls depth - if (Depth > MaxAddExprDepth) + // Limit recursion calls depth. + if (Depth > MaxArithDepth) return getOrCreateAddExpr(Ops, Flags); // Okay, check to see if the same value occurs in the operand list more than @@ -2293,7 +2293,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, ++Count; // Merge the values into a multiply. const SCEV *Scale = getConstant(Ty, Count); - const SCEV *Mul = getMulExpr(Scale, Ops[i]); + const SCEV *Mul = getMulExpr(Scale, Ops[i], SCEV::FlagAnyWrap, Depth + 1); if (Ops.size() == Count) return Mul; Ops[i] = Mul; @@ -2343,7 +2343,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, } } if (Ok) - LargeOps.push_back(getMulExpr(LargeMulOps)); + LargeOps.push_back(getMulExpr(LargeMulOps, SCEV::FlagAnyWrap, Depth + 1)); } else { Ok = false; break; @@ -2417,7 +2417,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, if (MulOp.first != 0) Ops.push_back(getMulExpr( getConstant(MulOp.first), - getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1))); + getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1), + SCEV::FlagAnyWrap, Depth + 1)); if (Ops.empty()) return getZero(Ty); if (Ops.size() == 1) @@ -2445,11 +2446,12 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, SmallVector MulOps(Mul->op_begin(), Mul->op_begin()+MulOp); MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end()); - InnerMul = getMulExpr(MulOps); + InnerMul = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1); } SmallVector TwoOps = {getOne(Ty), InnerMul}; const SCEV *AddOne = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1); - const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV); + const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV, + SCEV::FlagAnyWrap, Depth + 1); if (Ops.size() == 2) return OuterMul; if (AddOp < Idx) { Ops.erase(Ops.begin()+AddOp); @@ -2478,19 +2480,20 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, SmallVector MulOps(Mul->op_begin(), Mul->op_begin()+MulOp); MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end()); - InnerMul1 = getMulExpr(MulOps); + InnerMul1 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1); } const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0); if (OtherMul->getNumOperands() != 2) { SmallVector MulOps(OtherMul->op_begin(), OtherMul->op_begin()+OMulOp); MulOps.append(OtherMul->op_begin()+OMulOp+1, OtherMul->op_end()); - InnerMul2 = getMulExpr(MulOps); + InnerMul2 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1); } SmallVector TwoOps = {InnerMul1, InnerMul2}; const SCEV *InnerMulSum = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1); - const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum); + const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum, + SCEV::FlagAnyWrap, Depth + 1); if (Ops.size() == 2) return OuterMul; Ops.erase(Ops.begin()+Idx); Ops.erase(Ops.begin()+OtherMulIdx-1); @@ -2621,6 +2624,27 @@ ScalarEvolution::getOrCreateAddExpr(SmallVectorImpl &Ops, return S; } +const SCEV * +ScalarEvolution::getOrCreateMulExpr(SmallVectorImpl &Ops, + SCEV::NoWrapFlags Flags) { + FoldingSetNodeID ID; + ID.AddInteger(scMulExpr); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = nullptr; + SCEVMulExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); + S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator), + O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + } + S->setNoWrapFlags(Flags); + return S; +} + static uint64_t umul_ov(uint64_t i, uint64_t j, bool &Overflow) { uint64_t k = i*j; if (j > 1 && k / j != i) Overflow = true; @@ -2673,7 +2697,8 @@ static bool containsConstantSomewhere(const SCEV *StartExpr) { /// Get a canonical multiply expression, or something simpler if possible. const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, - SCEV::NoWrapFlags Flags) { + SCEV::NoWrapFlags Flags, + unsigned Depth) { assert(Flags == maskFlags(Flags, SCEV::FlagNUW | SCEV::FlagNSW) && "only nuw or nsw allowed"); assert(!Ops.empty() && "Cannot get empty mul!"); @@ -2690,6 +2715,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, Flags = StrengthenNoWrapFlags(this, scMulExpr, Ops, Flags); + // Limit recursion calls depth. + if (Depth > MaxArithDepth) + return getOrCreateMulExpr(Ops, Flags); + // If there are any constants, fold them together. unsigned Idx = 0; if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { @@ -2701,8 +2730,11 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // apply this transformation as well. if (Add->getNumOperands() == 2) if (containsConstantSomewhere(Add)) - return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), - getMulExpr(LHSC, Add->getOperand(1))); + return getAddExpr(getMulExpr(LHSC, Add->getOperand(0), + SCEV::FlagAnyWrap, Depth + 1), + getMulExpr(LHSC, Add->getOperand(1), + SCEV::FlagAnyWrap, Depth + 1), + SCEV::FlagAnyWrap, Depth + 1); ++Idx; while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { @@ -2730,17 +2762,19 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, SmallVector NewOps; bool AnyFolded = false; for (const SCEV *AddOp : Add->operands()) { - const SCEV *Mul = getMulExpr(Ops[0], AddOp); + const SCEV *Mul = getMulExpr(Ops[0], AddOp, SCEV::FlagAnyWrap, + Depth + 1); if (!isa(Mul)) AnyFolded = true; NewOps.push_back(Mul); } if (AnyFolded) - return getAddExpr(NewOps); + return getAddExpr(NewOps, SCEV::FlagAnyWrap, Depth + 1); } else if (const auto *AddRec = dyn_cast(Ops[1])) { // Negation preserves a recurrence's no self-wrap property. SmallVector Operands; for (const SCEV *AddRecOp : AddRec->operands()) - Operands.push_back(getMulExpr(Ops[0], AddRecOp)); + Operands.push_back(getMulExpr(Ops[0], AddRecOp, SCEV::FlagAnyWrap, + Depth + 1)); return getAddRecExpr(Operands, AddRec->getLoop(), AddRec->getNoWrapFlags(SCEV::FlagNW)); @@ -2762,18 +2796,18 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, while (const SCEVMulExpr *Mul = dyn_cast(Ops[Idx])) { if (Ops.size() > MulOpsInlineThreshold) break; - // If we have an mul, expand the mul operands onto the end of the operands - // list. + // If we have an mul, expand the mul operands onto the end of the + // operands list. Ops.erase(Ops.begin()+Idx); Ops.append(Mul->op_begin(), Mul->op_end()); DeletedMul = true; } - // If we deleted at least one mul, we added operands to the end of the list, - // and they are not necessarily sorted. Recurse to resort and resimplify - // any operands we just acquired. + // If we deleted at least one mul, we added operands to the end of the + // list, and they are not necessarily sorted. Recurse to resort and + // resimplify any operands we just acquired. if (DeletedMul) - return getMulExpr(Ops); + return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1); } // If there are any add recurrences in the operands list, see if any other @@ -2784,8 +2818,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // Scan over all recurrences, trying to fold loop invariants into them. for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { - // Scan all of the other operands to this mul and add them to the vector if - // they are loop invariant w.r.t. the recurrence. + // Scan all of the other operands to this mul and add them to the vector + // if they are loop invariant w.r.t. the recurrence. SmallVector LIOps; const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); const Loop *AddRecLoop = AddRec->getLoop(); @@ -2801,9 +2835,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // NLI * LI * {Start,+,Step} --> NLI * {LI*Start,+,LI*Step} SmallVector NewOps; NewOps.reserve(AddRec->getNumOperands()); - const SCEV *Scale = getMulExpr(LIOps); + const SCEV *Scale = getMulExpr(LIOps, SCEV::FlagAnyWrap, Depth + 1); for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) - NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i))); + NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i), + SCEV::FlagAnyWrap, Depth + 1)); // Build the new addrec. Propagate the NUW and NSW flags if both the // outer mul and the inner addrec are guaranteed to have no overflow. @@ -2822,12 +2857,12 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, Ops[i] = NewRec; break; } - return getMulExpr(Ops); + return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1); } - // Okay, if there weren't any loop invariants to be folded, check to see if - // there are multiple AddRec's with the same loop induction variable being - // multiplied together. If so, we can fold them. + // Okay, if there weren't any loop invariants to be folded, check to see + // if there are multiple AddRec's with the same loop induction variable + // being multiplied together. If so, we can fold them. // {A1,+,A2,+,...,+,An} * {B1,+,B2,+,...,+,Bn} // = {x=1 in [ sum y=x..2x [ sum z=max(y-x, y-n)..min(x,n) [ @@ -2869,7 +2904,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, const SCEV *CoeffTerm = getConstant(Ty, Coeff); const SCEV *Term1 = AddRec->getOperand(y-z); const SCEV *Term2 = OtherAddRec->getOperand(z); - Term = getAddExpr(Term, getMulExpr(CoeffTerm, Term1,Term2)); + Term = getAddExpr(Term, getMulExpr(CoeffTerm, Term1, Term2, + SCEV::FlagAnyWrap, Depth + 1), + SCEV::FlagAnyWrap, Depth + 1); } } AddRecOps.push_back(Term); @@ -2887,7 +2924,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, } } if (OpsModified) - return getMulExpr(Ops); + return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1); // Otherwise couldn't fold anything into this recurrence. Move onto the // next one. @@ -2895,22 +2932,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // Okay, it looks like we really DO need an mul expr. Check to see if we // already have one, otherwise create a new one. - FoldingSetNodeID ID; - ID.AddInteger(scMulExpr); - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - ID.AddPointer(Ops[i]); - void *IP = nullptr; - SCEVMulExpr *S = - static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); - if (!S) { - const SCEV **O = SCEVAllocator.Allocate(Ops.size()); - std::uninitialized_copy(Ops.begin(), Ops.end(), O); - S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator), - O, Ops.size()); - UniqueSCEVs.InsertNode(S, IP); - } - S->setNoWrapFlags(Flags); - return S; + return getOrCreateMulExpr(Ops, Flags); } /// Get a canonical unsigned division expression, or something simpler if @@ -3713,7 +3735,8 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { } const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, - SCEV::NoWrapFlags Flags) { + SCEV::NoWrapFlags Flags, + unsigned Depth) { // Fast path: X - X --> 0. if (LHS == RHS) return getZero(LHS->getType()); @@ -3747,7 +3770,7 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, // larger scope than intended. auto NegFlags = RHSIsNotMinSigned ? SCEV::FlagNSW : SCEV::FlagAnyWrap; - return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags); + return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth); } const SCEV * diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp index 488cb33..92328f6 100644 --- a/lib/Analysis/TargetTransformInfo.cpp +++ b/lib/Analysis/TargetTransformInfo.cpp @@ -103,6 +103,10 @@ bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const { return TTIImpl->isSourceOfDivergence(V); } +bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const { + return TTIImpl->isAlwaysUniform(V); +} + unsigned TargetTransformInfo::getFlatAddressSpace() const { return TTIImpl->getFlatAddressSpace(); } diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index c018166..b065f42 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -852,7 +852,8 @@ static void computeKnownBitsFromShiftOperator( Optional ShifterOperandIsNonZero; // Early exit if we can't constrain any well-defined shift amount. - if (!(ShiftAmtKZ & (BitWidth - 1)) && !(ShiftAmtKO & (BitWidth - 1))) { + if (!(ShiftAmtKZ & (PowerOf2Ceil(BitWidth) - 1)) && + !(ShiftAmtKO & (PowerOf2Ceil(BitWidth) - 1))) { ShifterOperandIsNonZero = isKnownNonZero(I->getOperand(1), Depth + 1, Q); if (!*ShifterOperandIsNonZero) @@ -3026,7 +3027,7 @@ bool llvm::getConstantDataArrayInfo(const Value *V, if (GV->getInitializer()->isNullValue()) { Type *GVTy = GV->getValueType(); if ( (ArrayTy = dyn_cast(GVTy)) ) { - // A zeroinitializer for the array; There is no ConstantDataArray. + // A zeroinitializer for the array; there is no ConstantDataArray. Array = nullptr; } else { const DataLayout &DL = GV->getParent()->getDataLayout(); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 95987fa..0629c2d 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -733,13 +733,13 @@ private: std::vector makeCallList(ArrayRef Record, bool IsOldProfileFormat, bool HasProfile); - Error parseEntireSummary(); + Error parseEntireSummary(unsigned ID); Error parseModuleStringTable(); std::pair getValueInfoFromValueId(unsigned ValueId); - ModulePathStringTableTy::iterator addThisModulePath(); + ModuleSummaryIndex::ModuleInfo *addThisModule(); }; } // end anonymous namespace @@ -2608,6 +2608,16 @@ Error BitcodeReader::materializeMetadata() { if (Error Err = MDLoader->parseModuleMetadata()) return Err; } + + // Upgrade "Linker Options" module flag to "llvm.linker.options" module-level + // metadata. + if (Metadata *Val = TheModule->getModuleFlag("Linker Options")) { + NamedMDNode *LinkerOpts = + TheModule->getOrInsertNamedMetadata("llvm.linker.options"); + for (const MDOperand &MDOptions : cast(Val)->operands()) + LinkerOpts->addOperand(cast(MDOptions)); + } + DeferredMetadataInfo.clear(); return Error::success(); } @@ -4691,9 +4701,9 @@ ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader( : BitcodeReaderBase(std::move(Cursor), Strtab), TheIndex(TheIndex), ModulePath(ModulePath), ModuleId(ModuleId) {} -ModulePathStringTableTy::iterator -ModuleSummaryIndexBitcodeReader::addThisModulePath() { - return TheIndex.addModulePath(ModulePath, ModuleId); +ModuleSummaryIndex::ModuleInfo * +ModuleSummaryIndexBitcodeReader::addThisModule() { + return TheIndex.addModule(ModulePath, ModuleId); } std::pair @@ -4844,6 +4854,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() { return error("Invalid record"); break; case bitc::GLOBALVAL_SUMMARY_BLOCK_ID: + case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID: assert(!SeenValueSymbolTable && "Already read VST when parsing summary block?"); // We might not have a VST if there were no values in the @@ -4856,7 +4867,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() { SeenValueSymbolTable = true; } SeenGlobalValSummary = true; - if (Error Err = parseEntireSummary()) + if (Error Err = parseEntireSummary(Entry.ID)) return Err; break; case bitc::MODULE_STRTAB_BLOCK_ID: @@ -4889,7 +4900,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() { case bitc::MODULE_CODE_HASH: { if (Record.size() != 5) return error("Invalid hash length " + Twine(Record.size()).str()); - auto &Hash = addThisModulePath()->second.second; + auto &Hash = addThisModule()->second.second; int Pos = 0; for (auto &Val : Record) { assert(!(Val >> 32) && "Unexpected high bits set"); @@ -4964,8 +4975,8 @@ std::vector ModuleSummaryIndexBitcodeReader::makeCallLi // Eagerly parse the entire summary block. This populates the GlobalValueSummary // objects in the index. -Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() { - if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID)) +Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) { + if (Stream.EnterSubBlock(ID)) return error("Invalid record"); SmallVector Record; @@ -5070,7 +5081,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() { PendingTypeTestAssumeConstVCalls.clear(); PendingTypeCheckedLoadConstVCalls.clear(); auto VIAndOriginalGUID = getValueInfoFromValueId(ValueID); - FS->setModulePath(addThisModulePath()->first()); + FS->setModulePath(addThisModule()->first()); FS->setOriginalName(VIAndOriginalGUID.second); TheIndex.addGlobalValueSummary(VIAndOriginalGUID.first, std::move(FS)); break; @@ -5090,7 +5101,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() { // string table section in the per-module index, we create a single // module path string table entry with an empty (0) ID to take // ownership. - AS->setModulePath(addThisModulePath()->first()); + AS->setModulePath(addThisModule()->first()); GlobalValue::GUID AliaseeGUID = getValueInfoFromValueId(AliaseeID).first.getGUID(); @@ -5113,7 +5124,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() { std::vector Refs = makeRefList(ArrayRef(Record).slice(2)); auto FS = llvm::make_unique(Flags, std::move(Refs)); - FS->setModulePath(addThisModulePath()->first()); + FS->setModulePath(addThisModule()->first()); auto GUID = getValueInfoFromValueId(ValueID); FS->setOriginalName(GUID.second); TheIndex.addGlobalValueSummary(GUID.first, std::move(FS)); @@ -5241,6 +5252,20 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() { {{Record[0], Record[1]}, {Record.begin() + 2, Record.end()}}); break; } + case bitc::FS_CFI_FUNCTION_DEFS: { + std::set &CfiFunctionDefs = TheIndex.cfiFunctionDefs(); + for (unsigned I = 0; I != Record.size(); I += 2) + CfiFunctionDefs.insert( + {Strtab.data() + Record[I], static_cast(Record[I + 1])}); + break; + } + case bitc::FS_CFI_FUNCTION_DECLS: { + std::set &CfiFunctionDecls = TheIndex.cfiFunctionDecls(); + for (unsigned I = 0; I != Record.size(); I += 2) + CfiFunctionDecls.insert( + {Strtab.data() + Record[I], static_cast(Record[I + 1])}); + break; + } } } llvm_unreachable("Exit infinite loop"); @@ -5255,7 +5280,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() { SmallVector Record; SmallString<128> ModulePath; - ModulePathStringTableTy::iterator LastSeenModulePath; + ModuleSummaryIndex::ModuleInfo *LastSeenModule = nullptr; while (true) { BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); @@ -5282,8 +5307,8 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() { if (convertToString(Record, 1, ModulePath)) return error("Invalid record"); - LastSeenModulePath = TheIndex.addModulePath(ModulePath, ModuleId); - ModuleIdMap[ModuleId] = LastSeenModulePath->first(); + LastSeenModule = TheIndex.addModule(ModulePath, ModuleId); + ModuleIdMap[ModuleId] = LastSeenModule->first(); ModulePath.clear(); break; @@ -5292,15 +5317,15 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() { case bitc::MST_CODE_HASH: { if (Record.size() != 5) return error("Invalid hash length " + Twine(Record.size()).str()); - if (LastSeenModulePath == TheIndex.modulePaths().end()) + if (!LastSeenModule) return error("Invalid hash that does not follow a module path"); int Pos = 0; for (auto &Val : Record) { assert(!(Val >> 32) && "Unexpected high bits set"); - LastSeenModulePath->second.second[Pos++] = Val; + LastSeenModule->second.second[Pos++] = Val; } - // Reset LastSeenModulePath to avoid overriding the hash unexpectedly. - LastSeenModulePath = TheIndex.modulePaths().end(); + // Reset LastSeenModule to avoid overriding the hash unexpectedly. + LastSeenModule = nullptr; break; } } @@ -5507,13 +5532,16 @@ BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata, } // Parse the specified bitcode buffer and merge the index into CombinedIndex. +// We don't use ModuleIdentifier here because the client may need to control the +// module path used in the combined summary (e.g. when reading summaries for +// regular LTO modules). Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex, - unsigned ModuleId) { + StringRef ModulePath, uint64_t ModuleId) { BitstreamCursor Stream(Buffer); Stream.JumpToBit(ModuleBit); ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex, - ModuleIdentifier, ModuleId); + ModulePath, ModuleId); return R.parseModule(); } @@ -5533,7 +5561,7 @@ Expected> BitcodeModule::getSummary() { } // Check if the given bitcode buffer contains a global value summary block. -Expected BitcodeModule::hasSummary() { +Expected BitcodeModule::getLTOInfo() { BitstreamCursor Stream(Buffer); Stream.JumpToBit(ModuleBit); @@ -5547,11 +5575,14 @@ Expected BitcodeModule::hasSummary() { case BitstreamEntry::Error: return error("Malformed block"); case BitstreamEntry::EndBlock: - return false; + return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false}; case BitstreamEntry::SubBlock: if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID) - return true; + return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true}; + + if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID) + return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true}; // Ignore other sub-blocks. if (Stream.SkipBlock()) @@ -5638,12 +5669,12 @@ Expected llvm::getBitcodeProducerString(MemoryBufferRef Buffer) { Error llvm::readModuleSummaryIndex(MemoryBufferRef Buffer, ModuleSummaryIndex &CombinedIndex, - unsigned ModuleId) { + uint64_t ModuleId) { Expected BM = getSingleModule(Buffer); if (!BM) return BM.takeError(); - return BM->readSummary(CombinedIndex, ModuleId); + return BM->readSummary(CombinedIndex, BM->getModuleIdentifier(), ModuleId); } Expected> @@ -5655,12 +5686,12 @@ llvm::getModuleSummaryIndex(MemoryBufferRef Buffer) { return BM->getSummary(); } -Expected llvm::hasGlobalValueSummary(MemoryBufferRef Buffer) { +Expected llvm::getBitcodeLTOInfo(MemoryBufferRef Buffer) { Expected BM = getSingleModule(Buffer); if (!BM) return BM.takeError(); - return BM->hasSummary(); + return BM->getLTOInfo(); } Expected> diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp index ee2fe2a..b1504a8 100644 --- a/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/lib/Bitcode/Reader/MetadataLoader.cpp @@ -407,6 +407,11 @@ void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) { } // anonynous namespace +static Error error(const Twine &Message) { + return make_error( + Message, make_error_code(BitcodeError::CorruptedBitcode)); +} + class MetadataLoader::MetadataLoaderImpl { BitcodeReaderMetadataList MetadataList; BitcodeReaderValueList &ValueList; @@ -533,6 +538,88 @@ class MetadataLoader::MetadataLoaderImpl { } } + /// Upgrade the expression from previous versions. + Error upgradeDIExpression(uint64_t FromVersion, + MutableArrayRef &Expr, + SmallVectorImpl &Buffer) { + auto N = Expr.size(); + switch (FromVersion) { + default: + return error("Invalid record"); + case 0: + if (N >= 3 && Expr[N - 3] == dwarf::DW_OP_bit_piece) + Expr[N - 3] = dwarf::DW_OP_LLVM_fragment; + LLVM_FALLTHROUGH; + case 1: + // Move DW_OP_deref to the end. + if (N && Expr[0] == dwarf::DW_OP_deref) { + auto End = Expr.end(); + if (Expr.size() >= 3 && + *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment) + End = std::prev(End, 3); + std::move(std::next(Expr.begin()), End, Expr.begin()); + *std::prev(End) = dwarf::DW_OP_deref; + } + NeedDeclareExpressionUpgrade = true; + LLVM_FALLTHROUGH; + case 2: { + // Change DW_OP_plus to DW_OP_plus_uconst. + // Change DW_OP_minus to DW_OP_uconst, DW_OP_minus + auto SubExpr = ArrayRef(Expr); + while (!SubExpr.empty()) { + // Skip past other operators with their operands + // for this version of the IR, obtained from + // from historic DIExpression::ExprOperand::getSize(). + size_t HistoricSize; + switch (SubExpr.front()) { + default: + HistoricSize = 1; + break; + case dwarf::DW_OP_constu: + case dwarf::DW_OP_minus: + case dwarf::DW_OP_plus: + HistoricSize = 2; + break; + case dwarf::DW_OP_LLVM_fragment: + HistoricSize = 3; + break; + } + + // If the expression is malformed, make sure we don't + // copy more elements than we should. + HistoricSize = std::min(SubExpr.size(), HistoricSize); + ArrayRef Args = SubExpr.slice(1, HistoricSize-1); + + switch (SubExpr.front()) { + case dwarf::DW_OP_plus: + Buffer.push_back(dwarf::DW_OP_plus_uconst); + Buffer.append(Args.begin(), Args.end()); + break; + case dwarf::DW_OP_minus: + Buffer.push_back(dwarf::DW_OP_constu); + Buffer.append(Args.begin(), Args.end()); + Buffer.push_back(dwarf::DW_OP_minus); + break; + default: + Buffer.push_back(*SubExpr.begin()); + Buffer.append(Args.begin(), Args.end()); + break; + } + + // Continue with remaining elements. + SubExpr = SubExpr.slice(HistoricSize); + } + Expr = MutableArrayRef(Buffer); + LLVM_FALLTHROUGH; + } + case 3: + // Up-to-date! + break; + } + + return Error::success(); + } + void upgradeDebugInfo() { upgradeCUSubprograms(); upgradeCUVariables(); @@ -590,11 +677,6 @@ public: void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); } }; -static Error error(const Twine &Message) { - return make_error( - Message, make_error_code(BitcodeError::CorruptedBitcode)); -} - Expected MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() { IndexCursor = Stream; @@ -1551,34 +1633,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( IsDistinct = Record[0] & 1; uint64_t Version = Record[0] >> 1; auto Elts = MutableArrayRef(Record).slice(1); - unsigned N = Elts.size(); - // Perform various upgrades. - switch (Version) { - case 0: - if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece) - Elts[N - 3] = dwarf::DW_OP_LLVM_fragment; - LLVM_FALLTHROUGH; - case 1: - // Move DW_OP_deref to the end. - if (N && Elts[0] == dwarf::DW_OP_deref) { - auto End = Elts.end(); - if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment) - End = std::prev(End, 3); - std::move(std::next(Elts.begin()), End, Elts.begin()); - *std::prev(End) = dwarf::DW_OP_deref; - } - NeedDeclareExpressionUpgrade = true; - LLVM_FALLTHROUGH; - case 2: - // Up-to-date! - break; - default: - return error("Invalid record"); - } + + SmallVector Buffer; + if (Error Err = upgradeDIExpression(Version, Elts, Buffer)) + return Err; MetadataList.assignValue( - GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))), - NextMetadataNo); + GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo); NextMetadataNo++; break; } diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index d5879fe..feeba31 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -77,10 +77,13 @@ protected: /// The stream created and owned by the client. BitstreamWriter &Stream; + StringTableBuilder &StrtabBuilder; + public: /// Constructs a BitcodeWriterBase object that writes to the provided /// \p Stream. - BitcodeWriterBase(BitstreamWriter &Stream) : Stream(Stream) {} + BitcodeWriterBase(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder) + : Stream(Stream), StrtabBuilder(StrtabBuilder) {} protected: void writeBitcodeHeader(); @@ -97,8 +100,6 @@ class ModuleBitcodeWriter : public BitcodeWriterBase { /// Pointer to the buffer allocated by caller for bitcode writing. const SmallVectorImpl &Buffer; - StringTableBuilder &StrtabBuilder; - /// The Module to write to bitcode. const Module &M; @@ -142,8 +143,8 @@ public: BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, bool GenerateHash, ModuleHash *ModHash = nullptr) - : BitcodeWriterBase(Stream), Buffer(Buffer), StrtabBuilder(StrtabBuilder), - M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index), + : BitcodeWriterBase(Stream, StrtabBuilder), Buffer(Buffer), M(*M), + VE(*M, ShouldPreserveUseListOrder), Index(Index), GenerateHash(GenerateHash), ModHash(ModHash), BitcodeStartBit(Stream.GetCurrentBitNo()) { // Assign ValueIds to any callee values in the index that came from @@ -331,10 +332,11 @@ public: /// Constructs a IndexBitcodeWriter object for the given combined index, /// writing to the provided \p Buffer. When writing a subset of the index /// for a distributed backend, provide a \p ModuleToSummariesForIndex map. - IndexBitcodeWriter(BitstreamWriter &Stream, const ModuleSummaryIndex &Index, + IndexBitcodeWriter(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder, + const ModuleSummaryIndex &Index, const std::map *ModuleToSummariesForIndex = nullptr) - : BitcodeWriterBase(Stream), Index(Index), + : BitcodeWriterBase(Stream, StrtabBuilder), Index(Index), ModuleToSummariesForIndex(ModuleToSummariesForIndex) { // Assign unique value ids to all summaries to be written, for use // in writing out the call graph edges. Save the mapping from GUID @@ -1663,7 +1665,7 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N, SmallVectorImpl &Record, unsigned Abbrev) { Record.reserve(N->getElements().size() + 1); - const uint64_t Version = 2 << 1; + const uint64_t Version = 3 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); Record.append(N->elements_begin(), N->elements_end()); @@ -3595,6 +3597,24 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() { MaybeEmitOriginalName(*AS); } + if (!Index.cfiFunctionDefs().empty()) { + for (auto &S : Index.cfiFunctionDefs()) { + NameVals.push_back(StrtabBuilder.add(S)); + NameVals.push_back(S.size()); + } + Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DEFS, NameVals); + NameVals.clear(); + } + + if (!Index.cfiFunctionDecls().empty()) { + for (auto &S : Index.cfiFunctionDecls()) { + NameVals.push_back(StrtabBuilder.add(S)); + NameVals.push_back(S.size()); + } + Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DECLS, NameVals); + NameVals.clear(); + } + Stream.ExitBlock(); } @@ -3829,6 +3849,14 @@ void BitcodeWriter::writeModule(const Module *M, ModuleWriter.write(); } +void BitcodeWriter::writeIndex( + const ModuleSummaryIndex *Index, + const std::map *ModuleToSummariesForIndex) { + IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index, + ModuleToSummariesForIndex); + IndexWriter.write(); +} + /// WriteBitcodeToFile - Write the specified module to the specified output /// stream. void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, @@ -3880,11 +3908,9 @@ void llvm::WriteIndexToFile( SmallVector Buffer; Buffer.reserve(256 * 1024); - BitstreamWriter Stream(Buffer); - writeBitcodeHeader(Stream); - - IndexBitcodeWriter IndexWriter(Stream, Index, ModuleToSummariesForIndex); - IndexWriter.write(); + BitcodeWriter Writer(Buffer); + Writer.writeIndex(&Index, ModuleToSummariesForIndex); + Writer.writeStrtab(); Out.write((char *)&Buffer.front(), Buffer.size()); } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f7c09be..946067e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -24,3 +24,4 @@ add_subdirectory(Fuzzer) add_subdirectory(Passes) add_subdirectory(ToolDrivers) add_subdirectory(XRay) +add_subdirectory(Testing) diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 407d562..ad348d7 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1286,11 +1286,7 @@ bool AsmPrinter::doFinalization(Module &M) { const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - // Emit module flags. - SmallVector ModuleFlags; - M.getModuleFlagsMetadata(ModuleFlags); - if (!ModuleFlags.empty()) - TLOF.emitModuleFlags(*OutStreamer, ModuleFlags, TM); + TLOF.emitModuleMetadata(*OutStreamer, M, TM); if (TM.getTargetTriple().isOSBinFormatELF()) { MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo(); diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 04073b3..dc39d1e 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -552,7 +552,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg); DwarfExpr.addFragmentOffset(Expr); SmallVector Ops; - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Offset); Ops.append(Expr->elements_begin(), Expr->elements_end()); DIExpressionCursor Cursor(Ops); @@ -821,7 +821,7 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, SmallVector Ops; if (Location.isIndirect() && Location.getOffset()) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Location.getOffset()); } DIExpressionCursor Cursor(Ops); @@ -850,7 +850,7 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, SmallVector Ops; if (Location.isIndirect() && Location.getOffset()) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Location.getOffset()); } Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index e3fd21a..75eb355 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1511,7 +1511,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, DwarfExpr.setMemoryLocationKind(); SmallVector Ops; if (Location.isIndirect() && Location.getOffset()) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Location.getOffset()); } Ops.append(DIExpr->elements_begin(), DIExpr->elements_end()); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index ebfba4c..5dfe06c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -134,6 +134,13 @@ public: assert(!FrameIndexExprs.empty() && "Expected an MMI entry"); assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry"); + if (FrameIndexExprs.size()) { + auto *Expr = FrameIndexExprs.back().Expr; + // Get rid of duplicate non-fragment entries. More than one non-fragment + // dbg.declare makes no sense so ignore all but the first. + if (!Expr || !Expr->isFragment()) + return; + } FrameIndexExprs.append(V.FrameIndexExprs.begin(), V.FrameIndexExprs.end()); assert(all_of(FrameIndexExprs, [](FrameIndexExpr &FIE) { diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index d96479f..fe38ee8 100644 --- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -248,15 +248,25 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, assert(Reg.Size == 0 && "subregister has same size as superregister"); // Pattern-match combinations for which more efficient representations exist. - // [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset]. - // [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset]. - // If Reg is a subregister we need to mask it out before subtracting. - if (Op && ((Op->getOp() == dwarf::DW_OP_plus) || - (Op->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) { - int Offset = Op->getArg(0); - SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset; + // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset]. + if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) { + SignedOffset = Op->getArg(0); ExprCursor.take(); } + + // [Reg, DW_OP_constu, Offset, DW_OP_plus] --> [DW_OP_breg, Offset] + // [Reg, DW_OP_constu, Offset, DW_OP_minus] --> [DW_OP_breg,-Offset] + // If Reg is a subregister we need to mask it out before subtracting. + if (Op && Op->getOp() == dwarf::DW_OP_constu) { + auto N = ExprCursor.peekNext(); + if (N && (N->getOp() == dwarf::DW_OP_plus || + (N->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) { + int Offset = Op->getArg(0); + SignedOffset = (N->getOp() == dwarf::DW_OP_minus) ? -Offset : Offset; + ExprCursor.consume(2); + } + } + if (FBReg) addFBReg(SignedOffset); else @@ -320,17 +330,14 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, LocationKind = Unknown; return; } - case dwarf::DW_OP_plus: + case dwarf::DW_OP_plus_uconst: assert(LocationKind != Register); emitOp(dwarf::DW_OP_plus_uconst); emitUnsigned(Op->getArg(0)); break; + case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: - assert(LocationKind != Register); - // There is no DW_OP_minus_uconst. - emitOp(dwarf::DW_OP_constu); - emitUnsigned(Op->getArg(0)); - emitOp(dwarf::DW_OP_minus); + emitOp(Op->getOp()); break; case dwarf::DW_OP_deref: { assert(LocationKind != Register); diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.h b/lib/CodeGen/AsmPrinter/DwarfExpression.h index de86132..728f8ad 100644 --- a/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -42,6 +42,9 @@ public: DIExpressionCursor(ArrayRef Expr) : Start(Expr.begin()), End(Expr.end()) {} + DIExpressionCursor(const DIExpressionCursor &C) + : Start(C.Start), End(C.End) {} + /// Consume one operation. Optional take() { if (Start == End) diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 7f7d3e6..708f5f7 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -475,7 +475,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, SmallVector Ops; if (Location.isIndirect() && Location.getOffset()) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Location.getOffset()); } // If we started with a pointer to the __Block_byref... struct, then @@ -487,7 +487,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(forwardingFieldOffset); } @@ -499,7 +499,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(varFieldOffset); } diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index c2037cb..37e1760 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -134,7 +134,7 @@ static cl::opt DisablePreheaderProtect( cl::desc("Disable protection against removing loop preheaders")); static cl::opt ProfileGuidedSectionPrefix( - "profile-guided-section-prefix", cl::Hidden, cl::init(true), + "profile-guided-section-prefix", cl::Hidden, cl::init(true), cl::ZeroOrMore, cl::desc("Use profile info to add section prefix for hot/cold functions")); static cl::opt FreqRatioToSkipMerge( diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index ef5818d..1d0d3df 100644 --- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -82,6 +82,12 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { case TargetOpcode::G_UDIV: assert(Size == 32 && "Unsupported size"); return RTLIB::UDIV_I32; + case TargetOpcode::G_SREM: + assert(Size == 32 && "Unsupported size"); + return RTLIB::SREM_I32; + case TargetOpcode::G_UREM: + assert(Size == 32 && "Unsupported size"); + return RTLIB::UREM_I32; case TargetOpcode::G_FADD: assert((Size == 32 || Size == 64) && "Unsupported size"); return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32; @@ -93,43 +99,57 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { llvm_unreachable("Unknown libcall function"); } -static LegalizerHelper::LegalizeResult -simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, - Type *OpType) { +LegalizerHelper::LegalizeResult llvm::replaceWithLibcall( + MachineInstr &MI, MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall, + const CallLowering::ArgInfo &Result, ArrayRef Args) { auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering(); auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); - auto Libcall = getRTLibDesc(MI.getOpcode(), Size); const char *Name = TLI.getLibcallName(Libcall); MIRBuilder.getMF().getFrameInfo().setHasCalls(true); - CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), - MachineOperand::CreateES(Name), - {MI.getOperand(0).getReg(), OpType}, - {{MI.getOperand(1).getReg(), OpType}, - {MI.getOperand(2).getReg(), OpType}}); + MIRBuilder.setInstr(MI); + if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall), + MachineOperand::CreateES(Name), Result, Args)) + return LegalizerHelper::UnableToLegalize; + + // We're about to remove MI, so move the insert point after it. + MIRBuilder.setInsertPt(MIRBuilder.getMBB(), + std::next(MIRBuilder.getInsertPt())); + MI.eraseFromParent(); return LegalizerHelper::Legalized; } +static LegalizerHelper::LegalizeResult +simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, + Type *OpType) { + auto Libcall = getRTLibDesc(MI.getOpcode(), Size); + return replaceWithLibcall(MI, MIRBuilder, Libcall, + {MI.getOperand(0).getReg(), OpType}, + {{MI.getOperand(1).getReg(), OpType}, + {MI.getOperand(2).getReg(), OpType}}); +} + LegalizerHelper::LegalizeResult LegalizerHelper::libcall(MachineInstr &MI) { - LLT Ty = MRI.getType(MI.getOperand(0).getReg()); - unsigned Size = Ty.getSizeInBits(); + LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); + unsigned Size = LLTy.getSizeInBits(); auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); - MIRBuilder.setInstr(MI); switch (MI.getOpcode()) { default: return UnableToLegalize; case TargetOpcode::G_SDIV: - case TargetOpcode::G_UDIV: { - Type *Ty = Type::getInt32Ty(Ctx); - return simpleLibcall(MI, MIRBuilder, Size, Ty); + case TargetOpcode::G_UDIV: + case TargetOpcode::G_SREM: + case TargetOpcode::G_UREM: { + Type *HLTy = Type::getInt32Ty(Ctx); + return simpleLibcall(MI, MIRBuilder, Size, HLTy); } case TargetOpcode::G_FADD: case TargetOpcode::G_FPOW: case TargetOpcode::G_FREM: { - Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); - return simpleLibcall(MI, MIRBuilder, Size, Ty); + Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx); + return simpleLibcall(MI, MIRBuilder, Size, HLTy); } } } @@ -237,17 +257,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, unsigned NarrowSize = NarrowTy.getSizeInBits(); int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; - LLT NarrowPtrTy = LLT::pointer( - MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); + LLT OffsetTy = LLT::scalar( + MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); SmallVector DstRegs; for (int i = 0; i < NumParts; ++i) { unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy); - unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy); - unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); + unsigned SrcReg = 0; + unsigned Adjustment = i * NarrowSize / 8; + + MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy, + Adjustment); - MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); - MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset); // TODO: This is conservatively correct, but we probably want to split the // memory operands in the future. MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin()); @@ -263,17 +284,19 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, unsigned NarrowSize = NarrowTy.getSizeInBits(); int NumParts = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize; - LLT NarrowPtrTy = LLT::pointer( - MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize); + LLT OffsetTy = LLT::scalar( + MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits()); SmallVector SrcRegs; extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs); for (int i = 0; i < NumParts; ++i) { - unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy); - unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64)); - MIRBuilder.buildConstant(Offset, i * NarrowSize / 8); - MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset); + unsigned DstReg = 0; + unsigned Adjustment = i * NarrowSize / 8; + + MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy, + Adjustment); + // TODO: This is conservatively correct, but we probably want to split the // memory operands in the future. MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin()); diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 54ef7e5..79d312f 100644 --- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -191,6 +191,24 @@ MachineInstrBuilder MachineIRBuilder::buildGEP(unsigned Res, unsigned Op0, .addUse(Op1); } +Optional +MachineIRBuilder::materializeGEP(unsigned &Res, unsigned Op0, + const LLT &ValueTy, uint64_t Value) { + assert(Res == 0 && "Res is a result argument"); + assert(ValueTy.isScalar() && "invalid offset type"); + + if (Value == 0) { + Res = Op0; + return None; + } + + Res = MRI->createGenericVirtualRegister(MRI->getType(Op0)); + unsigned TmpReg = MRI->createGenericVirtualRegister(ValueTy); + + buildConstant(TmpReg, Value); + return buildGEP(Res, Op0, TmpReg); +} + MachineInstrBuilder MachineIRBuilder::buildPtrMask(unsigned Res, unsigned Op0, uint32_t NumBits) { assert(MRI->getType(Res).isPointer() && diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp index fc52b0d..2d4b959 100644 --- a/lib/CodeGen/MachineBlockPlacement.cpp +++ b/lib/CodeGen/MachineBlockPlacement.cpp @@ -594,8 +594,8 @@ BranchProbability MachineBlockPlacement::collectViableSuccessors( // Assume A->C is very hot (>90%), and C->D has a 50% probability, then after // A->C is chosen as a fall-through, D won't be selected as a successor of C // due to CFG constraint (the probability of C->D is not greater than - // HotProb to break top-order). If we exclude E that is not in BlockFilter - // when calculating the probability of C->D, D will be selected and we + // HotProb to break topo-order). If we exclude E that is not in BlockFilter + // when calculating the probability of C->D, D will be selected and we // will get A C D B as the layout of this loop. auto AdjustedSumProb = BranchProbability::getOne(); for (MachineBasicBlock *Succ : BB->successors()) { @@ -1156,7 +1156,7 @@ void MachineBlockPlacement::precomputeTriangleChains() { continue; // Now we have an interesting triangle. Insert it if it's not part of an - // existing chain + // existing chain. // Note: This cannot be replaced with a call insert() or emplace() because // the find key is BB, but the insert/emplace key is PDom. auto Found = TriangleChainMap.find(&BB); @@ -1298,9 +1298,9 @@ bool MachineBlockPlacement::hasBetterLayoutPredecessor( // | | | | // ---BB | | BB // | | | | - // | pred-- | Succ-- + // | Pred-- | Succ-- // | | | | - // ---succ ---pred-- + // ---Succ ---Pred-- // // cost = freq(S->Pred) + freq(BB->Succ) cost = 2 * freq (S->Pred) // = freq(S->Pred) + freq(S->BB) diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 52d5819..c7113f1 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -895,8 +895,11 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { // If the physreg has no defs anywhere, it's just an ambient register // and we can freely move its uses. Alternatively, if it's allocatable, // it could get allocated to something with a def during allocation. - if (!MRI->isConstantPhysReg(Reg)) - return false; + // However, if the physreg is known to always be caller saved/restored + // then this use is safe to hoist. + if (!MRI->isConstantPhysReg(Reg) && + !(TRI->isCallerPreservedPhysReg(Reg, *I.getParent()->getParent()))) + return false; // Otherwise it's safe to move. continue; } else if (!MO.isDead()) { diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a0967f5..2d4422d 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2217,7 +2217,8 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn, SDNode *N) { // Iff the flag result is dead: // (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry) - if ((N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::UADDO) && + if ((N0.getOpcode() == ISD::ADD || + (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0)) && isNullConstant(N1) && !N->hasAnyUseOfValue(1)) return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(), N0.getOperand(0), N0.getOperand(1), CarryIn); @@ -12460,10 +12461,27 @@ bool DAGCombiner::MergeStoresOfConstantsOrVecElts( LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode; SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores); - SDValue NewStore = DAG.getStore(NewChain, DL, StoredVal, - FirstInChain->getBasePtr(), - FirstInChain->getPointerInfo(), - FirstInChain->getAlignment()); + + // make sure we use trunc store if it's necessary to be legal. + SDValue NewStore; + if (TLI.isTypeLegal(StoredVal.getValueType())) { + NewStore = DAG.getStore(NewChain, DL, StoredVal, FirstInChain->getBasePtr(), + FirstInChain->getPointerInfo(), + FirstInChain->getAlignment()); + } else { // Must be realized as a trunc store + EVT LegalizedStoredValueTy = + TLI.getTypeToTransformTo(*DAG.getContext(), StoredVal.getValueType()); + unsigned LegalizedStoreSize = LegalizedStoredValueTy.getSizeInBits(); + ConstantSDNode *C = cast(StoredVal); + SDValue ExtendedStoreVal = + DAG.getConstant(C->getAPIntValue().zextOrTrunc(LegalizedStoreSize), DL, + LegalizedStoredValueTy); + NewStore = DAG.getTruncStore( + NewChain, DL, ExtendedStoreVal, FirstInChain->getBasePtr(), + FirstInChain->getPointerInfo(), StoredVal.getValueType() /*TVT*/, + FirstInChain->getAlignment(), + FirstInChain->getMemOperand()->getFlags()); + } // Replace all merged stores with the new store. for (unsigned i = 0; i < NumStores; ++i) @@ -12731,8 +12749,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) { IsFast) { LastLegalType = i + 1; // Or check whether a truncstore is legal. - } else if (!LegalTypes && - TLI.getTypeAction(Context, StoreTy) == + } else if (TLI.getTypeAction(Context, StoreTy) == TargetLowering::TypePromoteInteger) { EVT LegalizedStoredValueTy = TLI.getTypeToTransformTo(Context, StoredVal.getValueType()); @@ -12947,8 +12964,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) { else if (TLI.getTypeAction(Context, StoreTy) == TargetLowering::TypePromoteInteger) { EVT LegalizedStoredValueTy = TLI.getTypeToTransformTo(Context, StoreTy); - if (!LegalTypes && - TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) && + if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) && TLI.canMergeStoresTo(FirstStoreAS, LegalizedStoredValueTy) && TLI.isLoadExtLegal(ISD::ZEXTLOAD, LegalizedStoredValueTy, StoreTy) && @@ -12958,8 +12974,8 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) { TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy, FirstStoreAS, FirstStoreAlign, &IsFastSt) && IsFastSt && - TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy, - FirstLoadAS, FirstLoadAlign, &IsFastLd) && + TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS, + FirstLoadAlign, &IsFastLd) && IsFastLd) LastLegalIntegerType = i + 1; } @@ -13189,10 +13205,6 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { Chain = ST->getChain(); } - // Try transforming N to an indexed store. - if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) - return SDValue(N, 0); - // FIXME: is there such a thing as a truncating indexed store? if (ST->isTruncatingStore() && ST->isUnindexed() && Value.getValueType().isInteger()) { @@ -13287,6 +13299,10 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { } } + // Try transforming N to an indexed store. + if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) + return SDValue(N, 0); + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' // // Make sure to do this only after attempting to merge stores in order to @@ -14692,21 +14708,7 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) { MachineMemOperand *MMO = MF.getMachineMemOperand(Ld->getMemOperand(), Offset, VT.getStoreSize()); SDValue NewLd = DAG.getLoad(VT, DL, Ld->getChain(), NewAddr, MMO); - - // The new load must have the same position as the old load in terms of memory - // dependency. Create a TokenFactor for Ld and NewLd and update uses of Ld's - // output chain to use that TokenFactor. - // TODO: This code is based on a similar sequence in x86 lowering. It should - // be moved to a helper function, so it can be shared and reused. - if (Ld->hasAnyUseOfValue(1)) { - SDValue OldChain = SDValue(Ld, 1); - SDValue NewChain = SDValue(NewLd.getNode(), 1); - SDValue TokenFactor = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, - OldChain, NewChain); - DAG.ReplaceAllUsesOfValueWith(OldChain, TokenFactor); - DAG.UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain); - } - + DAG.makeEquivalentMemoryOrdering(Ld, NewLd); return NewLd; } diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 606b895..b736037 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -523,3 +523,29 @@ void FunctionLoweringInfo::setCurrentSwiftErrorVReg( const MachineBasicBlock *MBB, const Value *Val, unsigned VReg) { SwiftErrorVRegDefMap[std::make_pair(MBB, Val)] = VReg; } + +std::pair +FunctionLoweringInfo::getOrCreateSwiftErrorVRegDefAt(const Instruction *I) { + auto Key = PointerIntPair(I, true); + auto It = SwiftErrorVRegDefUses.find(Key); + if (It == SwiftErrorVRegDefUses.end()) { + auto &DL = MF->getDataLayout(); + const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); + unsigned VReg = MF->getRegInfo().createVirtualRegister(RC); + SwiftErrorVRegDefUses[Key] = VReg; + return std::make_pair(VReg, true); + } + return std::make_pair(It->second, false); +} + +std::pair +FunctionLoweringInfo::getOrCreateSwiftErrorVRegUseAt(const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) { + auto Key = PointerIntPair(I, false); + auto It = SwiftErrorVRegDefUses.find(Key); + if (It == SwiftErrorVRegDefUses.end()) { + unsigned VReg = getOrCreateSwiftErrorVReg(MBB, Val); + SwiftErrorVRegDefUses[Key] = VReg; + return std::make_pair(VReg, true); + } + return std::make_pair(It->second, false); +} diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index e54eaa3..15e87b7 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2192,19 +2192,6 @@ static bool isSinCosLibcallAvailable(SDNode *Node, const TargetLowering &TLI) { return TLI.getLibcallName(LC) != nullptr; } -/// Return true if sincos libcall is available and can be used to combine sin -/// and cos. -static bool canCombineSinCosLibcall(SDNode *Node, const TargetLowering &TLI, - const TargetMachine &TM) { - if (!isSinCosLibcallAvailable(Node, TLI)) - return false; - // GNU sin/cos functions set errno while sincos does not. Therefore - // combining sin and cos is only safe if unsafe-fpmath is enabled. - if (TM.getTargetTriple().isGNUEnvironment() && !TM.Options.UnsafeFPMath) - return false; - return true; -} - /// Only issue sincos libcall if both sin and cos are needed. static bool useSinCos(SDNode *Node) { unsigned OtherOpcode = Node->getOpcode() == ISD::FSIN @@ -3247,7 +3234,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { // Turn fsin / fcos into ISD::FSINCOS node if there are a pair of fsin / // fcos which share the same operand and both are used. if ((TLI.isOperationLegalOrCustom(ISD::FSINCOS, VT) || - canCombineSinCosLibcall(Node, TLI, TM)) + isSinCosLibcallAvailable(Node, TLI)) && useSinCos(Node)) { SDVTList VTs = DAG.getVTList(VT, VT); Tmp1 = DAG.getNode(ISD::FSINCOS, dl, VTs, Node->getOperand(0)); diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 0d5e07d..a3ba52a 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1828,10 +1828,11 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, TLI.isOperationLegalOrCustom(N->getOpcode() == ISD::ADD ? ISD::UADDO : ISD::USUBO, TLI.getTypeToExpandTo(*DAG.getContext(), NVT)); + TargetLoweringBase::BooleanContent BoolType = TLI.getBooleanContents(NVT); + if (hasOVF) { EVT OvfVT = getSetCCResultType(NVT); SDVTList VTList = DAG.getVTList(NVT, OvfVT); - TargetLoweringBase::BooleanContent BoolType = TLI.getBooleanContents(NVT); int RevOpc; if (N->getOpcode() == ISD::ADD) { RevOpc = ISD::SUB; @@ -1864,6 +1865,13 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, Hi = DAG.getNode(ISD::ADD, dl, NVT, makeArrayRef(HiOps, 2)); SDValue Cmp1 = DAG.getSetCC(dl, getSetCCResultType(NVT), Lo, LoOps[0], ISD::SETULT); + + if (BoolType == TargetLoweringBase::ZeroOrOneBooleanContent) { + SDValue Carry = DAG.getZExtOrTrunc(Cmp1, dl, NVT); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, Carry); + return; + } + SDValue Carry1 = DAG.getSelect(dl, NVT, Cmp1, DAG.getConstant(1, dl, NVT), DAG.getConstant(0, dl, NVT)); @@ -1878,9 +1886,14 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, SDValue Cmp = DAG.getSetCC(dl, getSetCCResultType(LoOps[0].getValueType()), LoOps[0], LoOps[1], ISD::SETULT); - SDValue Borrow = DAG.getSelect(dl, NVT, Cmp, - DAG.getConstant(1, dl, NVT), - DAG.getConstant(0, dl, NVT)); + + SDValue Borrow; + if (BoolType == TargetLoweringBase::ZeroOrOneBooleanContent) + Borrow = DAG.getZExtOrTrunc(Cmp, dl, NVT); + else + Borrow = DAG.getSelect(dl, NVT, Cmp, DAG.getConstant(1, dl, NVT), + DAG.getConstant(0, dl, NVT)); + Hi = DAG.getNode(ISD::SUB, dl, NVT, Hi, Borrow); } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index dff8bd2..7abdc76 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -7244,6 +7244,24 @@ void SelectionDAG::TransferDbgValues(SDValue From, SDValue To) { AddDbgValue(I, ToNode, false); } +void SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad, + SDValue NewMemOp) { + assert(isa(NewMemOp.getNode()) && "Expected a memop node"); + if (!OldLoad->hasAnyUseOfValue(1)) + return; + + // The new memory operation must have the same position as the old load in + // terms of memory dependency. Create a TokenFactor for the old load and new + // memory operation and update uses of the old load's output chain to use that + // TokenFactor. + SDValue OldChain = SDValue(OldLoad, 1); + SDValue NewChain = SDValue(NewMemOp.getNode(), 1); + SDValue TokenFactor = + getNode(ISD::TokenFactor, SDLoc(OldLoad), MVT::Other, OldChain, NewChain); + ReplaceAllUsesOfValueWith(OldChain, TokenFactor); + UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain); +} + //===----------------------------------------------------------------------===// // SDNode Class //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index d34ac40..f9f431d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1496,9 +1496,10 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { true /*isfixed*/, 1 /*origidx*/, 0 /*partOffs*/)); // Create SDNode for the swifterror virtual register. - OutVals.push_back(DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVReg( - FuncInfo.MBB, FuncInfo.SwiftErrorArg), - EVT(TLI.getPointerTy(DL)))); + OutVals.push_back( + DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVRegUseAt( + &I, FuncInfo.MBB, FuncInfo.SwiftErrorArg).first, + EVT(TLI.getPointerTy(DL)))); } bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); @@ -3581,8 +3582,7 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) { } void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) { - const TargetLowering &TLI = DAG.getTargetLoweringInfo(); - assert(TLI.supportSwiftError() && + assert(DAG.getTargetLoweringInfo().supportSwiftError() && "call visitStoreToSwiftError when backend supports swifterror"); SmallVector ValueVTs; @@ -3595,15 +3595,15 @@ void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) { SDValue Src = getValue(SrcV); // Create a virtual register, then update the virtual register. - auto &DL = DAG.getDataLayout(); - const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL)); - unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC); + unsigned VReg; bool CreatedVReg; + std::tie(VReg, CreatedVReg) = FuncInfo.getOrCreateSwiftErrorVRegDefAt(&I); // Chain, DL, Reg, N or Chain, DL, Reg, N, Glue // Chain can be getRoot or getControlRoot. SDValue CopyNode = DAG.getCopyToReg(getRoot(), getCurSDLoc(), VReg, SDValue(Src.getNode(), Src.getResNo())); DAG.setRoot(CopyNode); - FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg); + if (CreatedVReg) + FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg); } void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) { @@ -3633,7 +3633,8 @@ void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) { // Chain, DL, Reg, VT, Glue or Chain, DL, Reg, VT SDValue L = DAG.getCopyFromReg( getRoot(), getCurSDLoc(), - FuncInfo.getOrCreateSwiftErrorVReg(FuncInfo.MBB, SV), ValueVTs[0]); + FuncInfo.getOrCreateSwiftErrorVRegUseAt(&I, FuncInfo.MBB, SV).first, + ValueVTs[0]); setValue(&I, L); } @@ -4942,11 +4943,12 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { updateDAGForMaybeTailCall(MM); return nullptr; } - case Intrinsic::memcpy_element_atomic: { - SDValue Dst = getValue(I.getArgOperand(0)); - SDValue Src = getValue(I.getArgOperand(1)); - SDValue NumElements = getValue(I.getArgOperand(2)); - SDValue ElementSize = getValue(I.getArgOperand(3)); + case Intrinsic::memcpy_element_unordered_atomic: { + const ElementUnorderedAtomicMemCpyInst &MI = + cast(I); + SDValue Dst = getValue(MI.getRawDest()); + SDValue Src = getValue(MI.getRawSource()); + SDValue Length = getValue(MI.getLength()); // Emit a library call. TargetLowering::ArgListTy Args; @@ -4958,18 +4960,13 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { Entry.Node = Src; Args.push_back(Entry); - Entry.Ty = I.getArgOperand(2)->getType(); - Entry.Node = NumElements; - Args.push_back(Entry); - - Entry.Ty = Type::getInt32Ty(*DAG.getContext()); - Entry.Node = ElementSize; + Entry.Ty = MI.getLength()->getType(); + Entry.Node = Length; Args.push_back(Entry); - uint64_t ElementSizeConstant = - cast(I.getArgOperand(3))->getZExtValue(); + uint64_t ElementSizeConstant = MI.getElementSizeInBytes(); RTLIB::Libcall LibraryCall = - RTLIB::getMEMCPY_ELEMENT_ATOMIC(ElementSizeConstant); + RTLIB::getMEMCPY_ELEMENT_UNORDERED_ATOMIC(ElementSizeConstant); if (LibraryCall == RTLIB::UNKNOWN_LIBCALL) report_fatal_error("Unsupported element size"); @@ -6030,9 +6027,11 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, SwiftErrorVal = V; // We find the virtual register for the actual swifterror argument. // Instead of using the Value, we use the virtual register instead. - Entry.Node = - DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVReg(FuncInfo.MBB, V), - EVT(TLI.getPointerTy(DL))); + Entry.Node = DAG.getRegister(FuncInfo + .getOrCreateSwiftErrorVRegUseAt( + CS.getInstruction(), FuncInfo.MBB, V) + .first, + EVT(TLI.getPointerTy(DL))); } Args.push_back(Entry); @@ -6073,11 +6072,13 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, if (SwiftErrorVal && TLI.supportSwiftError()) { // Get the last element of InVals. SDValue Src = CLI.InVals.back(); - const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL)); - unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC); + unsigned VReg; bool CreatedVReg; + std::tie(VReg, CreatedVReg) = + FuncInfo.getOrCreateSwiftErrorVRegDefAt(CS.getInstruction()); SDValue CopyNode = CLI.DAG.getCopyToReg(Result.second, CLI.DL, VReg, Src); // We update the virtual register for the actual swifterror argument. - FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg); + if (CreatedVReg) + FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg); DAG.setRoot(CopyNode); } } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index b67f11f..dcccd17 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1055,6 +1055,7 @@ static void setupSwiftErrorVals(const Function &Fn, const TargetLowering *TLI, FuncInfo->SwiftErrorVals.clear(); FuncInfo->SwiftErrorVRegDefMap.clear(); FuncInfo->SwiftErrorVRegUpwardsUse.clear(); + FuncInfo->SwiftErrorVRegDefUses.clear(); FuncInfo->SwiftErrorArg = nullptr; // Check if function has a swifterror argument. @@ -1278,6 +1279,80 @@ static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) { } } +void preassignSwiftErrorRegs(const TargetLowering *TLI, + FunctionLoweringInfo *FuncInfo, + BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End) { + if (!TLI->supportSwiftError() || FuncInfo->SwiftErrorVals.empty()) + return; + + // Iterator over instructions and assign vregs to swifterror defs and uses. + for (auto It = Begin; It != End; ++It) { + ImmutableCallSite CS(&*It); + if (CS) { + // A call-site with a swifterror argument is both use and def. + const Value *SwiftErrorAddr = nullptr; + for (auto &Arg : CS.args()) { + if (!Arg->isSwiftError()) + continue; + // Use of swifterror. + assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments"); + SwiftErrorAddr = &*Arg; + assert(SwiftErrorAddr->isSwiftError() && + "Must have a swifterror value argument"); + unsigned VReg; bool CreatedReg; + std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt( + &*It, FuncInfo->MBB, SwiftErrorAddr); + assert(CreatedReg); + } + if (!SwiftErrorAddr) + continue; + + // Def of swifterror. + unsigned VReg; bool CreatedReg; + std::tie(VReg, CreatedReg) = + FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It); + assert(CreatedReg); + FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg); + + // A load is a use. + } else if (const LoadInst *LI = dyn_cast(&*It)) { + const Value *V = LI->getOperand(0); + if (!V->isSwiftError()) + continue; + + unsigned VReg; bool CreatedReg; + std::tie(VReg, CreatedReg) = + FuncInfo->getOrCreateSwiftErrorVRegUseAt(LI, FuncInfo->MBB, V); + assert(CreatedReg); + + // A store is a def. + } else if (const StoreInst *SI = dyn_cast(&*It)) { + const Value *SwiftErrorAddr = SI->getOperand(1); + if (!SwiftErrorAddr->isSwiftError()) + continue; + + // Def of swifterror. + unsigned VReg; bool CreatedReg; + std::tie(VReg, CreatedReg) = + FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It); + assert(CreatedReg); + FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg); + + // A return in a swiferror returning function is a use. + } else if (const ReturnInst *R = dyn_cast(&*It)) { + const Function *F = R->getParent()->getParent(); + if(!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) + continue; + + unsigned VReg; bool CreatedReg; + std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt( + R, FuncInfo->MBB, FuncInfo->SwiftErrorArg); + assert(CreatedReg); + } + } +} + void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastISelFailed = false; // Initialize the Fast-ISel state, if needed. @@ -1384,6 +1459,10 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastIS->startNewBlock(); unsigned NumFastIselRemaining = std::distance(Begin, End); + + // Pre-assign swifterror vregs. + preassignSwiftErrorRegs(TLI, FuncInfo, Begin, End); + // Do FastISel on as many instructions as possible. for (; BI != Begin; --BI) { const Instruction *Inst = &*std::prev(BI); diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 3a50aaa..008b984 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -569,8 +569,7 @@ SlotIndex SplitEditor::buildCopy(unsigned FromReg, unsigned ToReg, // Greedy heuristic: Keep iterating keeping the best covering subreg index // each time. - LaneBitmask LanesLeft = - LaneMask & ~(TRI.getSubRegIndexLaneMask(BestCover)); + LaneBitmask LanesLeft = LaneMask & ~(TRI.getSubRegIndexLaneMask(BestIdx)); while (LanesLeft.any()) { unsigned BestIdx = 0; int BestCover = INT_MIN; diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp index acb3676..6bac39c 100644 --- a/lib/CodeGen/StackColoring.cpp +++ b/lib/CodeGen/StackColoring.cpp @@ -86,10 +86,134 @@ STATISTIC(StackSpaceSaved, "Number of bytes saved due to merging slots."); STATISTIC(StackSlotMerged, "Number of stack slot merged."); STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region"); +//===----------------------------------------------------------------------===// +// StackColoring Pass +//===----------------------------------------------------------------------===// +// +// Stack Coloring reduces stack usage by merging stack slots when they +// can't be used together. For example, consider the following C program: +// +// void bar(char *, int); +// void foo(bool var) { +// A: { +// char z[4096]; +// bar(z, 0); +// } +// +// char *p; +// char x[4096]; +// char y[4096]; +// if (var) { +// p = x; +// } else { +// bar(y, 1); +// p = y + 1024; +// } +// B: +// bar(p, 2); +// } +// +// Naively-compiled, this program would use 12k of stack space. However, the +// stack slot corresponding to `z` is always destroyed before either of the +// stack slots for `x` or `y` are used, and then `x` is only used if `var` +// is true, while `y` is only used if `var` is false. So in no time are 2 +// of the stack slots used together, and therefore we can merge them, +// compiling the function using only a single 4k alloca: +// +// void foo(bool var) { // equivalent +// char x[4096]; +// char *p; +// bar(x, 0); +// if (var) { +// p = x; +// } else { +// bar(x, 1); +// p = x + 1024; +// } +// bar(p, 2); +// } +// +// This is an important optimization if we want stack space to be under +// control in large functions, both open-coded ones and ones created by +// inlining. // // Implementation Notes: // --------------------- // +// An important part of the above reasoning is that `z` can't be accessed +// while the latter 2 calls to `bar` are running. This is justified because +// `z`'s lifetime is over after we exit from block `A:`, so any further +// accesses to it would be UB. The way we represent this information +// in LLVM is by having frontends delimit blocks with `lifetime.start` +// and `lifetime.end` intrinsics. +// +// The effect of these intrinsics seems to be as follows (maybe I should +// specify this in the reference?): +// +// L1) at start, each stack-slot is marked as *out-of-scope*, unless no +// lifetime intrinsic refers to that stack slot, in which case +// it is marked as *in-scope*. +// L2) on a `lifetime.start`, a stack slot is marked as *in-scope* and +// the stack slot is overwritten with `undef`. +// L3) on a `lifetime.end`, a stack slot is marked as *out-of-scope*. +// L4) on function exit, all stack slots are marked as *out-of-scope*. +// L5) `lifetime.end` is a no-op when called on a slot that is already +// *out-of-scope*. +// L6) memory accesses to *out-of-scope* stack slots are UB. +// L7) when a stack-slot is marked as *out-of-scope*, all pointers to it +// are invalidated, unless the slot is "degenerate". This is used to +// justify not marking slots as in-use until the pointer to them is +// used, but feels a bit hacky in the presence of things like LICM. See +// the "Degenerate Slots" section for more details. +// +// Now, let's ground stack coloring on these rules. We'll define a slot +// as *in-use* at a (dynamic) point in execution if it either can be +// written to at that point, or if it has a live and non-undef content +// at that point. +// +// Obviously, slots that are never *in-use* together can be merged, and +// in our example `foo`, the slots for `x`, `y` and `z` are never +// in-use together (of course, sometimes slots that *are* in-use together +// might still be mergable, but we don't care about that here). +// +// In this implementation, we successively merge pairs of slots that are +// not *in-use* together. We could be smarter - for example, we could merge +// a single large slot with 2 small slots, or we could construct the +// interference graph and run a "smart" graph coloring algorithm, but with +// that aside, how do we find out whether a pair of slots might be *in-use* +// together? +// +// From our rules, we see that *out-of-scope* slots are never *in-use*, +// and from (L7) we see that "non-degenerate" slots remain non-*in-use* +// until their address is taken. Therefore, we can approximate slot activity +// using dataflow. +// +// A subtle point: naively, we might try to figure out which pairs of +// stack-slots interfere by propagating `S in-use` through the CFG for every +// stack-slot `S`, and having `S` and `T` interfere if there is a CFG point in +// which they are both *in-use*. +// +// That is sound, but overly conservative in some cases: in our (artificial) +// example `foo`, either `x` or `y` might be in use at the label `B:`, but +// as `x` is only in use if we came in from the `var` edge and `y` only +// if we came from the `!var` edge, they still can't be in use together. +// See PR32488 for an important real-life case. +// +// If we wanted to find all points of interference precisely, we could +// propagate `S in-use` and `S&T in-use` predicates through the CFG. That +// would be precise, but requires propagating `O(n^2)` dataflow facts. +// +// However, we aren't interested in the *set* of points of interference +// between 2 stack slots, only *whether* there *is* such a point. So we +// can rely on a little trick: for `S` and `T` to be in-use together, +// one of them needs to become in-use while the other is in-use (or +// they might both become in use simultaneously). We can check this +// by also keeping track of the points at which a stack slot might *start* +// being in-use. +// +// Exact first use: +// ---------------- +// // Consider the following motivating example: // // int foo() { @@ -158,6 +282,9 @@ STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region"); // lifetime, we can additionally overlap b1 and b5, giving us a 3*1024 // byte stack (better). // +// Degenerate Slots: +// ----------------- +// // Relying entirely on first-use of stack slots is problematic, // however, due to the fact that optimizations can sometimes migrate // uses of a variable outside of its lifetime start/end region. Here @@ -237,10 +364,6 @@ STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region"); // for "b" then it will appear that 'b' has a degenerate lifetime. // -//===----------------------------------------------------------------------===// -// StackColoring Pass -//===----------------------------------------------------------------------===// - namespace { /// StackColoring - A machine pass for merging disjoint stack allocations, /// marked by the LIFETIME_START and LIFETIME_END pseudo instructions. @@ -271,8 +394,11 @@ class StackColoring : public MachineFunctionPass { /// Maps basic blocks to a serial number. SmallVector BasicBlockNumbering; - /// Maps liveness intervals for each slot. + /// Maps slots to their use interval. Outside of this interval, slots + /// values are either dead or `undef` and they will not be written to. SmallVector, 16> Intervals; + /// Maps slots to the points where they can become in-use. + SmallVector, 16> LiveStarts; /// VNInfo is used for the construction of LiveIntervals. VNInfo::Allocator VNInfoAllocator; /// SlotIndex analysis object. @@ -672,15 +798,22 @@ void StackColoring::calculateLocalLiveness() void StackColoring::calculateLiveIntervals(unsigned NumSlots) { SmallVector Starts; - SmallVector Finishes; + SmallVector DefinitelyInUse; // For each block, find which slots are active within this block // and update the live intervals. for (const MachineBasicBlock &MBB : *MF) { Starts.clear(); Starts.resize(NumSlots); - Finishes.clear(); - Finishes.resize(NumSlots); + DefinitelyInUse.clear(); + DefinitelyInUse.resize(NumSlots); + + // Start the interval of the slots that we previously found to be 'in-use'. + BlockLifetimeInfo &MBBLiveness = BlockLiveness[&MBB]; + for (int pos = MBBLiveness.LiveIn.find_first(); pos != -1; + pos = MBBLiveness.LiveIn.find_next(pos)) { + Starts[pos] = Indexes->getMBBStartIdx(&MBB); + } // Create the interval for the basic blocks containing lifetime begin/end. for (const MachineInstr &MI : MBB) { @@ -692,66 +825,35 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) { SlotIndex ThisIndex = Indexes->getInstructionIndex(MI); for (auto Slot : slots) { if (IsStart) { - if (!Starts[Slot].isValid() || Starts[Slot] > ThisIndex) + // If a slot is already definitely in use, we don't have to emit + // a new start marker because there is already a pre-existing + // one. + if (!DefinitelyInUse[Slot]) { + LiveStarts[Slot].push_back(ThisIndex); + DefinitelyInUse[Slot] = true; + } + if (!Starts[Slot].isValid()) Starts[Slot] = ThisIndex; } else { - if (!Finishes[Slot].isValid() || Finishes[Slot] < ThisIndex) - Finishes[Slot] = ThisIndex; + if (Starts[Slot].isValid()) { + VNInfo *VNI = Intervals[Slot]->getValNumInfo(0); + Intervals[Slot]->addSegment( + LiveInterval::Segment(Starts[Slot], ThisIndex, VNI)); + Starts[Slot] = SlotIndex(); // Invalidate the start index + DefinitelyInUse[Slot] = false; + } } } } - // Create the interval of the blocks that we previously found to be 'alive'. - BlockLifetimeInfo &MBBLiveness = BlockLiveness[&MBB]; - for (unsigned pos : MBBLiveness.LiveIn.set_bits()) { - Starts[pos] = Indexes->getMBBStartIdx(&MBB); - } - for (unsigned pos : MBBLiveness.LiveOut.set_bits()) { - Finishes[pos] = Indexes->getMBBEndIdx(&MBB); - } - + // Finish up started segments for (unsigned i = 0; i < NumSlots; ++i) { - // - // When LifetimeStartOnFirstUse is turned on, data flow analysis - // is forward (from starts to ends), not bidirectional. A - // consequence of this is that we can wind up in situations - // where Starts[i] is invalid but Finishes[i] is valid and vice - // versa. Example: - // - // LIFETIME_START x - // if (...) { - // - // throw ...; - // } - // LIFETIME_END x - // return 2; - // - // - // Here the slot for "x" will not be live into the block - // containing the "return 2" (since lifetimes start with first - // use, not at the dominating LIFETIME_START marker). - // - if (Starts[i].isValid() && !Finishes[i].isValid()) { - Finishes[i] = Indexes->getMBBEndIdx(&MBB); - } if (!Starts[i].isValid()) continue; - assert(Starts[i] && Finishes[i] && "Invalid interval"); - VNInfo *ValNum = Intervals[i]->getValNumInfo(0); - SlotIndex S = Starts[i]; - SlotIndex F = Finishes[i]; - if (S < F) { - // We have a single consecutive region. - Intervals[i]->addSegment(LiveInterval::Segment(S, F, ValNum)); - } else { - // We have two non-consecutive regions. This happens when - // LIFETIME_START appears after the LIFETIME_END marker. - SlotIndex NewStart = Indexes->getMBBStartIdx(&MBB); - SlotIndex NewFin = Indexes->getMBBEndIdx(&MBB); - Intervals[i]->addSegment(LiveInterval::Segment(NewStart, F, ValNum)); - Intervals[i]->addSegment(LiveInterval::Segment(S, NewFin, ValNum)); - } + SlotIndex EndIdx = Indexes->getMBBEndIdx(&MBB); + VNInfo *VNI = Intervals[i]->getValNumInfo(0); + Intervals[i]->addSegment(LiveInterval::Segment(Starts[i], EndIdx, VNI)); } } } @@ -981,6 +1083,7 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { BasicBlockNumbering.clear(); Markers.clear(); Intervals.clear(); + LiveStarts.clear(); VNInfoAllocator.Reset(); unsigned NumSlots = MFI->getObjectIndexEnd(); @@ -992,6 +1095,7 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { SmallVector SortedSlots; SortedSlots.reserve(NumSlots); Intervals.reserve(NumSlots); + LiveStarts.resize(NumSlots); unsigned NumMarkers = collectMarkers(NumSlots); @@ -1063,6 +1167,9 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { return MFI->getObjectSize(LHS) > MFI->getObjectSize(RHS); }); + for (auto &s : LiveStarts) + std::sort(s.begin(), s.end()); + bool Changed = true; while (Changed) { Changed = false; @@ -1078,12 +1185,22 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) { int SecondSlot = SortedSlots[J]; LiveInterval *First = &*Intervals[FirstSlot]; LiveInterval *Second = &*Intervals[SecondSlot]; + auto &FirstS = LiveStarts[FirstSlot]; + auto &SecondS = LiveStarts[SecondSlot]; assert (!First->empty() && !Second->empty() && "Found an empty range"); - // Merge disjoint slots. - if (!First->overlaps(*Second)) { + // Merge disjoint slots. This is a little bit tricky - see the + // Implementation Notes section for an explanation. + if (!First->isLiveAtIndexes(SecondS) && + !Second->isLiveAtIndexes(FirstS)) { Changed = true; First->MergeSegmentsInAsValue(*Second, First->getValNumInfo(0)); + + int OldSize = FirstS.size(); + FirstS.append(SecondS.begin(), SecondS.end()); + auto Mid = FirstS.begin() + OldSize; + std::inplace_merge(FirstS.begin(), Mid, FirstS.end()); + SlotRemap[SecondSlot] = FirstSlot; SortedSlots[J] = -1; DEBUG(dbgs()<<"Merging #"< ModuleFlags, - unsigned &Version, unsigned &Flags, +static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags, StringRef &Section) { + SmallVector ModuleFlags; + M.getModuleFlagsMetadata(ModuleFlags); + for (const auto &MFE: ModuleFlags) { // Ignore flags with 'Require' behaviour. if (MFE.Behavior == Module::Require) @@ -88,14 +90,13 @@ static void GetObjCImageInfo(ArrayRef ModuleFlags, // ELF //===----------------------------------------------------------------------===// -void TargetLoweringObjectFileELF::emitModuleFlags( - MCStreamer &Streamer, ArrayRef ModuleFlags, - const TargetMachine &TM) const { +void TargetLoweringObjectFileELF::emitModuleMetadata( + MCStreamer &Streamer, Module &M, const TargetMachine &TM) const { unsigned Version = 0; unsigned Flags = 0; StringRef Section; - GetObjCImageInfo(ModuleFlags, Version, Flags, Section); + GetObjCImageInfo(M, Version, Flags, Section); if (Section.empty()) return; @@ -618,20 +619,10 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, } } -/// emitModuleFlags - Perform code emission for module flags. -void TargetLoweringObjectFileMachO::emitModuleFlags( - MCStreamer &Streamer, ArrayRef ModuleFlags, - const TargetMachine &TM) const { - MDNode *LinkerOptions = nullptr; - - for (const auto &MFE : ModuleFlags) { - StringRef Key = MFE.Key->getString(); - if (Key == "Linker Options") - LinkerOptions = cast(MFE.Val); - } - +void TargetLoweringObjectFileMachO::emitModuleMetadata( + MCStreamer &Streamer, Module &M, const TargetMachine &TM) const { // Emit the linker options if present. - if (LinkerOptions) { + if (auto *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) { for (const auto &Option : LinkerOptions->operands()) { SmallVector StrOptions; for (const auto &Piece : cast(Option)->operands()) @@ -643,7 +634,8 @@ void TargetLoweringObjectFileMachO::emitModuleFlags( unsigned VersionVal = 0; unsigned ImageInfoFlags = 0; StringRef SectionVal; - GetObjCImageInfo(ModuleFlags, VersionVal, ImageInfoFlags, SectionVal); + + GetObjCImageInfo(M, VersionVal, ImageInfoFlags, SectionVal); // The section is mandatory. If we don't have it, then we don't have GC info. if (SectionVal.empty()) @@ -1159,18 +1151,9 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable( COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); } -void TargetLoweringObjectFileCOFF::emitModuleFlags( - MCStreamer &Streamer, ArrayRef ModuleFlags, - const TargetMachine &TM) const { - MDNode *LinkerOptions = nullptr; - - for (const auto &MFE : ModuleFlags) { - StringRef Key = MFE.Key->getString(); - if (Key == "Linker Options") - LinkerOptions = cast(MFE.Val); - } - - if (LinkerOptions) { +void TargetLoweringObjectFileCOFF::emitModuleMetadata( + MCStreamer &Streamer, Module &M, const TargetMachine &TM) const { + if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) { // Emit the linker options to the linker .drectve section. According to the // spec, this section is a space-separated string containing flags for // linker. @@ -1190,7 +1173,7 @@ void TargetLoweringObjectFileCOFF::emitModuleFlags( unsigned Flags = 0; StringRef Section; - GetObjCImageInfo(ModuleFlags, Version, Flags, Section); + GetObjCImageInfo(M, Version, Flags, Section); if (Section.empty()) return; diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 2f9e898..f916695 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -20,6 +20,7 @@ add_llvm_library(LLVMDebugInfoCodeView LazyRandomTypeCollection.cpp Line.cpp RecordSerialization.cpp + StringsAndChecksums.cpp SymbolRecordMapping.cpp SymbolDumper.cpp SymbolSerializer.cpp @@ -32,7 +33,7 @@ add_llvm_library(LLVMDebugInfoCodeView TypeSerializer.cpp TypeStreamMerger.cpp TypeTableCollection.cpp - + ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView ) diff --git a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index 6e647c4..de02525 100644 --- a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -58,6 +58,10 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { uint32_t Begin = Writer.getOffset(); uint32_t End = Begin + StringSize; + // Write a null string at the beginning. + if (auto EC = Writer.writeCString(StringRef())) + return EC; + for (auto &Pair : Strings) { StringRef S = Pair.getKey(); uint32_t Offset = Begin + Pair.getValue(); @@ -68,6 +72,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { } Writer.setOffset(End); + assert((End - Begin) == StringSize); return Error::success(); } diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index e9124e6..334c5e0 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -50,7 +50,7 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( - std::unique_ptr Subsection, CodeViewContainer Container) + std::shared_ptr Subsection, CodeViewContainer Container) : Subsection(std::move(Subsection)), Container(Container) {} uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { diff --git a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index 8550107..9b82433 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -26,40 +26,9 @@ using namespace llvm; using namespace llvm::codeview; -DebugSubsectionState::DebugSubsectionState() {} - -DebugSubsectionState::DebugSubsectionState( - const DebugStringTableSubsectionRef &Strings) - : Strings(&Strings) {} - -DebugSubsectionState::DebugSubsectionState( - const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums) - : Strings(&Strings), Checksums(&Checksums) {} - -void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) { - assert(SR.kind() == DebugSubsectionKind::StringTable); - assert(!Strings && "Found a string table even though we already have one!"); - - OwnedStrings = llvm::make_unique(); - consumeError(OwnedStrings->initialize(SR.getRecordData())); - Strings = OwnedStrings.get(); -} - -void DebugSubsectionState::initializeChecksums( - const DebugSubsectionRecord &FCR) { - assert(FCR.kind() == DebugSubsectionKind::FileChecksums); - if (Checksums) - return; - - OwnedChecksums = llvm::make_unique(); - consumeError(OwnedChecksums->initialize(FCR.getRecordData())); - Checksums = OwnedChecksums.get(); -} - -Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, - DebugSubsectionVisitor &V, - const DebugSubsectionState &State) { +Error llvm::codeview::visitDebugSubsection( + const DebugSubsectionRecord &R, DebugSubsectionVisitor &V, + const StringsAndChecksumsRef &State) { BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { case DebugSubsectionKind::Lines: { diff --git a/lib/DebugInfo/CodeView/StringsAndChecksums.cpp b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp new file mode 100644 index 0000000..928bf8c --- /dev/null +++ b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp @@ -0,0 +1,55 @@ +//===- StringsAndChecksums.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" + +using namespace llvm; +using namespace llvm::codeview; + +StringsAndChecksumsRef::StringsAndChecksumsRef() {} + +StringsAndChecksumsRef::StringsAndChecksumsRef( + const DebugStringTableSubsectionRef &Strings) + : Strings(&Strings) {} + +StringsAndChecksumsRef::StringsAndChecksumsRef( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) + : Strings(&Strings), Checksums(&Checksums) {} + +void StringsAndChecksumsRef::initializeStrings( + const DebugSubsectionRecord &SR) { + assert(SR.kind() == DebugSubsectionKind::StringTable); + assert(!Strings && "Found a string table even though we already have one!"); + + OwnedStrings = llvm::make_unique(); + consumeError(OwnedStrings->initialize(SR.getRecordData())); + Strings = OwnedStrings.get(); +} + +void StringsAndChecksumsRef::setChecksums( + const DebugChecksumsSubsectionRef &CS) { + OwnedChecksums = llvm::make_unique(); + *OwnedChecksums = CS; + Checksums = OwnedChecksums.get(); +} + +void StringsAndChecksumsRef::initializeChecksums( + const DebugSubsectionRecord &FCR) { + assert(FCR.kind() == DebugSubsectionKind::FileChecksums); + if (Checksums) + return; + + OwnedChecksums = llvm::make_unique(); + consumeError(OwnedChecksums->initialize(FCR.getRecordData())); + Checksums = OwnedChecksums.get(); +} diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 6604593..36abafc 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -212,7 +212,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FileStatic) { DictScope S(W, "FileStatic"); - W.printNumber("Index", FileStatic.Index); + printTypeIndex("Index", FileStatic.Index); W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset); W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames()); W.printString("Name", FileStatic.Name); @@ -516,7 +516,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, RegisterSym &Register) { DictScope S(W, "RegisterSym"); - W.printNumber("Type", Register.Index); + printTypeIndex("Type", Register.Index); W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames()); W.printString("Name", Register.Name); return Error::success(); @@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { DictScope S(W, "PublicSym"); - W.printNumber("Type", Public.Index); + printTypeIndex("Type", Public.Index); W.printNumber("Seg", Public.Segment); W.printNumber("Off", Public.Offset); W.printString("Name", Public.Name); @@ -631,7 +631,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printHex("Offset", RegRel.Offset); printTypeIndex("Type", RegRel.Type); - W.printHex("Register", RegRel.Register); + W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames()); W.printString("VarName", RegRel.Name); return Error::success(); } diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index ea46841..d731dc1 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -307,7 +307,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, error(IO.mapInteger(FrameCookie.CodeOffset)); error(IO.mapInteger(FrameCookie.Register)); - error(IO.mapInteger(FrameCookie.CookieKind)); + error(IO.mapEnum(FrameCookie.CookieKind)); error(IO.mapInteger(FrameCookie.Flags)); return Error::success(); @@ -439,7 +439,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, error(IO.mapInteger(RegRel.Offset)); error(IO.mapInteger(RegRel.Type)); - error(IO.mapInteger(RegRel.Register)); + error(IO.mapEnum(RegRel.Register)); error(IO.mapStringZ(RegRel.Name)); return Error::success(); diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp index af05d2d..08f848b 100644 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ b/lib/DebugInfo/CodeView/TypeDatabase.cpp @@ -12,59 +12,6 @@ using namespace llvm; using namespace llvm::codeview; -namespace { -struct SimpleTypeEntry { - StringRef Name; - SimpleTypeKind Kind; -}; -} - -/// The names here all end in "*". If the simple type is a pointer type, we -/// return the whole name. Otherwise we lop off the last character in our -/// StringRef. -static const SimpleTypeEntry SimpleTypeNames[] = { - {"void*", SimpleTypeKind::Void}, - {"*", SimpleTypeKind::NotTranslated}, - {"HRESULT*", SimpleTypeKind::HResult}, - {"signed char*", SimpleTypeKind::SignedCharacter}, - {"unsigned char*", SimpleTypeKind::UnsignedCharacter}, - {"char*", SimpleTypeKind::NarrowCharacter}, - {"wchar_t*", SimpleTypeKind::WideCharacter}, - {"char16_t*", SimpleTypeKind::Character16}, - {"char32_t*", SimpleTypeKind::Character32}, - {"__int8*", SimpleTypeKind::SByte}, - {"unsigned __int8*", SimpleTypeKind::Byte}, - {"short*", SimpleTypeKind::Int16Short}, - {"unsigned short*", SimpleTypeKind::UInt16Short}, - {"__int16*", SimpleTypeKind::Int16}, - {"unsigned __int16*", SimpleTypeKind::UInt16}, - {"long*", SimpleTypeKind::Int32Long}, - {"unsigned long*", SimpleTypeKind::UInt32Long}, - {"int*", SimpleTypeKind::Int32}, - {"unsigned*", SimpleTypeKind::UInt32}, - {"__int64*", SimpleTypeKind::Int64Quad}, - {"unsigned __int64*", SimpleTypeKind::UInt64Quad}, - {"__int64*", SimpleTypeKind::Int64}, - {"unsigned __int64*", SimpleTypeKind::UInt64}, - {"__int128*", SimpleTypeKind::Int128}, - {"unsigned __int128*", SimpleTypeKind::UInt128}, - {"__half*", SimpleTypeKind::Float16}, - {"float*", SimpleTypeKind::Float32}, - {"float*", SimpleTypeKind::Float32PartialPrecision}, - {"__float48*", SimpleTypeKind::Float48}, - {"double*", SimpleTypeKind::Float64}, - {"long double*", SimpleTypeKind::Float80}, - {"__float128*", SimpleTypeKind::Float128}, - {"_Complex float*", SimpleTypeKind::Complex32}, - {"_Complex double*", SimpleTypeKind::Complex64}, - {"_Complex long double*", SimpleTypeKind::Complex80}, - {"_Complex __float128*", SimpleTypeKind::Complex128}, - {"bool*", SimpleTypeKind::Boolean8}, - {"__bool16*", SimpleTypeKind::Boolean16}, - {"__bool32*", SimpleTypeKind::Boolean32}, - {"__bool64*", SimpleTypeKind::Boolean64}, -}; - TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { CVUDTNames.resize(Capacity); TypeRecords.resize(Capacity); @@ -103,22 +50,8 @@ StringRef TypeDatabase::saveTypeName(StringRef TypeName) { } StringRef TypeDatabase::getTypeName(TypeIndex Index) const { - if (Index.isNoneType()) - return ""; - - if (Index.isSimple()) { - // This is a simple type. - for (const auto &SimpleTypeName : SimpleTypeNames) { - if (SimpleTypeName.Kind == Index.getSimpleKind()) { - if (Index.getSimpleMode() == SimpleTypeMode::Direct) - return SimpleTypeName.Name.drop_back(1); - // Otherwise, this is a pointer type. We gloss over the distinction - // between near, far, 64, 32, etc, and just give a pointer type. - return SimpleTypeName.Name; - } - } - return ""; - } + if (Index.isNoneType() || Index.isSimple()) + return TypeIndex::simpleTypeName(Index); if (contains(Index)) return CVUDTNames[Index.toArrayIndex()]; diff --git a/lib/DebugInfo/CodeView/TypeIndex.cpp b/lib/DebugInfo/CodeView/TypeIndex.cpp index 20ba647..24fe5fc 100644 --- a/lib/DebugInfo/CodeView/TypeIndex.cpp +++ b/lib/DebugInfo/CodeView/TypeIndex.cpp @@ -15,11 +15,88 @@ using namespace llvm; using namespace llvm::codeview; +namespace { +struct SimpleTypeEntry { + StringRef Name; + SimpleTypeKind Kind; +}; + +/// The names here all end in "*". If the simple type is a pointer type, we +/// return the whole name. Otherwise we lop off the last character in our +/// StringRef. +static const SimpleTypeEntry SimpleTypeNames[] = { + {"void*", SimpleTypeKind::Void}, + {"*", SimpleTypeKind::NotTranslated}, + {"HRESULT*", SimpleTypeKind::HResult}, + {"signed char*", SimpleTypeKind::SignedCharacter}, + {"unsigned char*", SimpleTypeKind::UnsignedCharacter}, + {"char*", SimpleTypeKind::NarrowCharacter}, + {"wchar_t*", SimpleTypeKind::WideCharacter}, + {"char16_t*", SimpleTypeKind::Character16}, + {"char32_t*", SimpleTypeKind::Character32}, + {"__int8*", SimpleTypeKind::SByte}, + {"unsigned __int8*", SimpleTypeKind::Byte}, + {"short*", SimpleTypeKind::Int16Short}, + {"unsigned short*", SimpleTypeKind::UInt16Short}, + {"__int16*", SimpleTypeKind::Int16}, + {"unsigned __int16*", SimpleTypeKind::UInt16}, + {"long*", SimpleTypeKind::Int32Long}, + {"unsigned long*", SimpleTypeKind::UInt32Long}, + {"int*", SimpleTypeKind::Int32}, + {"unsigned*", SimpleTypeKind::UInt32}, + {"__int64*", SimpleTypeKind::Int64Quad}, + {"unsigned __int64*", SimpleTypeKind::UInt64Quad}, + {"__int64*", SimpleTypeKind::Int64}, + {"unsigned __int64*", SimpleTypeKind::UInt64}, + {"__int128*", SimpleTypeKind::Int128}, + {"unsigned __int128*", SimpleTypeKind::UInt128}, + {"__half*", SimpleTypeKind::Float16}, + {"float*", SimpleTypeKind::Float32}, + {"float*", SimpleTypeKind::Float32PartialPrecision}, + {"__float48*", SimpleTypeKind::Float48}, + {"double*", SimpleTypeKind::Float64}, + {"long double*", SimpleTypeKind::Float80}, + {"__float128*", SimpleTypeKind::Float128}, + {"_Complex float*", SimpleTypeKind::Complex32}, + {"_Complex double*", SimpleTypeKind::Complex64}, + {"_Complex long double*", SimpleTypeKind::Complex80}, + {"_Complex __float128*", SimpleTypeKind::Complex128}, + {"bool*", SimpleTypeKind::Boolean8}, + {"__bool16*", SimpleTypeKind::Boolean16}, + {"__bool32*", SimpleTypeKind::Boolean32}, + {"__bool64*", SimpleTypeKind::Boolean64}, +}; +} // namespace + +StringRef TypeIndex::simpleTypeName(TypeIndex TI) { + assert(TI.isNoneType() || TI.isSimple()); + + if (TI.isNoneType()) + return ""; + + // This is a simple type. + for (const auto &SimpleTypeName : SimpleTypeNames) { + if (SimpleTypeName.Kind == TI.getSimpleKind()) { + if (TI.getSimpleMode() == SimpleTypeMode::Direct) + return SimpleTypeName.Name.drop_back(1); + // Otherwise, this is a pointer type. We gloss over the distinction + // between near, far, 64, 32, etc, and just give a pointer type. + return SimpleTypeName.Name; + } + } + return ""; +} + void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, TypeCollection &Types) { StringRef TypeName; - if (!TI.isNoneType()) - TypeName = Types.getTypeName(TI); + if (!TI.isNoneType()) { + if (TI.isSimple()) + TypeName = TypeIndex::simpleTypeName(TI); + else + TypeName = Types.getTypeName(TI); + } + if (!TypeName.empty()) Printer.printHex(FieldName, TypeName, TI.getIndex()); else diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index 11e2e21..8704cea 100644 --- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -34,7 +34,7 @@ static inline PointerMode getPointerMode(uint32_t Attrs) { static inline bool isMemberPointer(uint32_t Attrs) { PointerMode Mode = getPointerMode(Attrs); return Mode == PointerMode::PointerToDataMember || - Mode == PointerMode::PointerToDataMember; + Mode == PointerMode::PointerToMemberFunction; } static inline uint32_t getEncodedIntegerLength(ArrayRef Data) { diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 97b52f0..87009bf 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -55,6 +55,13 @@ bool DWARFAcceleratorTable::extract() { return true; } +uint32_t DWARFAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; } +uint32_t DWARFAcceleratorTable::getNumHashes() { return Hdr.NumHashes; } +uint32_t DWARFAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } +uint32_t DWARFAcceleratorTable::getHeaderDataLength() { + return Hdr.HeaderDataLength; +} + LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const { // Dump the header. OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n' diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 42ab488..9bafcde 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -425,248 +425,6 @@ DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) { return DWARFDie(); } -namespace { - -class Verifier { - raw_ostream &OS; - DWARFContext &DCtx; -public: - Verifier(raw_ostream &S, DWARFContext &D) : OS(S), DCtx(D) {} - - bool HandleDebugInfo() { - bool Success = true; - // A map that tracks all references (converted absolute references) so we - // can verify each reference points to a valid DIE and not an offset that - // lies between to valid DIEs. - std::map> ReferenceToDIEOffsets; - - OS << "Verifying .debug_info...\n"; - for (const auto &CU : DCtx.compile_units()) { - unsigned NumDies = CU->getNumDIEs(); - for (unsigned I = 0; I < NumDies; ++I) { - auto Die = CU->getDIEAtIndex(I); - const auto Tag = Die.getTag(); - if (Tag == DW_TAG_null) - continue; - for (auto AttrValue : Die.attributes()) { - const auto Attr = AttrValue.Attr; - const auto Form = AttrValue.Value.getForm(); - switch (Attr) { - case DW_AT_ranges: - // Make sure the offset in the DW_AT_ranges attribute is valid. - if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getRangeSection().Data.size()) { - Success = false; - OS << "error: DW_AT_ranges offset is beyond .debug_ranges " - "bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - } else { - Success = false; - OS << "error: DIE has invalid DW_AT_ranges encoding:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - case DW_AT_stmt_list: - // Make sure the offset in the DW_AT_stmt_list attribute is valid. - if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getLineSection().Data.size()) { - Success = false; - OS << "error: DW_AT_stmt_list offset is beyond .debug_line " - "bounds: " - << format("0x%08" PRIx32, *SectionOffset) << "\n"; - CU->getUnitDIE().dump(OS, 0); - OS << "\n"; - } - } else { - Success = false; - OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - - default: - break; - } - switch (Form) { - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: { - // Verify all CU relative references are valid CU offsets. - Optional RefVal = AttrValue.Value.getAsReference(); - assert(RefVal); - if (RefVal) { - auto DieCU = Die.getDwarfUnit(); - auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset(); - auto CUOffset = AttrValue.Value.getRawUValue(); - if (CUOffset >= CUSize) { - Success = false; - OS << "error: " << FormEncodingString(Form) << " CU offset " - << format("0x%08" PRIx32, CUOffset) - << " is invalid (must be less than CU size of " - << format("0x%08" PRIx32, CUSize) << "):\n"; - Die.dump(OS, 0); - OS << "\n"; - } else { - // Valid reference, but we will verify it points to an actual - // DIE later. - ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset()); - } - } - break; - } - case DW_FORM_ref_addr: { - // Verify all absolute DIE references have valid offsets in the - // .debug_info section. - Optional RefVal = AttrValue.Value.getAsReference(); - assert(RefVal); - if (RefVal) { - if(*RefVal >= DCtx.getInfoSection().Data.size()) { - Success = false; - OS << "error: DW_FORM_ref_addr offset beyond .debug_info " - "bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } else { - // Valid reference, but we will verify it points to an actual - // DIE later. - ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset()); - } - } - break; - } - case DW_FORM_strp: { - auto SecOffset = AttrValue.Value.getAsSectionOffset(); - assert(SecOffset); // DW_FORM_strp is a section offset. - if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) { - Success = false; - OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - } - default: - break; - } - } - } - } - - // Take all references and make sure they point to an actual DIE by - // getting the DIE by offset and emitting an error - OS << "Verifying .debug_info references...\n"; - for (auto Pair: ReferenceToDIEOffsets) { - auto Die = DCtx.getDIEForOffset(Pair.first); - if (Die) - continue; - Success = false; - OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first) - << ". Offset is in between DIEs:\n"; - for (auto Offset: Pair.second) { - auto ReferencingDie = DCtx.getDIEForOffset(Offset); - ReferencingDie.dump(OS, 0); - OS << "\n"; - } - OS << "\n"; - } - return Success; - } - - bool HandleDebugLine() { - std::map StmtListToDie; - bool Success = true; - OS << "Verifying .debug_line...\n"; - for (const auto &CU : DCtx.compile_units()) { - uint32_t LineTableOffset = 0; - auto CUDie = CU->getUnitDIE(); - auto StmtFormValue = CUDie.find(DW_AT_stmt_list); - if (!StmtFormValue) { - // No line table for this compile unit. - continue; - } - // Get the attribute value as a section offset. No need to produce an - // error here if the encoding isn't correct because we validate this in - // the .debug_info verifier. - if (auto StmtSectionOffset = toSectionOffset(StmtFormValue)) { - LineTableOffset = *StmtSectionOffset; - if (LineTableOffset >= DCtx.getLineSection().Data.size()) { - // Make sure we don't get a valid line table back if the offset - // is wrong. - assert(DCtx.getLineTableForUnit(CU.get()) == nullptr); - // Skip this line table as it isn't valid. No need to create an error - // here because we validate this in the .debug_info verifier. - continue; - } else { - auto Iter = StmtListToDie.find(LineTableOffset); - if (Iter != StmtListToDie.end()) { - Success = false; - OS << "error: two compile unit DIEs, " - << format("0x%08" PRIx32, Iter->second.getOffset()) << " and " - << format("0x%08" PRIx32, CUDie.getOffset()) - << ", have the same DW_AT_stmt_list section offset:\n"; - Iter->second.dump(OS, 0); - CUDie.dump(OS, 0); - OS << '\n'; - // Already verified this line table before, no need to do it again. - continue; - } - StmtListToDie[LineTableOffset] = CUDie; - } - } - auto LineTable = DCtx.getLineTableForUnit(CU.get()); - if (!LineTable) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "] was not able to be parsed for CU:\n"; - CUDie.dump(OS, 0); - OS << '\n'; - continue; - } - uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size(); - uint64_t PrevAddress = 0; - uint32_t RowIndex = 0; - for (const auto &Row : LineTable->Rows) { - if (Row.Address < PrevAddress) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "] row[" << RowIndex - << "] decreases in address from previous row:\n"; - - DWARFDebugLine::Row::dumpTableHeader(OS); - if (RowIndex > 0) - LineTable->Rows[RowIndex - 1].dump(OS); - Row.dump(OS); - OS << '\n'; - } - - if (Row.File > MaxFileIndex) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "][" << RowIndex << "] has invalid file index " << Row.File - << " (valid values are [1," << MaxFileIndex << "]):\n"; - DWARFDebugLine::Row::dumpTableHeader(OS); - Row.dump(OS); - OS << '\n'; - } - if (Row.EndSequence) - PrevAddress = 0; - else - PrevAddress = Row.Address; - ++RowIndex; - } - } - return Success; - } -}; - -} // anonymous namespace - bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) { bool Success = true; DWARFVerifier verifier(OS, *this); @@ -678,8 +436,13 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) { if (!verifier.handleDebugLine()) Success = false; } + if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) { + if (!verifier.handleAppleNames()) + Success = false; + } return Success; } + const DWARFUnitIndex &DWARFContext::getCUIndex() { if (CUIndex) return *CUIndex; @@ -1250,7 +1013,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, continue; RelSecName = RelSecName.substr( - RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. + RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index e6e0078..cf9fec2 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -514,6 +514,20 @@ static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, } } +// This is a workaround for old compilers which do not allow +// noreturn attribute usage in lambdas. Once the support for those +// compilers are phased out, we can remove this and return back to +// a ReportError lambda: [StartOffset](const char *ErrorMsg). +#define ReportError(ErrorMsg) ReportErrorImpl(StartOffset,ErrorMsg) +static void LLVM_ATTRIBUTE_NORETURN +ReportErrorImpl(uint32_t StartOffset, const char *ErrorMsg) { + std::string Str; + raw_string_ostream OS(Str); + OS << format(ErrorMsg, StartOffset); + OS.flush(); + report_fatal_error(Str); +} + void DWARFDebugFrame::parse(DataExtractor Data) { uint32_t Offset = 0; DenseMap CIEs; @@ -521,14 +535,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { while (Data.isValidOffset(Offset)) { uint32_t StartOffset = Offset; - auto ReportError = [StartOffset](const char *ErrorMsg) { - std::string Str; - raw_string_ostream OS(Str); - OS << format(ErrorMsg, StartOffset); - OS.flush(); - report_fatal_error(Str); - }; - bool IsDWARF64 = false; uint64_t Length = Data.getU32(&Offset); uint64_t Id; @@ -585,7 +591,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { switch (AugmentationString[i]) { default: ReportError("Unknown augmentation character in entry at %lx"); - llvm_unreachable("ReportError should not return."); case 'L': LSDAPointerEncoding = Data.getU8(&Offset); break; diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 8a54429..a6240fb 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -275,3 +276,36 @@ bool DWARFVerifier::handleDebugLine() { verifyDebugLineRows(); return NumDebugLineErrors == 0; } + +bool DWARFVerifier::handleAppleNames() { + NumAppleNamesErrors = 0; + OS << "Verifying .apple_names...\n"; + + DataExtractor AppleNamesSection(DCtx.getAppleNamesSection().Data, + DCtx.isLittleEndian(), 0); + DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0); + DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData, + DCtx.getAppleNamesSection().Relocs); + + if (!AppleNames.extract()) { + OS << "error: cannot extract .apple_names accelerator table\n"; + return false; + } + + // Verify that all buckets have a valid hash index or are empty + uint32_t NumBuckets = AppleNames.getNumBuckets(); + uint32_t NumHashes = AppleNames.getNumHashes(); + + uint32_t BucketsOffset = + AppleNames.getSizeHdr() + AppleNames.getHeaderDataLength(); + + for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) { + uint32_t HashIdx = AppleNamesSection.getU32(&BucketsOffset); + if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) { + OS << format("error: Bucket[%d] has invalid hash index: [%d]\n", + BucketIdx, HashIdx); + ++NumAppleNamesErrors; + } + } + return NumAppleNamesErrors == 0; +} diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 396dffa..81a9d3e 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -177,7 +177,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, } void DbiModuleDescriptorBuilder::addDebugSubsection( - std::unique_ptr Subsection) { + std::shared_ptr Subsection) { assert(Subsection); C13Builders.push_back(llvm::make_unique( std::move(Subsection), CodeViewContainer::Pdb)); diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 355c7b5..e7304b4 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -45,10 +45,6 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; } void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } -void DbiStreamBuilder::setSectionContribs(ArrayRef Arr) { - SectionContribs = Arr; -} - void DbiStreamBuilder::setSectionMap(ArrayRef SecMap) { SectionMap = SecMap; } @@ -293,23 +289,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) { return Ret; } -// A utility function to create Section Contributions -// for a given input sections. -std::vector DbiStreamBuilder::createSectionContribs( - ArrayRef SecHdrs) { - std::vector Ret; - - // Create a SectionContrib for each input section. - for (auto &Sec : SecHdrs) { - Ret.emplace_back(); - auto &Entry = Ret.back(); - memset(&Entry, 0, sizeof(Entry)); - - Entry.Off = Sec.PointerToRawData; - Entry.Size = Sec.SizeOfRawData; - Entry.Characteristics = Sec.Characteristics; - } - return Ret; +void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi, + const object::coff_section *SecHdr) { + SectionContrib SC; + memset(&SC, 0, sizeof(SC)); + SC.ISect = (uint16_t)~0U; // This represents nil. + SC.Off = SecHdr->PointerToRawData; + SC.Size = SecHdr->SizeOfRawData; + SC.Characteristics = SecHdr->Characteristics; + // Use the module index in the module dbi stream or nil (-1). + SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U; + SectionContribs.emplace_back(SC); } // A utility function to create a Section Map for a given list of COFF sections. @@ -372,7 +362,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (!SectionContribs.empty()) { if (auto EC = Writer.writeEnum(DbiSecContribVer60)) return EC; - if (auto EC = Writer.writeArray(SectionContribs)) + if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs))) return EC; } diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp index 7c60696..a3979d4 100644 --- a/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -102,6 +102,10 @@ InfoStream::named_streams() const { return NamedStreams.entries(); } +bool InfoStream::containsIdStream() const { + return !!(Features & PdbFeatureContainsIdStream); +} + PdbRaw_ImplVer InfoStream::getVersion() const { return static_cast(Version); } diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 1254e23..a9597cd 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -363,6 +363,16 @@ Expected PDBFile::getStringTable() { return *Strings; } +uint32_t PDBFile::getPointerSize() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) + return 0; + PDB_Machine Machine = DbiS->getMachineType(); + if (Machine == PDB_Machine::Amd64) + return 8; + return 4; +} + bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); } bool PDBFile::hasPDBGlobalsStream() { diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 2c6465e..12b0c3b 100644 --- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -80,6 +80,16 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { } Expected PDBFileBuilder::finalizeMsfLayout() { + + if (Ipi && Ipi->getRecordCount() > 0) { + // In theory newer PDBs always have an ID stream, but by saying that we're + // only going to *really* have an ID stream if there is at least one ID + // record, we leave open the opportunity to test older PDBs such as those + // that don't have an ID stream. + auto &Info = getInfoBuilder(); + Info.addFeature(PdbRaw_FeatureSig::VC140); + } + uint32_t StringsLen = Strings.calculateSerializedSize(); if (auto EC = addNamedStream("/names", StringsLen)) diff --git a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index 6013c34..f9f8ac2 100644 --- a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -56,7 +56,8 @@ Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { return Error::success(); } -codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const { +const codeview::DebugStringTableSubsectionRef & +PDBStringTable::getStringTable() const { return Strings; } diff --git a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index a472181..90acfad 100644 --- a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -52,6 +52,11 @@ uint32_t PDBStringTableBuilder::calculateSerializedSize() const { return Size; } +void PDBStringTableBuilder::setStrings( + const codeview::DebugStringTableSubsection &Strings) { + this->Strings = Strings; +} + Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const { // Write a header PDBStringTableHeader H; diff --git a/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/lib/DebugInfo/PDB/Native/PublicsStream.cpp index 091ac67..8f3474b 100644 --- a/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -130,4 +130,13 @@ PublicsStream::getSymbols(bool *HadError) const { return SS.getSymbols(HadError); } +Expected +PublicsStream::getSymbolArray() const { + auto SymbolS = Pdb.getPDBSymbolStream(); + if (!SymbolS) + return SymbolS.takeError(); + + return SymbolS->getSymbolArray(); +} + Error PublicsStream::commit() { return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp index 16904a5..91b8d64 100644 --- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp +++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" diff --git a/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp index aacefae..da353cb 100644 --- a/lib/DebugInfo/PDB/UDTLayout.cpp +++ b/lib/DebugInfo/PDB/UDTLayout.cpp @@ -181,13 +181,14 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { if (Data->getDataKind() == PDB_DataKind::Member) Members.push_back(std::move(Data)); else - Other.push_back(std::move(Child)); + Other.push_back(std::move(Data)); } else if (auto VT = unique_dyn_cast(Child)) VTables.push_back(std::move(VT)); else if (auto Func = unique_dyn_cast(Child)) Funcs.push_back(std::move(Func)); - else + else { Other.push_back(std::move(Child)); + } } // We don't want to have any re-allocations in the list of bases, so make diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp index 9aad377..0453a7f 100644 --- a/lib/Fuzzer/FuzzerDriver.cpp +++ b/lib/Fuzzer/FuzzerDriver.cpp @@ -553,12 +553,12 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); const size_t kMaxSaneLen = 1 << 20; - const size_t kMinDefaultLen = 64; + const size_t kMinDefaultLen = 4096; FuzzingOptions Options; Options.Verbosity = Flags.verbosity; Options.MaxLen = Flags.max_len; Options.ExperimentalLenControl = Flags.experimental_len_control; - if (Flags.experimental_len_control && Flags.max_len == 64) + if (Flags.experimental_len_control && Flags.max_len == kMinDefaultLen) Options.MaxLen = 1 << 20; Options.UnitTimeoutSec = Flags.timeout; Options.ErrorExitCode = Flags.error_exitcode; diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp index f608328..fbf1835 100644 --- a/lib/Fuzzer/FuzzerLoop.cpp +++ b/lib/Fuzzer/FuzzerLoop.cpp @@ -301,7 +301,9 @@ void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { this->MaxInputLen = MaxInputLen; this->MaxMutationLen = MaxInputLen; AllocateCurrentUnitData(); - Printf("INFO: -max_len is not provided, using %zd\n", MaxInputLen); + Printf("INFO: -max_len is not provided; " + "libFuzzer will not generate inputs larger than %zd bytes\n", + MaxInputLen); } void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { diff --git a/lib/Fuzzer/FuzzerTracePC.cpp b/lib/Fuzzer/FuzzerTracePC.cpp index ea93468..6f5c7be 100644 --- a/lib/Fuzzer/FuzzerTracePC.cpp +++ b/lib/Fuzzer/FuzzerTracePC.cpp @@ -53,6 +53,17 @@ size_t TracePC::GetTotalPCCoverage() { return Res; } + +void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { + if (Start == Stop) return; + if (NumModulesWithInline8bitCounters && + ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return; + assert(NumModulesWithInline8bitCounters < + sizeof(ModuleCounters) / sizeof(ModuleCounters[0])); + ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop}; + NumInline8bitCounters += Stop - Start; +} + void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) { if (Start == Stop || *Start) return; assert(NumModules < sizeof(Modules) / sizeof(Modules[0])); @@ -76,6 +87,13 @@ void TracePC::PrintModuleInfo() { for (size_t i = 0; i < NumModules; i++) Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop); Printf("\n"); + if (NumModulesWithInline8bitCounters) { + Printf("INFO: Loaded %zd modules with %zd inline 8-bit counters\n", + NumModulesWithInline8bitCounters, NumInline8bitCounters); + for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) + Printf("[%p, %p), ", ModuleCounters[i].Start, ModuleCounters[i].Stop); + Printf("\n"); + } } ATTRIBUTE_NO_SANITIZE_ALL @@ -304,6 +322,11 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { } ATTRIBUTE_INTERFACE +void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) { + fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop); +} + +ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_ALL void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { uintptr_t PC = reinterpret_cast(__builtin_return_address(0)); diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h index 6523fa0..5ec8c59 100644 --- a/lib/Fuzzer/FuzzerTracePC.h +++ b/lib/Fuzzer/FuzzerTracePC.h @@ -51,7 +51,8 @@ class TracePC { // How many bits of PC are used from __sanitizer_cov_trace_pc. static const size_t kTracePcBits = 18; - void HandleInit(uint32_t *start, uint32_t *stop); + void HandleInit(uint32_t *Start, uint32_t *Stop); + void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop); void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); template void HandleCmp(uintptr_t PC, T Arg1, T Arg2); size_t GetTotalPCCoverage(); @@ -104,6 +105,10 @@ private: size_t NumModules; // linker-initialized. size_t NumGuards; // linker-initialized. + struct { uint8_t *Start, *Stop; } ModuleCounters[4096]; + size_t NumModulesWithInline8bitCounters; // linker-initialized. + size_t NumInline8bitCounters; + uint8_t *Counters() const; uintptr_t *PCs() const; @@ -118,12 +123,24 @@ void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End, size_t FirstFeature, Callback Handle8bitCounter) { typedef uintptr_t LargeType; const size_t Step = sizeof(LargeType) / sizeof(uint8_t); - assert(!(reinterpret_cast(Begin) % 64)); - for (auto P = Begin; P < End; P += Step) + const size_t StepMask = Step - 1; + auto P = Begin; + // Iterate by 1 byte until either the alignment boundary or the end. + for (; reinterpret_cast(P) & StepMask && P < End; P++) + if (uint8_t V = *P) + Handle8bitCounter(FirstFeature + P - Begin, V); + + // Iterate by Step bytes at a time. + for (; P < End; P += Step) if (LargeType Bundle = *reinterpret_cast(P)) for (size_t I = 0; I < Step; I++, Bundle >>= 8) if (uint8_t V = Bundle & 0xff) Handle8bitCounter(FirstFeature + P - Begin + I, V); + + // Iterate by 1 byte until the end. + for (; P < End; P++) + if (uint8_t V = *P) + Handle8bitCounter(FirstFeature + P - Begin, V); } template // bool Callback(size_t Feature) @@ -145,8 +162,16 @@ void TracePC::CollectFeatures(Callback HandleFeature) const { HandleFeature(Idx * 8 + Bit); }; - ForEachNonZeroByte(Counters, Counters + N, 0, Handle8bitCounter); - ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), N * 8, + size_t FirstFeature = 0; + ForEachNonZeroByte(Counters, Counters + N, FirstFeature, Handle8bitCounter); + FirstFeature += N * 8; + for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { + ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop, + FirstFeature, Handle8bitCounter); + FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start); + } + + ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature, Handle8bitCounter); if (UseValueProfile) diff --git a/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp b/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp index dfb6007..b5a61dd 100644 --- a/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp +++ b/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp @@ -9,7 +9,7 @@ #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size < 16) return 0; + if (Size < 16 || Size > 64) return 0; int64_t x; uint64_t y; memcpy(&x, Data, sizeof(x)); diff --git a/lib/Fuzzer/test/CMakeLists.txt b/lib/Fuzzer/test/CMakeLists.txt index b39938a..1cf6c95 100644 --- a/lib/Fuzzer/test/CMakeLists.txt +++ b/lib/Fuzzer/test/CMakeLists.txt @@ -206,6 +206,9 @@ include_directories(..) add_subdirectory(no-coverage) add_subdirectory(trace-pc) add_subdirectory(ubsan) +if (NOT MSVC) + add_subdirectory(inline-8bit-counters) +endif() add_library(LLVMFuzzer-DSO1 SHARED DSO1.cpp) add_library(LLVMFuzzer-DSO2 SHARED DSO2.cpp) diff --git a/lib/Fuzzer/test/FourIndependentBranchesTest.cpp b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp index bbf5ea2..ba963d9 100644 --- a/lib/Fuzzer/test/FourIndependentBranchesTest.cpp +++ b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp @@ -8,6 +8,7 @@ #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 64) return 0; int bits = 0; if (Size > 0 && Data[0] == 'F') bits |= 1; if (Size > 1 && Data[1] == 'U') bits |= 2; diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp index c8beb43..812894f 100644 --- a/lib/Fuzzer/test/FuzzerUnittest.cpp +++ b/lib/Fuzzer/test/FuzzerUnittest.cpp @@ -772,4 +772,16 @@ TEST(Fuzzer, ForEachNonZeroByte) { Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4}, {135, 5}, {137, 6}, {146, 7}, {163, 8}}; EXPECT_EQ(Res, Expected); + + Res.clear(); + ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB); + Expected = { {109, 2}, {118, 3}, {120, 4}, + {135, 5}, {137, 6}, {146, 7}, {163, 8}}; + EXPECT_EQ(Res, Expected); + + Res.clear(); + ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB); + Expected = { {109, 2}, {118, 3}, {120, 4}, + {135, 5}, {137, 6}, {146, 7}}; + EXPECT_EQ(Res, Expected); } diff --git a/lib/Fuzzer/test/ShrinkControlFlowTest.cpp b/lib/Fuzzer/test/ShrinkControlFlowTest.cpp index d095429..37eeede 100644 --- a/lib/Fuzzer/test/ShrinkControlFlowTest.cpp +++ b/lib/Fuzzer/test/ShrinkControlFlowTest.cpp @@ -11,6 +11,7 @@ static volatile int Sink; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 64) return 0; int8_t Ids[256]; memset(Ids, -1, sizeof(Ids)); for (size_t i = 0; i < Size; i++) diff --git a/lib/Fuzzer/test/SimpleHashTest.cpp b/lib/Fuzzer/test/SimpleHashTest.cpp index 99e96cb..a3f4211 100644 --- a/lib/Fuzzer/test/SimpleHashTest.cpp +++ b/lib/Fuzzer/test/SimpleHashTest.cpp @@ -26,7 +26,7 @@ static uint32_t simple_hash(const uint8_t *Data, size_t Size) { } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size < 14) + if (Size < 14 || Size > 64) return 0; uint32_t Hash = simple_hash(&Data[0], Size - 4); diff --git a/lib/Fuzzer/test/SingleStrncmpTest.cpp b/lib/Fuzzer/test/SingleStrncmpTest.cpp index b302670..b38c799 100644 --- a/lib/Fuzzer/test/SingleStrncmpTest.cpp +++ b/lib/Fuzzer/test/SingleStrncmpTest.cpp @@ -8,6 +8,7 @@ #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size > 64) return 0; char *S = (char*)Data; volatile auto Strncmp = &(strncmp); // Make sure strncmp is not inlined. if (Size >= 6 && !Strncmp(S, "qwerty", 6)) { diff --git a/lib/Fuzzer/test/TableLookupTest.cpp b/lib/Fuzzer/test/TableLookupTest.cpp index 8126eea..4d8ab06 100644 --- a/lib/Fuzzer/test/TableLookupTest.cpp +++ b/lib/Fuzzer/test/TableLookupTest.cpp @@ -15,7 +15,6 @@ const size_t N = 1 << 12; // Define an array of counters that will be understood by libFuzzer // as extra coverage signal. The array must be: // * uint8_t -// * aligned by 64 // * in the section named __libfuzzer_extra_counters. // The target code may declare more than one such array. // @@ -23,7 +22,7 @@ const size_t N = 1 << 12; // depending on whether multiple occurrences of the event 'Idx' // is important to distinguish from one occurrence. #ifdef __linux__ -alignas(64) __attribute__((section("__libfuzzer_extra_counters"))) +__attribute__((section("__libfuzzer_extra_counters"))) #endif static uint8_t Counters[N]; diff --git a/lib/Fuzzer/test/fuzzer-dirs.test b/lib/Fuzzer/test/fuzzer-dirs.test index 3de64f2..622ff5d 100644 --- a/lib/Fuzzer/test/fuzzer-dirs.test +++ b/lib/Fuzzer/test/fuzzer-dirs.test @@ -5,9 +5,13 @@ RUN: echo b > %t/SUB1/SUB2/b RUN: echo c > %t/SUB1/SUB2/SUB3/c RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS SUBDIRS: READ units: 3 -RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/long +RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/f64 +RUN: cat %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 > %t/SUB1/f256 +RUN: cat %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 > %t/SUB1/f1024 +RUN: cat %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 > %t/SUB1/f4096 +RUN: cat %t/SUB1/f4096 %t/SUB1/f4096 > %t/SUB1/f8192 RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG -LONG: INFO: -max_len is not provided, using 93 +LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes RUN: rm -rf %t/SUB1 RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR diff --git a/lib/Fuzzer/test/inline-8bit-counters.test b/lib/Fuzzer/test/inline-8bit-counters.test new file mode 100644 index 0000000..8747af8 --- /dev/null +++ b/lib/Fuzzer/test/inline-8bit-counters.test @@ -0,0 +1,4 @@ +REQUIRES: linux +CHECK: INFO: Loaded 1 modules with {{.*}} inline 8-bit counters +CHECK: BINGO +RUN: LLVMFuzzer-SimpleTest-Inline8bitCounters -runs=1000000 -seed=1 2>&1 | FileCheck %s diff --git a/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt b/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt new file mode 100644 index 0000000..088ab04 --- /dev/null +++ b/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt @@ -0,0 +1,12 @@ +# These tests are instrumented with -fsanitize-coverage=inline-8bit-counters + +set(CMAKE_CXX_FLAGS + "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=trace-pc-guard -fsanitize-coverage=inline-8bit-counters") + +set(Inline8bitCounterTests + SimpleTest + ) + +foreach(Test ${Inline8bitCounterTests}) + add_libfuzzer_test(${Test}-Inline8bitCounters SOURCES ../${Test}.cpp) +endforeach() diff --git a/lib/Fuzzer/test/trace-pc/CMakeLists.txt b/lib/Fuzzer/test/trace-pc/CMakeLists.txt index e800f82..572fcc9 100644 --- a/lib/Fuzzer/test/trace-pc/CMakeLists.txt +++ b/lib/Fuzzer/test/trace-pc/CMakeLists.txt @@ -1,5 +1,4 @@ -# These tests are not instrumented with coverage and don't -# have coverage rt in the binary. +# These tests are instrumented with -fsanitize-coverage=trace-pc set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc") diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index a20f3f8..3469026 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -348,8 +348,7 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart, /// factors factored out. If Folded is false, return null if no factoring was /// possible, to avoid endlessly bouncing an unfoldable expression back into the /// top-level folder. -static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, - bool Folded) { +static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) { if (ArrayType *ATy = dyn_cast(Ty)) { Constant *N = ConstantInt::get(DestTy, ATy->getNumElements()); Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true); @@ -404,8 +403,7 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, /// factors factored out. If Folded is false, return null if no factoring was /// possible, to avoid endlessly bouncing an unfoldable expression back into the /// top-level folder. -static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, - bool Folded) { +static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, bool Folded) { // The alignment of an array is equal to the alignment of the // array element. Note that this is not always true for vectors. if (ArrayType *ATy = dyn_cast(Ty)) { @@ -469,8 +467,7 @@ static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, /// any known factors factored out. If Folded is false, return null if no /// factoring was possible, to avoid endlessly bouncing an unfoldable expression /// back into the top-level folder. -static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, - Type *DestTy, +static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, Type *DestTy, bool Folded) { if (ArrayType *ATy = dyn_cast(Ty)) { Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false, diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h index 6c189cf..6585304 100644 --- a/lib/IR/ConstantsContext.h +++ b/lib/IR/ConstantsContext.h @@ -55,8 +55,6 @@ public: return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -77,8 +75,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -99,8 +95,6 @@ public: return User::operator new(s, 3); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -122,8 +116,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -146,8 +138,6 @@ public: return User::operator new(s, 3); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -173,8 +163,6 @@ public: return User::operator new(s, 3); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; @@ -196,8 +184,6 @@ public: return User::operator new(s, 1); } - void *operator new(size_t, unsigned) = delete; - /// Indices - These identify which value to extract. const SmallVector Indices; @@ -230,8 +216,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Indices - These identify the position for the insertion. const SmallVector Indices; @@ -297,8 +281,6 @@ public: return User::operator new(s, 2); } - void *operator new(size_t, unsigned) = delete; - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index e6c49ca..0bf68b4 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -598,8 +598,7 @@ unsigned DIExpression::ExprOperand::getSize() const { case dwarf::DW_OP_LLVM_fragment: return 3; case dwarf::DW_OP_constu: - case dwarf::DW_OP_plus: - case dwarf::DW_OP_minus: + case dwarf::DW_OP_plus_uconst: return 2; default: return 1; @@ -641,6 +640,7 @@ bool DIExpression::isValid() const { break; } case dwarf::DW_OP_constu: + case dwarf::DW_OP_plus_uconst: case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: case dwarf::DW_OP_deref: @@ -664,11 +664,12 @@ DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) { void DIExpression::appendOffset(SmallVectorImpl &Ops, int64_t Offset) { if (Offset > 0) { - Ops.push_back(dwarf::DW_OP_plus); + Ops.push_back(dwarf::DW_OP_plus_uconst); Ops.push_back(Offset); } else if (Offset < 0) { - Ops.push_back(dwarf::DW_OP_minus); + Ops.push_back(dwarf::DW_OP_constu); Ops.push_back(-Offset); + Ops.push_back(dwarf::DW_OP_minus); } } @@ -677,16 +678,23 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const { Offset = 0; return true; } - if (getNumElements() != 2) - return false; - if (Elements[0] == dwarf::DW_OP_plus) { + + if (getNumElements() == 2 && Elements[0] == dwarf::DW_OP_plus_uconst) { Offset = Elements[1]; return true; } - if (Elements[0] == dwarf::DW_OP_minus) { - Offset = -Elements[1]; - return true; + + if (getNumElements() == 3 && Elements[0] == dwarf::DW_OP_constu) { + if (Elements[2] == dwarf::DW_OP_plus) { + Offset = Elements[1]; + return true; + } + if (Elements[2] == dwarf::DW_OP_minus) { + Offset = -Elements[1]; + return true; + } } + return false; } diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 81b0294..b7fa07c 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -134,18 +134,17 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, return CI; } -CallInst *IRBuilderBase::CreateElementAtomicMemCpy( - Value *Dst, Value *Src, Value *NumElements, uint32_t ElementSize, - MDNode *TBAATag, MDNode *TBAAStructTag, MDNode *ScopeTag, - MDNode *NoAliasTag) { +CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( + Value *Dst, Value *Src, Value *Size, uint32_t ElementSize, MDNode *TBAATag, + MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); - Value *Ops[] = {Dst, Src, NumElements, getInt32(ElementSize)}; - Type *Tys[] = {Dst->getType(), Src->getType()}; + Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)}; + Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()}; Module *M = BB->getParent()->getParent(); - Value *TheFn = - Intrinsic::getDeclaration(M, Intrinsic::memcpy_element_atomic, Tys); + Value *TheFn = Intrinsic::getDeclaration( + M, Intrinsic::memcpy_element_unordered_atomic, Tys); CallInst *CI = createCallHelper(TheFn, Ops, this); diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 0b1bc9a..92e5798 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -1470,7 +1470,7 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) { if (E) OrigElements = E->getElements(); std::vector Elements(OrigElements.size() + 2); - Elements[0] = dwarf::DW_OP_plus; + Elements[0] = dwarf::DW_OP_plus_uconst; Elements[1] = Offset; std::copy(OrigElements.begin(), OrigElements.end(), Elements.begin() + 2); E = DIExpression::get(getContext(), Elements); diff --git a/lib/IR/ModuleSummaryIndex.cpp b/lib/IR/ModuleSummaryIndex.cpp index 9dd712f..51c4bae 100644 --- a/lib/IR/ModuleSummaryIndex.cpp +++ b/lib/IR/ModuleSummaryIndex.cpp @@ -56,3 +56,16 @@ ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID, auto &Summary = VI.getSummaryList()[0]; return Summary.get(); } + +bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const { + auto VI = getValueInfo(GUID); + if (!VI) + return true; + const auto &SummaryList = VI.getSummaryList(); + if (SummaryList.empty()) + return true; + for (auto &I : SummaryList) + if (isGlobalValueLive(I.get())) + return true; + return false; +} diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 5c1b341..819f635 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -1330,6 +1330,14 @@ Verifier::visitModuleFlag(const MDNode *Op, = mdconst::dyn_extract_or_null(Op->getOperand(2)); Assert(Value, "wchar_size metadata requires constant integer argument"); } + + if (ID->getString() == "Linker Options") { + // If the llvm.linker.options named metadata exists, we assume that the + // bitcode reader has upgraded the module flag. Otherwise the flag might + // have been created by a client directly. + Assert(M.getNamedMetadata("llvm.linker.options"), + "'Linker Options' named metadata no longer supported"); + } } /// Return true if this attribute kind only applies to functions. @@ -4004,10 +4012,16 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { CS); break; } - case Intrinsic::memcpy_element_atomic: { - ConstantInt *ElementSizeCI = dyn_cast(CS.getArgOperand(3)); - Assert(ElementSizeCI, "element size of the element-wise atomic memory " - "intrinsic must be a constant int", + case Intrinsic::memcpy_element_unordered_atomic: { + const ElementUnorderedAtomicMemCpyInst *MI = + cast(CS.getInstruction()); + ; + + ConstantInt *ElementSizeCI = + dyn_cast(MI->getRawElementSizeInBytes()); + Assert(ElementSizeCI, + "element size of the element-wise unordered atomic memory " + "intrinsic must be a constant int", CS); const APInt &ElementSizeVal = ElementSizeCI->getValue(); Assert(ElementSizeVal.isPowerOf2(), @@ -4015,19 +4029,24 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) { "must be a power of 2", CS); + if (auto *LengthCI = dyn_cast(MI->getLength())) { + uint64_t Length = LengthCI->getZExtValue(); + uint64_t ElementSize = MI->getElementSizeInBytes(); + Assert((Length % ElementSize) == 0, + "constant length must be a multiple of the element size in the " + "element-wise atomic memory intrinsic", + CS); + } + auto IsValidAlignment = [&](uint64_t Alignment) { return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment); }; - uint64_t DstAlignment = CS.getParamAlignment(0), SrcAlignment = CS.getParamAlignment(1); - Assert(IsValidAlignment(DstAlignment), - "incorrect alignment of the destination argument", - CS); + "incorrect alignment of the destination argument", CS); Assert(IsValidAlignment(SrcAlignment), - "incorrect alignment of the source argument", - CS); + "incorrect alignment of the source argument", CS); break; } case Intrinsic::gcroot: diff --git a/lib/LLVMBuild.txt b/lib/LLVMBuild.txt index 9e58646..1d22c2a 100644 --- a/lib/LLVMBuild.txt +++ b/lib/LLVMBuild.txt @@ -39,6 +39,7 @@ subdirectories = Support TableGen Target + Testing ToolDrivers Transforms diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp index 9d2a440..35032fd 100644 --- a/lib/LTO/LTO.cpp +++ b/lib/LTO/LTO.cpp @@ -364,31 +364,40 @@ LTO::LTO(Config Conf, ThinBackend Backend, // Requires a destructor for MapVector. LTO::~LTO() = default; -// Add the given symbol to the GlobalResolutions map, and resolve its partition. -void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym, - SymbolResolution Res, unsigned Partition) { - auto &GlobalRes = GlobalResolutions[Sym.getName()]; - GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr(); - if (Res.Prevailing) - GlobalRes.IRName = Sym.getIRName(); - - // Set the partition to external if we know it is re-defined by the linker - // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a - // regular object, is referenced from llvm.compiler_used, or was already - // recorded as being referenced from a different partition. - if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || - (GlobalRes.Partition != GlobalResolution::Unknown && - GlobalRes.Partition != Partition)) { - GlobalRes.Partition = GlobalResolution::External; - } else - // First recorded reference, save the current partition. - GlobalRes.Partition = Partition; - - // Flag as visible outside of ThinLTO if visible from a regular object or - // if this is a reference in the regular LTO partition. - GlobalRes.VisibleOutsideThinLTO |= - (Res.VisibleToRegularObj || Sym.isUsed() || - Partition == GlobalResolution::RegularLTO); +// Add the symbols in the given module to the GlobalResolutions map, and resolve +// their partitions. +void LTO::addModuleToGlobalRes(ArrayRef Syms, + ArrayRef Res, + unsigned Partition, bool InSummary) { + auto *ResI = Res.begin(); + auto *ResE = Res.end(); + (void)ResE; + for (const InputFile::Symbol &Sym : Syms) { + assert(ResI != ResE); + SymbolResolution Res = *ResI++; + + auto &GlobalRes = GlobalResolutions[Sym.getName()]; + GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr(); + if (Res.Prevailing) + GlobalRes.IRName = Sym.getIRName(); + + // Set the partition to external if we know it is re-defined by the linker + // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a + // regular object, is referenced from llvm.compiler_used, or was already + // recorded as being referenced from a different partition. + if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || + (GlobalRes.Partition != GlobalResolution::Unknown && + GlobalRes.Partition != Partition)) { + GlobalRes.Partition = GlobalResolution::External; + } else + // First recorded reference, save the current partition. + GlobalRes.Partition = Partition; + + // Flag as visible outside of summary if visible from a regular object or + // from a module that does not have a summary. + GlobalRes.VisibleOutsideSummary |= + (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary); + } } static void writeToResolutionFile(raw_ostream &OS, InputFile *Input, @@ -434,46 +443,61 @@ Error LTO::add(std::unique_ptr Input, Error LTO::addModule(InputFile &Input, unsigned ModI, const SymbolResolution *&ResI, const SymbolResolution *ResE) { - Expected HasThinLTOSummary = Input.Mods[ModI].hasSummary(); - if (!HasThinLTOSummary) - return HasThinLTOSummary.takeError(); + Expected LTOInfo = Input.Mods[ModI].getLTOInfo(); + if (!LTOInfo) + return LTOInfo.takeError(); + BitcodeModule BM = Input.Mods[ModI]; auto ModSyms = Input.module_symbols(ModI); - if (*HasThinLTOSummary) - return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE); - else - return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE); + addModuleToGlobalRes(ModSyms, {ResI, ResE}, + LTOInfo->IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0, + LTOInfo->HasSummary); + + if (LTOInfo->IsThinLTO) + return addThinLTO(BM, ModSyms, ResI, ResE); + + Expected ModOrErr = + addRegularLTO(BM, ModSyms, ResI, ResE); + if (!ModOrErr) + return ModOrErr.takeError(); + + if (!LTOInfo->HasSummary) + return linkRegularLTO(std::move(*ModOrErr), /*LivenessFromIndex=*/false); + + // Regular LTO module summaries are added to a dummy module that represents + // the combined regular LTO module. + if (Error Err = BM.readSummary(ThinLTO.CombinedIndex, "", -1ull)) + return Err; + RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr)); + return Error::success(); } // Add a regular LTO object to the link. -Error LTO::addRegularLTO(BitcodeModule BM, - ArrayRef Syms, - const SymbolResolution *&ResI, - const SymbolResolution *ResE) { - if (!RegularLTO.CombinedModule) { - RegularLTO.CombinedModule = - llvm::make_unique("ld-temp.o", RegularLTO.Ctx); - RegularLTO.Mover = llvm::make_unique(*RegularLTO.CombinedModule); - } +// The resulting module needs to be linked into the combined LTO module with +// linkRegularLTO. +Expected +LTO::addRegularLTO(BitcodeModule BM, ArrayRef Syms, + const SymbolResolution *&ResI, + const SymbolResolution *ResE) { + RegularLTOState::AddedModule Mod; Expected> MOrErr = BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true, /*IsImporting*/ false); if (!MOrErr) return MOrErr.takeError(); - Module &M = **MOrErr; + Mod.M = std::move(*MOrErr); + if (Error Err = M.materializeMetadata()) - return Err; + return std::move(Err); UpgradeDebugInfo(M); ModuleSymbolTable SymTab; SymTab.addModule(&M); - std::vector Keep; - for (GlobalVariable &GV : M.globals()) if (GV.hasAppendingLinkage()) - Keep.push_back(&GV); + Mod.Keep.push_back(&GV); DenseSet AliasedGlobals; for (auto &GA : M.aliases()) @@ -502,7 +526,6 @@ Error LTO::addRegularLTO(BitcodeModule BM, for (const InputFile::Symbol &Sym : Syms) { assert(ResI != ResE); SymbolResolution Res = *ResI++; - addSymbolToGlobalRes(Sym, Res, 0); assert(MsymI != MsymE); ModuleSymbolTable::Symbol Msym = *MsymI++; @@ -512,7 +535,7 @@ Error LTO::addRegularLTO(BitcodeModule BM, if (Res.Prevailing) { if (Sym.isUndefined()) continue; - Keep.push_back(GV); + Mod.Keep.push_back(GV); // For symbols re-defined with linker -wrap and -defsym options, // set the linkage to weak to inhibit IPO. The linkage will be // restored by the linker. @@ -527,17 +550,14 @@ Error LTO::addRegularLTO(BitcodeModule BM, (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() || GV->hasAvailableExternallyLinkage()) && !AliasedGlobals.count(cast(GV))) { - // Either of the above three types of linkage indicates that the + // Any of the above three types of linkage indicates that the // chosen prevailing symbol will have the same semantics as this copy of - // the symbol, so we can link it with available_externally linkage. We - // only need to do this if the symbol is undefined. - GlobalValue *CombinedGV = - RegularLTO.CombinedModule->getNamedValue(GV->getName()); - if (!CombinedGV || CombinedGV->isDeclaration()) { - Keep.push_back(GV); - GV->setLinkage(GlobalValue::AvailableExternallyLinkage); - cast(GV)->setComdat(nullptr); - } + // the symbol, so we may be able to link it with available_externally + // linkage. We will decide later whether to do that when we link this + // module (in linkRegularLTO), based on whether it is undefined. + Mod.Keep.push_back(GV); + GV->setLinkage(GlobalValue::AvailableExternallyLinkage); + cast(GV)->setComdat(nullptr); } } // Common resolution: collect the maximum size/alignment over all commons. @@ -555,25 +575,54 @@ Error LTO::addRegularLTO(BitcodeModule BM, // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit. } assert(MsymI == MsymE); + return std::move(Mod); +} + +Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod, + bool LivenessFromIndex) { + if (!RegularLTO.CombinedModule) { + RegularLTO.CombinedModule = + llvm::make_unique("ld-temp.o", RegularLTO.Ctx); + RegularLTO.Mover = llvm::make_unique(*RegularLTO.CombinedModule); + } + + std::vector Keep; + for (GlobalValue *GV : Mod.Keep) { + if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) + continue; - return RegularLTO.Mover->move(std::move(*MOrErr), Keep, + if (!GV->hasAvailableExternallyLinkage()) { + Keep.push_back(GV); + continue; + } + + // Only link available_externally definitions if we don't already have a + // definition. + GlobalValue *CombinedGV = + RegularLTO.CombinedModule->getNamedValue(GV->getName()); + if (CombinedGV && !CombinedGV->isDeclaration()) + continue; + + Keep.push_back(GV); + } + + return RegularLTO.Mover->move(std::move(Mod.M), Keep, [](GlobalValue &, IRMover::ValueAdder) {}, /* IsPerformingImport */ false); } -// Add a ThinLTO object to the link. -Error LTO::addThinLTO(BitcodeModule BM, - ArrayRef Syms, +// Add a ThinLTO module to the link. +Error LTO::addThinLTO(BitcodeModule BM, ArrayRef Syms, const SymbolResolution *&ResI, const SymbolResolution *ResE) { if (Error Err = - BM.readSummary(ThinLTO.CombinedIndex, ThinLTO.ModuleMap.size())) + BM.readSummary(ThinLTO.CombinedIndex, BM.getModuleIdentifier(), + ThinLTO.ModuleMap.size())) return Err; for (const InputFile::Symbol &Sym : Syms) { assert(ResI != ResE); SymbolResolution Res = *ResI++; - addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1); if (Res.Prevailing) { if (!Sym.getIRName().empty()) { @@ -601,7 +650,7 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) { // Compute "dead" symbols, we don't want to import/export these! DenseSet GUIDPreservedSymbols; for (auto &Res : GlobalResolutions) { - if (Res.second.VisibleOutsideThinLTO && + if (Res.second.VisibleOutsideSummary && // IRName will be defined if we have seen the prevailing copy of // this value. If not, no need to preserve any ThinLTO copies. !Res.second.IRName.empty()) @@ -614,7 +663,8 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) { // Save the status of having a regularLTO combined module, as // this is needed for generating the ThinLTO Task ID, and // the CombinedModule will be moved at the end of runRegularLTO. - bool HasRegularLTO = RegularLTO.CombinedModule != nullptr; + bool HasRegularLTO = RegularLTO.CombinedModule != nullptr || + !RegularLTO.ModsWithSummaries.empty(); // Invoke regular LTO if there was a regular LTO module to start with. if (HasRegularLTO) if (auto E = runRegularLTO(AddStream)) @@ -623,6 +673,11 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) { } Error LTO::runRegularLTO(AddStreamFn AddStream) { + for (auto &M : RegularLTO.ModsWithSummaries) + if (Error Err = linkRegularLTO(std::move(M), + /*LivenessFromIndex=*/true)) + return Err; + // Make sure commons have the right size/alignment: we kept the largest from // all the prevailing when adding the inputs, and we apply it here. const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout(); @@ -920,17 +975,6 @@ ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix, }; } -static bool IsLiveByGUID(const ModuleSummaryIndex &Index, - GlobalValue::GUID GUID) { - auto VI = Index.getValueInfo(GUID); - if (!VI) - return false; - for (auto &I : VI.getSummaryList()) - if (Index.isGlobalValueLive(I.get())) - return true; - return false; -} - Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, bool HasRegularLTO) { if (ThinLTO.ModuleMap.empty()) @@ -979,7 +1023,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache, auto GUID = GlobalValue::getGUID( GlobalValue::dropLLVMManglingEscape(Res.second.IRName)); // Mark exported unless index-based analysis determined it to be dead. - if (IsLiveByGUID(ThinLTO.CombinedIndex, GUID)) + if (ThinLTO.CombinedIndex.isGUIDLive(GUID)) ExportedGUIDs.insert(GUID); } diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index 11f0982..3cc8b7d 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -77,14 +77,12 @@ bool LTOModule::isBitcodeFile(StringRef Path) { } bool LTOModule::isThinLTO() { - // Right now the detection is only based on the summary presence. We may want - // to add a dedicated flag at some point. - Expected Result = hasGlobalValueSummary(MBRef); + Expected Result = getBitcodeLTOInfo(MBRef); if (!Result) { logAllUnhandledErrors(Result.takeError(), errs(), ""); return false; } - return *Result; + return Result->IsThinLTO; } bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, @@ -637,10 +635,10 @@ void LTOModule::parseMetadata() { raw_string_ostream OS(LinkerOpts); // Linker Options - if (Metadata *Val = getModule().getModuleFlag("Linker Options")) { - MDNode *LinkerOptions = cast(Val); + if (NamedMDNode *LinkerOptions = + getModule().getNamedMetadata("llvm.linker.options")) { for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { - MDNode *MDOptions = cast(LinkerOptions->getOperand(i)); + MDNode *MDOptions = LinkerOptions->getOperand(i); for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast(MDOptions->getOperand(ii)); OS << " " << MDOption->getString(); diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index f1dfb91..a407691 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -603,6 +603,8 @@ EndStmt: Type = ELF::SHT_NOTE; else if (TypeName == "unwind") Type = ELF::SHT_X86_64_UNWIND; + else if (TypeName == "llvm_odrtab") + Type = ELF::SHT_LLVM_ODRTAB; else if (TypeName.getAsInteger(0, Type)) return TokError("unknown section type"); } diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index a75068e..2f4f61a 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -147,6 +147,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T, // Print hex value of the flag while we do not have // any standard symbolic representation of the flag. OS << "0x7000001e"; + else if (Type == ELF::SHT_LLVM_ODRTAB) + OS << "llvm_odrtab"; else report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) + " for section " + getSectionName()); diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 4b3dc6e..db304c0 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -181,7 +181,10 @@ class WasmObjectWriter : public MCObjectWriter { // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; - + // Maps function symbols to the table element index space. Used + // for TABLE_INDEX relocation types (i.e. address taken functions). + DenseMap IndirectSymbolIndices; + // Maps function/global symbols to the function/global index space. DenseMap SymbolIndices; DenseMap @@ -189,9 +192,8 @@ class WasmObjectWriter : public MCObjectWriter { // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const { - return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); + unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const { + return TargetObjectWriter->getRelocType(Target, Fixup); } void startSection(SectionBookkeeping &Section, unsigned SectionId, @@ -210,6 +212,7 @@ private: DataRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); + IndirectSymbolIndices.clear(); FunctionTypeIndices.clear(); MCObjectWriter::reset(); } @@ -233,7 +236,7 @@ private: void writeTypeSection(const SmallVector &FunctionTypes); void writeImportSection(const SmallVector &Imports); void writeFunctionSection(const SmallVector &Functions); - void writeTableSection(const SmallVector &TableElems); + void writeTableSection(uint32_t NumElements); void writeMemorySection(const SmallVector &DataBytes); void writeGlobalSection(const SmallVector &Globals); void writeExportSection(const SmallVector &Exports); @@ -402,7 +405,9 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, SymA->setUsedInReloc(); } - unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); + assert(!IsPCRel); + unsigned Type = getRelocType(Target, Fixup); + WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); if (FixupSection.hasInstructions()) @@ -464,9 +469,11 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) { uint32_t WasmObjectWriter::getRelocationIndexValue( const WasmRelocationEntry &RelEntry) { switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + assert(IndirectSymbolIndices.count(RelEntry.Symbol)); + return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: @@ -617,21 +624,19 @@ void WasmObjectWriter::writeFunctionSection( endSection(Section); } -void WasmObjectWriter::writeTableSection( - const SmallVector &TableElems) { +void WasmObjectWriter::writeTableSection(uint32_t NumElements) { // For now, always emit the table section, since indirect calls are not // valid without it. In the future, we could perhaps be more clever and omit // it if there are no indirect calls. + SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_TABLE); - // The number of tables, fixed to 1 for now. - encodeULEB128(1, getStream()); - - encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); - - encodeULEB128(0, getStream()); // flags - encodeULEB128(TableElems.size(), getStream()); // initial + encodeULEB128(1, getStream()); // The number of tables. + // Fixed to 1 for now. + encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumElements, getStream()); // initial endSection(Section); } @@ -1072,8 +1077,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, } // If needed, prepare the function to be called indirectly. - if (IsAddressTaken.count(&WS)) + if (IsAddressTaken.count(&WS)) { + IndirectSymbolIndices[&WS] = TableElems.size(); TableElems.push_back(Index); + } } else { if (WS.isTemporary() && !WS.getSize()) continue; @@ -1180,7 +1187,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeTypeSection(FunctionTypes); writeImportSection(Imports); writeFunctionSection(Functions); - writeTableSection(TableElems); + writeTableSection(TableElems.size()); writeMemorySection(DataBytes); writeGlobalSection(Globals); writeExportSection(Exports); diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index e1c35ed..4034f90 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -36,7 +36,8 @@ using namespace llvm; NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef) - : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {} + : Buf(MemoryBuffer::getMemBuffer(BufRef, false)), + MemberName(BufRef.getBufferIdentifier()) {} Expected NewArchiveMember::getOldMember(const object::Archive::Child &OldMember, @@ -48,6 +49,7 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember, NewArchiveMember M; assert(M.IsNew == false); M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false); + M.MemberName = M.Buf->getBufferIdentifier(); if (!Deterministic) { auto ModTimeOrErr = OldMember.getLastModified(); if (!ModTimeOrErr) @@ -97,6 +99,7 @@ Expected NewArchiveMember::getFile(StringRef FileName, NewArchiveMember M; M.IsNew = true; M.Buf = std::move(*MemberBufferOrErr); + M.MemberName = M.Buf->getBufferIdentifier(); if (!Deterministic) { M.ModTime = std::chrono::time_point_cast( Status.getLastModificationTime()); @@ -185,7 +188,7 @@ printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name, } static bool useStringTable(bool Thin, StringRef Name) { - return Thin || Name.size() >= 16; + return Thin || Name.size() >= 16 || Name.contains('/'); } static void @@ -239,7 +242,7 @@ static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName, unsigned StartOffset = 0; for (const NewArchiveMember &M : Members) { StringRef Path = M.Buf->getBufferIdentifier(); - StringRef Name = sys::path::filename(Path); + StringRef Name = M.MemberName; if (!useStringTable(Thin, Name)) continue; if (StartOffset == 0) { @@ -423,9 +426,8 @@ llvm::writeArchive(StringRef ArcName, if (Kind == object::Archive::K_DARWIN) Padding = OffsetToAlignment(M.Buf->getBufferSize(), 8); - printMemberHeader(Out, Kind, Thin, - sys::path::filename(M.Buf->getBufferIdentifier()), - StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms, + printMemberHeader(Out, Kind, Thin, M.MemberName, StringMapIndexIter, + M.ModTime, M.UID, M.GID, M.Perms, M.Buf->getBufferSize() + Padding); if (!Thin) diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index 9bc28dc..448fb1b 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -192,6 +192,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY); STRINGIFY_ENUM_CASE(ELF, SHT_GROUP); STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX); + STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH); STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef); diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp index d21acdb..a6cd5dd 100644 --- a/lib/Object/IRSymtab.cpp +++ b/lib/Object/IRSymtab.cpp @@ -109,9 +109,9 @@ Error Builder::addModule(Module *M) { if (TT.isOSBinFormatCOFF()) { if (auto E = M->materializeMetadata()) return E; - if (Metadata *Val = M->getModuleFlag("Linker Options")) { - MDNode *LinkerOptions = cast(Val); - for (const MDOperand &MDOptions : LinkerOptions->operands()) + if (NamedMDNode *LinkerOptions = + M->getNamedMetadata("llvm.linker.options")) { + for (MDNode *MDOptions : LinkerOptions->operands()) for (const MDOperand &MDOption : cast(MDOptions)->operands()) COFFLinkerOptsOS << " " << cast(MDOption)->getString(); } diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp index 041659e..3f6080d 100644 --- a/lib/Object/WindowsResource.cpp +++ b/lib/Object/WindowsResource.cpp @@ -30,6 +30,10 @@ namespace object { const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t); +// COFF files seem to be inconsistent with alignment between sections, just use +// 8-byte because it makes everyone happy. +const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t); + static const size_t ResourceMagicSize = 16; static const size_t NullEntrySize = 16; @@ -66,7 +70,7 @@ ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner, Error &Err) : Reader(Ref), OwningRes(Owner) { if (loadNext()) - Err = make_error("Could not read first entry.", + Err = make_error("Could not read first entry.\n", object_error::unexpected_eof); } @@ -133,31 +137,35 @@ Error WindowsResourceParser::parse(WindowsResource *WR) { ResourceEntryRef Entry = EntryOrErr.get(); bool End = false; while (!End) { - Data.push_back(Entry.getData()); - if (Entry.checkTypeString()) + bool IsNewTypeString = false; + bool IsNewNameString = false; + + Root.addEntry(Entry, IsNewTypeString, IsNewNameString); + + if (IsNewTypeString) StringTable.push_back(Entry.getTypeString()); - if (Entry.checkNameString()) + if (IsNewNameString) StringTable.push_back(Entry.getNameString()); - Root.addEntry(Entry); - RETURN_IF_ERROR(Entry.moveNext(End)); } return Error::success(); } -void WindowsResourceParser::printTree() const { - ScopedPrinter Writer(outs()); +void WindowsResourceParser::printTree(raw_ostream &OS) const { + ScopedPrinter Writer(OS); Root.print(Writer, "Resource Tree"); } -void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry) { - TreeNode &TypeNode = addTypeNode(Entry); - TreeNode &NameNode = TypeNode.addNameNode(Entry); +void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry, + bool &IsNewTypeString, + bool &IsNewNameString) { + TreeNode &TypeNode = addTypeNode(Entry, IsNewTypeString); + TreeNode &NameNode = TypeNode.addNameNode(Entry, IsNewNameString); NameNode.addLanguageNode(Entry); } @@ -171,7 +179,6 @@ WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion, uint32_t Characteristics) : IsDataNode(true), MajorVersion(MajorVersion), MinorVersion(MinorVersion), Characteristics(Characteristics) { - if (IsDataNode) DataIndex = DataCount++; } @@ -194,17 +201,19 @@ WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion, } WindowsResourceParser::TreeNode & -WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) { +WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry, + bool &IsNewTypeString) { if (Entry.checkTypeString()) - return addChild(Entry.getTypeString()); + return addChild(Entry.getTypeString(), IsNewTypeString); else return addChild(Entry.getTypeID()); } WindowsResourceParser::TreeNode & -WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry) { +WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry, + bool &IsNewNameString) { if (Entry.checkNameString()) - return addChild(Entry.getNameString()); + return addChild(Entry.getNameString(), IsNewNameString); else return addChild(Entry.getNameID()); } @@ -232,7 +241,8 @@ WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addChild( } WindowsResourceParser::TreeNode & -WindowsResourceParser::TreeNode::addChild(ArrayRef NameRef) { +WindowsResourceParser::TreeNode::addChild(ArrayRef NameRef, + bool &IsNewString) { std::string NameString; ArrayRef CorrectedName; std::vector EndianCorrectedName; @@ -248,6 +258,7 @@ WindowsResourceParser::TreeNode::addChild(ArrayRef NameRef) { auto Child = StringChildren.find(NameString); if (Child == StringChildren.end()) { auto NewChild = createStringNode(); + IsNewString = true; WindowsResourceParser::TreeNode &Node = *NewChild; StringChildren.emplace(NameString, std::move(NewChild)); return Node; @@ -296,7 +307,6 @@ class WindowsResourceCOFFWriter { public: WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType, const WindowsResourceParser &Parser, Error &E); - Error write(); private: @@ -314,7 +324,8 @@ private: void writeDirectoryStringTable(); void writeFirstSectionRelocations(); std::unique_ptr Buffer; - uint8_t *Current; + uint8_t *BufferStart; + uint64_t CurrentOffset = 0; Machine MachineType; const WindowsResourceParser::TreeNode &Resources; const ArrayRef> Data; @@ -386,6 +397,7 @@ void WindowsResourceCOFFWriter::performSectionOneLayout() { FileSize += SectionOneSize; FileSize += Data.size() * llvm::COFF::RelocationSize; // one relocation for each resource. + FileSize = alignTo(FileSize, SECTION_ALIGNMENT); } void WindowsResourceCOFFWriter::performSectionTwoLayout() { @@ -398,6 +410,7 @@ void WindowsResourceCOFFWriter::performSectionTwoLayout() { SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t)); } FileSize += SectionTwoSize; + FileSize = alignTo(FileSize, SECTION_ALIGNMENT); } static std::time_t getTime() { @@ -408,7 +421,7 @@ static std::time_t getTime() { } Error WindowsResourceCOFFWriter::write() { - Current = Buffer->getBufferStart(); + BufferStart = Buffer->getBufferStart(); writeCOFFHeader(); writeFirstSectionHeader(); @@ -427,7 +440,8 @@ Error WindowsResourceCOFFWriter::write() { void WindowsResourceCOFFWriter::writeCOFFHeader() { // Write the COFF header. - auto *Header = reinterpret_cast(Current); + auto *Header = + reinterpret_cast(BufferStart); switch (MachineType) { case Machine::ARM: Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; @@ -452,9 +466,9 @@ void WindowsResourceCOFFWriter::writeCOFFHeader() { void WindowsResourceCOFFWriter::writeFirstSectionHeader() { // Write the first section header. - Current += sizeof(llvm::object::coff_file_header); - auto *SectionOneHeader = - reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_file_header); + auto *SectionOneHeader = reinterpret_cast( + BufferStart + CurrentOffset); strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize); SectionOneHeader->VirtualSize = 0; SectionOneHeader->VirtualAddress = 0; @@ -473,9 +487,9 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() { void WindowsResourceCOFFWriter::writeSecondSectionHeader() { // Write the second section header. - Current += sizeof(llvm::object::coff_section); - auto *SectionTwoHeader = - reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_section); + auto *SectionTwoHeader = reinterpret_cast( + BufferStart + CurrentOffset); strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize); SectionTwoHeader->VirtualSize = 0; SectionTwoHeader->VirtualAddress = 0; @@ -492,75 +506,85 @@ void WindowsResourceCOFFWriter::writeSecondSectionHeader() { void WindowsResourceCOFFWriter::writeFirstSection() { // Write section one. - Current += sizeof(llvm::object::coff_section); + CurrentOffset += sizeof(llvm::object::coff_section); writeDirectoryTree(); writeDirectoryStringTable(); writeFirstSectionRelocations(); + + CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT); } void WindowsResourceCOFFWriter::writeSecondSection() { // Now write the .rsrc$02 section. for (auto const &RawDataEntry : Data) { - std::copy(RawDataEntry.begin(), RawDataEntry.end(), Current); - Current += alignTo(RawDataEntry.size(), sizeof(uint64_t)); + std::copy(RawDataEntry.begin(), RawDataEntry.end(), + BufferStart + CurrentOffset); + CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t)); } + + CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT); } void WindowsResourceCOFFWriter::writeSymbolTable() { // Now write the symbol table. // First, the feat symbol. - auto *Symbol = reinterpret_cast(Current); + auto *Symbol = reinterpret_cast(BufferStart + + CurrentOffset); strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)llvm::COFF::NameSize); Symbol->Value = 0x11; Symbol->SectionNumber = 0xffff; Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL; Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC; Symbol->NumberOfAuxSymbols = 0; - Current += sizeof(llvm::object::coff_symbol16); + CurrentOffset += sizeof(llvm::object::coff_symbol16); // Now write the .rsrc1 symbol + aux. - Symbol = reinterpret_cast(Current); + Symbol = reinterpret_cast(BufferStart + + CurrentOffset); strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)llvm::COFF::NameSize); Symbol->Value = 0; Symbol->SectionNumber = 1; Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL; Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC; Symbol->NumberOfAuxSymbols = 1; - Current += sizeof(llvm::object::coff_symbol16); - auto *Aux = - reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_symbol16); + auto *Aux = reinterpret_cast( + BufferStart + CurrentOffset); Aux->Length = SectionOneSize; Aux->NumberOfRelocations = Data.size(); Aux->NumberOfLinenumbers = 0; Aux->CheckSum = 0; Aux->NumberLowPart = 0; Aux->Selection = 0; - Current += sizeof(llvm::object::coff_aux_section_definition); + CurrentOffset += sizeof(llvm::object::coff_aux_section_definition); // Now write the .rsrc2 symbol + aux. - Symbol = reinterpret_cast(Current); + Symbol = reinterpret_cast(BufferStart + + CurrentOffset); strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)llvm::COFF::NameSize); Symbol->Value = 0; Symbol->SectionNumber = 2; Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL; Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC; Symbol->NumberOfAuxSymbols = 1; - Current += sizeof(llvm::object::coff_symbol16); - Aux = reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_symbol16); + Aux = reinterpret_cast( + BufferStart + CurrentOffset); Aux->Length = SectionTwoSize; Aux->NumberOfRelocations = 0; Aux->NumberOfLinenumbers = 0; Aux->CheckSum = 0; Aux->NumberLowPart = 0; Aux->Selection = 0; - Current += sizeof(llvm::object::coff_aux_section_definition); + CurrentOffset += sizeof(llvm::object::coff_aux_section_definition); // Now write a symbol for each relocation. for (unsigned i = 0; i < Data.size(); i++) { char RelocationName[9]; sprintf(RelocationName, "$R%06X", DataOffsets[i]); - Symbol = reinterpret_cast(Current); + Symbol = reinterpret_cast(BufferStart + + CurrentOffset); strncpy(Symbol->Name.ShortName, RelocationName, (size_t)llvm::COFF::NameSize); Symbol->Value = DataOffsets[i]; @@ -568,14 +592,14 @@ void WindowsResourceCOFFWriter::writeSymbolTable() { Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL; Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC; Symbol->NumberOfAuxSymbols = 0; - Current += sizeof(llvm::object::coff_symbol16); + CurrentOffset += sizeof(llvm::object::coff_symbol16); } } void WindowsResourceCOFFWriter::writeStringTable() { // Just 4 null bytes for the string table. - auto COFFStringTable = reinterpret_cast(Current); - *COFFStringTable = 0; + auto COFFStringTable = reinterpret_cast(BufferStart + CurrentOffset); + memset(COFFStringTable, 0, 4); } void WindowsResourceCOFFWriter::writeDirectoryTree() { @@ -593,8 +617,8 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { while (!Queue.empty()) { auto CurrentNode = Queue.front(); Queue.pop(); - auto *Table = - reinterpret_cast(Current); + auto *Table = reinterpret_cast( + BufferStart + CurrentOffset); Table->Characteristics = CurrentNode->getCharacteristics(); Table->TimeDateStamp = 0; Table->MajorVersion = CurrentNode->getMajorVersion(); @@ -603,13 +627,13 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { auto &StringChildren = CurrentNode->getStringChildren(); Table->NumberOfNameEntries = StringChildren.size(); Table->NumberOfIDEntries = IDChildren.size(); - Current += sizeof(llvm::object::coff_resource_dir_table); + CurrentOffset += sizeof(llvm::object::coff_resource_dir_table); CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_table); // Write the directory entries immediately following each directory table. for (auto const &Child : StringChildren) { - auto *Entry = - reinterpret_cast(Current); + auto *Entry = reinterpret_cast( + BufferStart + CurrentOffset); Entry->Identifier.NameOffset = StringTableOffsets[Child.second->getStringIndex()]; if (Child.second->checkIsDataNode()) { @@ -624,12 +648,12 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { sizeof(llvm::object::coff_resource_dir_entry); Queue.push(Child.second.get()); } - Current += sizeof(llvm::object::coff_resource_dir_entry); + CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry); CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry); } for (auto const &Child : IDChildren) { - auto *Entry = - reinterpret_cast(Current); + auto *Entry = reinterpret_cast( + BufferStart + CurrentOffset); Entry->Identifier.ID = Child.first; if (Child.second->checkIsDataNode()) { Entry->Offset.DataEntryOffset = NextLevelOffset; @@ -643,7 +667,7 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { sizeof(llvm::object::coff_resource_dir_entry); Queue.push(Child.second.get()); } - Current += sizeof(llvm::object::coff_resource_dir_entry); + CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry); CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry); } } @@ -651,14 +675,14 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { RelocationAddresses.resize(Data.size()); // Now write all the resource data entries. for (auto DataNodes : DataEntriesTreeOrder) { - auto *Entry = - reinterpret_cast(Current); + auto *Entry = reinterpret_cast( + BufferStart + CurrentOffset); RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset; Entry->DataRVA = 0; // Set to zero because it is a relocation. Entry->DataSize = Data[DataNodes->getDataIndex()].size(); Entry->Codepage = 0; Entry->Reserved = 0; - Current += sizeof(llvm::object::coff_resource_data_entry); + CurrentOffset += sizeof(llvm::object::coff_resource_data_entry); CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry); } } @@ -666,17 +690,16 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() { void WindowsResourceCOFFWriter::writeDirectoryStringTable() { // Now write the directory string table for .rsrc$01 uint32_t TotalStringTableSize = 0; - for (auto String : StringTable) { - auto *LengthField = reinterpret_cast(Current); + for (auto &String : StringTable) { uint16_t Length = String.size(); - *LengthField = Length; - Current += sizeof(uint16_t); - auto *Start = reinterpret_cast(Current); + support::endian::write16le(BufferStart + CurrentOffset, Length); + CurrentOffset += sizeof(uint16_t); + auto *Start = reinterpret_cast(BufferStart + CurrentOffset); std::copy(String.begin(), String.end(), Start); - Current += Length * sizeof(UTF16); + CurrentOffset += Length * sizeof(UTF16); TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t); } - Current += + CurrentOffset += alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize; } @@ -687,7 +710,8 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { // .rsrc section. uint32_t NextSymbolIndex = 5; for (unsigned i = 0; i < Data.size(); i++) { - auto *Reloc = reinterpret_cast(Current); + auto *Reloc = reinterpret_cast( + BufferStart + CurrentOffset); Reloc->VirtualAddress = RelocationAddresses[i]; Reloc->SymbolTableIndex = NextSymbolIndex++; switch (MachineType) { @@ -703,7 +727,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { default: Reloc->Type = 0; } - Current += sizeof(llvm::object::coff_relocation); + CurrentOffset += sizeof(llvm::object::coff_relocation); } } diff --git a/lib/ObjectYAML/COFFYAML.cpp b/lib/ObjectYAML/COFFYAML.cpp index 7f9f4c1..c8cbea1 100644 --- a/lib/ObjectYAML/COFFYAML.cpp +++ b/lib/ObjectYAML/COFFYAML.cpp @@ -488,7 +488,16 @@ void MappingTraits::mapping(IO &IO, COFFYAML::Section &Sec) { IO.mapOptional("VirtualAddress", Sec.Header.VirtualAddress, 0U); IO.mapOptional("VirtualSize", Sec.Header.VirtualSize, 0U); IO.mapOptional("Alignment", Sec.Alignment, 0U); - IO.mapRequired("SectionData", Sec.SectionData); + + // If this is a .debug$S or .debug$T section parse the semantic representation + // of the symbols/types. If it is any other kind of section, just deal in raw + // bytes. + IO.mapOptional("SectionData", Sec.SectionData); + if (Sec.Name == ".debug$S") + IO.mapOptional("Subsections", Sec.DebugS); + else if (Sec.Name == ".debug$T") + IO.mapOptional("Types", Sec.DebugT); + IO.mapOptional("Relocations", Sec.Relocations); } diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index 08a4bb7..d194420 100644 --- a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -28,6 +28,7 @@ #include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h" #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" @@ -75,10 +76,9 @@ struct YAMLSubsectionBase { virtual ~YAMLSubsectionBase() {} virtual void map(IO &IO) = 0; - virtual std::unique_ptr + virtual std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *UseStrings, - DebugChecksumsSubsection *UseChecksums) const = 0; + const codeview::StringsAndChecksums &SC) const = 0; }; } } @@ -90,10 +90,9 @@ struct YAMLChecksumsSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &FC); @@ -105,10 +104,9 @@ struct YAMLLinesSubsection : public YAMLSubsectionBase { YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, @@ -122,10 +120,9 @@ struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, @@ -139,10 +136,9 @@ struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports); @@ -154,10 +150,9 @@ struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, const DebugCrossModuleImportsSubsectionRef &Imports); @@ -169,10 +164,9 @@ struct YAMLSymbolsSubsection : public YAMLSubsectionBase { YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols); @@ -184,10 +178,9 @@ struct YAMLStringTableSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings); @@ -199,10 +192,9 @@ struct YAMLFrameDataSubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, const DebugFrameDataSubsectionRef &Frames); @@ -215,10 +207,9 @@ struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase { : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {} void map(IO &IO) override; - std::unique_ptr + std::shared_ptr toCodeViewSubsection(BumpPtrAllocator &Allocator, - DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const override; + const codeview::StringsAndChecksums &SC) const override; static Expected> fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs); @@ -389,34 +380,23 @@ void MappingTraits::mapping( Subsection.Subsection->map(IO); } -static std::shared_ptr -findChecksums(ArrayRef Subsections) { - for (const auto &SS : Subsections) { - if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) { - return std::static_pointer_cast(SS.Subsection); - } - } - - return nullptr; -} - -std::unique_ptr YAMLChecksumsSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, - DebugChecksumsSubsection *UseChecksums) const { - assert(UseStrings && !UseChecksums); - auto Result = llvm::make_unique(*UseStrings); +std::shared_ptr YAMLChecksumsSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + assert(SC.hasStrings()); + auto Result = std::make_shared(*SC.strings()); for (const auto &CS : Checksums) { Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes); } - return std::move(Result); + return Result; } -std::unique_ptr YAMLLinesSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, - DebugChecksumsSubsection *UseChecksums) const { - assert(UseStrings && UseChecksums); +std::shared_ptr YAMLLinesSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + assert(SC.hasStrings() && SC.hasChecksums()); auto Result = - llvm::make_unique(*UseChecksums, *UseStrings); + std::make_shared(*SC.checksums(), *SC.strings()); Result->setCodeSize(Lines.CodeSize); Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset); Result->setFlags(Lines.Flags); @@ -438,16 +418,16 @@ std::unique_ptr YAMLLinesSubsection::toCodeViewSubsection( } } } - return llvm::cast(std::move(Result)); + return Result; } -std::unique_ptr +std::shared_ptr YAMLInlineeLinesSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, - DebugChecksumsSubsection *UseChecksums) const { - assert(UseChecksums); - auto Result = llvm::make_unique( - *UseChecksums, InlineeLines.HasExtraFiles); + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + assert(SC.hasChecksums()); + auto Result = std::make_shared( + *SC.checksums(), InlineeLines.HasExtraFiles); for (const auto &Site : InlineeLines.Sites) { Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName, @@ -459,56 +439,60 @@ YAMLInlineeLinesSubsection::toCodeViewSubsection( Result->addExtraFile(EF); } } - return llvm::cast(std::move(Result)); + return Result; } -std::unique_ptr +std::shared_ptr YAMLCrossModuleExportsSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - auto Result = llvm::make_unique(); + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + auto Result = std::make_shared(); for (const auto &M : Exports) Result->addMapping(M.Local, M.Global); - return llvm::cast(std::move(Result)); + return Result; } -std::unique_ptr +std::shared_ptr YAMLCrossModuleImportsSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - auto Result = llvm::make_unique(*Strings); + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + assert(SC.hasStrings()); + + auto Result = + std::make_shared(*SC.strings()); for (const auto &M : Imports) { for (const auto Id : M.ImportIds) Result->addImport(M.ModuleName, Id); } - return llvm::cast(std::move(Result)); + return Result; } -std::unique_ptr YAMLSymbolsSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - auto Result = llvm::make_unique(); +std::shared_ptr YAMLSymbolsSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + auto Result = std::make_shared(); for (const auto &Sym : Symbols) Result->addSymbol( Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile)); - return std::move(Result); + return Result; } -std::unique_ptr +std::shared_ptr YAMLStringTableSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - auto Result = llvm::make_unique(); + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + auto Result = std::make_shared(); for (const auto &Str : this->Strings) Result->insert(Str); - return std::move(Result); + return Result; } -std::unique_ptr YAMLFrameDataSubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - assert(Strings); - auto Result = llvm::make_unique(); +std::shared_ptr YAMLFrameDataSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + assert(SC.hasStrings()); + + auto Result = std::make_shared(); for (const auto &YF : Frames) { codeview::FrameData F; F.CodeSize = YF.CodeSize; @@ -519,20 +503,20 @@ std::unique_ptr YAMLFrameDataSubsection::toCodeViewSubsection( F.PrologSize = YF.PrologSize; F.RvaStart = YF.RvaStart; F.SavedRegsSize = YF.SavedRegsSize; - F.FrameFunc = Strings->insert(YF.FrameFunc); + F.FrameFunc = SC.strings()->insert(YF.FrameFunc); Result->addFrameData(F); } - return std::move(Result); + return Result; } -std::unique_ptr +std::shared_ptr YAMLCoffSymbolRVASubsection::toCodeViewSubsection( - BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, - DebugChecksumsSubsection *Checksums) const { - auto Result = llvm::make_unique(); + BumpPtrAllocator &Allocator, + const codeview::StringsAndChecksums &SC) const { + auto Result = std::make_shared(); for (const auto &RVA : RVAs) Result->addRVA(RVA); - return std::move(Result); + return Result; } static Expected @@ -741,63 +725,17 @@ YAMLCoffSymbolRVASubsection::fromCodeViewSubsection( return Result; } -Expected>> +Expected>> llvm::CodeViewYAML::toCodeViewSubsectionList( BumpPtrAllocator &Allocator, ArrayRef Subsections, - DebugStringTableSubsection &Strings) { - std::vector> Result; + const codeview::StringsAndChecksums &SC) { + std::vector> Result; if (Subsections.empty()) return std::move(Result); - auto Checksums = findChecksums(Subsections); - std::unique_ptr ChecksumsBase; - if (Checksums) - ChecksumsBase = - Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr); - DebugChecksumsSubsection *CS = - static_cast(ChecksumsBase.get()); for (const auto &SS : Subsections) { - // We've already converted the checksums subsection, don't do it - // twice. - std::unique_ptr CVS; - if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) - CVS = std::move(ChecksumsBase); - else - CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS); - assert(CVS != nullptr); - Result.push_back(std::move(CVS)); - } - return std::move(Result); -} - -Expected>> -llvm::CodeViewYAML::toCodeViewSubsectionList( - BumpPtrAllocator &Allocator, ArrayRef Subsections, - std::unique_ptr &TakeStrings, - DebugStringTableSubsection *StringsRef) { - std::vector> Result; - if (Subsections.empty()) - return std::move(Result); - - auto Checksums = findChecksums(Subsections); - - std::unique_ptr ChecksumsBase; - if (Checksums) - ChecksumsBase = - Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr); - DebugChecksumsSubsection *CS = - static_cast(ChecksumsBase.get()); - for (const auto &SS : Subsections) { - // We've already converted the checksums and string table subsection, don't - // do it twice. - std::unique_ptr CVS; - if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) - CVS = std::move(ChecksumsBase); - else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) { - assert(TakeStrings && "No string table!"); - CVS = std::move(TakeStrings); - } else - CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS); + std::shared_ptr CVS; + CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC); assert(CVS != nullptr); Result.push_back(std::move(CVS)); } @@ -810,23 +748,23 @@ struct SubsectionConversionVisitor : public DebugSubsectionVisitor { Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; Error visitLines(DebugLinesSubsectionRef &Lines, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitStringTable(DebugStringTableSubsectionRef &ST, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitFrameData(DebugFrameDataSubsectionRef &Symbols, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols, - const DebugSubsectionState &State) override; + const StringsAndChecksumsRef &State) override; YAMLDebugSubsection Subsection; }; @@ -837,7 +775,7 @@ Error SubsectionConversionVisitor::visitUnknown( } Error SubsectionConversionVisitor::visitLines( - DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) { + DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) { auto Result = YAMLLinesSubsection::fromCodeViewSubsection( State.strings(), State.checksums(), Lines); if (!Result) @@ -847,7 +785,8 @@ Error SubsectionConversionVisitor::visitLines( } Error SubsectionConversionVisitor::visitFileChecksums( - DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) { + DebugChecksumsSubsectionRef &Checksums, + const StringsAndChecksumsRef &State) { auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(), Checksums); if (!Result) @@ -858,7 +797,7 @@ Error SubsectionConversionVisitor::visitFileChecksums( Error SubsectionConversionVisitor::visitInlineeLines( DebugInlineeLinesSubsectionRef &Inlinees, - const DebugSubsectionState &State) { + const StringsAndChecksumsRef &State) { auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( State.strings(), State.checksums(), Inlinees); if (!Result) @@ -869,7 +808,7 @@ Error SubsectionConversionVisitor::visitInlineeLines( Error SubsectionConversionVisitor::visitCrossModuleExports( DebugCrossModuleExportsSubsectionRef &Exports, - const DebugSubsectionState &State) { + const StringsAndChecksumsRef &State) { auto Result = YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports); if (!Result) @@ -880,7 +819,7 @@ Error SubsectionConversionVisitor::visitCrossModuleExports( Error SubsectionConversionVisitor::visitCrossModuleImports( DebugCrossModuleImportsSubsectionRef &Imports, - const DebugSubsectionState &State) { + const StringsAndChecksumsRef &State) { auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( State.strings(), Imports); if (!Result) @@ -890,7 +829,8 @@ Error SubsectionConversionVisitor::visitCrossModuleImports( } Error SubsectionConversionVisitor::visitStringTable( - DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) { + DebugStringTableSubsectionRef &Strings, + const StringsAndChecksumsRef &State) { auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings); if (!Result) return Result.takeError(); @@ -899,7 +839,7 @@ Error SubsectionConversionVisitor::visitStringTable( } Error SubsectionConversionVisitor::visitSymbols( - DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) { + DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) { auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols); if (!Result) return Result.takeError(); @@ -908,7 +848,7 @@ Error SubsectionConversionVisitor::visitSymbols( } Error SubsectionConversionVisitor::visitFrameData( - DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) { + DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) { auto Result = YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames); if (!Result) @@ -918,7 +858,7 @@ Error SubsectionConversionVisitor::visitFrameData( } Error SubsectionConversionVisitor::visitCOFFSymbolRVAs( - DebugSymbolRVASubsectionRef &RVAs, const DebugSubsectionState &State) { + DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) { auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs); if (!Result) return Result.takeError(); @@ -927,29 +867,71 @@ Error SubsectionConversionVisitor::visitCOFFSymbolRVAs( } } -Expected YAMLDebugSubsection::fromCodeViewSubection( - const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums, - const DebugSubsectionRecord &SS) { - DebugSubsectionState State(Strings, Checksums); +Expected +YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC, + const DebugSubsectionRecord &SS) { SubsectionConversionVisitor V; - if (auto EC = visitDebugSubsection(SS, V, State)) + if (auto EC = visitDebugSubsection(SS, V, SC)) return std::move(EC); return V.Subsection; } -std::unique_ptr -llvm::CodeViewYAML::findStringTable(ArrayRef Sections) { - for (const auto &SS : Sections) { - if (SS.Subsection->Kind != DebugSubsectionKind::StringTable) - continue; +std::vector +llvm::CodeViewYAML::fromDebugS(ArrayRef Data, + const StringsAndChecksumsRef &SC) { + BinaryStreamReader Reader(Data, support::little); + uint32_t Magic; + + ExitOnError Err("Invalid .debug$S section!"); + Err(Reader.readInteger(Magic)); + assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!"); + + DebugSubsectionArray Subsections; + Err(Reader.readArray(Subsections, Reader.bytesRemaining())); + + std::vector Result; - // String Table doesn't use the allocator. - BumpPtrAllocator Allocator; - auto Result = - SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr); - return llvm::cast(std::move(Result)); + for (const auto &SS : Subsections) { + auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS)); + Result.push_back(YamlSS); + } + return Result; +} + +void llvm::CodeViewYAML::initializeStringsAndChecksums( + ArrayRef Sections, codeview::StringsAndChecksums &SC) { + // String Table and Checksums subsections don't use the allocator. + BumpPtrAllocator Allocator; + + // It's possible for checksums and strings to even appear in different debug$S + // sections, so we have to make this a stateful function that can build up + // the strings and checksums field over multiple iterations. + + // File Checksums require the string table, but may become before it, so we + // have to scan for strings first, then scan for checksums again from the + // beginning. + if (!SC.hasStrings()) { + for (const auto &SS : Sections) { + if (SS.Subsection->Kind != DebugSubsectionKind::StringTable) + continue; + + auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC); + SC.setStrings( + std::static_pointer_cast(Result)); + break; + } + } + + if (SC.hasStrings() && !SC.hasChecksums()) { + for (const auto &SS : Sections) { + if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums) + continue; + + auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC); + SC.setChecksums( + std::static_pointer_cast(Result)); + break; + } } - return nullptr; } diff --git a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index fa3f1e0..ba3a2ab 100644 --- a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -35,6 +35,7 @@ LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false) LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false) LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind) +LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind) LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags) LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags) @@ -149,6 +150,15 @@ void ScalarEnumerationTraits::enumeration(IO &io, } } +void ScalarEnumerationTraits::enumeration( + IO &io, FrameCookieKind &FC) { + auto ThunkNames = getFrameCookieKindNames(); + for (const auto &E : ThunkNames) { + io.enumCase(FC, E.Name.str().c_str(), + static_cast(E.Value)); + } +} + namespace llvm { namespace CodeViewYAML { namespace detail { @@ -183,8 +193,47 @@ template struct SymbolRecordImpl : public SymbolRecordBase { mutable T Symbol; }; +struct UnknownSymbolRecord : public SymbolRecordBase { + explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {} + + void map(yaml::IO &io) override; + + CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator, + CodeViewContainer Container) const override { + RecordPrefix Prefix; + uint32_t TotalLen = sizeof(RecordPrefix) + Data.size(); + Prefix.RecordKind = Kind; + Prefix.RecordLen = TotalLen - 2; + uint8_t *Buffer = Allocator.Allocate(TotalLen); + ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix)); + ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size()); + return CVSymbol(Kind, ArrayRef(Buffer, TotalLen)); + } + Error fromCodeViewSymbol(CVSymbol CVS) override { + this->Kind = CVS.kind(); + Data = CVS.RecordData.drop_front(sizeof(RecordPrefix)); + return Error::success(); + } + + std::vector Data; +}; + template <> void SymbolRecordImpl::map(IO &IO) {} +void UnknownSymbolRecord::map(yaml::IO &io) { + yaml::BinaryRef Binary; + if (io.outputting()) + Binary = yaml::BinaryRef(Data); + io.mapRequired("Data", Binary); + if (!io.outputting()) { + std::string Str; + raw_string_ostream OS(Str); + Binary.writeAsBinary(OS); + OS.flush(); + Data.assign(Str.begin(), Str.end()); + } +} + template <> void SymbolRecordImpl::map(IO &IO) { IO.mapRequired("Parent", Symbol.Parent); IO.mapRequired("End", Symbol.End); @@ -461,7 +510,7 @@ static inline Expected fromCodeViewSymbolImpl(CVSymbol Symbol) { CodeViewYAML::SymbolRecord Result; - auto Impl = std::make_shared>(Symbol.kind()); + auto Impl = std::make_shared(Symbol.kind()); if (auto EC = Impl->fromCodeViewSymbol(Symbol)) return std::move(EC); Result.Symbol = Impl; @@ -472,12 +521,13 @@ Expected CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) { #define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \ case EnumName: \ - return fromCodeViewSymbolImpl(Symbol); + return fromCodeViewSymbolImpl>(Symbol); #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \ SYMBOL_RECORD(EnumName, EnumVal, ClassName) switch (Symbol.kind()) { #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" - default: { llvm_unreachable("Unknown symbol kind!"); } + default: + return fromCodeViewSymbolImpl(Symbol); } return make_error(cv_error_code::corrupt_record); } @@ -486,7 +536,7 @@ template static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind, CodeViewYAML::SymbolRecord &Obj) { if (!IO.outputting()) - Obj.Symbol = std::make_shared>(Kind); + Obj.Symbol = std::make_shared(Kind); IO.mapRequired(Class, *Obj.Symbol); } @@ -500,12 +550,14 @@ void MappingTraits::mapping( #define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \ case EnumName: \ - mapSymbolRecordImpl(IO, #ClassName, Kind, Obj); \ + mapSymbolRecordImpl>(IO, #ClassName, Kind, \ + Obj); \ break; #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \ SYMBOL_RECORD(EnumName, EnumVal, ClassName) switch (Kind) { #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" - default: { llvm_unreachable("Unknown symbol kind!"); } + default: + mapSymbolRecordImpl(IO, "UnknownSym", Kind, Obj); } } diff --git a/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/lib/ObjectYAML/CodeViewYAMLTypes.cpp index 1302b07..a03b9cd 100644 --- a/lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ b/lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -714,3 +714,43 @@ void MappingTraits::mapping(IO &IO, MemberRecord &Obj) { default: { llvm_unreachable("Unknown member kind!"); } } } + +std::vector +llvm::CodeViewYAML::fromDebugT(ArrayRef DebugT) { + ExitOnError Err("Invalid .debug$T section!"); + BinaryStreamReader Reader(DebugT, support::little); + CVTypeArray Types; + uint32_t Magic; + + Err(Reader.readInteger(Magic)); + assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$T section!"); + + std::vector Result; + Err(Reader.readArray(Types, Reader.bytesRemaining())); + for (const auto &T : Types) { + auto CVT = Err(LeafRecord::fromCodeViewRecord(T)); + Result.push_back(CVT); + } + return Result; +} + +ArrayRef llvm::CodeViewYAML::toDebugT(ArrayRef Leafs, + BumpPtrAllocator &Alloc) { + TypeTableBuilder TTB(Alloc, false); + uint32_t Size = sizeof(uint32_t); + for (const auto &Leaf : Leafs) { + CVType T = Leaf.toCodeViewRecord(TTB); + Size += T.length(); + assert(T.length() % 4 == 0 && "Improper type record alignment!"); + } + uint8_t *ResultBuffer = Alloc.Allocate(Size); + MutableArrayRef Output(ResultBuffer, Size); + BinaryStreamWriter Writer(Output, support::little); + ExitOnError Err("Error writing type record to .debug$T section"); + Err(Writer.writeInteger(COFF::DEBUG_SECTION_MAGIC)); + for (const auto &R : TTB.records()) { + Err(Writer.writeBytes(R)); + } + assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!"); + return Output; +} diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp index 70e25ea..dbd5498 100644 --- a/lib/ObjectYAML/ELFYAML.cpp +++ b/lib/ObjectYAML/ELFYAML.cpp @@ -372,6 +372,7 @@ void ScalarEnumerationTraits::enumeration( ECase(SHT_GROUP); ECase(SHT_SYMTAB_SHNDX); ECase(SHT_LOOS); + ECase(SHT_LLVM_ODRTAB); ECase(SHT_GNU_ATTRIBUTES); ECase(SHT_GNU_HASH); ECase(SHT_GNU_verdef); diff --git a/lib/Option/Arg.cpp b/lib/Option/Arg.cpp index e416df6..e581fee 100644 --- a/lib/Option/Arg.cpp +++ b/lib/Option/Arg.cpp @@ -1,4 +1,4 @@ -//===--- Arg.cpp - Argument Implementations -------------------------------===// +//===- Arg.cpp - Argument Implementations ---------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Option/Arg.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -67,7 +67,7 @@ LLVM_DUMP_METHOD void Arg::dump() const { print(dbgs()); } std::string Arg::getAsString(const ArgList &Args) const { SmallString<256> Res; - llvm::raw_svector_ostream OS(Res); + raw_svector_ostream OS(Res); ArgStringList ASL; render(Args, ASL); @@ -98,7 +98,7 @@ void Arg::render(const ArgList &Args, ArgStringList &Output) const { case Option::RenderCommaJoinedStyle: { SmallString<256> Res; - llvm::raw_svector_ostream OS(Res); + raw_svector_ostream OS(Res); OS << getSpelling(); for (unsigned i = 0, e = getNumValues(); i != e; ++i) { if (i) OS << ','; diff --git a/lib/Option/ArgList.cpp b/lib/Option/ArgList.cpp index 39dbce8..cbccc19 100644 --- a/lib/Option/ArgList.cpp +++ b/lib/Option/ArgList.cpp @@ -1,4 +1,4 @@ -//===--- ArgList.cpp - Argument List Management ---------------------------===// +//===- ArgList.cpp - Argument List Management -----------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,25 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Option/ArgList.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Option/OptSpecifier.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include using namespace llvm; using namespace llvm::opt; @@ -197,8 +208,6 @@ void ArgList::print(raw_ostream &O) const { LLVM_DUMP_METHOD void ArgList::dump() const { print(dbgs()); } #endif -// - void InputArgList::releaseMemory() { // An InputArgList always owns its arguments. for (Arg *A : *this) @@ -234,8 +243,6 @@ const char *InputArgList::MakeArgStringRef(StringRef Str) const { return getArgString(MakeIndex(Str)); } -// - DerivedArgList::DerivedArgList(const InputArgList &BaseArgs) : BaseArgs(BaseArgs) {} diff --git a/lib/Option/OptTable.cpp b/lib/Option/OptTable.cpp index b00d21e..52a81ff 100644 --- a/lib/Option/OptTable.cpp +++ b/lib/Option/OptTable.cpp @@ -1,4 +1,4 @@ -//===--- OptTable.cpp - Option Table Implementation -----------------------===// +//===- OptTable.cpp - Option Table Implementation -------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,16 +7,25 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Option/OptTable.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" +#include "llvm/Option/OptSpecifier.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include +#include #include +#include #include +#include +#include +#include using namespace llvm; using namespace llvm::opt; @@ -80,14 +89,14 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) { static inline bool operator<(const OptTable::Info &I, const char *Name) { return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0; } -} -} + +} // end namespace opt +} // end namespace llvm OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {} OptTable::OptTable(ArrayRef OptionInfos, bool IgnoreCase) - : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase), TheInputOptionID(0), - TheUnknownOptionID(0), FirstSearchableIndex(0) { + : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) { // Explicitly zero initialize the error to work around a bug in array // value-initialization on MinGW with gcc 4.3.5. @@ -138,8 +147,8 @@ OptTable::OptTable(ArrayRef OptionInfos, bool IgnoreCase) } // Build prefix chars. - for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(), - E = PrefixesUnion.end(); I != E; ++I) { + for (StringSet<>::const_iterator I = PrefixesUnion.begin(), + E = PrefixesUnion.end(); I != E; ++I) { StringRef Prefix = I->getKey(); for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end(); C != CE; ++C) @@ -148,8 +157,7 @@ OptTable::OptTable(ArrayRef OptionInfos, bool IgnoreCase) } } -OptTable::~OptTable() { -} +OptTable::~OptTable() = default; const Option OptTable::getOption(OptSpecifier Opt) const { unsigned id = Opt.getID(); @@ -159,11 +167,11 @@ const Option OptTable::getOption(OptSpecifier Opt) const { return Option(&getInfo(id), this); } -static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) { +static bool isInput(const StringSet<> &Prefixes, StringRef Arg) { if (Arg == "-") return true; - for (llvm::StringSet<>::const_iterator I = Prefixes.begin(), - E = Prefixes.end(); I != E; ++I) + for (StringSet<>::const_iterator I = Prefixes.begin(), + E = Prefixes.end(); I != E; ++I) if (Arg.startswith(I->getKey())) return false; return true; @@ -346,7 +354,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { static void PrintHelpOptionList(raw_ostream &OS, StringRef Title, std::vector > &OptionHelp) { + const char*>> &OptionHelp) { OS << Title << ":\n"; // Find the maximum option length. @@ -412,8 +420,8 @@ void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title, // Render help text into a map of group-name to a list of (option, help) // pairs. - typedef std::map > > helpmap_ty; + using helpmap_ty = + std::map>>; helpmap_ty GroupedOptionHelp; for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { diff --git a/lib/Option/Option.cpp b/lib/Option/Option.cpp index 736b939..4832e65 100644 --- a/lib/Option/Option.cpp +++ b/lib/Option/Option.cpp @@ -1,4 +1,4 @@ -//===--- Option.cpp - Abstract Driver Options -----------------------------===// +//===- Option.cpp - Abstract Driver Options -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,22 +7,24 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Option/Option.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include #include +#include using namespace llvm; using namespace llvm::opt; Option::Option(const OptTable::Info *info, const OptTable *owner) : Info(info), Owner(owner) { - // Multi-level aliases are not supported. This just simplifies option // tracking, it is not an inherent limitation. assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) && diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index 1f638e7..afd66f5 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -160,6 +160,10 @@ static cl::opt cl::Hidden, cl::ZeroOrMore, cl::desc("Run NewGVN instead of GVN")); +static cl::opt EnableEarlyCSEMemSSA( + "enable-npm-earlycse-memssa", cl::init(false), cl::Hidden, + cl::desc("Enable the EarlyCSE w/ MemorySSA pass for the new PM (default = off)")); + static cl::opt EnableGVNHoist( "enable-npm-gvn-hoist", cl::init(false), cl::Hidden, cl::desc("Enable the GVN hoisting pass for the new PM (default = off)")); @@ -312,7 +316,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, FPM.addPass(SROA()); // Catch trivial redundancies - FPM.addPass(EarlyCSEPass()); + FPM.addPass(EarlyCSEPass(EnableEarlyCSEMemSSA)); // Hoisting of scalars and load expressions. if (EnableGVNHoist) diff --git a/lib/Support/BinaryStreamWriter.cpp b/lib/Support/BinaryStreamWriter.cpp index b22eb1e..c427651 100644 --- a/lib/Support/BinaryStreamWriter.cpp +++ b/lib/Support/BinaryStreamWriter.cpp @@ -83,6 +83,8 @@ Error BinaryStreamWriter::padToAlignment(uint32_t Align) { uint32_t NewOffset = alignTo(Offset, Align); if (NewOffset > getLength()) return make_error(stream_error_code::stream_too_short); - Offset = NewOffset; + while (Offset < NewOffset) + if (auto EC = writeInteger('\0')) + return EC; return Error::success(); } diff --git a/lib/Support/DebugCounter.cpp b/lib/Support/DebugCounter.cpp index a10ac8e..1d46de0 100644 --- a/lib/Support/DebugCounter.cpp +++ b/lib/Support/DebugCounter.cpp @@ -102,9 +102,13 @@ void DebugCounter::push_back(const std::string &Val) { } } -void DebugCounter::print(raw_ostream &OS) { +void DebugCounter::print(raw_ostream &OS) const { OS << "Counters and values:\n"; for (const auto &KV : Counters) OS << left_justify(RegisteredCounters[KV.first], 32) << ": {" << KV.second.first << "," << KV.second.second << "}\n"; } + +LLVM_DUMP_METHOD void DebugCounter::dump() const { + print(dbgs()); +} diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp index c9bca7f..4496d06 100644 --- a/lib/Support/FoldingSet.cpp +++ b/lib/Support/FoldingSet.cpp @@ -26,7 +26,7 @@ using namespace llvm; // FoldingSetNodeIDRef Implementation /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, -/// used to lookup the node in the FoldingSetImpl. +/// used to lookup the node in the FoldingSetBase. unsigned FoldingSetNodeIDRef::ComputeHash() const { return static_cast(hash_combine_range(Data, Data+Size)); } @@ -142,7 +142,7 @@ void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) { } /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to -/// lookup the node in the FoldingSetImpl. +/// lookup the node in the FoldingSetBase. unsigned FoldingSetNodeID::ComputeHash() const { return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash(); } @@ -180,7 +180,7 @@ FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const { } //===----------------------------------------------------------------------===// -/// Helper functions for FoldingSetImpl. +/// Helper functions for FoldingSetBase. /// GetNextPtr - In order to save space, each bucket is a /// singly-linked-list. In order to make deletion more efficient, we make @@ -188,12 +188,12 @@ FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const { /// The problem with this is that the start of the hash buckets are not /// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null: /// use GetBucketPtr when this happens. -static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) { +static FoldingSetBase::Node *GetNextPtr(void *NextInBucketPtr) { // The low bit is set if this is the pointer back to the bucket. if (reinterpret_cast(NextInBucketPtr) & 1) return nullptr; - return static_cast(NextInBucketPtr); + return static_cast(NextInBucketPtr); } @@ -221,11 +221,11 @@ static void **AllocateBuckets(unsigned NumBuckets) { } //===----------------------------------------------------------------------===// -// FoldingSetImpl Implementation +// FoldingSetBase Implementation -void FoldingSetImpl::anchor() {} +void FoldingSetBase::anchor() {} -FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { +FoldingSetBase::FoldingSetBase(unsigned Log2InitSize) { assert(5 < Log2InitSize && Log2InitSize < 32 && "Initial hash table size out of range"); NumBuckets = 1 << Log2InitSize; @@ -233,14 +233,14 @@ FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { NumNodes = 0; } -FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg) +FoldingSetBase::FoldingSetBase(FoldingSetBase &&Arg) : Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) { Arg.Buckets = nullptr; Arg.NumBuckets = 0; Arg.NumNodes = 0; } -FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) { +FoldingSetBase &FoldingSetBase::operator=(FoldingSetBase &&RHS) { free(Buckets); // This may be null if the set is in a moved-from state. Buckets = RHS.Buckets; NumBuckets = RHS.NumBuckets; @@ -251,11 +251,11 @@ FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) { return *this; } -FoldingSetImpl::~FoldingSetImpl() { +FoldingSetBase::~FoldingSetBase() { free(Buckets); } -void FoldingSetImpl::clear() { +void FoldingSetBase::clear() { // Set all but the last bucket to null pointers. memset(Buckets, 0, NumBuckets*sizeof(void*)); @@ -266,7 +266,7 @@ void FoldingSetImpl::clear() { NumNodes = 0; } -void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) { +void FoldingSetBase::GrowBucketCount(unsigned NewBucketCount) { assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount"); assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!"); void **OldBuckets = Buckets; @@ -300,11 +300,11 @@ void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) { /// GrowHashTable - Double the size of the hash table and rehash everything. /// -void FoldingSetImpl::GrowHashTable() { +void FoldingSetBase::GrowHashTable() { GrowBucketCount(NumBuckets * 2); } -void FoldingSetImpl::reserve(unsigned EltCount) { +void FoldingSetBase::reserve(unsigned EltCount) { // This will give us somewhere between EltCount / 2 and // EltCount buckets. This puts us in the load factor // range of 1.0 - 2.0. @@ -316,9 +316,9 @@ void FoldingSetImpl::reserve(unsigned EltCount) { /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, /// return it. If not, return the insertion token that will make insertion /// faster. -FoldingSetImpl::Node -*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID, - void *&InsertPos) { +FoldingSetBase::Node * +FoldingSetBase::FindNodeOrInsertPos(const FoldingSetNodeID &ID, + void *&InsertPos) { unsigned IDHash = ID.ComputeHash(); void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets); void *Probe = *Bucket; @@ -342,7 +342,7 @@ FoldingSetImpl::Node /// InsertNode - Insert the specified node into the folding set, knowing that it /// is not already in the map. InsertPos must be obtained from /// FindNodeOrInsertPos. -void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { +void FoldingSetBase::InsertNode(Node *N, void *InsertPos) { assert(!N->getNextInBucket()); // Do we need to grow the hashtable? if (NumNodes+1 > capacity()) { @@ -371,7 +371,7 @@ void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { /// RemoveNode - Remove a node from the folding set, returning true if one was /// removed or false if the node was not in the folding set. -bool FoldingSetImpl::RemoveNode(Node *N) { +bool FoldingSetBase::RemoveNode(Node *N) { // Because each bucket is a circular list, we don't need to compute N's hash // to remove it. void *Ptr = N->getNextInBucket(); @@ -412,7 +412,7 @@ bool FoldingSetImpl::RemoveNode(Node *N) { /// GetOrInsertNode - If there is an existing simple Node exactly /// equal to the specified node, return it. Otherwise, insert 'N' and it /// instead. -FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) { +FoldingSetBase::Node *FoldingSetBase::GetOrInsertNode(FoldingSetBase::Node *N) { FoldingSetNodeID ID; GetNodeProfile(N, ID); void *IP; diff --git a/lib/Support/ThreadPool.cpp b/lib/Support/ThreadPool.cpp index db03a4d..22b7550 100644 --- a/lib/Support/ThreadPool.cpp +++ b/lib/Support/ThreadPool.cpp @@ -53,11 +53,7 @@ ThreadPool::ThreadPool(unsigned ThreadCount) Tasks.pop(); } // Run the task we just grabbed -#ifndef _MSC_VER Task(); -#else - Task(/* unused */ false); -#endif { // Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait() @@ -82,7 +78,7 @@ void ThreadPool::wait() { [&] { return !ActiveThreads && Tasks.empty(); }); } -std::shared_future ThreadPool::asyncImpl(TaskTy Task) { +std::shared_future ThreadPool::asyncImpl(TaskTy Task) { /// Wrap the Task in a packaged_task to return a future object. PackagedTaskTy PackagedTask(std::move(Task)); auto Future = PackagedTask.get_future(); @@ -128,25 +124,16 @@ void ThreadPool::wait() { while (!Tasks.empty()) { auto Task = std::move(Tasks.front()); Tasks.pop(); -#ifndef _MSC_VER - Task(); -#else - Task(/* unused */ false); -#endif + Task(); } } -std::shared_future ThreadPool::asyncImpl(TaskTy Task) { -#ifndef _MSC_VER +std::shared_future ThreadPool::asyncImpl(TaskTy Task) { // Get a Future with launch::deferred execution using std::async auto Future = std::async(std::launch::deferred, std::move(Task)).share(); // Wrap the future so that both ThreadPool::wait() can operate and the // returned future can be sync'ed on. PackagedTaskTy PackagedTask([Future]() { Future.get(); }); -#else - auto Future = std::async(std::launch::deferred, std::move(Task), false).share(); - PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; }); -#endif Tasks.push(std::move(PackagedTask)); return Future; } diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index 7d3537e..2df0eaf 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -163,16 +163,6 @@ static void SetMemoryLimits (unsigned size) r.rlim_cur = limit; setrlimit (RLIMIT_RSS, &r); #endif -#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. - // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb - // of virtual memory for shadow memory mapping. -#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD - // Virtual memory. - getrlimit (RLIMIT_AS, &r); - r.rlim_cur = limit; - setrlimit (RLIMIT_AS, &r); -#endif -#endif #endif } diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp index 83f7147..b2636e1 100644 --- a/lib/TableGen/Record.cpp +++ b/lib/TableGen/Record.cpp @@ -11,20 +11,28 @@ // //===----------------------------------------------------------------------===// -#include "llvm/TableGen/Record.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include #include -#include +#include +#include +#include +#include using namespace llvm; @@ -162,7 +170,8 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { // Initializer implementations //===----------------------------------------------------------------------===// -void Init::anchor() { } +void Init::anchor() {} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void Init::dump() const { return print(errs()); } #endif @@ -301,7 +310,6 @@ static Init *fixBitInit(const RecordVal *RV, Init *Before, Init *After) { // resolveReferences - If there are any field references that refer to fields // that have been filled in, we can propagate the values now. -// Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const { bool Changed = false; SmallVector NewBits(getNumBits()); @@ -615,7 +623,7 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const { Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { switch (getOpcode()) { - case CAST: { + case CAST: if (isa(getType())) { if (StringInit *LHSs = dyn_cast(LHS)) return LHSs; @@ -680,15 +688,15 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { } } break; - } - case HEAD: { + + case HEAD: if (ListInit *LHSl = dyn_cast(LHS)) { assert(!LHSl->empty() && "Empty list in head"); return LHSl->getElement(0); } break; - } - case TAIL: { + + case TAIL: if (ListInit *LHSl = dyn_cast(LHS)) { assert(!LHSl->empty() && "Empty list in tail"); // Note the +1. We can't just pass the result of getValues() @@ -696,16 +704,14 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { return ListInit::get(LHSl->getValues().slice(1), LHSl->getType()); } break; - } - case EMPTY: { + + case EMPTY: if (ListInit *LHSl = dyn_cast(LHS)) return IntInit::get(LHSl->empty()); if (StringInit *LHSs = dyn_cast(LHS)) return IntInit::get(LHSs->getValue().empty()); - break; } - } return const_cast(this); } @@ -948,7 +954,6 @@ static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg, static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, Record *CurRec, MultiClass *CurMultiClass) { - OpInit *RHSo = dyn_cast(RHS); if (!RHSo) @@ -1245,7 +1250,7 @@ VarInit *VarInit::get(StringRef VN, RecTy *T) { } VarInit *VarInit::get(Init *VN, RecTy *T) { - typedef std::pair Key; + using Key = std::pair; static DenseMap ThePool; Key TheKey(std::make_pair(T, VN)); @@ -1320,7 +1325,7 @@ Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const { } VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) { - typedef std::pair Key; + using Key = std::pair; static DenseMap ThePool; Key TheKey(std::make_pair(T, B)); @@ -1352,7 +1357,7 @@ Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const { VarListElementInit *VarListElementInit::get(TypedInit *T, unsigned E) { - typedef std::pair Key; + using Key = std::pair; static DenseMap ThePool; Key TheKey(std::make_pair(T, E)); @@ -1422,7 +1427,7 @@ std::string DefInit::getAsString() const { } FieldInit *FieldInit::get(Init *R, StringInit *FN) { - typedef std::pair Key; + using Key = std::pair; static DenseMap ThePool; Key TheKey(std::make_pair(R, FN)); diff --git a/lib/TableGen/SetTheory.cpp b/lib/TableGen/SetTheory.cpp index a4d3305..733e0ae 100644 --- a/lib/TableGen/SetTheory.cpp +++ b/lib/TableGen/SetTheory.cpp @@ -12,18 +12,29 @@ // //===----------------------------------------------------------------------===// -#include "llvm/TableGen/SetTheory.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Format.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" +#include +#include +#include +#include using namespace llvm; // Define the standard operators. namespace { -typedef SetTheory::RecSet RecSet; -typedef SetTheory::RecVec RecVec; +using RecSet = SetTheory::RecSet; +using RecVec = SetTheory::RecVec; // (add a, b, ...) Evaluate and union all arguments. struct AddOp : public SetTheory::Operator { @@ -237,13 +248,13 @@ struct FieldExpander : public SetTheory::Expander { ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); } }; + } // end anonymous namespace // Pin the vtables to this file. void SetTheory::Operator::anchor() {} void SetTheory::Expander::anchor() {} - SetTheory::SetTheory() { addOperator("add", llvm::make_unique()); addOperator("sub", llvm::make_unique()); @@ -321,4 +332,3 @@ const RecVec *SetTheory::expand(Record *Set) { // Set is not expandable. return nullptr; } - diff --git a/lib/Target/AArch64/AArch64.td b/lib/Target/AArch64/AArch64.td index abe2846..53eef79 100644 --- a/lib/Target/AArch64/AArch64.td +++ b/lib/Target/AArch64/AArch64.td @@ -362,6 +362,7 @@ def ProcThunderXT83 : SubtargetFeature<"thunderxt83", "ARMProcFamily", def : ProcessorModel<"generic", NoSchedModel, [ FeatureFPARMv8, + FeatureFuseAES, FeatureNEON, FeaturePerfMon, FeaturePostRAScheduler diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index e8fcf1a..7bf2097 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -1282,6 +1282,10 @@ unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg, bool WantResult) { assert(LHSReg && RHSReg && "Invalid register number."); + if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP || + RHSReg == AArch64::SP || RHSReg == AArch64::WSP) + return 0; + if (RetVT != MVT::i32 && RetVT != MVT::i64) return 0; @@ -1362,6 +1366,8 @@ unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg, uint64_t ShiftImm, bool SetFlags, bool WantResult) { assert(LHSReg && RHSReg && "Invalid register number."); + assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP && + RHSReg != AArch64::SP && RHSReg != AArch64::WSP); if (RetVT != MVT::i32 && RetVT != MVT::i64) return 0; @@ -1403,6 +1409,8 @@ unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg, uint64_t ShiftImm, bool SetFlags, bool WantResult) { assert(LHSReg && RHSReg && "Invalid register number."); + assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR && + RHSReg != AArch64::XZR && RHSReg != AArch64::WZR); if (RetVT != MVT::i32 && RetVT != MVT::i64) return 0; diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 059556a..083ca21 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -9366,7 +9366,7 @@ static SDValue splitStores(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, return SDValue(); StoreSDNode *S = cast(N); - if (S->isVolatile()) + if (S->isVolatile() || S->isIndexed()) return SDValue(); SDValue StVal = S->getValue(); diff --git a/lib/Target/AArch64/AArch64SchedFalkorDetails.td b/lib/Target/AArch64/AArch64SchedFalkorDetails.td index 7402bcf..3d73740 100644 --- a/lib/Target/AArch64/AArch64SchedFalkorDetails.td +++ b/lib/Target/AArch64/AArch64SchedFalkorDetails.td @@ -160,6 +160,21 @@ def FalkorWr_1VX_1VY_10cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> { let NumMicroOps = 2; } +def FalkorWr_1VX_1VY_12cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> { + let Latency = 12; + let NumMicroOps = 2; +} + +def FalkorWr_1VX_1VY_14cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> { + let Latency = 14; + let NumMicroOps = 2; +} + +def FalkorWr_1VX_1VY_21cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> { + let Latency = 21; + let NumMicroOps = 2; +} + def FalkorWr_1GTOV_1VXVY_2cyc : SchedWriteRes<[FalkorUnitGTOV, FalkorUnitVXVY]> { let Latency = 2; let NumMicroOps = 2; @@ -195,10 +210,10 @@ def FalkorWr_1X_1Z_8cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> { let ResourceCycles = [2, 8]; } -def FalkorWr_1X_1Z_16cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> { - let Latency = 16; +def FalkorWr_1X_1Z_11cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> { + let Latency = 11; let NumMicroOps = 2; - let ResourceCycles = [2, 16]; + let ResourceCycles = [2, 11]; } def FalkorWr_1LD_1Z_3cyc : SchedWriteRes<[FalkorUnitLD, FalkorUnitZ]> { @@ -289,9 +304,27 @@ def FalkorWr_1XYZ_1VSD_1ST_0cyc: SchedWriteRes<[FalkorUnitXYZ, FalkorUnitVSD, Fa //===----------------------------------------------------------------------===// // Define 4 micro-op types -def FalkorWr_2VX_2VY_2cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY, - FalkorUnitVX, FalkorUnitVY]> { - let Latency = 2; +def FalkorWr_2VX_2VY_14cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY, + FalkorUnitVX, FalkorUnitVY]> { + let Latency = 14; + let NumMicroOps = 4; +} + +def FalkorWr_2VX_2VY_20cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY, + FalkorUnitVX, FalkorUnitVY]> { + let Latency = 20; + let NumMicroOps = 4; +} + +def FalkorWr_2VX_2VY_21cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY, + FalkorUnitVX, FalkorUnitVY]> { + let Latency = 21; + let NumMicroOps = 4; +} + +def FalkorWr_2VX_2VY_24cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY, + FalkorUnitVX, FalkorUnitVY]> { + let Latency = 24; let NumMicroOps = 4; } @@ -575,7 +608,8 @@ def : InstRW<[FalkorWr_2VXVY_2cyc], (instregex "^FCM(EQ|LE|GE|GT|LT)(v2i64|v4i def : InstRW<[FalkorWr_2VXVY_2cyc], (instrs FCVTLv4i16, FCVTLv2i32)>; def : InstRW<[FalkorWr_2VXVY_2cyc], (instregex "^FRINT(A|I|M|N|P|X|Z)(v2f64|v4f32)$")>; -def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instregex "^(FDIV|FSQRT)v2f32$")>; +def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instrs FDIVv2f32)>; +def : InstRW<[FalkorWr_1VX_1VY_12cyc],(instrs FSQRTv2f32)>; def : InstRW<[FalkorWr_2VXVY_3cyc], (instregex "^(FABD|FADD(P)?|FSUB)(v2f64|v4f32)$")>; @@ -592,7 +626,10 @@ def : InstRW<[FalkorWr_FMUL64_2VXVY_6cyc], def : InstRW<[FalkorWr_3VXVY_4cyc], (instrs FCVTNv4i16, FCVTNv2i32, FCVTXNv2f32)>; def : InstRW<[FalkorWr_3VXVY_5cyc], (instrs FCVTNv8i16, FCVTNv4i32, FCVTXNv4f32)>; -def : InstRW<[FalkorWr_2VX_2VY_2cyc], (instregex "^(FDIV|FSQRT)(v2f64|v4f32)$")>; +def : InstRW<[FalkorWr_2VX_2VY_14cyc],(instrs FDIVv2f64)>; +def : InstRW<[FalkorWr_2VX_2VY_20cyc],(instrs FDIVv4f32)>; +def : InstRW<[FalkorWr_2VX_2VY_21cyc],(instrs FSQRTv2f64)>; +def : InstRW<[FalkorWr_2VX_2VY_24cyc],(instrs FSQRTv4f32)>; def : InstRW<[FalkorWr_VMUL32_1VXVY_4cyc, FalkorReadVMA], (instregex "^ML(A|S)(v8i8|v4i16|v2i32)(_indexed)?$")>; @@ -1039,8 +1076,10 @@ def : InstRW<[FalkorWr_FMUL32_1VXVY_5cyc], def : InstRW<[FalkorWr_FMUL64_1VXVY_6cyc], (instregex "^F(N)?MULDrr$")>; -def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instregex "^FDIV(S|D)rr$")>; -def : InstRW<[FalkorWr_1VX_1VY_2cyc], (instregex "^FSQRT(S|D)r$")>; +def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instrs FDIVSrr)>; +def : InstRW<[FalkorWr_1VX_1VY_14cyc],(instrs FDIVDrr)>; +def : InstRW<[FalkorWr_1VX_1VY_12cyc],(instrs FSQRTSr)>; +def : InstRW<[FalkorWr_1VX_1VY_21cyc],(instrs FSQRTDr)>; def : InstRW<[FalkorWr_FMUL32_1VXVY_5cyc, ReadDefault, ReadDefault, FalkorReadFMA32], (instregex "^F(N)?M(ADD|SUB)Srrr$")>; @@ -1112,7 +1151,7 @@ def : InstRW<[FalkorWr_IMUL64_1X_5cyc, ReadDefault, ReadDefault, FalkorReadIMA64 (instregex "^M(ADD|SUB)Xrrr$")>; def : InstRW<[FalkorWr_1X_1Z_8cyc], (instregex "^(S|U)DIVWr$")>; -def : InstRW<[FalkorWr_1X_1Z_16cyc], (instregex "^(S|U)DIVXr$")>; +def : InstRW<[FalkorWr_1X_1Z_11cyc], (instregex "^(S|U)DIVXr$")>; def : InstRW<[FalkorWr_VMUL32_2VXVY_4cyc], (instregex "^(S|U)MULLv.*$")>; diff --git a/lib/Target/AArch64/AArch64Subtarget.cpp b/lib/Target/AArch64/AArch64Subtarget.cpp index d3cab1a..a9a9d5c 100644 --- a/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/lib/Target/AArch64/AArch64Subtarget.cpp @@ -92,6 +92,10 @@ void AArch64Subtarget::initializeProperties() { MaxInterleaveFactor = 4; // FIXME: remove this to enable 64-bit SLP if performance looks good. MinVectorRegisterBitWidth = 128; + CacheLineSize = 128; + PrefetchDistance = 820; + MinPrefetchStride = 2048; + MaxPrefetchIterationsAhead = 8; break; case Kryo: MaxInterleaveFactor = 4; diff --git a/lib/Target/AArch64/AArch64TargetTransformInfo.h b/lib/Target/AArch64/AArch64TargetTransformInfo.h index d029914..290a1ca 100644 --- a/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ b/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -78,7 +78,7 @@ public: return 31; } - unsigned getRegisterBitWidth(bool Vector) { + unsigned getRegisterBitWidth(bool Vector) const { if (Vector) { if (ST->hasNEON()) return 128; diff --git a/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp b/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp index 8084d36..6f3742e 100644 --- a/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp +++ b/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp @@ -9,7 +9,7 @@ // /// \file /// This pass marks all internal functions as always_inline and creates -/// duplicates of all other functions a marks the duplicates as always_inline. +/// duplicates of all other functions and marks the duplicates as always_inline. // //===----------------------------------------------------------------------===// diff --git a/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp b/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp index 3c788fa..6f00286 100644 --- a/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp +++ b/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp @@ -107,7 +107,7 @@ bool AMDGPUAnnotateUniformValues::isClobberedInFunction(LoadInst * Load) { DFS(Start, Checklist); for (auto &BB : Checklist) { - BasicBlock::iterator StartIt = (BB == Load->getParent()) ? + BasicBlock::iterator StartIt = (!L && (BB == Load->getParent())) ? BasicBlock::iterator(Load) : BB->end(); if (MDR->getPointerDependencyFrom(MemoryLocation(Ptr), true, StartIt, BB, Load).isClobber()) diff --git a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp index 251c2f9..f235313 100644 --- a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -138,7 +138,10 @@ private: bool SelectMUBUFIntrinsicVOffset(SDValue Offset, SDValue &SOffset, SDValue &ImmOffset, SDValue &VOffset) const; - bool SelectFlat(SDValue Addr, SDValue &VAddr, SDValue &SLC) const; + bool SelectFlatAtomic(SDValue Addr, SDValue &VAddr, + SDValue &Offset, SDValue &SLC) const; + bool SelectFlatOffset(SDValue Addr, SDValue &VAddr, + SDValue &Offset, SDValue &SLC) const; bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, bool &Imm) const; @@ -1313,14 +1316,37 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicVOffset(SDValue Offset, return true; } -bool AMDGPUDAGToDAGISel::SelectFlat(SDValue Addr, - SDValue &VAddr, - SDValue &SLC) const { +bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDValue Addr, + SDValue &VAddr, + SDValue &Offset, + SDValue &SLC) const { + int64_t OffsetVal = 0; + + if (Subtarget->hasFlatInstOffsets() && + CurDAG->isBaseWithConstantOffset(Addr)) { + SDValue N0 = Addr.getOperand(0); + SDValue N1 = Addr.getOperand(1); + uint64_t COffsetVal = cast(N1)->getZExtValue(); + if (isUInt<12>(COffsetVal)) { + Addr = N0; + OffsetVal = COffsetVal; + } + } + VAddr = Addr; + Offset = CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i16); SLC = CurDAG->getTargetConstant(0, SDLoc(), MVT::i1); + return true; } +bool AMDGPUDAGToDAGISel::SelectFlatAtomic(SDValue Addr, + SDValue &VAddr, + SDValue &Offset, + SDValue &SLC) const { + return SelectFlatOffset(Addr, VAddr, Offset, SLC); +} + bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, bool &Imm) const { diff --git a/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp index a7eac08..e54c887 100644 --- a/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ b/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -126,8 +126,9 @@ bool AMDGPUInstructionSelector::selectG_STORE(MachineInstr &I) const { MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(AMDGPU::FLAT_STORE_DWORD)) .add(I.getOperand(1)) .add(I.getOperand(0)) - .addImm(0) - .addImm(0); + .addImm(0) // offset + .addImm(0) // glc + .addImm(0); // slc // Now that we selected an opcode, we need to constrain the register @@ -392,8 +393,9 @@ bool AMDGPUInstructionSelector::selectG_LOAD(MachineInstr &I) const { MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode)) .add(I.getOperand(0)) .addReg(PtrReg) - .addImm(0) - .addImm(0); + .addImm(0) // offset + .addImm(0) // glc + .addImm(0); // slc bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI); I.eraseFromParent(); diff --git a/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index b889788..790a69b 100644 --- a/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -34,6 +34,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo() { const LLT P1 = LLT::pointer(1, 64); const LLT P2 = LLT::pointer(2, 64); + setAction({G_ADD, S32}, Legal); + // FIXME: i1 operands to intrinsics should always be legal, but other i1 // values may not be legal. We need to figure out how to distinguish // between these two scenarios. diff --git a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp index dee3d28..0d6689b 100644 --- a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp +++ b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp @@ -195,7 +195,7 @@ unsigned AMDGPUTTIImpl::getNumberOfRegisters(bool Vec) { return 4 * 128; // XXX - 4 channels. Should these count as vector instead? } -unsigned AMDGPUTTIImpl::getRegisterBitWidth(bool Vector) { +unsigned AMDGPUTTIImpl::getRegisterBitWidth(bool Vector) const { return Vector ? 0 : 32; } @@ -489,6 +489,19 @@ bool AMDGPUTTIImpl::isSourceOfDivergence(const Value *V) const { return false; } +bool AMDGPUTTIImpl::isAlwaysUniform(const Value *V) const { + if (const IntrinsicInst *Intrinsic = dyn_cast(V)) { + switch (Intrinsic->getIntrinsicID()) { + default: + return false; + case Intrinsic::amdgcn_readfirstlane: + case Intrinsic::amdgcn_readlane: + return true; + } + } + return false; +} + unsigned AMDGPUTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, Type *SubTp) { if (ST->hasVOP3PInsts()) { diff --git a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h index e0024e2..a60b1bb 100644 --- a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h +++ b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h @@ -76,7 +76,7 @@ public: } unsigned getNumberOfRegisters(bool Vector); - unsigned getRegisterBitWidth(bool Vector); + unsigned getRegisterBitWidth(bool Vector) const; unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const; bool isLegalToVectorizeMemChain(unsigned ChainSizeInBytes, @@ -103,6 +103,7 @@ public: int getVectorInstrCost(unsigned Opcode, Type *ValTy, unsigned Index); bool isSourceOfDivergence(const Value *V) const; + bool isAlwaysUniform(const Value *V) const; unsigned getFlatAddressSpace() const { // Don't bother running InferAddressSpaces pass on graphics shaders which diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 16e3b7b..392e9d8 100644 --- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -285,6 +285,9 @@ public: bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); } bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); } bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } + + bool isOffsetU12() const { return isImmTy(ImmTyOffset) && isUInt<12>(getImm()); } + bool isOffsetS13() const { return isImmTy(ImmTyOffset) && isInt<13>(getImm()); } bool isGDS() const { return isImmTy(ImmTyGDS); } bool isGLC() const { return isImmTy(ImmTyGLC); } bool isSLC() const { return isImmTy(ImmTySLC); } @@ -886,6 +889,10 @@ public: return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; } + bool hasFlatOffsets() const { + return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets]; + } + bool hasSGPR102_SGPR103() const { return !isVI(); } @@ -1034,6 +1041,7 @@ public: AMDGPUOperand::Ptr defaultSMRDOffset8() const; AMDGPUOperand::Ptr defaultSMRDOffset20() const; AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const; + AMDGPUOperand::Ptr defaultOffsetU12() const; OperandMatchResultTy parseOModOperand(OperandVector &Operands); @@ -1970,6 +1978,15 @@ unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { } } + if ((TSFlags & SIInstrFlags::FLAT) && !hasFlatOffsets()) { + // FIXME: Produces error without correct column reported. + auto OpNum = + AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::offset); + const auto &Op = Inst.getOperand(OpNum); + if (Op.getImm() != 0) + return Match_InvalidOperand; + } + return Match_Success; } @@ -3849,6 +3866,10 @@ AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const { return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); } +AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const { + return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); +} + //===----------------------------------------------------------------------===// // vop3 //===----------------------------------------------------------------------===// diff --git a/lib/Target/AMDGPU/FLATInstructions.td b/lib/Target/AMDGPU/FLATInstructions.td index 8ba9efd..98eda28 100644 --- a/lib/Target/AMDGPU/FLATInstructions.td +++ b/lib/Target/AMDGPU/FLATInstructions.td @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -def FLATAtomic : ComplexPattern; +def FLATAtomic : ComplexPattern; +def FLATOffset : ComplexPattern; //===----------------------------------------------------------------------===// // FLAT classes @@ -55,6 +56,8 @@ class FLAT_Real op, FLAT_Pseudo ps> : // copy relevant pseudo op flags let SubtargetPredicate = ps.SubtargetPredicate; let AsmMatchConverter = ps.AsmMatchConverter; + let TSFlags = ps.TSFlags; + let UseNamedOperandTable = ps.UseNamedOperandTable; // encoding fields bits<8> vaddr; @@ -63,10 +66,23 @@ class FLAT_Real op, FLAT_Pseudo ps> : bits<1> slc; bits<1> glc; + // Only valid on gfx9 + bits<1> lds = 0; // XXX - What does this actually do? + bits<2> seg; // Segment, 00=flat, 01=scratch, 10=global, 11=reserved + + // Signed offset. Highest bit ignored for flat and treated as 12-bit + // unsigned for flat acceses. + bits<13> offset; + bits<1> nv = 0; // XXX - What does this actually do? + // We don't use tfe right now, and it was removed in gfx9. bits<1> tfe = 0; - // 15-0 is reserved. + // Only valid on GFX9+ + let Inst{12-0} = offset; + let Inst{13} = lds; + let Inst{15-14} = 0; + let Inst{16} = !if(ps.has_glc, glc, ps.glcValue); let Inst{17} = slc; let Inst{24-18} = op; @@ -74,24 +90,30 @@ class FLAT_Real op, FLAT_Pseudo ps> : let Inst{39-32} = vaddr; let Inst{47-40} = !if(ps.has_data, vdata, ?); // 54-48 is reserved. - let Inst{55} = tfe; + let Inst{55} = nv; // nv on GFX9+, TFE before. let Inst{63-56} = !if(ps.has_vdst, vdst, ?); } -class FLAT_Load_Pseudo : FLAT_Pseudo< +class FLAT_Load_Pseudo : FLAT_Pseudo< opName, (outs regClass:$vdst), - (ins VReg_64:$vaddr, GLC:$glc, slc:$slc), - " $vdst, $vaddr$glc$slc"> { + !if(HasSignedOffset, + (ins VReg_64:$vaddr, offset_s13:$offset, GLC:$glc, slc:$slc), + (ins VReg_64:$vaddr, offset_u12:$offset, GLC:$glc, slc:$slc)), + " $vdst, $vaddr$offset$glc$slc"> { let has_data = 0; let mayLoad = 1; } -class FLAT_Store_Pseudo : FLAT_Pseudo< +class FLAT_Store_Pseudo : FLAT_Pseudo< opName, (outs), - (ins VReg_64:$vaddr, vdataClass:$vdata, GLC:$glc, slc:$slc), - " $vaddr, $vdata$glc$slc"> { + !if(HasSignedOffset, + (ins VReg_64:$vaddr, vdataClass:$vdata, offset_s13:$offset, GLC:$glc, slc:$slc), + (ins VReg_64:$vaddr, vdataClass:$vdata, offset_u12:$offset, GLC:$glc, slc:$slc)), + " $vaddr, $vdata$offset$glc$slc"> { let mayLoad = 0; let mayStore = 1; let has_vdst = 0; @@ -103,12 +125,15 @@ multiclass FLAT_Atomic_Pseudo< ValueType vt, SDPatternOperator atomic = null_frag, ValueType data_vt = vt, - RegisterClass data_rc = vdst_rc> { + RegisterClass data_rc = vdst_rc, + bit HasSignedOffset = 0> { def "" : FLAT_Pseudo , AtomicNoRet { let mayLoad = 1; @@ -121,10 +146,12 @@ multiclass FLAT_Atomic_Pseudo< def _RTN : FLAT_Pseudo , + (atomic (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), data_vt:$vdata))]>, AtomicNoRet { let mayLoad = 1; let mayStore = 1; @@ -312,31 +339,31 @@ def flat_truncstorei16 : flat_st ; // Patterns for global loads with no offset. class FlatLoadPat : Pat < - (vt (node i64:$addr)), - (inst $addr, 0, 0) + (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc))), + (inst $vaddr, $offset, 0, $slc) >; class FlatLoadAtomicPat : Pat < - (vt (node i64:$addr)), - (inst $addr, 1, 0) + (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc))), + (inst $vaddr, $offset, 1, $slc) >; class FlatStorePat : Pat < - (node vt:$data, i64:$addr), - (inst $addr, $data, 0, 0) + (node vt:$data, (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc)), + (inst $vaddr, $data, $offset, 0, $slc) >; class FlatStoreAtomicPat : Pat < // atomic store follows atomic binop convention so the address comes // first. - (node i64:$addr, vt:$data), - (inst $addr, $data, 1, 0) + (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), vt:$data), + (inst $vaddr, $data, $offset, 1, $slc) >; class FlatAtomicPat : Pat < - (vt (node i64:$addr, data_vt:$data)), - (inst $addr, $data, 0) + (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), data_vt:$data)), + (inst $vaddr, $data, $offset, $slc) >; let Predicates = [isCIVI] in { diff --git a/lib/Target/AMDGPU/SIISelLowering.cpp b/lib/Target/AMDGPU/SIISelLowering.cpp index 599ee94..441f1ef 100644 --- a/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/lib/Target/AMDGPU/SIISelLowering.cpp @@ -567,9 +567,17 @@ bool SITargetLowering::getAddrModeArguments(IntrinsicInst *II, } bool SITargetLowering::isLegalFlatAddressingMode(const AddrMode &AM) const { - // Flat instructions do not have offsets, and only have the register - // address. - return AM.BaseOffs == 0 && (AM.Scale == 0 || AM.Scale == 1); + if (!Subtarget->hasFlatInstOffsets()) { + // Flat instructions do not have offsets, and only have the register + // address. + return AM.BaseOffs == 0 && AM.Scale == 0; + } + + // GFX9 added a 13-bit signed offset. When using regular flat instructions, + // the sign bit is ignored and is treated as a 12-bit unsigned offset. + + // Just r + i + return isUInt<12>(AM.BaseOffs) && AM.Scale == 0; } bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const { diff --git a/lib/Target/AMDGPU/SIInstrInfo.cpp b/lib/Target/AMDGPU/SIInstrInfo.cpp index 58c05cf..1097814 100644 --- a/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -468,13 +468,11 @@ void SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB, Builder.addReg(RI.getSubReg(SrcReg, SubIdx)); - if (Idx == SubIndices.size() - 1) - Builder.addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit); - if (Idx == 0) Builder.addReg(DestReg, RegState::Define | RegState::Implicit); - Builder.addReg(SrcReg, RegState::Implicit); + bool UseKill = KillSrc && Idx == SubIndices.size() - 1; + Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit); } } @@ -2331,11 +2329,12 @@ static bool isSubRegOf(const SIRegisterInfo &TRI, bool SIInstrInfo::verifyInstruction(const MachineInstr &MI, StringRef &ErrInfo) const { uint16_t Opcode = MI.getOpcode(); - if (SIInstrInfo::isGenericOpcode(MI.getOpcode())) return true; - const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); + const MachineFunction *MF = MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF->getRegInfo(); + int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); @@ -2565,6 +2564,14 @@ bool SIInstrInfo::verifyInstruction(const MachineInstr &MI, } } + if (isFLAT(MI) && !MF->getSubtarget().hasFlatInstOffsets()) { + const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset); + if (Offset->getImm() != 0) { + ErrInfo = "subtarget does not support offsets in flat instructions"; + return false; + } + } + return true; } diff --git a/lib/Target/AMDGPU/SIInstrInfo.td b/lib/Target/AMDGPU/SIInstrInfo.td index 445bf79..470a47b 100644 --- a/lib/Target/AMDGPU/SIInstrInfo.td +++ b/lib/Target/AMDGPU/SIInstrInfo.td @@ -492,11 +492,21 @@ class NamedOperandU8 : Operand { let ParserMatchClass = MatchClass; } +class NamedOperandU12 : Operand { + let PrintMethod = "print"#Name; + let ParserMatchClass = MatchClass; +} + class NamedOperandU16 : Operand { let PrintMethod = "print"#Name; let ParserMatchClass = MatchClass; } +class NamedOperandS13 : Operand { + let PrintMethod = "print"#Name; + let ParserMatchClass = MatchClass; +} + class NamedOperandU32 : Operand { let PrintMethod = "print"#Name; let ParserMatchClass = MatchClass; @@ -514,6 +524,8 @@ def offen : NamedOperandBit<"Offen", NamedMatchClass<"Offen">>; def idxen : NamedOperandBit<"Idxen", NamedMatchClass<"Idxen">>; def addr64 : NamedOperandBit<"Addr64", NamedMatchClass<"Addr64">>; +def offset_u12 : NamedOperandU12<"Offset", NamedMatchClass<"OffsetU12">>; +def offset_s13 : NamedOperandS13<"Offset", NamedMatchClass<"OffsetS13">>; def offset : NamedOperandU16<"Offset", NamedMatchClass<"Offset">>; def offset0 : NamedOperandU8<"Offset0", NamedMatchClass<"Offset0">>; def offset1 : NamedOperandU8<"Offset1", NamedMatchClass<"Offset1">>; diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp index a7ac9a1..e498f70 100644 --- a/lib/Target/ARM/ARMCallLowering.cpp +++ b/lib/Target/ARM/ARMCallLowering.cpp @@ -35,9 +35,19 @@ ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI, Type *T) { - if (T->isArrayTy() || T->isStructTy()) + if (T->isArrayTy()) return true; + if (T->isStructTy()) { + // For now we only allow homogeneous structs that we can manipulate with + // G_MERGE_VALUES and G_UNMERGE_VALUES + auto StructT = cast(T); + for (unsigned i = 1, e = StructT->getNumElements(); i != e; ++i) + if (StructT->getElementType(i) != StructT->getElementType(0)) + return false; + return true; + } + EVT VT = TLI.getValueType(DL, T, true); if (!VT.isSimple() || VT.isVector() || !(VT.isInteger() || VT.isFloatingPoint())) @@ -220,12 +230,16 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, return false; SmallVector SplitVTs; + SmallVector Regs; ArgInfo RetInfo(VReg, Val->getType()); setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F); splitToValueTypes(RetInfo, SplitVTs, MF, [&](unsigned Reg, uint64_t Offset) { - MIRBuilder.buildExtract(Reg, VReg, Offset); + Regs.push_back(Reg); }); + if (Regs.size() > 1) + MIRBuilder.buildUnmerge(Regs, VReg); + CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg()); @@ -344,26 +358,6 @@ struct IncomingValueHandler : public CallLowering::ValueHandler { return 1; } - /// Merge the values in \p SrcRegs into \p DstReg at offsets \p SrcOffsets. - /// Note that the source registers are not required to have homogeneous types, - /// so we use G_INSERT rather than G_MERGE_VALUES. - // FIXME: Use G_MERGE_VALUES if the types are homogeneous. - void mergeRegisters(unsigned DstReg, ArrayRef SrcRegs, - ArrayRef SrcOffsets) { - LLT Ty = MRI.getType(DstReg); - - unsigned Dst = MRI.createGenericVirtualRegister(Ty); - MIRBuilder.buildUndef(Dst); - - for (unsigned i = 0; i < SrcRegs.size(); ++i) { - unsigned Tmp = MRI.createGenericVirtualRegister(Ty); - MIRBuilder.buildInsert(Tmp, Dst, SrcRegs[i], SrcOffsets[i]); - Dst = Tmp; - } - - MIRBuilder.buildCopy(DstReg, Dst); - } - /// Marking a physical register as used is different between formal /// parameters, where it's a basic block live-in, and call returns, where it's /// an implicit-def of the call instruction. @@ -413,22 +407,19 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, SmallVector ArgInfos; SmallVector SplitRegs; - SmallVector RegOffsets; unsigned Idx = 0; for (auto &Arg : F.args()) { ArgInfo AInfo(VRegs[Idx], Arg.getType()); setArgFlags(AInfo, Idx + AttributeList::FirstArgIndex, DL, F); SplitRegs.clear(); - RegOffsets.clear(); splitToValueTypes(AInfo, ArgInfos, MF, [&](unsigned Reg, uint64_t Offset) { SplitRegs.push_back(Reg); - RegOffsets.push_back(Offset); }); if (!SplitRegs.empty()) - ArgHandler.mergeRegisters(VRegs[Idx], SplitRegs, RegOffsets); + MIRBuilder.buildMerge(VRegs[Idx], SplitRegs); Idx++; } @@ -490,9 +481,13 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (!Arg.IsFixed) return false; + SmallVector Regs; splitToValueTypes(Arg, ArgInfos, MF, [&](unsigned Reg, uint64_t Offset) { - MIRBuilder.buildExtract(Reg, Arg.Reg, Offset); + Regs.push_back(Reg); }); + + if (Regs.size() > 1) + MIRBuilder.buildUnmerge(Regs, Arg.Reg); } auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false); @@ -508,11 +503,9 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; ArgInfos.clear(); - SmallVector RegOffsets; SmallVector SplitRegs; splitToValueTypes(OrigRet, ArgInfos, MF, [&](unsigned Reg, uint64_t Offset) { - RegOffsets.push_back(Offset); SplitRegs.push_back(Reg); }); @@ -521,10 +514,10 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler)) return false; - if (!RegOffsets.empty()) { + if (!SplitRegs.empty()) { // We have split the value and allocated each individual piece, now build // it up again. - RetHandler.mergeRegisters(OrigRet.Reg, SplitRegs, RegOffsets); + MIRBuilder.buildMerge(OrigRet.Reg, SplitRegs); } } diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 817b567..5d887c4 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -2010,7 +2010,8 @@ def VFNMAD : ADbI<0b11101, 0b01, 1, 0, [(set DPR:$Dd,(fsub_mlx (fneg (fmul_su DPR:$Dn,DPR:$Dm)), (f64 DPR:$Ddin)))]>, RegConstraint<"$Ddin = $Dd">, - Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>; + Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>, + Sched<[WriteFPMAC64, ReadFPMAC, ReadFPMUL, ReadFPMUL]>; def VFNMAS : ASbI<0b11101, 0b01, 1, 0, (outs SPR:$Sd), (ins SPR:$Sdin, SPR:$Sn, SPR:$Sm), @@ -2018,7 +2019,8 @@ def VFNMAS : ASbI<0b11101, 0b01, 1, 0, [(set SPR:$Sd, (fsub_mlx (fneg (fmul_su SPR:$Sn, SPR:$Sm)), SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, - Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]> { + Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]>, + Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]> { // Some single precision VFP instructions may be executed on both NEON and // VFP pipelines. } @@ -2028,7 +2030,8 @@ def VFNMAH : AHbI<0b11101, 0b01, 1, 0, IIC_fpFMAC16, "vfnma", ".f16\t$Sd, $Sn, $Sm", []>, RegConstraint<"$Sdin = $Sd">, - Requires<[HasFullFP16,UseFusedMAC]>; + Requires<[HasFullFP16,UseFusedMAC]>, + Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]>; def : Pat<(fsub_mlx (fneg (fmul_su DPR:$a, (f64 DPR:$b))), DPR:$dstin), (VFNMAD DPR:$dstin, DPR:$a, DPR:$b)>, @@ -2059,14 +2062,16 @@ def VFNMSD : ADbI<0b11101, 0b01, 0, 0, [(set DPR:$Dd, (fsub_mlx (fmul_su DPR:$Dn, DPR:$Dm), (f64 DPR:$Ddin)))]>, RegConstraint<"$Ddin = $Dd">, - Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>; + Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>, + Sched<[WriteFPMAC64, ReadFPMAC, ReadFPMUL, ReadFPMUL]>; def VFNMSS : ASbI<0b11101, 0b01, 0, 0, (outs SPR:$Sd), (ins SPR:$Sdin, SPR:$Sn, SPR:$Sm), IIC_fpFMAC32, "vfnms", ".f32\t$Sd, $Sn, $Sm", [(set SPR:$Sd, (fsub_mlx (fmul_su SPR:$Sn, SPR:$Sm), SPR:$Sdin))]>, RegConstraint<"$Sdin = $Sd">, - Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]> { + Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]>, + Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]> { // Some single precision VFP instructions may be executed on both NEON and // VFP pipelines. } @@ -2076,7 +2081,8 @@ def VFNMSH : AHbI<0b11101, 0b01, 0, 0, IIC_fpFMAC16, "vfnms", ".f16\t$Sd, $Sn, $Sm", []>, RegConstraint<"$Sdin = $Sd">, - Requires<[HasFullFP16,UseFusedMAC]>; + Requires<[HasFullFP16,UseFusedMAC]>, + Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]>; def : Pat<(fsub_mlx (fmul_su DPR:$a, (f64 DPR:$b)), DPR:$dstin), (VFNMSD DPR:$dstin, DPR:$a, DPR:$b)>, diff --git a/lib/Target/ARM/ARMLegalizerInfo.cpp b/lib/Target/ARM/ARMLegalizerInfo.cpp index 2d490b7..a706079 100644 --- a/lib/Target/ARM/ARMLegalizerInfo.cpp +++ b/lib/Target/ARM/ARMLegalizerInfo.cpp @@ -12,8 +12,10 @@ //===----------------------------------------------------------------------===// #include "ARMLegalizerInfo.h" +#include "ARMCallLowering.h" #include "ARMSubtarget.h" #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DerivedTypes.h" @@ -63,6 +65,16 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) { setAction({Op, s32}, Libcall); } + // FIXME: Support s8 and s16 as well + for (unsigned Op : {G_SREM, G_UREM}) + if (ST.hasDivideInARMMode()) + setAction({Op, s32}, Lower); + else if (ST.isTargetAEABI() || ST.isTargetGNUAEABI() || + ST.isTargetMuslAEABI()) + setAction({Op, s32}, Custom); + else + setAction({Op, s32}, Libcall); + for (unsigned Op : {G_SEXT, G_ZEXT}) { setAction({Op, s32}, Legal); for (auto Ty : {s1, s8, s16}) @@ -134,5 +146,38 @@ bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI, } return true; } + case G_SREM: + case G_UREM: { + unsigned OriginalResult = MI.getOperand(0).getReg(); + auto Size = MRI.getType(OriginalResult).getSizeInBits(); + if (Size != 32) + return false; + + auto Libcall = + MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; + + // Our divmod libcalls return a struct containing the quotient and the + // remainder. We need to create a virtual register for it. + auto &Ctx = MIRBuilder.getMF().getFunction()->getContext(); + Type *ArgTy = Type::getInt32Ty(Ctx); + StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true); + auto RetVal = MRI.createGenericVirtualRegister( + getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout())); + + auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy}, + {{MI.getOperand(1).getReg(), ArgTy}, + {MI.getOperand(2).getReg(), ArgTy}}); + if (Status != LegalizerHelper::Legalized) + return false; + + // The remainder is the second result of divmod. Split the return value into + // a new, unused register for the quotient and the destination of the + // original instruction for the remainder. + MIRBuilder.buildUnmerge( + {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult}, + RetVal); + + return LegalizerHelper::Legalized; + } } } diff --git a/lib/Target/ARM/ARMTargetTransformInfo.h b/lib/Target/ARM/ARMTargetTransformInfo.h index 7de0543..8a1a378 100644 --- a/lib/Target/ARM/ARMTargetTransformInfo.h +++ b/lib/Target/ARM/ARMTargetTransformInfo.h @@ -78,7 +78,7 @@ public: return 13; } - unsigned getRegisterBitWidth(bool Vector) { + unsigned getRegisterBitWidth(bool Vector) const { if (Vector) { if (ST->hasNEON()) return 128; diff --git a/lib/Target/BPF/BPFAsmPrinter.cpp b/lib/Target/BPF/BPFAsmPrinter.cpp index fcd903b..9397c78 100644 --- a/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/lib/Target/BPF/BPFAsmPrinter.cpp @@ -35,14 +35,15 @@ using namespace llvm; namespace { class BPFAsmPrinter : public AsmPrinter { public: - explicit BPFAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) + explicit BPFAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) : AsmPrinter(TM, std::move(Streamer)) {} StringRef getPassName() const override { return "BPF Assembly Printer"; } void EmitInstruction(const MachineInstr *MI) override; }; -} +} // namespace void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) { diff --git a/lib/Target/BPF/BPFISelDAGToDAG.cpp b/lib/Target/BPF/BPFISelDAGToDAG.cpp index 279cdb1..7d5fb6c 100644 --- a/lib/Target/BPF/BPFISelDAGToDAG.cpp +++ b/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -22,11 +22,14 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" + using namespace llvm; #define DEBUG_TYPE "bpf-isel" @@ -42,6 +45,8 @@ public: return "BPF DAG->DAG Pattern Instruction Selection"; } + void PreprocessISelDAG() override; + private: // Include the pieces autogenerated from the target description. #include "BPFGenDAGISel.inc" @@ -51,15 +56,31 @@ private: // Complex Pattern for address selection. bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset); bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset); + + // Find constants from a constant structure + typedef std::vector val_vec_type; + bool fillGenericConstant(const DataLayout &DL, const Constant *CV, + val_vec_type &Vals, uint64_t Offset); + bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA, + val_vec_type &Vals, int Offset); + bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA, + val_vec_type &Vals, int Offset); + bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS, + val_vec_type &Vals, int Offset); + bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset, + uint64_t Size, unsigned char *ByteSeq); + + // Mapping from ConstantStruct global value to corresponding byte-list values + std::map cs_vals_; }; -} +} // namespace // ComplexPattern used on BPF Load/Store instructions bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { // if Address is FI, get the TargetFrameIndex. SDLoc DL(Addr); if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; } @@ -85,13 +106,14 @@ bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { } } - Base = Addr; + Base = Addr; Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; } // ComplexPattern used on BPF FI instruction -bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { +bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, + SDValue &Offset) { SDLoc DL(Addr); if (!CurDAG->isBaseWithConstantOffset(Addr)) @@ -102,8 +124,7 @@ bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) if (isInt<16>(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = - dyn_cast(Addr.getOperand(0))) + if (FrameIndexSDNode *FIN = dyn_cast(Addr.getOperand(0))) Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); else return false; @@ -129,7 +150,8 @@ void BPFDAGToDAGISel::Select(SDNode *Node) { // tablegen selection should be handled here. switch (Opcode) { - default: break; + default: + break; case ISD::SDIV: { DebugLoc Empty; const DebugLoc &DL = Node->getDebugLoc(); @@ -181,6 +203,210 @@ void BPFDAGToDAGISel::Select(SDNode *Node) { SelectCode(Node); } +void BPFDAGToDAGISel::PreprocessISelDAG() { + // Iterate through all nodes, only interested in loads from ConstantStruct + // ConstantArray should have converted by IR->DAG processing + for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), + E = CurDAG->allnodes_end(); + I != E;) { + SDNode *Node = &*I++; + unsigned Opcode = Node->getOpcode(); + if (Opcode != ISD::LOAD) + continue; + + unsigned char new_val[8]; // hold up the constant values replacing loads. + bool to_replace = false; + SDLoc DL(Node); + const LoadSDNode *LD = cast(Node); + uint64_t size = LD->getMemOperand()->getSize(); + if (!size || size > 8 || (size & (size - 1))) + continue; + + SDNode *LDAddrNode = LD->getOperand(1).getNode(); + // Match LDAddr against either global_addr or (global_addr + offset) + unsigned opcode = LDAddrNode->getOpcode(); + if (opcode == ISD::ADD) { + SDValue OP1 = LDAddrNode->getOperand(0); + SDValue OP2 = LDAddrNode->getOperand(1); + + // We want to find the pattern global_addr + offset + SDNode *OP1N = OP1.getNode(); + if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END || + OP1N->getNumOperands() == 0) + continue; + + DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n'); + + const GlobalAddressSDNode *GADN = + dyn_cast(OP1N->getOperand(0).getNode()); + const ConstantSDNode *CDN = dyn_cast(OP2.getNode()); + if (GADN && CDN) + to_replace = + getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val); + } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END && + LDAddrNode->getNumOperands() > 0) { + DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n'); + + SDValue OP1 = LDAddrNode->getOperand(0); + if (const GlobalAddressSDNode *GADN = + dyn_cast(OP1.getNode())) + to_replace = getConstantFieldValue(GADN, 0, size, new_val); + } + + if (!to_replace) + continue; + + // replacing the old with a new value + uint64_t val; + if (size == 1) + val = *(uint8_t *)new_val; + else if (size == 2) + val = *(uint16_t *)new_val; + else if (size == 4) + val = *(uint32_t *)new_val; + else { + val = *(uint64_t *)new_val; + } + + DEBUG(dbgs() << "Replacing load of size " << size << " with constant " + << val << '\n'); + SDValue NVal = CurDAG->getConstant(val, DL, MVT::i64); + + // After replacement, the current node is dead, we need to + // go backward one step to make iterator still work + I--; + SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)}; + SDValue To[] = {NVal, NVal}; + CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2); + I++; + // It is safe to delete node now + CurDAG->DeleteNode(Node); + } +} + +bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node, + uint64_t Offset, uint64_t Size, + unsigned char *ByteSeq) { + const GlobalVariable *V = dyn_cast(Node->getGlobal()); + + if (!V || !V->hasInitializer()) + return false; + + const Constant *Init = V->getInitializer(); + const DataLayout &DL = CurDAG->getDataLayout(); + val_vec_type TmpVal; + + auto it = cs_vals_.find(static_cast(Init)); + if (it != cs_vals_.end()) { + TmpVal = it->second; + } else { + uint64_t total_size = 0; + if (const ConstantStruct *CS = dyn_cast(Init)) + total_size = + DL.getStructLayout(cast(CS->getType()))->getSizeInBytes(); + else if (const ConstantArray *CA = dyn_cast(Init)) + total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) * + CA->getNumOperands(); + else + return false; + + val_vec_type Vals(total_size, 0); + if (fillGenericConstant(DL, Init, Vals, 0) == false) + return false; + cs_vals_[static_cast(Init)] = Vals; + TmpVal = std::move(Vals); + } + + // test whether host endianness matches target + uint8_t test_buf[2]; + uint16_t test_val = 0x2345; + if (DL.isLittleEndian()) + support::endian::write16le(test_buf, test_val); + else + support::endian::write16be(test_buf, test_val); + + bool endian_match = *(uint16_t *)test_buf == test_val; + for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++) + ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j]; + + return true; +} + +bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL, + const Constant *CV, + val_vec_type &Vals, uint64_t Offset) { + uint64_t Size = DL.getTypeAllocSize(CV->getType()); + + if (isa(CV) || isa(CV)) + return true; // already done + + if (const ConstantInt *CI = dyn_cast(CV)) { + uint64_t val = CI->getZExtValue(); + DEBUG(dbgs() << "Byte array at offset " << Offset << " with value " << val + << '\n'); + + if (Size > 8 || (Size & (Size - 1))) + return false; + + // Store based on target endian + for (uint64_t i = 0; i < Size; ++i) { + Vals[Offset + i] = DL.isLittleEndian() + ? ((val >> (i * 8)) & 0xFF) + : ((val >> ((Size - i - 1) * 8)) & 0xFF); + } + return true; + } + + if (const ConstantDataArray *CDA = dyn_cast(CV)) + return fillConstantDataArray(DL, CDA, Vals, Offset); + + if (const ConstantArray *CA = dyn_cast(CV)) + return fillConstantArray(DL, CA, Vals, Offset); + + if (const ConstantStruct *CVS = dyn_cast(CV)) + return fillConstantStruct(DL, CVS, Vals, Offset); + + return false; +} + +bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL, + const ConstantDataArray *CDA, + val_vec_type &Vals, int Offset) { + for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) { + if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) == + false) + return false; + Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType()); + } + + return true; +} + +bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL, + const ConstantArray *CA, + val_vec_type &Vals, int Offset) { + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) { + if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false) + return false; + Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType()); + } + + return true; +} + +bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout &DL, + const ConstantStruct *CS, + val_vec_type &Vals, int Offset) { + const StructLayout *Layout = DL.getStructLayout(CS->getType()); + for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) { + const Constant *Field = CS->getOperand(i); + uint64_t SizeSoFar = Layout->getElementOffset(i); + if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false) + return false; + } + return true; +} + FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) { return new BPFDAGToDAGISel(TM); } diff --git a/lib/Target/BPF/BPFInstrInfo.td b/lib/Target/BPF/BPFInstrInfo.td index c6c0ff5..5ad7772 100644 --- a/lib/Target/BPF/BPFInstrInfo.td +++ b/lib/Target/BPF/BPFInstrInfo.td @@ -51,7 +51,7 @@ def u64imm : Operand { let PrintMethod = "printImm64Operand"; } -def i64immSExt32 : PatLeaf<(imm), +def i64immSExt32 : PatLeaf<(i64 imm), [{return isInt<32>(N->getSExtValue()); }]>; // Addressing modes. @@ -67,17 +67,17 @@ def MEMri : Operand { } // Conditional code predicates - used for pattern matching for jump instructions -def BPF_CC_EQ : PatLeaf<(imm), +def BPF_CC_EQ : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETEQ);}]>; -def BPF_CC_NE : PatLeaf<(imm), +def BPF_CC_NE : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETNE);}]>; -def BPF_CC_GE : PatLeaf<(imm), +def BPF_CC_GE : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETGE);}]>; -def BPF_CC_GT : PatLeaf<(imm), +def BPF_CC_GT : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETGT);}]>; -def BPF_CC_GTU : PatLeaf<(imm), +def BPF_CC_GTU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETUGT);}]>; -def BPF_CC_GEU : PatLeaf<(imm), +def BPF_CC_GEU : PatLeaf<(i64 imm), [{return (N->getZExtValue() == ISD::SETUGE);}]>; // jump instructions diff --git a/lib/Target/Hexagon/HexagonGenMux.cpp b/lib/Target/Hexagon/HexagonGenMux.cpp index 3c37d9e..11ac545 100644 --- a/lib/Target/Hexagon/HexagonGenMux.cpp +++ b/lib/Target/Hexagon/HexagonGenMux.cpp @@ -59,9 +59,7 @@ namespace { public: static char ID; - HexagonGenMux() : MachineFunctionPass(ID), HII(nullptr), HRI(nullptr) { - initializeHexagonGenMuxPass(*PassRegistry::getPassRegistry()); - } + HexagonGenMux() : MachineFunctionPass(ID) {} StringRef getPassName() const override { return "Hexagon generate mux instructions"; @@ -79,8 +77,8 @@ namespace { } private: - const HexagonInstrInfo *HII; - const HexagonRegisterInfo *HRI; + const HexagonInstrInfo *HII = nullptr; + const HexagonRegisterInfo *HRI = nullptr; struct CondsetInfo { unsigned PredR = 0; @@ -134,7 +132,7 @@ namespace { } // end anonymous namespace -INITIALIZE_PASS(HexagonGenMux, "hexagon-mux", +INITIALIZE_PASS(HexagonGenMux, "hexagon-gen-mux", "Hexagon generate mux instructions", false, false) void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const { @@ -297,12 +295,15 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) { unsigned SR1 = Src1->isReg() ? Src1->getReg() : 0; unsigned SR2 = Src2->isReg() ? Src2->getReg() : 0; bool Failure = false, CanUp = true, CanDown = true; + bool Used1 = false, Used2 = false; for (unsigned X = MinX+1; X < MaxX; X++) { const DefUseInfo &DU = DUM.lookup(X); if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) { Failure = true; break; } + Used1 |= DU.Uses[SR1]; + Used2 |= DU.Uses[SR2]; if (CanDown && DU.Defs[SR1]) CanDown = false; if (CanUp && DU.Defs[SR2]) @@ -316,6 +317,45 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) { // Prefer "down", since this will move the MUX farther away from the // predicate definition. MachineBasicBlock::iterator At = CanDown ? Def2 : Def1; + if (CanDown) { + // If the MUX is placed "down", we need to make sure that there aren't + // any kills of the source registers between the two defs. + if (Used1 || Used2) { + auto ResetKill = [this] (unsigned Reg, MachineInstr &MI) -> bool { + if (MachineOperand *Op = MI.findRegisterUseOperand(Reg, true, HRI)) { + Op->setIsKill(false); + return true; + } + return false; + }; + bool KilledSR1 = false, KilledSR2 = false; + for (MachineInstr &MJ : make_range(std::next(It1), It2)) { + if (SR1) + KilledSR1 |= ResetKill(SR1, MJ); + if (SR2) + KilledSR2 |= ResetKill(SR1, MJ); + } + // If any of the source registers were killed in this range, transfer + // the kills to the source operands: they will me "moved" to the + // resulting MUX and their parent instructions will be deleted. + if (KilledSR1) { + assert(Src1->isReg()); + Src1->setIsKill(true); + } + if (KilledSR2) { + assert(Src2->isReg()); + Src2->setIsKill(true); + } + } + } else { + // If the MUX is placed "up", it shouldn't kill any source registers + // that are still used afterwards. We can reset the kill flags directly + // on the operands, because the source instructions will be erased. + if (Used1 && Src1->isReg()) + Src1->setIsKill(false); + if (Used2 && Src2->isReg()) + Src2->setIsKill(false); + } ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2)); } diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index e443413..e5f49ca 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -124,6 +124,7 @@ private: bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src); bool isOrEquivalentToAdd(const SDNode *N) const; bool isAlignedMemNode(const MemSDNode *N) const; + bool isSmallStackStore(const StoreSDNode *N) const; bool isPositiveHalfWord(const SDNode *N) const; // DAG preprocessing functions. @@ -1462,6 +1463,20 @@ bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const { return N->getAlignment() >= N->getMemoryVT().getStoreSize(); } +bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const { + unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF); + switch (N->getMemoryVT().getStoreSize()) { + case 1: + return StackSize <= 56; // 1*2^6 - 8 + case 2: + return StackSize <= 120; // 2*2^6 - 8 + case 4: + return StackSize <= 248; // 4*2^6 - 8 + default: + return false; + } +} + // Return true when the given node fits in a positive half word. bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const { if (const ConstantSDNode *CN = dyn_cast(N)) { diff --git a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp index b748b58..f82ad6c 100644 --- a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp +++ b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp @@ -1744,7 +1744,8 @@ bool PolynomialMultiplyRecognize::recognize() { // wide as the target's pmpy instruction. if (!promoteTypes(LoopB, ExitB)) return false; - convertShiftsToLeft(LoopB, ExitB, IterCount); + if (!convertShiftsToLeft(LoopB, ExitB, IterCount)) + return false; cleanupLoopBody(LoopB); } diff --git a/lib/Target/Hexagon/HexagonPatterns.td b/lib/Target/Hexagon/HexagonPatterns.td index f269b74..6894196 100644 --- a/lib/Target/Hexagon/HexagonPatterns.td +++ b/lib/Target/Hexagon/HexagonPatterns.td @@ -401,6 +401,11 @@ def Aext64: PatFrag<(ops node:$Rs), (i64 (anyext node:$Rs))>; def Zext64: PatFrag<(ops node:$Rs), (i64 (zext node:$Rs))>; def Sext64: PatLeaf<(i64 Usxtw:$Rs)>; +def: Pat<(i32 (trunc (sra (mul Sext64:$Rs, Sext64:$Rt), (i32 32)))), + (M2_mpy_up (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>; +def: Pat<(i32 (trunc (srl (mul Sext64:$Rs, Sext64:$Rt), (i32 32)))), + (M2_mpy_up (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>; + def: Pat<(mul (Aext64 I32:$Rs), (Aext64 I32:$Rt)), (M2_dpmpyuu_s0 I32:$Rs, I32:$Rt)>; @@ -1470,16 +1475,22 @@ def i32in8ImmPred: PatLeaf<(i32 imm), [{ return v == (int64_t)(int8_t)v; }]>; +class SmallStackStore + : PatFrag<(ops node:$Val, node:$Addr), (Store node:$Val, node:$Addr), [{ + return isSmallStackStore(cast(N)); +}]>; let AddedComplexity = 40 in { // Even though the offset is not extendable in the store-immediate, we // can still generate the fi# in the base address. If the final offset // is not valid for the instruction, we will replace it with a scratch // register. -// def: Storexm_fi_pat ; -// def: Storexm_fi_pat ; -// def: Storexm_fi_pat ; + def: Storexm_fi_pat , s32_0ImmPred, + ToImmByte, S4_storeirb_io>; + def: Storexm_fi_pat , i16in8ImmPred, + ToImmHalf, S4_storeirh_io>; + def: Storexm_fi_pat , i32in8ImmPred, + ToImmWord, S4_storeiri_io>; // defm: Storexm_fi_add_pat ; diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp index c757b6e..e507a79 100644 --- a/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -111,6 +111,7 @@ namespace llvm { extern char &HexagonExpandCondsetsID; void initializeHexagonExpandCondsetsPass(PassRegistry&); void initializeHexagonLoopIdiomRecognizePass(PassRegistry&); + void initializeHexagonGenMuxPass(PassRegistry&); void initializeHexagonOptAddrModePass(PassRegistry&); Pass *createHexagonLoopIdiomPass(); @@ -152,8 +153,11 @@ static Reloc::Model getEffectiveRelocModel(Optional RM) { extern "C" void LLVMInitializeHexagonTarget() { // Register the target. RegisterTargetMachine X(getTheHexagonTarget()); - initializeHexagonLoopIdiomRecognizePass(*PassRegistry::getPassRegistry()); - initializeHexagonOptAddrModePass(*PassRegistry::getPassRegistry()); + + PassRegistry &PR = *PassRegistry::getPassRegistry(); + initializeHexagonLoopIdiomRecognizePass(PR); + initializeHexagonGenMuxPass(PR); + initializeHexagonOptAddrModePass(PR); } HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT, diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index f219301..68708dc 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -364,6 +364,18 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::UDIV, MVT::i64, Expand); setOperationAction(ISD::UREM, MVT::i64, Expand); + if (!(Subtarget.hasDSP() && Subtarget.hasMips32r2())) { + setOperationAction(ISD::ADDC, MVT::i32, Expand); + setOperationAction(ISD::ADDE, MVT::i32, Expand); + } + + setOperationAction(ISD::ADDC, MVT::i64, Expand); + setOperationAction(ISD::ADDE, MVT::i64, Expand); + setOperationAction(ISD::SUBC, MVT::i32, Expand); + setOperationAction(ISD::SUBE, MVT::i32, Expand); + setOperationAction(ISD::SUBC, MVT::i64, Expand); + setOperationAction(ISD::SUBE, MVT::i64, Expand); + // Operations not directly supported by Mips. setOperationAction(ISD::BR_CC, MVT::f32, Expand); setOperationAction(ISD::BR_CC, MVT::f64, Expand); @@ -469,6 +481,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::AND); setTargetDAGCombine(ISD::OR); setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::SUB); setTargetDAGCombine(ISD::AssertZext); setTargetDAGCombine(ISD::SHL); @@ -918,14 +931,130 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, } } +static SDValue performMADD_MSUBCombine(SDNode *ROOTNode, SelectionDAG &CurDAG, + const MipsSubtarget &Subtarget) { + // ROOTNode must have a multiplication as an operand for the match to be + // successful. + if (ROOTNode->getOperand(0).getOpcode() != ISD::MUL && + ROOTNode->getOperand(1).getOpcode() != ISD::MUL) + return SDValue(); + + // We don't handle vector types here. + if (ROOTNode->getValueType(0).isVector()) + return SDValue(); + + // For MIPS64, madd / msub instructions are inefficent to use with 64 bit + // arithmetic. E.g. + // (add (mul a b) c) => + // let res = (madd (mthi (drotr c 32))x(mtlo c) a b) in + // MIPS64: (or (dsll (mfhi res) 32) (dsrl (dsll (mflo res) 32) 32) + // or + // MIPS64R2: (dins (mflo res) (mfhi res) 32 32) + // + // The overhead of setting up the Hi/Lo registers and reassembling the + // result makes this a dubious optimzation for MIPS64. The core of the + // problem is that Hi/Lo contain the upper and lower 32 bits of the + // operand and result. + // + // It requires a chain of 4 add/mul for MIPS64R2 to get better code + // density than doing it naively, 5 for MIPS64. Additionally, using + // madd/msub on MIPS64 requires the operands actually be 32 bit sign + // extended operands, not true 64 bit values. + // + // FIXME: For the moment, disable this completely for MIPS64. + if (Subtarget.hasMips64()) + return SDValue(); + + SDValue Mult = ROOTNode->getOperand(0).getOpcode() == ISD::MUL + ? ROOTNode->getOperand(0) + : ROOTNode->getOperand(1); + + SDValue AddOperand = ROOTNode->getOperand(0).getOpcode() == ISD::MUL + ? ROOTNode->getOperand(1) + : ROOTNode->getOperand(0); + + // Transform this to a MADD only if the user of this node is the add. + // If there are other users of the mul, this function returns here. + if (!Mult.hasOneUse()) + return SDValue(); + + // maddu and madd are unusual instructions in that on MIPS64 bits 63..31 + // must be in canonical form, i.e. sign extended. For MIPS32, the operands + // of the multiply must have 32 or more sign bits, otherwise we cannot + // perform this optimization. We have to check this here as we're performing + // this optimization pre-legalization. + SDValue MultLHS = Mult->getOperand(0); + SDValue MultRHS = Mult->getOperand(1); + unsigned LHSSB = CurDAG.ComputeNumSignBits(MultLHS); + unsigned RHSSB = CurDAG.ComputeNumSignBits(MultRHS); + + if (LHSSB < 32 || RHSSB < 32) + return SDValue(); + + APInt HighMask = + APInt::getHighBitsSet(Mult->getValueType(0).getScalarSizeInBits(), 32); + bool IsUnsigned = CurDAG.MaskedValueIsZero(Mult->getOperand(0), HighMask) && + CurDAG.MaskedValueIsZero(Mult->getOperand(1), HighMask) && + CurDAG.MaskedValueIsZero(AddOperand, HighMask); + + // Initialize accumulator. + SDLoc DL(ROOTNode); + SDValue TopHalf; + SDValue BottomHalf; + BottomHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand, + CurDAG.getIntPtrConstant(0, DL)); + + TopHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand, + CurDAG.getIntPtrConstant(1, DL)); + SDValue ACCIn = CurDAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, + BottomHalf, + TopHalf); + + // Create MipsMAdd(u) / MipsMSub(u) node. + bool IsAdd = ROOTNode->getOpcode() == ISD::ADD; + unsigned Opcode = IsAdd ? (IsUnsigned ? MipsISD::MAddu : MipsISD::MAdd) + : (IsUnsigned ? MipsISD::MSubu : MipsISD::MSub); + SDValue MAddOps[3] = { + CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(0)), + CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(1)), ACCIn}; + EVT VTs[2] = {MVT::i32, MVT::i32}; + SDValue MAdd = CurDAG.getNode(Opcode, DL, VTs, MAddOps); + + SDValue ResLo = CurDAG.getNode(MipsISD::MFLO, DL, MVT::i32, MAdd); + SDValue ResHi = CurDAG.getNode(MipsISD::MFHI, DL, MVT::i32, MAdd); + SDValue Combined = + CurDAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResLo, ResHi); + return Combined; +} + +static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + // (sub v0 (mul v1, v2)) => (msub v1, v2, v0) + if (DCI.isBeforeLegalizeOps()) { + if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() && + !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64) + return performMADD_MSUBCombine(N, DAG, Subtarget); + + return SDValue(); + } + + return SDValue(); +} + static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const MipsSubtarget &Subtarget) { - // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt)) + // (add v0 (mul v1, v2)) => (madd v1, v2, v0) + if (DCI.isBeforeLegalizeOps()) { + if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() && + !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64) + return performMADD_MSUBCombine(N, DAG, Subtarget); - if (DCI.isBeforeLegalizeOps()) return SDValue(); + } + // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt)) SDValue Add = N->getOperand(1); if (Add.getOpcode() != ISD::ADD) @@ -1053,6 +1182,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performAssertZextCombine(N, DAG, DCI, Subtarget); case ISD::SHL: return performSHLCombine(N, DAG, DCI, Subtarget); + case ISD::SUB: + return performSUBCombine(N, DAG, DCI, Subtarget); } return SDValue(); diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index df62c66..4adf77f 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -103,12 +103,9 @@ void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); for (unsigned i = 1; i < Cond.size(); ++i) { - if (Cond[i].isReg()) - MIB.addReg(Cond[i].getReg()); - else if (Cond[i].isImm()) - MIB.addImm(Cond[i].getImm()); - else - assert(false && "Cannot copy operand"); + assert((Cond[i].isImm() || Cond[i].isReg()) && + "Cannot copy operand for conditional branch!"); + MIB.add(Cond[i]); } MIB.addMBB(TBB); } diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index b95f115..272595a 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -274,8 +274,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); - LongBrMBB->addSuccessor(BalTgtMBB); - BalTgtMBB->addSuccessor(TgtMBB); + LongBrMBB->addSuccessor(BalTgtMBB, BranchProbability::getOne()); + BalTgtMBB->addSuccessor(&*FallThroughMBB, BranchProbability::getOne()); // We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an @@ -342,8 +342,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { .addReg(Mips::SP).addImm(8); if (Subtarget.hasMips32r6()) - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR)) - .addReg(Mips::ZERO).addReg(Mips::AT); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR), Mips::ZERO) + .addReg(Mips::AT); else BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT); @@ -415,8 +415,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { .addReg(Mips::SP_64).addImm(0); if (Subtarget.hasMips64r6()) - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64)) - .addReg(Mips::ZERO_64).addReg(Mips::AT_64); + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64), Mips::ZERO_64) + .addReg(Mips::AT_64); else BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 49ae6dd..4be26dd 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -245,46 +245,64 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { } } -void MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, - SDValue CmpLHS, const SDLoc &DL, - SDNode *Node) const { - unsigned Opc = InFlag.getOpcode(); (void)Opc; - - assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || - (Opc == ISD::SUBC || Opc == ISD::SUBE)) && - "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); - - unsigned SLTuOp = Mips::SLTu, ADDuOp = Mips::ADDu; - if (Subtarget->isGP64bit()) { - SLTuOp = Mips::SLTu64; - ADDuOp = Mips::DADDu; - } - - SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; +void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { + SDValue InFlag = Node->getOperand(2); + unsigned Opc = InFlag.getOpcode(); SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1); EVT VT = LHS.getValueType(); - SDNode *Carry = CurDAG->getMachineNode(SLTuOp, DL, VT, Ops); - - if (Subtarget->isGP64bit()) { - // On 64-bit targets, sltu produces an i64 but our backend currently says - // that SLTu64 produces an i32. We need to fix this in the long run but for - // now, just make the DAG type-correct by asserting the upper bits are zero. - Carry = CurDAG->getMachineNode(Mips::SUBREG_TO_REG, DL, VT, - CurDAG->getTargetConstant(0, DL, VT), - SDValue(Carry, 0), - CurDAG->getTargetConstant(Mips::sub_32, DL, - VT)); + // In the base case, we can rely on the carry bit from the addsc + // instruction. + if (Opc == ISD::ADDC) { + SDValue Ops[3] = {LHS, RHS, InFlag}; + CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Ops); + return; } - // Generate a second addition only if we know that RHS is not a - // constant-zero node. - SDNode *AddCarry = Carry; - ConstantSDNode *C = dyn_cast(RHS); - if (!C || C->getZExtValue()) - AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS); + assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!"); + + // The more complex case is when there is a chain of ISD::ADDE nodes like: + // (adde (adde (adde (addc a b) c) d) e). + // + // The addwc instruction does not write to the carry bit, instead it writes + // to bit 20 of the dsp control register. To match this series of nodes, each + // intermediate adde node must be expanded to write the carry bit before the + // addition. + + // Start by reading the overflow field for addsc and moving the value to the + // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP + // corresponds to reading/writing the entire control register to/from a GPR. + + SDValue CstOne = CurDAG->getTargetConstant(1, DL, MVT::i32); + + SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32); + + SDNode *DSPCtrlField = + CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, MVT::Glue, CstOne, InFlag); + + SDNode *Carry = CurDAG->getMachineNode( + Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne); - CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0)); + SDValue Ops[4] = {SDValue(DSPCtrlField, 0), + CurDAG->getTargetConstant(6, DL, MVT::i32), CstOne, + SDValue(Carry, 0)}; + SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops); + + // My reading of the the MIPS DSP 3.01 specification isn't as clear as I + // would like about whether bit 20 always gets overwritten by addwc. + // Hence take an extremely conservative view and presume it's sticky. We + // therefore need to clear it. + + SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32); + + SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)}; + SDNode *DSPCtrlFinal = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps); + + SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue, + SDValue(DSPCtrlFinal, 0), CstOne); + + SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)}; + CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Operands); } /// Match frameindex @@ -765,19 +783,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { switch(Opcode) { default: break; - case ISD::SUBE: { - SDValue InFlag = Node->getOperand(2); - unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu; - selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node); - return true; - } - case ISD::ADDE: { - if (Subtarget->hasDSP()) // Select DSP instructions, ADDSC and ADDWC. - break; - SDValue InFlag = Node->getOperand(2); - unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu; - selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node); + selectAddE(Node, DL); return true; } diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index f89a350..6f38289 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -41,8 +41,7 @@ private: const SDLoc &dl, EVT Ty, bool HasLo, bool HasHi); - void selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS, - const SDLoc &DL, SDNode *Node) const; + void selectAddE(SDNode *Node, const SDLoc &DL) const; bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const; bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index bf7f079..2382ea2 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -179,8 +179,6 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::LOAD, MVT::i32, Custom); setOperationAction(ISD::STORE, MVT::i32, Custom); - setTargetDAGCombine(ISD::ADDE); - setTargetDAGCombine(ISD::SUBE); setTargetDAGCombine(ISD::MUL); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); @@ -421,163 +419,6 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op, return MipsTargetLowering::LowerOperation(Op, DAG); } -// selectMADD - -// Transforms a subgraph in CurDAG if the following pattern is found: -// (addc multLo, Lo0), (adde multHi, Hi0), -// where, -// multHi/Lo: product of multiplication -// Lo0: initial value of Lo register -// Hi0: initial value of Hi register -// Return true if pattern matching was successful. -static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) { - // ADDENode's second operand must be a flag output of an ADDC node in order - // for the matching to be successful. - SDNode *ADDCNode = ADDENode->getOperand(2).getNode(); - - if (ADDCNode->getOpcode() != ISD::ADDC) - return false; - - SDValue MultHi = ADDENode->getOperand(0); - SDValue MultLo = ADDCNode->getOperand(0); - SDNode *MultNode = MultHi.getNode(); - unsigned MultOpc = MultHi.getOpcode(); - - // MultHi and MultLo must be generated by the same node, - if (MultLo.getNode() != MultNode) - return false; - - // and it must be a multiplication. - if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) - return false; - - // MultLo amd MultHi must be the first and second output of MultNode - // respectively. - if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) - return false; - - // Transform this to a MADD only if ADDENode and ADDCNode are the only users - // of the values of MultNode, in which case MultNode will be removed in later - // phases. - // If there exist users other than ADDENode or ADDCNode, this function returns - // here, which will result in MultNode being mapped to a single MULT - // instruction node rather than a pair of MULT and MADD instructions being - // produced. - if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) - return false; - - SDLoc DL(ADDENode); - - // Initialize accumulator. - SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped, - ADDCNode->getOperand(1), - ADDENode->getOperand(1)); - - // create MipsMAdd(u) node - MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; - - SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped, - MultNode->getOperand(0),// Factor 0 - MultNode->getOperand(1),// Factor 1 - ACCIn); - - // replace uses of adde and addc here - if (!SDValue(ADDCNode, 0).use_empty()) { - SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MAdd); - CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut); - } - if (!SDValue(ADDENode, 0).use_empty()) { - SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MAdd); - CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut); - } - - return true; -} - -// selectMSUB - -// Transforms a subgraph in CurDAG if the following pattern is found: -// (addc Lo0, multLo), (sube Hi0, multHi), -// where, -// multHi/Lo: product of multiplication -// Lo0: initial value of Lo register -// Hi0: initial value of Hi register -// Return true if pattern matching was successful. -static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) { - // SUBENode's second operand must be a flag output of an SUBC node in order - // for the matching to be successful. - SDNode *SUBCNode = SUBENode->getOperand(2).getNode(); - - if (SUBCNode->getOpcode() != ISD::SUBC) - return false; - - SDValue MultHi = SUBENode->getOperand(1); - SDValue MultLo = SUBCNode->getOperand(1); - SDNode *MultNode = MultHi.getNode(); - unsigned MultOpc = MultHi.getOpcode(); - - // MultHi and MultLo must be generated by the same node, - if (MultLo.getNode() != MultNode) - return false; - - // and it must be a multiplication. - if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) - return false; - - // MultLo amd MultHi must be the first and second output of MultNode - // respectively. - if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) - return false; - - // Transform this to a MSUB only if SUBENode and SUBCNode are the only users - // of the values of MultNode, in which case MultNode will be removed in later - // phases. - // If there exist users other than SUBENode or SUBCNode, this function returns - // here, which will result in MultNode being mapped to a single MULT - // instruction node rather than a pair of MULT and MSUB instructions being - // produced. - if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) - return false; - - SDLoc DL(SUBENode); - - // Initialize accumulator. - SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped, - SUBCNode->getOperand(0), - SUBENode->getOperand(0)); - - // create MipsSub(u) node - MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; - - SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue, - MultNode->getOperand(0),// Factor 0 - MultNode->getOperand(1),// Factor 1 - ACCIn); - - // replace uses of sube and subc here - if (!SDValue(SUBCNode, 0).use_empty()) { - SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MSub); - CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut); - } - if (!SDValue(SUBENode, 0).use_empty()) { - SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MSub); - CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut); - } - - return true; -} - -static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalize()) - return SDValue(); - - if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() && - N->getValueType(0) == MVT::i32 && selectMADD(N, &DAG)) - return SDValue(N, 0); - - return SDValue(); -} - // Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT // // Performs the following transformations: @@ -820,19 +661,6 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } -static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI, - const MipsSubtarget &Subtarget) { - if (DCI.isBeforeLegalize()) - return SDValue(); - - if (Subtarget.hasMips32() && N->getValueType(0) == MVT::i32 && - selectMSUB(N, &DAG)) - return SDValue(N, 0); - - return SDValue(); -} - static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT, EVT ShiftTy, SelectionDAG &DAG) { // Clear the upper (64 - VT.sizeInBits) bits. @@ -1110,16 +938,12 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SDValue Val; switch (N->getOpcode()) { - case ISD::ADDE: - return performADDECombine(N, DAG, DCI, Subtarget); case ISD::AND: Val = performANDCombine(N, DAG, DCI, Subtarget); break; case ISD::OR: Val = performORCombine(N, DAG, DCI, Subtarget); break; - case ISD::SUBE: - return performSUBECombine(N, DAG, DCI, Subtarget); case ISD::MUL: return performMULCombine(N, DAG, DCI, this); case ISD::SHL: diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 625a652..ccd47f0 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -78,7 +78,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // IsNan2008 - IEEE 754-2008 NaN encoding. bool IsNaN2008bit; - // IsFP64bit - General-purpose registers are 64 bits wide + // IsGP64bit - General-purpose registers are 64 bits wide bool IsGP64bit; // IsPTR64bit - Pointers are 64 bit wide diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 28d496e..afd2e87 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -2907,19 +2907,6 @@ SDValue PPCDAGToDAGISel::get64BitZExtCompare(SDValue LHS, SDValue RHS, getI64Imm(58, dl), getI64Imm(63, dl)), 0); } - case ISD::SETNE: { - // {addc.reg, addc.CA} = (addcarry (xor %a, %b), -1) - // (zext (setcc %a, %b, setne)) -> (sube addc.reg, addc.reg, addc.CA) - // {addcz.reg, addcz.CA} = (addcarry %a, -1) - // (zext (setcc %a, 0, setne)) -> (sube addcz.reg, addcz.reg, addcz.CA) - SDValue Xor = IsRHSZero ? LHS : - SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0); - SDValue AC = - SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue, - Xor, getI32Imm(~0U, dl)), 0); - return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, AC, - Xor, AC.getValue(1)), 0); - } } } @@ -2944,19 +2931,6 @@ SDValue PPCDAGToDAGISel::get64BitSExtCompare(SDValue LHS, SDValue RHS, return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, Addic, Addic, Addic.getValue(1)), 0); } - case ISD::SETNE: { - // {subfc.reg, subfc.CA} = (subcarry 0, (xor %a, %b)) - // (sext (setcc %a, %b, setne)) -> (sube subfc.reg, subfc.reg, subfc.CA) - // {subfcz.reg, subfcz.CA} = (subcarry 0, %a) - // (sext (setcc %a, 0, setne)) -> (sube subfcz.reg, subfcz.reg, subfcz.CA) - SDValue Xor = IsRHSZero ? LHS : - SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0); - SDValue SC = - SDValue(CurDAG->getMachineNode(PPC::SUBFIC8, dl, MVT::i64, MVT::Glue, - Xor, getI32Imm(0, dl)), 0); - return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, SC, - SC, SC.getValue(1)), 0); - } } } diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index bda4e5e..662550f 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -136,7 +136,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, addRegisterClass(MVT::f64, &PPC::F8RCRegClass); } - // PowerPC has an i16 but no i8 (or i1) SEXTLOAD + // PowerPC has an i16 but no i8 (or i1) SEXTLOAD. for (MVT VT : MVT::integer_valuetypes()) { setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand); @@ -175,7 +175,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::UINT_TO_FP, MVT::i1, Custom); } - // PowerPC does not support direct load / store of condition registers + // PowerPC does not support direct load/store of condition registers. setOperationAction(ISD::LOAD, MVT::i1, Custom); setOperationAction(ISD::STORE, MVT::i1, Custom); @@ -204,11 +204,23 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, setOperationAction(ISD::FNEARBYINT, MVT::ppcf128, Expand); setOperationAction(ISD::FREM, MVT::ppcf128, Expand); - // PowerPC has no SREM/UREM instructions - setOperationAction(ISD::SREM, MVT::i32, Expand); - setOperationAction(ISD::UREM, MVT::i32, Expand); - setOperationAction(ISD::SREM, MVT::i64, Expand); - setOperationAction(ISD::UREM, MVT::i64, Expand); + // PowerPC has no SREM/UREM instructions unless we are on P9 + // On P9 we may use a hardware instruction to compute the remainder. + // The instructions are not legalized directly because in the cases where the + // result of both the remainder and the division is required it is more + // efficient to compute the remainder from the result of the division rather + // than use the remainder instruction. + if (Subtarget.isISA3_0()) { + setOperationAction(ISD::SREM, MVT::i32, Custom); + setOperationAction(ISD::UREM, MVT::i32, Custom); + setOperationAction(ISD::SREM, MVT::i64, Custom); + setOperationAction(ISD::UREM, MVT::i64, Custom); + } else { + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); + } // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM. setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); @@ -1116,6 +1128,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { case PPCISD::VPERM: return "PPCISD::VPERM"; case PPCISD::XXSPLT: return "PPCISD::XXSPLT"; case PPCISD::XXINSERT: return "PPCISD::XXINSERT"; + case PPCISD::XXREVERSE: return "PPCISD::XXREVERSE"; case PPCISD::XXPERMDI: return "PPCISD::XXPERMDI"; case PPCISD::VECSHL: return "PPCISD::VECSHL"; case PPCISD::CMPB: return "PPCISD::CMPB"; @@ -1598,22 +1611,34 @@ bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { return true; } -// Check that the mask is shuffling N byte elements. -static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width) { +/// Check that the mask is shuffling N byte elements. Within each N byte +/// element of the mask, the indices could be either in increasing or +/// decreasing order as long as they are consecutive. +/// \param[in] N the shuffle vector SD Node to analyze +/// \param[in] Width the element width in bytes, could be 2/4/8/16 (HalfWord/ +/// Word/DoubleWord/QuadWord). +/// \param[in] StepLen the delta indices number among the N byte element, if +/// the mask is in increasing/decreasing order then it is 1/-1. +/// \return true iff the mask is shuffling N byte elements. +static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width, + int StepLen) { assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) && "Unexpected element width."); + assert((StepLen == 1 || StepLen == -1) && "Unexpected element width."); unsigned NumOfElem = 16 / Width; unsigned MaskVal[16]; // Width is never greater than 16 for (unsigned i = 0; i < NumOfElem; ++i) { MaskVal[0] = N->getMaskElt(i * Width); - if (MaskVal[0] % Width) { + if ((StepLen == 1) && (MaskVal[0] % Width)) { + return false; + } else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) { return false; } for (unsigned int j = 1; j < Width; ++j) { MaskVal[j] = N->getMaskElt(i * Width + j); - if (MaskVal[j] != MaskVal[j-1] + 1) { + if (MaskVal[j] != MaskVal[j-1] + StepLen) { return false; } } @@ -1624,7 +1649,7 @@ static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width) { bool PPC::isXXINSERTWMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, unsigned &InsertAtByte, bool &Swap, bool IsLE) { - if (!isNByteElemShuffleMask(N, 4)) + if (!isNByteElemShuffleMask(N, 4, 1)) return false; // Now we look at mask elements 0,4,8,12 @@ -1701,7 +1726,7 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE) { assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8"); // Ensure each byte index of the word is consecutive. - if (!isNByteElemShuffleMask(N, 4)) + if (!isNByteElemShuffleMask(N, 4, 1)) return false; // Now we look at mask elements 0,4,8,12, which are the beginning of words. @@ -1759,6 +1784,35 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, } } +bool static isXXBRShuffleMaskHelper(ShuffleVectorSDNode *N, int Width) { + assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8"); + + if (!isNByteElemShuffleMask(N, Width, -1)) + return false; + + for (int i = 0; i < 16; i += Width) + if (N->getMaskElt(i) != i + Width - 1) + return false; + + return true; +} + +bool PPC::isXXBRHShuffleMask(ShuffleVectorSDNode *N) { + return isXXBRShuffleMaskHelper(N, 2); +} + +bool PPC::isXXBRWShuffleMask(ShuffleVectorSDNode *N) { + return isXXBRShuffleMaskHelper(N, 4); +} + +bool PPC::isXXBRDShuffleMask(ShuffleVectorSDNode *N) { + return isXXBRShuffleMaskHelper(N, 8); +} + +bool PPC::isXXBRQShuffleMask(ShuffleVectorSDNode *N) { + return isXXBRShuffleMaskHelper(N, 16); +} + /// Can node \p N be lowered to an XXPERMDI instruction? If so, set \p Swap /// if the inputs to the instruction should be swapped and set \p DM to the /// value for the immediate. @@ -1772,7 +1826,7 @@ bool PPC::isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &DM, assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8"); // Ensure each byte index of the double word is consecutive. - if (!isNByteElemShuffleMask(N, 8)) + if (!isNByteElemShuffleMask(N, 8, 1)) return false; unsigned M0 = N->getMaskElt(0) / 8; @@ -6819,6 +6873,7 @@ bool PPCTargetLowering::canReuseLoadAddress(SDValue Op, EVT MemVT, // Given the head of the old chain, ResChain, insert a token factor containing // it and NewResChain, and make users of ResChain now be users of that token // factor. +// TODO: Remove and use DAG::makeEquivalentMemoryOrdering() instead. void PPCTargetLowering::spliceIntoChain(SDValue ResChain, SDValue NewResChain, SelectionDAG &DAG) const { @@ -7846,6 +7901,26 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, PermDI); } + if (Subtarget.hasP9Vector()) { + if (PPC::isXXBRHShuffleMask(SVOp)) { + SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v8i16, V1); + SDValue ReveHWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v8i16, Conv); + return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveHWord); + } else if (PPC::isXXBRWShuffleMask(SVOp)) { + SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, V1); + SDValue ReveWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v4i32, Conv); + return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveWord); + } else if (PPC::isXXBRDShuffleMask(SVOp)) { + SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v2i64, V1); + SDValue ReveDWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v2i64, Conv); + return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveDWord); + } else if (PPC::isXXBRQShuffleMask(SVOp)) { + SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v1i128, V1); + SDValue ReveQWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v1i128, Conv); + return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveQWord); + } + } + if (Subtarget.hasVSX()) { if (V2.isUndef() && PPC::isSplatShuffleMask(SVOp, 4)) { int SplatIdx = PPC::getVSPLTImmediate(SVOp, 4, DAG); @@ -8393,6 +8468,18 @@ SDValue PPCTargetLowering::LowerINTRINSIC_VOID(SDValue Op, return SDValue(); } +SDValue PPCTargetLowering::LowerREM(SDValue Op, SelectionDAG &DAG) const { + // Check for a DIV with the same operands as this REM. + for (auto UI : Op.getOperand(1)->uses()) { + if ((Op.getOpcode() == ISD::SREM && UI->getOpcode() == ISD::SDIV) || + (Op.getOpcode() == ISD::UREM && UI->getOpcode() == ISD::UDIV)) + if (UI->getOperand(0) == Op.getOperand(0) && + UI->getOperand(1) == Op.getOperand(1)) + return SDValue(); + } + return Op; +} + SDValue PPCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const { SDLoc dl(Op); @@ -8861,6 +8948,9 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::INTRINSIC_VOID: return LowerINTRINSIC_VOID(Op, DAG); + case ISD::SREM: + case ISD::UREM: + return LowerREM(Op, DAG); } } diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index 7982a4a..a510872 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -86,6 +86,10 @@ namespace llvm { /// XXINSERT, + /// XXREVERSE - The PPC VSX reverse instruction + /// + XXREVERSE, + /// VECSHL - The PPC VSX shift left instruction /// VECSHL, @@ -458,6 +462,23 @@ namespace llvm { /// for a XXSLDWI instruction. bool isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, bool &Swap, bool IsLE); + + /// isXXBRHShuffleMask - Return true if this is a shuffle mask suitable + /// for a XXBRH instruction. + bool isXXBRHShuffleMask(ShuffleVectorSDNode *N); + + /// isXXBRWShuffleMask - Return true if this is a shuffle mask suitable + /// for a XXBRW instruction. + bool isXXBRWShuffleMask(ShuffleVectorSDNode *N); + + /// isXXBRDShuffleMask - Return true if this is a shuffle mask suitable + /// for a XXBRD instruction. + bool isXXBRDShuffleMask(ShuffleVectorSDNode *N); + + /// isXXBRQShuffleMask - Return true if this is a shuffle mask suitable + /// for a XXBRQ instruction. + bool isXXBRQShuffleMask(ShuffleVectorSDNode *N); + /// isXXPERMDIShuffleMask - Return true if this is a shuffle mask suitable /// for a XXPERMDI instruction. bool isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts, @@ -918,6 +939,7 @@ namespace llvm { SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerREM(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index 295590b..70536a6 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -683,6 +683,16 @@ def DIVDE : XOForm_1<31, 425, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), "divde $rT, $rA, $rB", IIC_IntDivD, [(set i64:$rT, (int_ppc_divde g8rc:$rA, g8rc:$rB))]>, isPPC64, Requires<[HasExtDiv]>; + +let Predicates = [IsISA3_0] in { +def MODSD : XForm_8<31, 777, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), + "modsd $rT, $rA, $rB", IIC_IntDivW, + [(set i64:$rT, (srem i64:$rA, i64:$rB))]>; +def MODUD : XForm_8<31, 265, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), + "modud $rT, $rA, $rB", IIC_IntDivW, + [(set i64:$rT, (urem i64:$rA, i64:$rB))]>; +} + let Defs = [CR0] in def DIVDEo : XOForm_1<31, 425, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB), "divde. $rT, $rA, $rB", IIC_IntDivD, diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index f3c68c4..236e513 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1964,7 +1964,7 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { } case PPC::CFENCE8: { auto Val = MI.getOperand(0).getReg(); - BuildMI(MBB, MI, DL, get(PPC::CMPW), PPC::CR7).addReg(Val).addReg(Val); + BuildMI(MBB, MI, DL, get(PPC::CMPD), PPC::CR7).addReg(Val).addReg(Val); BuildMI(MBB, MI, DL, get(PPC::CTRL_DEP)) .addImm(PPC::PRED_NE_MINUS) .addReg(PPC::CR7) diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 8223aa6..47d59c2 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -53,6 +53,10 @@ def SDT_PPCVecInsert : SDTypeProfile<1, 3, [ SDTCisVec<0>, SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3> ]>; +def SDT_PPCVecReverse: SDTypeProfile<1, 1, [ SDTCisVec<0>, + SDTCisVec<1> +]>; + def SDT_PPCxxpermdi: SDTypeProfile<1, 3, [ SDTCisVec<0>, SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3> ]>; @@ -174,6 +178,7 @@ def PPCaddiDtprelL : SDNode<"PPCISD::ADDI_DTPREL_L", SDTIntBinOp>; def PPCvperm : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>; def PPCxxsplt : SDNode<"PPCISD::XXSPLT", SDT_PPCVecSplat, []>; def PPCxxinsert : SDNode<"PPCISD::XXINSERT", SDT_PPCVecInsert, []>; +def PPCxxreverse : SDNode<"PPCISD::XXREVERSE", SDT_PPCVecReverse, []>; def PPCxxpermdi : SDNode<"PPCISD::XXPERMDI", SDT_PPCxxpermdi, []>; def PPCvecshl : SDNode<"PPCISD::VECSHL", SDT_PPCVecShift, []>; @@ -2544,6 +2549,14 @@ let Uses = [RM] in { "mffs. $rT", IIC_IntMFFS, []>, isDOT; } +let Predicates = [IsISA3_0] in { +def MODSW : XForm_8<31, 779, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB), + "modsw $rT, $rA, $rB", IIC_IntDivW, + [(set i32:$rT, (srem i32:$rA, i32:$rB))]>; +def MODUW : XForm_8<31, 267, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB), + "moduw $rT, $rA, $rB", IIC_IntDivW, + [(set i32:$rT, (urem i32:$rA, i32:$rB))]>; +} let PPC970_Unit = 1, hasSideEffects = 0 in { // FXU Operations. // XO-Form instructions. Arithmetic instructions that can set overflow bit diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td index e214d26..9cfc897 100644 --- a/lib/Target/PowerPC/PPCInstrVSX.td +++ b/lib/Target/PowerPC/PPCInstrVSX.td @@ -2340,6 +2340,16 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def XXBRD : XX2_XT6_XO5_XB6<60, 23, 475, "xxbrd", vsrc, []>; def XXBRQ : XX2_XT6_XO5_XB6<60, 31, 475, "xxbrq", vsrc, []>; + // Vector Reverse + def : Pat<(v8i16 (PPCxxreverse v8i16 :$A)), + (v8i16 (COPY_TO_REGCLASS (XXBRH (COPY_TO_REGCLASS $A, VSRC)), VRRC))>; + def : Pat<(v4i32 (PPCxxreverse v4i32 :$A)), + (v4i32 (XXBRW $A))>; + def : Pat<(v2i64 (PPCxxreverse v2i64 :$A)), + (v2i64 (XXBRD $A))>; + def : Pat<(v1i128 (PPCxxreverse v1i128 :$A)), + (v1i128 (COPY_TO_REGCLASS (XXBRQ (COPY_TO_REGCLASS $A, VSRC)), VRRC))>; + // Vector Permute def XXPERM : XX3_XT5_XA5_XB5<60, 26, "xxperm" , vsrc, vsrc, vsrc, IIC_VecPerm, []>; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index aad9139..637e52b 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -273,6 +273,20 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { return Reserved; } +bool PPCRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg, + const MachineFunction &MF) const { + assert(TargetRegisterInfo::isPhysicalRegister(PhysReg)); + if (TM.isELFv2ABI() && PhysReg == PPC::X2) { + // X2 is guaranteed to be preserved within a function if it is reserved. + // The reason it's reserved is that it's the TOC pointer (and the function + // uses the TOC). In functions where it isn't reserved (i.e. leaf functions + // with no TOC access), we can't claim that it is preserved. + return (getReservedRegs(MF).test(PPC::X2)); + } else { + return false; + } +} + unsigned PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const { const PPCFrameLowering *TFI = getFrameLowering(MF); diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 4a96327..0bbb71f 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -83,6 +83,7 @@ public: void adjustStackMapLiveOutMask(uint32_t *Mask) const override; BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isCallerPreservedPhysReg(unsigned PhysReg, const MachineFunction &MF) const override; /// We require the register scavenger. bool requiresRegisterScavenging(const MachineFunction &MF) const override { diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index 5559cdc..3dbd5f5 100644 --- a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -230,7 +230,7 @@ unsigned PPCTTIImpl::getNumberOfRegisters(bool Vector) { return ST->hasVSX() ? 64 : 32; } -unsigned PPCTTIImpl::getRegisterBitWidth(bool Vector) { +unsigned PPCTTIImpl::getRegisterBitWidth(bool Vector) const { if (Vector) { if (ST->hasQPX()) return 256; if (ST->hasAltivec()) return 128; diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.h b/lib/Target/PowerPC/PPCTargetTransformInfo.h index 2e0116f..758c335 100644 --- a/lib/Target/PowerPC/PPCTargetTransformInfo.h +++ b/lib/Target/PowerPC/PPCTargetTransformInfo.h @@ -63,7 +63,7 @@ public: bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize); bool enableInterleavedAccessVectorization(); unsigned getNumberOfRegisters(bool Vector); - unsigned getRegisterBitWidth(bool Vector); + unsigned getRegisterBitWidth(bool Vector) const; unsigned getCacheLineSize(); unsigned getPrefetchDistance(); unsigned getMaxInterleaveFactor(unsigned VF); diff --git a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp index 6a3dc67..422c16b 100644 --- a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp +++ b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -302,7 +302,7 @@ unsigned SystemZTTIImpl::getNumberOfRegisters(bool Vector) { return 0; } -unsigned SystemZTTIImpl::getRegisterBitWidth(bool Vector) { +unsigned SystemZTTIImpl::getRegisterBitWidth(bool Vector) const { if (!Vector) return 64; if (ST->hasVector()) diff --git a/lib/Target/SystemZ/SystemZTargetTransformInfo.h b/lib/Target/SystemZ/SystemZTargetTransformInfo.h index ad597f5..bdba760 100644 --- a/lib/Target/SystemZ/SystemZTargetTransformInfo.h +++ b/lib/Target/SystemZ/SystemZTargetTransformInfo.h @@ -53,7 +53,7 @@ public: /// @{ unsigned getNumberOfRegisters(bool Vector); - unsigned getRegisterBitWidth(bool Vector); + unsigned getRegisterBitWidth(bool Vector) const; bool prefersVectorizedAddressing() { return false; } bool supportsEfficientVectorElementLoadStore() { return true; } diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index ddf964e..5ad147e 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -46,9 +46,7 @@ public: /// .functype virtual void emitIndirectFunctionType(StringRef name, SmallVectorImpl &Params, - SmallVectorImpl &Results) { - llvm_unreachable("emitIndirectFunctionType not implemented"); - } + SmallVectorImpl &Results) = 0; /// .indidx virtual void emitIndIdx(const MCExpr *Value) = 0; /// .import_global diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp index 27c01cb..19e14f3 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -16,11 +16,15 @@ #include "MCTargetDesc/WebAssemblyFixupKinds.h" #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "llvm/BinaryFormat/Wasm.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCSymbolWasm.h" #include "llvm/MC/MCWasmObjectWriter.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" + using namespace llvm; namespace { @@ -29,8 +33,8 @@ public: explicit WebAssemblyWasmObjectWriter(bool Is64Bit); private: - unsigned getRelocType(MCContext &Ctx, const MCValue &Target, - const MCFixup &Fixup, bool IsPCRel) const override; + unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup) const override; }; } // end anonymous namespace @@ -39,16 +43,13 @@ WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit) // Test whether the given expression computes a function address. static bool IsFunctionExpr(const MCExpr *Expr) { - if (const MCSymbolRefExpr *SyExp = - dyn_cast(Expr)) + if (auto SyExp = dyn_cast(Expr)) return cast(SyExp->getSymbol()).isFunction(); - if (const MCBinaryExpr *BinOp = - dyn_cast(Expr)) + if (auto BinOp = dyn_cast(Expr)) return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS()); - if (const MCUnaryExpr *UnOp = - dyn_cast(Expr)) + if (auto UnOp = dyn_cast(Expr)) return IsFunctionExpr(UnOp->getSubExpr()); return false; @@ -59,15 +60,13 @@ static bool IsFunctionType(const MCValue &Target) { return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX; } -unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx, - const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const { +unsigned +WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, + const MCFixup &Fixup) const { // WebAssembly functions are not allocated in the data address space. To // resolve a pointer to a function, we must use a special relocation type. bool IsFunction = IsFunctionExpr(Fixup.getValue()); - assert(!IsPCRel); switch (unsigned(Fixup.getKind())) { case WebAssembly::fixup_code_sleb128_i32: if (IsFunction) diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index 4178ec0..b999091 100644 --- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -33,6 +33,8 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolWasm.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -218,9 +220,13 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MCExpr *WebAssemblyAsmPrinter::lowerConstant(const Constant *CV) { if (const GlobalValue *GV = dyn_cast(CV)) - if (GV->getValueType()->isFunctionTy()) + if (GV->getValueType()->isFunctionTy()) { + MCSymbol* Sym = getSymbol(GV); + if (!isa(Sym)) + cast(Sym)->setIsFunction(true); return MCSymbolRefExpr::create( - getSymbol(GV), MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext); + Sym, MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext); + } return AsmPrinter::lowerConstant(CV); } diff --git a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp index 47aadf9..b3ce4bd 100644 --- a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp +++ b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp @@ -36,7 +36,7 @@ unsigned WebAssemblyTTIImpl::getNumberOfRegisters(bool Vector) { return Result; } -unsigned WebAssemblyTTIImpl::getRegisterBitWidth(bool Vector) { +unsigned WebAssemblyTTIImpl::getRegisterBitWidth(bool Vector) const { if (Vector && getST()->hasSIMD128()) return 128; diff --git a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h index f658609..7b35fc9 100644 --- a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h +++ b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h @@ -55,7 +55,7 @@ public: /// @{ unsigned getNumberOfRegisters(bool Vector); - unsigned getRegisterBitWidth(bool Vector); + unsigned getRegisterBitWidth(bool Vector) const; unsigned getArithmeticInstrCost( unsigned Opcode, Type *Ty, TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 831e9bd..172eba0 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1,4 +1,3 @@ - //===-- X86ISelLowering.cpp - X86 DAG Lowering Implementation -------------===// // // The LLVM Compiler Infrastructure @@ -5314,20 +5313,37 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, assert((SizeInBits % EltSizeInBits) == 0 && "Can't split constant!"); unsigned NumElts = SizeInBits / EltSizeInBits; - unsigned SrcEltSizeInBits = VT.getScalarSizeInBits(); - unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits; + // Bitcast a source array of element bits to the target size. + auto CastBitData = [&](APInt &UndefSrcElts, ArrayRef SrcEltBits) { + unsigned NumSrcElts = UndefSrcElts.getBitWidth(); + unsigned SrcEltSizeInBits = SrcEltBits[0].getBitWidth(); + assert((NumSrcElts * SrcEltSizeInBits) == SizeInBits && + "Constant bit sizes don't match"); - // Extract all the undef/constant element data and pack into single bitsets. - APInt UndefBits(SizeInBits, 0); - APInt MaskBits(SizeInBits, 0); - - // Split the undef/constant single bitset data into the target elements. - auto SplitBitData = [&]() { // Don't split if we don't allow undef bits. bool AllowUndefs = AllowWholeUndefs || AllowPartialUndefs; - if (UndefBits.getBoolValue() && !AllowUndefs) + if (UndefSrcElts.getBoolValue() && !AllowUndefs) return false; + // If we're already the right size, don't bother bitcasting. + if (NumSrcElts == NumElts) { + UndefElts = UndefSrcElts; + EltBits.assign(SrcEltBits.begin(), SrcEltBits.end()); + return true; + } + + // Extract all the undef/constant element data and pack into single bitsets. + APInt UndefBits(SizeInBits, 0); + APInt MaskBits(SizeInBits, 0); + + for (unsigned i = 0; i != NumSrcElts; ++i) { + unsigned BitOffset = i * SrcEltSizeInBits; + if (UndefSrcElts[i]) + UndefBits.setBits(BitOffset, BitOffset + SrcEltSizeInBits); + MaskBits.insertBits(SrcEltBits[i], BitOffset); + } + + // Split the undef/constant single bitset data into the target elements. UndefElts = APInt(NumElts, 0); EltBits.resize(NumElts, APInt(EltSizeInBits, 0)); @@ -5356,20 +5372,19 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, // Collect constant bits and insert into mask/undef bit masks. auto CollectConstantBits = [](const Constant *Cst, APInt &Mask, APInt &Undefs, - unsigned BitOffset) { + unsigned UndefBitIndex) { if (!Cst) return false; if (isa(Cst)) { - unsigned CstSizeInBits = Cst->getType()->getPrimitiveSizeInBits(); - Undefs.setBits(BitOffset, BitOffset + CstSizeInBits); + Undefs.setBit(UndefBitIndex); return true; } if (auto *CInt = dyn_cast(Cst)) { - Mask.insertBits(CInt->getValue(), BitOffset); + Mask = CInt->getValue(); return true; } if (auto *CFP = dyn_cast(Cst)) { - Mask.insertBits(CFP->getValueAPF().bitcastToAPInt(), BitOffset); + Mask = CFP->getValueAPF().bitcastToAPInt(); return true; } return false; @@ -5377,18 +5392,21 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, // Extract constant bits from build vector. if (ISD::isBuildVectorOfConstantSDNodes(Op.getNode())) { + unsigned SrcEltSizeInBits = VT.getScalarSizeInBits(); + unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits; + + APInt UndefSrcElts(NumSrcElts, 0); + SmallVector SrcEltBits(NumSrcElts, APInt(SrcEltSizeInBits, 0)); for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) { const SDValue &Src = Op.getOperand(i); - unsigned BitOffset = i * SrcEltSizeInBits; if (Src.isUndef()) { - UndefBits.setBits(BitOffset, BitOffset + SrcEltSizeInBits); + UndefSrcElts.setBit(i); continue; } auto *Cst = cast(Src); - APInt Bits = Cst->getAPIntValue().zextOrTrunc(SrcEltSizeInBits); - MaskBits.insertBits(Bits, BitOffset); + SrcEltBits[i] = Cst->getAPIntValue().zextOrTrunc(SrcEltSizeInBits); } - return SplitBitData(); + return CastBitData(UndefSrcElts, SrcEltBits); } // Extract constant bits from constant pool vector. @@ -5397,27 +5415,33 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, if (!CstTy->isVectorTy() || (SizeInBits != CstTy->getPrimitiveSizeInBits())) return false; - unsigned CstEltSizeInBits = CstTy->getScalarSizeInBits(); - for (unsigned i = 0, e = CstTy->getVectorNumElements(); i != e; ++i) - if (!CollectConstantBits(Cst->getAggregateElement(i), MaskBits, UndefBits, - i * CstEltSizeInBits)) + unsigned SrcEltSizeInBits = CstTy->getScalarSizeInBits(); + unsigned NumSrcElts = CstTy->getVectorNumElements(); + + APInt UndefSrcElts(NumSrcElts, 0); + SmallVector SrcEltBits(NumSrcElts, APInt(SrcEltSizeInBits, 0)); + for (unsigned i = 0; i != NumSrcElts; ++i) + if (!CollectConstantBits(Cst->getAggregateElement(i), SrcEltBits[i], + UndefSrcElts, i)) return false; - return SplitBitData(); + return CastBitData(UndefSrcElts, SrcEltBits); } // Extract constant bits from a broadcasted constant pool scalar. if (Op.getOpcode() == X86ISD::VBROADCAST && - EltSizeInBits <= SrcEltSizeInBits) { + EltSizeInBits <= VT.getScalarSizeInBits()) { if (auto *Broadcast = getTargetConstantFromNode(Op.getOperand(0))) { - APInt Bits(SizeInBits, 0); - APInt Undefs(SizeInBits, 0); - if (CollectConstantBits(Broadcast, Bits, Undefs, 0)) { - for (unsigned i = 0; i != NumSrcElts; ++i) { - MaskBits |= Bits.shl(i * SrcEltSizeInBits); - UndefBits |= Undefs.shl(i * SrcEltSizeInBits); - } - return SplitBitData(); + unsigned SrcEltSizeInBits = Broadcast->getType()->getScalarSizeInBits(); + unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits; + + APInt UndefSrcElts(NumSrcElts, 0); + SmallVector SrcEltBits(1, APInt(SrcEltSizeInBits, 0)); + if (CollectConstantBits(Broadcast, SrcEltBits[0], UndefSrcElts, 0)) { + if (UndefSrcElts[0]) + UndefSrcElts.setBits(0, NumSrcElts); + SrcEltBits.append(NumSrcElts - 1, SrcEltBits[0]); + return CastBitData(UndefSrcElts, SrcEltBits); } } } @@ -5426,10 +5450,15 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, if (Op.getOpcode() == X86ISD::VZEXT_MOVL && Op.getOperand(0).getOpcode() == ISD::SCALAR_TO_VECTOR && isa(Op.getOperand(0).getOperand(0))) { + unsigned SrcEltSizeInBits = VT.getScalarSizeInBits(); + unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits; + + APInt UndefSrcElts(NumSrcElts, 0); + SmallVector SrcEltBits; auto *CN = cast(Op.getOperand(0).getOperand(0)); - MaskBits = CN->getAPIntValue().zextOrTrunc(SrcEltSizeInBits); - MaskBits = MaskBits.zext(SizeInBits); - return SplitBitData(); + SrcEltBits.push_back(CN->getAPIntValue().zextOrTrunc(SrcEltSizeInBits)); + SrcEltBits.append(NumSrcElts - 1, APInt(SrcEltSizeInBits, 0)); + return CastBitData(UndefSrcElts, SrcEltBits); } return false; @@ -6491,16 +6520,7 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, ArrayRef Elts, SDValue NewLd = DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(), LDBase->getPointerInfo(), LDBase->getAlignment(), MMOFlags); - - if (LDBase->hasAnyUseOfValue(1)) { - SDValue NewChain = - DAG.getNode(ISD::TokenFactor, DL, MVT::Other, SDValue(LDBase, 1), - SDValue(NewLd.getNode(), 1)); - DAG.ReplaceAllUsesOfValueWith(SDValue(LDBase, 1), NewChain); - DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(LDBase, 1), - SDValue(NewLd.getNode(), 1)); - } - + DAG.makeEquivalentMemoryOrdering(LDBase, NewLd); return NewLd; }; @@ -6565,19 +6585,7 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, ArrayRef Elts, LDBase->getAlignment(), false/*isVolatile*/, true/*ReadMem*/, false/*WriteMem*/); - - // Make sure the newly-created LOAD is in the same position as LDBase in - // terms of dependency. We create a TokenFactor for LDBase and ResNode, - // and update uses of LDBase's output chain to use the TokenFactor. - if (LDBase->hasAnyUseOfValue(1)) { - SDValue NewChain = - DAG.getNode(ISD::TokenFactor, DL, MVT::Other, SDValue(LDBase, 1), - SDValue(ResNode.getNode(), 1)); - DAG.ReplaceAllUsesOfValueWith(SDValue(LDBase, 1), NewChain); - DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(LDBase, 1), - SDValue(ResNode.getNode(), 1)); - } - + DAG.makeEquivalentMemoryOrdering(LDBase, ResNode); return DAG.getBitcast(VT, ResNode); } } @@ -9930,17 +9938,7 @@ static SDValue lowerVectorShuffleAsBroadcast(const SDLoc &DL, MVT VT, V = DAG.getLoad(SVT, DL, Ld->getChain(), NewAddr, DAG.getMachineFunction().getMachineMemOperand( Ld->getMemOperand(), Offset, SVT.getStoreSize())); - - // Make sure the newly-created LOAD is in the same position as Ld in - // terms of dependency. We create a TokenFactor for Ld and V, - // and update uses of Ld's output chain to use the TokenFactor. - if (Ld->hasAnyUseOfValue(1)) { - SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, - SDValue(Ld, 1), SDValue(V.getNode(), 1)); - DAG.ReplaceAllUsesOfValueWith(SDValue(Ld, 1), NewChain); - DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(Ld, 1), - SDValue(V.getNode(), 1)); - } + DAG.makeEquivalentMemoryOrdering(Ld, V); } else if (!BroadcastFromReg) { // We can't broadcast from a vector register. return SDValue(); @@ -10891,9 +10889,10 @@ static SDValue lowerV8I16GeneralSingleInputVectorShuffle( "We need to be changing the number of flipped inputs!"); int PSHUFHalfMask[] = {0, 1, 2, 3}; std::swap(PSHUFHalfMask[FixFreeIdx % 4], PSHUFHalfMask[FixIdx % 4]); - V = DAG.getNode(FixIdx < 4 ? X86ISD::PSHUFLW : X86ISD::PSHUFHW, DL, - MVT::v8i16, V, - getV4X86ShuffleImm8ForMask(PSHUFHalfMask, DL, DAG)); + V = DAG.getNode( + FixIdx < 4 ? X86ISD::PSHUFLW : X86ISD::PSHUFHW, DL, + MVT::getVectorVT(MVT::i16, V.getValueSizeInBits() / 16), V, + getV4X86ShuffleImm8ForMask(PSHUFHalfMask, DL, DAG)); for (int &M : Mask) if (M >= 0 && M == FixIdx) @@ -12007,18 +12006,22 @@ static SDValue lowerV2X128VectorShuffle(const SDLoc &DL, MVT VT, SDValue V1, // subvector. bool OnlyUsesV1 = isShuffleEquivalent(V1, V2, Mask, {0, 1, 0, 1}); if (OnlyUsesV1 || isShuffleEquivalent(V1, V2, Mask, {0, 1, 4, 5})) { - // With AVX2 we should use VPERMQ/VPERMPD to allow memory folding. + // With AVX2, use VPERMQ/VPERMPD to allow memory folding. if (Subtarget.hasAVX2() && V2.isUndef()) return SDValue(); - MVT SubVT = MVT::getVectorVT(VT.getVectorElementType(), - VT.getVectorNumElements() / 2); - SDValue LoV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, V1, - DAG.getIntPtrConstant(0, DL)); - SDValue HiV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, - OnlyUsesV1 ? V1 : V2, - DAG.getIntPtrConstant(0, DL)); - return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoV, HiV); + // With AVX1, use vperm2f128 (below) to allow load folding. Otherwise, + // this will likely become vinsertf128 which can't fold a 256-bit memop. + if (!isa(peekThroughBitcasts(V1))) { + MVT SubVT = MVT::getVectorVT(VT.getVectorElementType(), + VT.getVectorNumElements() / 2); + SDValue LoV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, V1, + DAG.getIntPtrConstant(0, DL)); + SDValue HiV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, + OnlyUsesV1 ? V1 : V2, + DAG.getIntPtrConstant(0, DL)); + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoV, HiV); + } } } @@ -19117,7 +19120,7 @@ static SDValue getScalarMaskingNode(SDValue Op, SDValue Mask, SDValue IMask = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v1i1, Mask); if (Op.getOpcode() == X86ISD::FSETCCM || - Op.getOpcode() == X86ISD::FSETCCM_RND) + Op.getOpcode() == X86ISD::FSETCCM_RND) return DAG.getNode(ISD::AND, dl, VT, Op, IMask); if (Op.getOpcode() == X86ISD::VFPCLASSS) return DAG.getNode(ISD::OR, dl, VT, Op, IMask); @@ -27968,28 +27971,45 @@ static bool combineX86ShufflesRecursively(ArrayRef SrcOps, OpMask.size() % RootMask.size() == 0) || OpMask.size() == RootMask.size()) && "The smaller number of elements must divide the larger."); - int MaskWidth = std::max(OpMask.size(), RootMask.size()); - int RootRatio = std::max(1, OpMask.size() / RootMask.size()); - int OpRatio = std::max(1, RootMask.size() / OpMask.size()); - assert(((RootRatio == 1 && OpRatio == 1) || - (RootRatio == 1) != (OpRatio == 1)) && + + // This function can be performance-critical, so we rely on the power-of-2 + // knowledge that we have about the mask sizes to replace div/rem ops with + // bit-masks and shifts. + assert(isPowerOf2_32(RootMask.size()) && "Non-power-of-2 shuffle mask sizes"); + assert(isPowerOf2_32(OpMask.size()) && "Non-power-of-2 shuffle mask sizes"); + unsigned RootMaskSizeLog2 = countTrailingZeros(RootMask.size()); + unsigned OpMaskSizeLog2 = countTrailingZeros(OpMask.size()); + + unsigned MaskWidth = std::max(OpMask.size(), RootMask.size()); + unsigned RootRatio = std::max(1, OpMask.size() >> RootMaskSizeLog2); + unsigned OpRatio = std::max(1, RootMask.size() >> OpMaskSizeLog2); + assert((RootRatio == 1 || OpRatio == 1) && "Must not have a ratio for both incoming and op masks!"); - SmallVector Mask((unsigned)MaskWidth, SM_SentinelUndef); + assert(isPowerOf2_32(MaskWidth) && "Non-power-of-2 shuffle mask sizes"); + assert(isPowerOf2_32(RootRatio) && "Non-power-of-2 shuffle mask sizes"); + assert(isPowerOf2_32(OpRatio) && "Non-power-of-2 shuffle mask sizes"); + unsigned RootRatioLog2 = countTrailingZeros(RootRatio); + unsigned OpRatioLog2 = countTrailingZeros(OpRatio); + + SmallVector Mask(MaskWidth, SM_SentinelUndef); // Merge this shuffle operation's mask into our accumulated mask. Note that // this shuffle's mask will be the first applied to the input, followed by the // root mask to get us all the way to the root value arrangement. The reason // for this order is that we are recursing up the operation chain. - for (int i = 0; i < MaskWidth; ++i) { - int RootIdx = i / RootRatio; + for (unsigned i = 0; i < MaskWidth; ++i) { + unsigned RootIdx = i >> RootRatioLog2; if (RootMask[RootIdx] < 0) { // This is a zero or undef lane, we're done. Mask[i] = RootMask[RootIdx]; continue; } - int RootMaskedIdx = RootMask[RootIdx] * RootRatio + i % RootRatio; + unsigned RootMaskedIdx = + RootRatio == 1 + ? RootMask[RootIdx] + : (RootMask[RootIdx] << RootRatioLog2) + (i & (RootRatio - 1)); // Just insert the scaled root mask value if it references an input other // than the SrcOp we're currently inserting. @@ -27999,9 +28019,8 @@ static bool combineX86ShufflesRecursively(ArrayRef SrcOps, continue; } - RootMaskedIdx %= MaskWidth; - - int OpIdx = RootMaskedIdx / OpRatio; + RootMaskedIdx = RootMaskedIdx & (MaskWidth - 1); + unsigned OpIdx = RootMaskedIdx >> OpRatioLog2; if (OpMask[OpIdx] < 0) { // The incoming lanes are zero or undef, it doesn't matter which ones we // are using. @@ -28010,9 +28029,12 @@ static bool combineX86ShufflesRecursively(ArrayRef SrcOps, } // Ok, we have non-zero lanes, map them through to one of the Op's inputs. - int OpMaskedIdx = OpMask[OpIdx] * OpRatio + RootMaskedIdx % OpRatio; - OpMaskedIdx %= MaskWidth; + unsigned OpMaskedIdx = + OpRatio == 1 + ? OpMask[OpIdx] + : (OpMask[OpIdx] << OpRatioLog2) + (RootMaskedIdx & (OpRatio - 1)); + OpMaskedIdx = OpMaskedIdx & (MaskWidth - 1); if (OpMask[OpIdx] < (int)OpMask.size()) { assert(0 <= InputIdx0 && "Unknown target shuffle input"); OpMaskedIdx += InputIdx0 * MaskWidth; diff --git a/lib/Target/X86/X86InstrAVX512.td b/lib/Target/X86/X86InstrAVX512.td index d870269..2620679 100644 --- a/lib/Target/X86/X86InstrAVX512.td +++ b/lib/Target/X86/X86InstrAVX512.td @@ -1631,6 +1631,7 @@ multiclass avx512_icmp_packed opc, string OpcodeStr, SDNode OpNode, [(set _.KRC:$dst, (OpNode (_.VT _.RC:$src1), (_.VT (bitconvert (_.LdFrag addr:$src2)))))], IIC_SSE_ALU_F32P_RM>, EVEX_4V; + let isCommutable = IsCommutable in def rrk : AVX512BI opc, string Suffix, SDNode OpNode, (_.VT (bitconvert (_.LdFrag addr:$src2))), imm:$cc))], IIC_SSE_ALU_F32P_RM>, EVEX_4V; + let isCommutable = 1 in def rrik : AVX512AIi8; -// Like 'load', but uses special alignment checks suitable for use in +// Like 'vec128load', but uses special alignment checks suitable for use in // memory operands in most SSE instructions, which are required to // be naturally aligned on some targets but not on others. If the subtarget // allows unaligned accesses, match any load, though this may require // setting a feature bit in the processor (on startup, for example). // Opteron 10h and later implement such a feature. -// Avoid non-temporal aligned loads on supported targets. -def memop : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - return (Subtarget->hasSSEUnalignedMem() || - cast(N)->getAlignment() >= 16) && - (!Subtarget->hasSSE41() || - !(cast(N)->getAlignment() >= 16 && - cast(N)->isNonTemporal())); +def memop : PatFrag<(ops node:$ptr), (vec128load node:$ptr), [{ + return Subtarget->hasSSEUnalignedMem() || + cast(N)->getAlignment() >= 16; }]>; // 128-bit memop pattern fragments diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index ff5d90c..f3094b7 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -898,10 +898,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZrr, X86::VPABSDZrm, 0 }, { X86::VPABSQZrr, X86::VPABSQZrm, 0 }, { X86::VPABSWZrr, X86::VPABSWZrm, 0 }, + { X86::VPCONFLICTDZrr, X86::VPCONFLICTDZrm, 0 }, + { X86::VPCONFLICTQZrr, X86::VPCONFLICTQZrm, 0 }, { X86::VPERMILPDZri, X86::VPERMILPDZmi, 0 }, { X86::VPERMILPSZri, X86::VPERMILPSZmi, 0 }, { X86::VPERMPDZri, X86::VPERMPDZmi, 0 }, { X86::VPERMQZri, X86::VPERMQZmi, 0 }, + { X86::VPLZCNTDZrr, X86::VPLZCNTDZrm, 0 }, + { X86::VPLZCNTQZrr, X86::VPLZCNTQZrm, 0 }, { X86::VPMOVSXBDZrr, X86::VPMOVSXBDZrm, 0 }, { X86::VPMOVSXBQZrr, X86::VPMOVSXBQZrm, TB_NO_REVERSE }, { X86::VPMOVSXBWZrr, X86::VPMOVSXBWZrm, 0 }, @@ -948,10 +952,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ256rr, X86::VPABSDZ256rm, 0 }, { X86::VPABSQZ256rr, X86::VPABSQZ256rm, 0 }, { X86::VPABSWZ256rr, X86::VPABSWZ256rm, 0 }, + { X86::VPCONFLICTDZ256rr, X86::VPCONFLICTDZ256rm, 0 }, + { X86::VPCONFLICTQZ256rr, X86::VPCONFLICTQZ256rm, 0 }, { X86::VPERMILPDZ256ri, X86::VPERMILPDZ256mi, 0 }, { X86::VPERMILPSZ256ri, X86::VPERMILPSZ256mi, 0 }, { X86::VPERMPDZ256ri, X86::VPERMPDZ256mi, 0 }, { X86::VPERMQZ256ri, X86::VPERMQZ256mi, 0 }, + { X86::VPLZCNTDZ256rr, X86::VPLZCNTDZ256rm, 0 }, + { X86::VPLZCNTQZ256rr, X86::VPLZCNTQZ256rm, 0 }, { X86::VPMOVSXBDZ256rr, X86::VPMOVSXBDZ256rm, TB_NO_REVERSE }, { X86::VPMOVSXBQZ256rr, X86::VPMOVSXBQZ256rm, TB_NO_REVERSE }, { X86::VPMOVSXBWZ256rr, X86::VPMOVSXBWZ256rm, 0 }, @@ -995,8 +1003,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ128rr, X86::VPABSDZ128rm, 0 }, { X86::VPABSQZ128rr, X86::VPABSQZ128rm, 0 }, { X86::VPABSWZ128rr, X86::VPABSWZ128rm, 0 }, + { X86::VPCONFLICTDZ128rr, X86::VPCONFLICTDZ128rm, 0 }, + { X86::VPCONFLICTQZ128rr, X86::VPCONFLICTQZ128rm, 0 }, { X86::VPERMILPDZ128ri, X86::VPERMILPDZ128mi, 0 }, { X86::VPERMILPSZ128ri, X86::VPERMILPSZ128mi, 0 }, + { X86::VPLZCNTDZ128rr, X86::VPLZCNTDZ128rm, 0 }, + { X86::VPLZCNTQZ128rr, X86::VPLZCNTQZ128rm, 0 }, { X86::VPMOVSXBDZ128rr, X86::VPMOVSXBDZ128rm, TB_NO_REVERSE }, { X86::VPMOVSXBQZ128rr, X86::VPMOVSXBQZ128rm, TB_NO_REVERSE }, { X86::VPMOVSXBWZ128rr, X86::VPMOVSXBWZ128rm, TB_NO_REVERSE }, @@ -2312,10 +2324,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZrrkz, X86::VPABSDZrmkz, 0 }, { X86::VPABSQZrrkz, X86::VPABSQZrmkz, 0 }, { X86::VPABSWZrrkz, X86::VPABSWZrmkz, 0 }, + { X86::VPCONFLICTDZrrkz, X86::VPCONFLICTDZrmkz, 0 }, + { X86::VPCONFLICTQZrrkz, X86::VPCONFLICTQZrmkz, 0 }, { X86::VPERMILPDZrikz, X86::VPERMILPDZmikz, 0 }, { X86::VPERMILPSZrikz, X86::VPERMILPSZmikz, 0 }, { X86::VPERMPDZrikz, X86::VPERMPDZmikz, 0 }, { X86::VPERMQZrikz, X86::VPERMQZmikz, 0 }, + { X86::VPLZCNTDZrrkz, X86::VPLZCNTDZrmkz, 0 }, + { X86::VPLZCNTQZrrkz, X86::VPLZCNTQZrmkz, 0 }, { X86::VPMOVSXBDZrrkz, X86::VPMOVSXBDZrmkz, 0 }, { X86::VPMOVSXBQZrrkz, X86::VPMOVSXBQZrmkz, TB_NO_REVERSE }, { X86::VPMOVSXBWZrrkz, X86::VPMOVSXBWZrmkz, 0 }, @@ -2350,10 +2366,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ256rrkz, X86::VPABSDZ256rmkz, 0 }, { X86::VPABSQZ256rrkz, X86::VPABSQZ256rmkz, 0 }, { X86::VPABSWZ256rrkz, X86::VPABSWZ256rmkz, 0 }, + { X86::VPCONFLICTDZ256rrkz, X86::VPCONFLICTDZ256rmkz, 0 }, + { X86::VPCONFLICTQZ256rrkz, X86::VPCONFLICTQZ256rmkz, 0 }, { X86::VPERMILPDZ256rikz, X86::VPERMILPDZ256mikz, 0 }, { X86::VPERMILPSZ256rikz, X86::VPERMILPSZ256mikz, 0 }, { X86::VPERMPDZ256rikz, X86::VPERMPDZ256mikz, 0 }, { X86::VPERMQZ256rikz, X86::VPERMQZ256mikz, 0 }, + { X86::VPLZCNTDZ256rrkz, X86::VPLZCNTDZ256rmkz, 0 }, + { X86::VPLZCNTQZ256rrkz, X86::VPLZCNTQZ256rmkz, 0 }, { X86::VPMOVSXBDZ256rrkz, X86::VPMOVSXBDZ256rmkz, TB_NO_REVERSE }, { X86::VPMOVSXBQZ256rrkz, X86::VPMOVSXBQZ256rmkz, TB_NO_REVERSE }, { X86::VPMOVSXBWZ256rrkz, X86::VPMOVSXBWZ256rmkz, 0 }, @@ -2385,8 +2405,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ128rrkz, X86::VPABSDZ128rmkz, 0 }, { X86::VPABSQZ128rrkz, X86::VPABSQZ128rmkz, 0 }, { X86::VPABSWZ128rrkz, X86::VPABSWZ128rmkz, 0 }, + { X86::VPCONFLICTDZ128rrkz, X86::VPCONFLICTDZ128rmkz, 0 }, + { X86::VPCONFLICTQZ128rrkz, X86::VPCONFLICTQZ128rmkz, 0 }, { X86::VPERMILPDZ128rikz, X86::VPERMILPDZ128mikz, 0 }, { X86::VPERMILPSZ128rikz, X86::VPERMILPSZ128mikz, 0 }, + { X86::VPLZCNTDZ128rrkz, X86::VPLZCNTDZ128rmkz, 0 }, + { X86::VPLZCNTQZ128rrkz, X86::VPLZCNTQZ128rmkz, 0 }, { X86::VPMOVSXBDZ128rrkz, X86::VPMOVSXBDZ128rmkz, TB_NO_REVERSE }, { X86::VPMOVSXBQZ128rrkz, X86::VPMOVSXBQZ128rmkz, TB_NO_REVERSE }, { X86::VPMOVSXBWZ128rrkz, X86::VPMOVSXBWZ128rmkz, TB_NO_REVERSE }, @@ -2935,10 +2959,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZrrk, X86::VPABSDZrmk, 0 }, { X86::VPABSQZrrk, X86::VPABSQZrmk, 0 }, { X86::VPABSWZrrk, X86::VPABSWZrmk, 0 }, + { X86::VPCONFLICTDZrrk, X86::VPCONFLICTDZrmk, 0 }, + { X86::VPCONFLICTQZrrk, X86::VPCONFLICTQZrmk, 0 }, { X86::VPERMILPDZrik, X86::VPERMILPDZmik, 0 }, { X86::VPERMILPSZrik, X86::VPERMILPSZmik, 0 }, { X86::VPERMPDZrik, X86::VPERMPDZmik, 0 }, { X86::VPERMQZrik, X86::VPERMQZmik, 0 }, + { X86::VPLZCNTDZrrk, X86::VPLZCNTDZrmk, 0 }, + { X86::VPLZCNTQZrrk, X86::VPLZCNTQZrmk, 0 }, { X86::VPMOVSXBDZrrk, X86::VPMOVSXBDZrmk, 0 }, { X86::VPMOVSXBQZrrk, X86::VPMOVSXBQZrmk, TB_NO_REVERSE }, { X86::VPMOVSXBWZrrk, X86::VPMOVSXBWZrmk, 0 }, @@ -2973,10 +3001,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ256rrk, X86::VPABSDZ256rmk, 0 }, { X86::VPABSQZ256rrk, X86::VPABSQZ256rmk, 0 }, { X86::VPABSWZ256rrk, X86::VPABSWZ256rmk, 0 }, + { X86::VPCONFLICTDZ256rrk, X86::VPCONFLICTDZ256rmk, 0 }, + { X86::VPCONFLICTQZ256rrk, X86::VPCONFLICTQZ256rmk, 0 }, { X86::VPERMILPDZ256rik, X86::VPERMILPDZ256mik, 0 }, { X86::VPERMILPSZ256rik, X86::VPERMILPSZ256mik, 0 }, { X86::VPERMPDZ256rik, X86::VPERMPDZ256mik, 0 }, { X86::VPERMQZ256rik, X86::VPERMQZ256mik, 0 }, + { X86::VPLZCNTDZ256rrk, X86::VPLZCNTDZ256rmk, 0 }, + { X86::VPLZCNTQZ256rrk, X86::VPLZCNTQZ256rmk, 0 }, { X86::VPMOVSXBDZ256rrk, X86::VPMOVSXBDZ256rmk, TB_NO_REVERSE }, { X86::VPMOVSXBQZ256rrk, X86::VPMOVSXBQZ256rmk, TB_NO_REVERSE }, { X86::VPMOVSXBWZ256rrk, X86::VPMOVSXBWZ256rmk, 0 }, @@ -3008,8 +3040,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPABSDZ128rrk, X86::VPABSDZ128rmk, 0 }, { X86::VPABSQZ128rrk, X86::VPABSQZ128rmk, 0 }, { X86::VPABSWZ128rrk, X86::VPABSWZ128rmk, 0 }, + { X86::VPCONFLICTDZ128rrk, X86::VPCONFLICTDZ128rmk, 0 }, + { X86::VPCONFLICTQZ128rrk, X86::VPCONFLICTQZ128rmk, 0 }, { X86::VPERMILPDZ128rik, X86::VPERMILPDZ128mik, 0 }, { X86::VPERMILPSZ128rik, X86::VPERMILPSZ128mik, 0 }, + { X86::VPLZCNTDZ128rrk, X86::VPLZCNTDZ128rmk, 0 }, + { X86::VPLZCNTQZ128rrk, X86::VPLZCNTQZ128rmk, 0 }, { X86::VPMOVSXBDZ128rrk, X86::VPMOVSXBDZ128rmk, TB_NO_REVERSE }, { X86::VPMOVSXBQZ128rrk, X86::VPMOVSXBQZ128rmk, TB_NO_REVERSE }, { X86::VPMOVSXBWZ128rrk, X86::VPMOVSXBWZ128rmk, TB_NO_REVERSE }, @@ -3034,6 +3070,64 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI) { X86::VPSRLDZ128rik, X86::VPSRLDZ128mik, 0 }, { X86::VPSRLQZ128rik, X86::VPSRLQZ128mik, 0 }, { X86::VPSRLWZ128rik, X86::VPSRLWZ128mik, 0 }, + + // AVX-512 masked compare instructions + { X86::VCMPPDZ128rrik, X86::VCMPPDZ128rmik, 0 }, + { X86::VCMPPSZ128rrik, X86::VCMPPSZ128rmik, 0 }, + { X86::VCMPPDZ256rrik, X86::VCMPPDZ256rmik, 0 }, + { X86::VCMPPSZ256rrik, X86::VCMPPSZ256rmik, 0 }, + { X86::VCMPPDZrrik, X86::VCMPPDZrmik, 0 }, + { X86::VCMPPSZrrik, X86::VCMPPSZrmik, 0 }, + { X86::VCMPSDZrr_Intk, X86::VCMPSDZrm_Intk, TB_NO_REVERSE }, + { X86::VCMPSSZrr_Intk, X86::VCMPSSZrm_Intk, TB_NO_REVERSE }, + { X86::VPCMPBZ128rrik, X86::VPCMPBZ128rmik, 0 }, + { X86::VPCMPBZ256rrik, X86::VPCMPBZ256rmik, 0 }, + { X86::VPCMPBZrrik, X86::VPCMPBZrmik, 0 }, + { X86::VPCMPDZ128rrik, X86::VPCMPDZ128rmik, 0 }, + { X86::VPCMPDZ256rrik, X86::VPCMPDZ256rmik, 0 }, + { X86::VPCMPDZrrik, X86::VPCMPDZrmik, 0 }, + { X86::VPCMPEQBZ128rrk, X86::VPCMPEQBZ128rmk, 0 }, + { X86::VPCMPEQBZ256rrk, X86::VPCMPEQBZ256rmk, 0 }, + { X86::VPCMPEQBZrrk, X86::VPCMPEQBZrmk, 0 }, + { X86::VPCMPEQDZ128rrk, X86::VPCMPEQDZ128rmk, 0 }, + { X86::VPCMPEQDZ256rrk, X86::VPCMPEQDZ256rmk, 0 }, + { X86::VPCMPEQDZrrk, X86::VPCMPEQDZrmk, 0 }, + { X86::VPCMPEQQZ128rrk, X86::VPCMPEQQZ128rmk, 0 }, + { X86::VPCMPEQQZ256rrk, X86::VPCMPEQQZ256rmk, 0 }, + { X86::VPCMPEQQZrrk, X86::VPCMPEQQZrmk, 0 }, + { X86::VPCMPEQWZ128rrk, X86::VPCMPEQWZ128rmk, 0 }, + { X86::VPCMPEQWZ256rrk, X86::VPCMPEQWZ256rmk, 0 }, + { X86::VPCMPEQWZrrk, X86::VPCMPEQWZrmk, 0 }, + { X86::VPCMPGTBZ128rrk, X86::VPCMPGTBZ128rmk, 0 }, + { X86::VPCMPGTBZ256rrk, X86::VPCMPGTBZ256rmk, 0 }, + { X86::VPCMPGTBZrrk, X86::VPCMPGTBZrmk, 0 }, + { X86::VPCMPGTDZ128rrk, X86::VPCMPGTDZ128rmk, 0 }, + { X86::VPCMPGTDZ256rrk, X86::VPCMPGTDZ256rmk, 0 }, + { X86::VPCMPGTDZrrk, X86::VPCMPGTDZrmk, 0 }, + { X86::VPCMPGTQZ128rrk, X86::VPCMPGTQZ128rmk, 0 }, + { X86::VPCMPGTQZ256rrk, X86::VPCMPGTQZ256rmk, 0 }, + { X86::VPCMPGTQZrrk, X86::VPCMPGTQZrmk, 0 }, + { X86::VPCMPGTWZ128rrk, X86::VPCMPGTWZ128rmk, 0 }, + { X86::VPCMPGTWZ256rrk, X86::VPCMPGTWZ256rmk, 0 }, + { X86::VPCMPGTWZrrk, X86::VPCMPGTWZrmk, 0 }, + { X86::VPCMPQZ128rrik, X86::VPCMPQZ128rmik, 0 }, + { X86::VPCMPQZ256rrik, X86::VPCMPQZ256rmik, 0 }, + { X86::VPCMPQZrrik, X86::VPCMPQZrmik, 0 }, + { X86::VPCMPUBZ128rrik, X86::VPCMPUBZ128rmik, 0 }, + { X86::VPCMPUBZ256rrik, X86::VPCMPUBZ256rmik, 0 }, + { X86::VPCMPUBZrrik, X86::VPCMPUBZrmik, 0 }, + { X86::VPCMPUDZ128rrik, X86::VPCMPUDZ128rmik, 0 }, + { X86::VPCMPUDZ256rrik, X86::VPCMPUDZ256rmik, 0 }, + { X86::VPCMPUDZrrik, X86::VPCMPUDZrmik, 0 }, + { X86::VPCMPUQZ128rrik, X86::VPCMPUQZ128rmik, 0 }, + { X86::VPCMPUQZ256rrik, X86::VPCMPUQZ256rmik, 0 }, + { X86::VPCMPUQZrrik, X86::VPCMPUQZrmik, 0 }, + { X86::VPCMPUWZ128rrik, X86::VPCMPUWZ128rmik, 0 }, + { X86::VPCMPUWZ256rrik, X86::VPCMPUWZ256rmik, 0 }, + { X86::VPCMPUWZrrik, X86::VPCMPUWZrmik, 0 }, + { X86::VPCMPWZ128rrik, X86::VPCMPWZ128rmik, 0 }, + { X86::VPCMPWZ256rrik, X86::VPCMPWZ256rmik, 0 }, + { X86::VPCMPWZrrik, X86::VPCMPWZrmik, 0 }, }; for (X86MemoryFoldTableEntry Entry : MemoryFoldTable3) { @@ -5136,20 +5230,32 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, return nullptr; } } - case X86::VPCMPBZ128rri: case X86::VPCMPUBZ128rri: - case X86::VPCMPBZ256rri: case X86::VPCMPUBZ256rri: - case X86::VPCMPBZrri: case X86::VPCMPUBZrri: - case X86::VPCMPDZ128rri: case X86::VPCMPUDZ128rri: - case X86::VPCMPDZ256rri: case X86::VPCMPUDZ256rri: - case X86::VPCMPDZrri: case X86::VPCMPUDZrri: - case X86::VPCMPQZ128rri: case X86::VPCMPUQZ128rri: - case X86::VPCMPQZ256rri: case X86::VPCMPUQZ256rri: - case X86::VPCMPQZrri: case X86::VPCMPUQZrri: - case X86::VPCMPWZ128rri: case X86::VPCMPUWZ128rri: - case X86::VPCMPWZ256rri: case X86::VPCMPUWZ256rri: - case X86::VPCMPWZrri: case X86::VPCMPUWZrri: { + case X86::VPCMPBZ128rri: case X86::VPCMPUBZ128rri: + case X86::VPCMPBZ256rri: case X86::VPCMPUBZ256rri: + case X86::VPCMPBZrri: case X86::VPCMPUBZrri: + case X86::VPCMPDZ128rri: case X86::VPCMPUDZ128rri: + case X86::VPCMPDZ256rri: case X86::VPCMPUDZ256rri: + case X86::VPCMPDZrri: case X86::VPCMPUDZrri: + case X86::VPCMPQZ128rri: case X86::VPCMPUQZ128rri: + case X86::VPCMPQZ256rri: case X86::VPCMPUQZ256rri: + case X86::VPCMPQZrri: case X86::VPCMPUQZrri: + case X86::VPCMPWZ128rri: case X86::VPCMPUWZ128rri: + case X86::VPCMPWZ256rri: case X86::VPCMPUWZ256rri: + case X86::VPCMPWZrri: case X86::VPCMPUWZrri: + case X86::VPCMPBZ128rrik: case X86::VPCMPUBZ128rrik: + case X86::VPCMPBZ256rrik: case X86::VPCMPUBZ256rrik: + case X86::VPCMPBZrrik: case X86::VPCMPUBZrrik: + case X86::VPCMPDZ128rrik: case X86::VPCMPUDZ128rrik: + case X86::VPCMPDZ256rrik: case X86::VPCMPUDZ256rrik: + case X86::VPCMPDZrrik: case X86::VPCMPUDZrrik: + case X86::VPCMPQZ128rrik: case X86::VPCMPUQZ128rrik: + case X86::VPCMPQZ256rrik: case X86::VPCMPUQZ256rrik: + case X86::VPCMPQZrrik: case X86::VPCMPUQZrrik: + case X86::VPCMPWZ128rrik: case X86::VPCMPUWZ128rrik: + case X86::VPCMPWZ256rrik: case X86::VPCMPUWZ256rrik: + case X86::VPCMPWZrrik: case X86::VPCMPUWZrrik: { // Flip comparison mode immediate (if necessary). - unsigned Imm = MI.getOperand(3).getImm() & 0x7; + unsigned Imm = MI.getOperand(MI.getNumOperands() - 1).getImm() & 0x7; switch (Imm) { default: llvm_unreachable("Unreachable!"); case 0x01: Imm = 0x06; break; // LT -> NLE @@ -5163,7 +5269,7 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, break; } auto &WorkingMI = cloneIfNew(MI); - WorkingMI.getOperand(3).setImm(Imm); + WorkingMI.getOperand(MI.getNumOperands() - 1).setImm(Imm); return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false, OpIdx1, OpIdx2); } diff --git a/lib/Testing/CMakeLists.txt b/lib/Testing/CMakeLists.txt new file mode 100644 index 0000000..fc23e64 --- /dev/null +++ b/lib/Testing/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Support) diff --git a/lib/Testing/LLVMBuild.txt b/lib/Testing/LLVMBuild.txt new file mode 100644 index 0000000..cdf8373 --- /dev/null +++ b/lib/Testing/LLVMBuild.txt @@ -0,0 +1,19 @@ +;===- ./lib/Testing/LLVMBuild.txt ------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[common] +subdirectories = Support diff --git a/lib/Testing/Support/CMakeLists.txt b/lib/Testing/Support/CMakeLists.txt new file mode 100644 index 0000000..fa8dfe5 --- /dev/null +++ b/lib/Testing/Support/CMakeLists.txt @@ -0,0 +1,12 @@ +add_llvm_library(LLVMTestingSupport + Error.cpp + + BUILDTREE_ONLY + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Testing/Support + ) + +include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include) +include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include) +target_link_libraries(LLVMTestingSupport PRIVATE gtest) \ No newline at end of file diff --git a/lib/Testing/Support/Error.cpp b/lib/Testing/Support/Error.cpp new file mode 100644 index 0000000..ce0da44 --- /dev/null +++ b/lib/Testing/Support/Error.cpp @@ -0,0 +1,22 @@ +//===- llvm/Testing/Support/Error.cpp -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Testing/Support/Error.h" + +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +llvm::detail::ErrorHolder llvm::detail::TakeError(llvm::Error Err) { + bool Succeeded = !static_cast(Err); + std::string Message; + if (!Succeeded) + Message = toString(std::move(Err)); + return {Succeeded, Message}; +} diff --git a/lib/Testing/Support/LLVMBuild.txt b/lib/Testing/Support/LLVMBuild.txt new file mode 100644 index 0000000..40853e8 --- /dev/null +++ b/lib/Testing/Support/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./Testing/Support/LLVMBuild.txt --------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = TestingSupport +parent = Libraries +required_libraries = Support diff --git a/lib/Transforms/IPO/CrossDSOCFI.cpp b/lib/Transforms/IPO/CrossDSOCFI.cpp index 1b111de..d94aa5d 100644 --- a/lib/Transforms/IPO/CrossDSOCFI.cpp +++ b/lib/Transforms/IPO/CrossDSOCFI.cpp @@ -95,6 +95,17 @@ void CrossDSOCFI::buildCFICheck(Module &M) { } } + NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions"); + if (CfiFunctionsMD) { + for (auto Func : CfiFunctionsMD->operands()) { + assert(Func->getNumOperands() >= 2); + for (unsigned I = 2; I < Func->getNumOperands(); ++I) + if (ConstantInt *TypeId = + extractNumericTypeId(cast(Func->getOperand(I).get()))) + TypeIds.insert(TypeId->getZExtValue()); + } + } + LLVMContext &Ctx = M.getContext(); Constant *C = M.getOrInsertFunction( "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx), diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index c0dfeed..ad89e40 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -523,40 +523,47 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, if (!Callee || Callee->isDeclaration()) continue; - // If this call site is dead and it is to a readonly function, we should - // just delete the call instead of trying to inline it, regardless of - // size. This happens because IPSCCP propagates the result out of the - // call and then we're left with the dead call. - if (isInstructionTriviallyDead(CS.getInstruction(), &TLI)) { - DEBUG(dbgs() << " -> Deleting dead call: " << *CS.getInstruction() - << "\n"); - // Update the call graph by deleting the edge from Callee to Caller. - CG[Caller]->removeCallEdgeFor(CS); - CS.getInstruction()->eraseFromParent(); - ++NumCallsDeleted; - } else { + Instruction *Instr = CS.getInstruction(); + + bool IsTriviallyDead = isInstructionTriviallyDead(Instr, &TLI); + + int InlineHistoryID; + if (!IsTriviallyDead) { // If this call site was obtained by inlining another function, verify // that the include path for the function did not include the callee // itself. If so, we'd be recursively inlining the same function, // which would provide the same callsites, which would cause us to // infinitely inline. - int InlineHistoryID = CallSites[CSi].second; + InlineHistoryID = CallSites[CSi].second; if (InlineHistoryID != -1 && InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory)) continue; + } + // FIXME for new PM: because of the old PM we currently generate ORE and + // in turn BFI on demand. With the new PM, the ORE dependency should + // just become a regular analysis dependency. + OptimizationRemarkEmitter ORE(Caller); + + // If the policy determines that we should inline this function, + // delete the call instead. + if (!shouldInline(CS, GetInlineCost, ORE)) + continue; + + // If this call site is dead and it is to a readonly function, we should + // just delete the call instead of trying to inline it, regardless of + // size. This happens because IPSCCP propagates the result out of the + // call and then we're left with the dead call. + if (IsTriviallyDead) { + DEBUG(dbgs() << " -> Deleting dead call: " << *Instr << "\n"); + // Update the call graph by deleting the edge from Callee to Caller. + CG[Caller]->removeCallEdgeFor(CS); + Instr->eraseFromParent(); + ++NumCallsDeleted; + } else { // Get DebugLoc to report. CS will be invalid after Inliner. - DebugLoc DLoc = CS.getInstruction()->getDebugLoc(); + DebugLoc DLoc = Instr->getDebugLoc(); BasicBlock *Block = CS.getParent(); - // FIXME for new PM: because of the old PM we currently generate ORE and - // in turn BFI on demand. With the new PM, the ORE dependency should - // just become a regular analysis dependency. - OptimizationRemarkEmitter ORE(Caller); - - // If the policy determines that we should inline this function, - // try to do so. - if (!shouldInline(CS, GetInlineCost, ORE)) - continue; // Attempt to inline the function. using namespace ore; diff --git a/lib/Transforms/IPO/LowerTypeTests.cpp b/lib/Transforms/IPO/LowerTypeTests.cpp index 90896d2..b406c22 100644 --- a/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/lib/Transforms/IPO/LowerTypeTests.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/TypeMetadataUtils.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -206,17 +207,26 @@ struct ByteArrayInfo { class GlobalTypeMember final : TrailingObjects { GlobalObject *GO; size_t NTypes; + // For functions: true if this is a definition (either in the merged module or + // in one of the thinlto modules). + bool IsDefinition; + // For functions: true if this function is either defined or used in a thinlto + // module and its jumptable entry needs to be exported to thinlto backends. + bool IsExported; friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { return NTypes; } public: static GlobalTypeMember *create(BumpPtrAllocator &Alloc, GlobalObject *GO, + bool IsDefinition, bool IsExported, ArrayRef Types) { auto *GTM = static_cast(Alloc.Allocate( totalSizeToAlloc(Types.size()), alignof(GlobalTypeMember))); GTM->GO = GO; GTM->NTypes = Types.size(); + GTM->IsDefinition = IsDefinition; + GTM->IsExported = IsExported; std::uninitialized_copy(Types.begin(), Types.end(), GTM->getTrailingObjects()); return GTM; @@ -224,6 +234,12 @@ public: GlobalObject *getGlobal() const { return GO; } + bool isDefinition() const { + return IsDefinition; + } + bool isExported() const { + return IsExported; + } ArrayRef types() const { return makeArrayRef(getTrailingObjects(), NTypes); } @@ -294,6 +310,7 @@ class LowerTypeTestsModule { void exportTypeId(StringRef TypeId, const TypeIdLowering &TIL); TypeIdLowering importTypeId(StringRef TypeId); void importTypeTest(CallInst *CI); + void importFunction(Function *F, bool isDefinition); BitSetInfo buildBitSet(Metadata *TypeId, @@ -820,6 +837,41 @@ void LowerTypeTestsModule::importTypeTest(CallInst *CI) { CI->eraseFromParent(); } +// ThinLTO backend: the function F has a jump table entry; update this module +// accordingly. isDefinition describes the type of the jump table entry. +void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) { + assert(F->getType()->getAddressSpace() == 0); + + // Declaration of a local function - nothing to do. + if (F->isDeclarationForLinker() && isDefinition) + return; + + GlobalValue::VisibilityTypes Visibility = F->getVisibility(); + std::string Name = F->getName(); + Function *FDecl; + + if (F->isDeclarationForLinker() && !isDefinition) { + // Declaration of an external function. + FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, + Name + ".cfi_jt", &M); + FDecl->setVisibility(GlobalValue::HiddenVisibility); + } else { + // Definition. + assert(isDefinition); + F->setName(Name + ".cfi"); + F->setLinkage(GlobalValue::ExternalLinkage); + F->setVisibility(GlobalValue::HiddenVisibility); + FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage, + Name, &M); + FDecl->setVisibility(Visibility); + } + + if (F->isWeakForLinker()) + replaceWeakDeclarationWithJumpTablePtr(F, FDecl); + else + F->replaceAllUsesWith(FDecl); +} + void LowerTypeTestsModule::lowerTypeTestCalls( ArrayRef TypeIds, Constant *CombinedGlobalAddr, const DenseMap &GlobalLayout) { @@ -1143,7 +1195,6 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative( // arithmetic that we normally use for globals. // FIXME: find a better way to represent the jumptable in the IR. - assert(!Functions.empty()); // Build a simple layout based on the regular layout of jump tables. @@ -1167,6 +1218,7 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative( // references to the original functions with references to the aliases. for (unsigned I = 0; I != Functions.size(); ++I) { Function *F = cast(Functions[I]->getGlobal()); + bool IsDefinition = Functions[I]->isDefinition(); Constant *CombinedGlobalElemPtr = ConstantExpr::getBitCast( ConstantExpr::getInBoundsGetElementPtr( @@ -1174,7 +1226,18 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative( ArrayRef{ConstantInt::get(IntPtrTy, 0), ConstantInt::get(IntPtrTy, I)}), F->getType()); - if (F->isDeclarationForLinker()) { + if (Functions[I]->isExported()) { + if (IsDefinition) { + ExportSummary->cfiFunctionDefs().insert(F->getName()); + } else { + GlobalAlias *JtAlias = GlobalAlias::create( + F->getValueType(), 0, GlobalValue::ExternalLinkage, + F->getName() + ".cfi_jt", CombinedGlobalElemPtr, &M); + JtAlias->setVisibility(GlobalValue::HiddenVisibility); + ExportSummary->cfiFunctionDecls().insert(F->getName()); + } + } + if (!IsDefinition) { if (F->isWeakForLinker()) replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr); else @@ -1182,9 +1245,8 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative( } else { assert(F->getType()->getAddressSpace() == 0); - GlobalAlias *FAlias = GlobalAlias::create(F->getValueType(), 0, - F->getLinkage(), "", - CombinedGlobalElemPtr, &M); + GlobalAlias *FAlias = GlobalAlias::create( + F->getValueType(), 0, F->getLinkage(), "", CombinedGlobalElemPtr, &M); FAlias->setVisibility(F->getVisibility()); FAlias->takeName(F); if (FAlias->hasName()) @@ -1353,15 +1415,37 @@ bool LowerTypeTestsModule::runForTesting(Module &M) { bool LowerTypeTestsModule::lower() { Function *TypeTestFunc = M.getFunction(Intrinsic::getName(Intrinsic::type_test)); - if ((!TypeTestFunc || TypeTestFunc->use_empty()) && !ExportSummary) + if ((!TypeTestFunc || TypeTestFunc->use_empty()) && !ExportSummary && + !ImportSummary) return false; if (ImportSummary) { - for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end(); - UI != UE;) { - auto *CI = cast((*UI++).getUser()); - importTypeTest(CI); + if (TypeTestFunc) { + for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end(); + UI != UE;) { + auto *CI = cast((*UI++).getUser()); + importTypeTest(CI); + } + } + + SmallVector Defs; + SmallVector Decls; + for (auto &F : M) { + // CFI functions are either external, or promoted. A local function may + // have the same name, but it's not the one we are looking for. + if (F.hasLocalLinkage()) + continue; + if (ImportSummary->cfiFunctionDefs().count(F.getName())) + Defs.push_back(&F); + else if (ImportSummary->cfiFunctionDecls().count(F.getName())) + Decls.push_back(&F); } + + for (auto F : Defs) + importFunction(F, /*isDefinition*/ true); + for (auto F : Decls) + importFunction(F, /*isDefinition*/ false); + return true; } @@ -1387,6 +1471,58 @@ bool LowerTypeTestsModule::lower() { llvm::DenseMap TypeIdInfo; unsigned I = 0; SmallVector Types; + + struct ExportedFunctionInfo { + CfiFunctionLinkage Linkage; + MDNode *FuncMD; // {name, linkage, type[, type...]} + }; + DenseMap ExportedFunctions; + if (ExportSummary) { + NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions"); + if (CfiFunctionsMD) { + for (auto FuncMD : CfiFunctionsMD->operands()) { + assert(FuncMD->getNumOperands() >= 2); + StringRef FunctionName = + cast(FuncMD->getOperand(0))->getString(); + if (!ExportSummary->isGUIDLive(GlobalValue::getGUID( + GlobalValue::dropLLVMManglingEscape(FunctionName)))) + continue; + CfiFunctionLinkage Linkage = static_cast( + cast(FuncMD->getOperand(1)) + ->getValue() + ->getUniqueInteger() + .getZExtValue()); + auto P = ExportedFunctions.insert({FunctionName, {Linkage, FuncMD}}); + if (!P.second && P.first->second.Linkage != CFL_Definition) + P.first->second = {Linkage, FuncMD}; + } + + for (const auto &P : ExportedFunctions) { + StringRef FunctionName = P.first; + CfiFunctionLinkage Linkage = P.second.Linkage; + MDNode *FuncMD = P.second.FuncMD; + Function *F = M.getFunction(FunctionName); + if (!F) + F = Function::Create( + FunctionType::get(Type::getVoidTy(M.getContext()), false), + GlobalVariable::ExternalLinkage, FunctionName, &M); + + if (Linkage == CFL_Definition) + F->eraseMetadata(LLVMContext::MD_type); + + if (F->isDeclaration()) { + if (Linkage == CFL_WeakDeclaration) + F->setLinkage(GlobalValue::ExternalWeakLinkage); + + SmallVector Types; + for (unsigned I = 2; I < FuncMD->getNumOperands(); ++I) + F->addMetadata(LLVMContext::MD_type, + *cast(FuncMD->getOperand(I).get())); + } + } + } + } + for (GlobalObject &GO : M.global_objects()) { if (isa(GO) && GO.isDeclarationForLinker()) continue; @@ -1396,7 +1532,15 @@ bool LowerTypeTestsModule::lower() { if (Types.empty()) continue; - auto *GTM = GlobalTypeMember::create(Alloc, &GO, Types); + bool IsDefinition = !GO.isDeclarationForLinker(); + bool IsExported = false; + if (isa(GO) && ExportedFunctions.count(GO.getName())) { + IsDefinition |= ExportedFunctions[GO.getName()].Linkage == CFL_Definition; + IsExported = true; + } + + auto *GTM = + GlobalTypeMember::create(Alloc, &GO, IsDefinition, IsExported, Types); for (MDNode *Type : Types) { verifyTypeMDNode(&GO, Type); auto &Info = TypeIdInfo[cast(Type)->getOperand(1)]; diff --git a/lib/Transforms/IPO/PartialInlining.cpp b/lib/Transforms/IPO/PartialInlining.cpp index ea805ef..8840435 100644 --- a/lib/Transforms/IPO/PartialInlining.cpp +++ b/lib/Transforms/IPO/PartialInlining.cpp @@ -103,6 +103,35 @@ struct PartialInlinerImpl { bool run(Module &M); Function *unswitchFunction(Function *F); + // This class speculatively clones the the function to be partial inlined. + // At the end of partial inlining, the remaining callsites to the cloned + // function that are not partially inlined will be fixed up to reference + // the original function, and the cloned function will be erased. + struct FunctionCloner { + FunctionCloner(Function *F, FunctionOutliningInfo *OI); + ~FunctionCloner(); + + // Prepare for function outlining: making sure there is only + // one incoming edge from the extracted/outlined region to + // the return block. + void NormalizeReturnBlock(); + + // Do function outlining: + Function *doFunctionOutlining(); + + Function *OrigFunc = nullptr; + Function *ClonedFunc = nullptr; + Function *OutlinedFunc = nullptr; + BasicBlock *OutliningCallBB = nullptr; + // ClonedFunc is inlined in one of its callers after function + // outlining. + bool IsFunctionInlined = false; + // The cost of the region to be outlined. + int OutlinedRegionCost = 0; + std::unique_ptr ClonedOI = nullptr; + std::unique_ptr ClonedFuncBFI = nullptr; + }; + private: int NumPartialInlining = 0; std::function *GetAssumptionCache; @@ -114,27 +143,18 @@ private: // The result is no larger than 1 and is represented using BP. // (Note that the outlined region's 'head' block can only have incoming // edges from the guarding entry blocks). - BranchProbability getOutliningCallBBRelativeFreq(Function *F, - FunctionOutliningInfo *OI, - Function *DuplicateFunction, - BlockFrequencyInfo *BFI, - BasicBlock *OutliningCallBB); + BranchProbability getOutliningCallBBRelativeFreq(FunctionCloner &Cloner); // Return true if the callee of CS should be partially inlined with // profit. - bool shouldPartialInline(CallSite CS, Function *F, FunctionOutliningInfo *OI, - BlockFrequencyInfo *CalleeBFI, - BasicBlock *OutliningCallBB, - int OutliningCallOverhead, + bool shouldPartialInline(CallSite CS, FunctionCloner &Cloner, + BlockFrequency WeightedOutliningRcost, OptimizationRemarkEmitter &ORE); // Try to inline DuplicateFunction (cloned from F with call to // the OutlinedFunction into its callers. Return true // if there is any successful inlining. - bool tryPartialInline(Function *DuplicateFunction, - Function *F, /*orignal function */ - FunctionOutliningInfo *OI, Function *OutlinedFunction, - BlockFrequencyInfo *CalleeBFI); + bool tryPartialInline(FunctionCloner &Cloner); // Compute the mapping from use site of DuplicationFunction to the enclosing // BB's profile count. @@ -146,7 +166,7 @@ private: NumPartialInlining >= MaxNumPartialInlining); } - CallSite getCallSite(User *U) { + static CallSite getCallSite(User *U) { CallSite CS; if (CallInst *CI = dyn_cast(U)) CS = CallSite(CI); @@ -157,7 +177,7 @@ private: return CS; } - CallSite getOneCallSiteTo(Function *F) { + static CallSite getOneCallSiteTo(Function *F) { User *User = *F->user_begin(); return getCallSite(User); } @@ -171,20 +191,15 @@ private: // Returns the costs associated with function outlining: // - The first value is the non-weighted runtime cost for making the call - // to the outlined function 'OutlinedFunction', including the addtional - // setup cost in the outlined function itself; + // to the outlined function, including the addtional setup cost in the + // outlined function itself; // - The second value is the estimated size of the new call sequence in - // basic block 'OutliningCallBB'; - // - The third value is the estimated size of the original code from - // function 'F' that is extracted into the outlined function. - std::tuple - computeOutliningCosts(Function *F, const FunctionOutliningInfo *OutliningInfo, - Function *OutlinedFunction, - BasicBlock *OutliningCallBB); + // basic block Cloner.OutliningCallBB; + std::tuple computeOutliningCosts(FunctionCloner &Cloner); // Compute the 'InlineCost' of block BB. InlineCost is a proxy used to // approximate both the size and runtime cost (Note that in the current // inline cost analysis, there is no clear distinction there either). - int computeBBInlineCost(BasicBlock *BB); + static int computeBBInlineCost(BasicBlock *BB); std::unique_ptr computeOutliningInfo(Function *F); @@ -396,19 +411,19 @@ static bool hasProfileData(Function *F, FunctionOutliningInfo *OI) { return false; } -BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq( - Function *F, FunctionOutliningInfo *OI, Function *DuplicateFunction, - BlockFrequencyInfo *BFI, BasicBlock *OutliningCallBB) { +BranchProbability +PartialInlinerImpl::getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) { auto EntryFreq = - BFI->getBlockFreq(&DuplicateFunction->getEntryBlock()); - auto OutliningCallFreq = BFI->getBlockFreq(OutliningCallBB); + Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock()); + auto OutliningCallFreq = + Cloner.ClonedFuncBFI->getBlockFreq(Cloner.OutliningCallBB); auto OutlineRegionRelFreq = BranchProbability::getBranchProbability(OutliningCallFreq.getFrequency(), EntryFreq.getFrequency()); - if (hasProfileData(F, OI)) + if (hasProfileData(Cloner.OrigFunc, Cloner.ClonedOI.get())) return OutlineRegionRelFreq; // When profile data is not available, we need to be conservative in @@ -433,15 +448,17 @@ BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq( } bool PartialInlinerImpl::shouldPartialInline( - CallSite CS, Function *F /* Original Callee */, FunctionOutliningInfo *OI, - BlockFrequencyInfo *CalleeBFI, BasicBlock *OutliningCallBB, - int NonWeightedOutliningRcost, OptimizationRemarkEmitter &ORE) { + CallSite CS, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost, + OptimizationRemarkEmitter &ORE) { + using namespace ore; if (SkipCostAnalysis) return true; Instruction *Call = CS.getInstruction(); Function *Callee = CS.getCalledFunction(); + assert(Callee == Cloner.ClonedFunc); + Function *Caller = CS.getCaller(); auto &CalleeTTI = (*GetTTI)(*Callee); InlineCost IC = getInlineCost(CS, getInlineParams(), CalleeTTI, @@ -449,14 +466,14 @@ bool PartialInlinerImpl::shouldPartialInline( if (IC.isAlways()) { ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", Call) - << NV("Callee", F) + << NV("Callee", Cloner.OrigFunc) << " should always be fully inlined, not partially"); return false; } if (IC.isNever()) { ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) - << NV("Callee", F) << " not partially inlined into " + << NV("Callee", Cloner.OrigFunc) << " not partially inlined into " << NV("Caller", Caller) << " because it should never be inlined (cost=never)"); return false; @@ -464,29 +481,25 @@ bool PartialInlinerImpl::shouldPartialInline( if (!IC) { ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", Call) - << NV("Callee", F) << " not partially inlined into " + << NV("Callee", Cloner.OrigFunc) << " not partially inlined into " << NV("Caller", Caller) << " because too costly to inline (cost=" << NV("Cost", IC.getCost()) << ", threshold=" << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")"); return false; } const DataLayout &DL = Caller->getParent()->getDataLayout(); + // The savings of eliminating the call: int NonWeightedSavings = getCallsiteCost(CS, DL); BlockFrequency NormWeightedSavings(NonWeightedSavings); - auto RelativeFreq = - getOutliningCallBBRelativeFreq(F, OI, Callee, CalleeBFI, OutliningCallBB); - auto NormWeightedRcost = - BlockFrequency(NonWeightedOutliningRcost) * RelativeFreq; - // Weighted saving is smaller than weighted cost, return false - if (NormWeightedSavings < NormWeightedRcost) { + if (NormWeightedSavings < WeightedOutliningRcost) { ORE.emit( OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh", Call) - << NV("Callee", F) << " not partially inlined into " + << NV("Callee", Cloner.OrigFunc) << " not partially inlined into " << NV("Caller", Caller) << " runtime overhead (overhead=" - << NV("Overhead", (unsigned)NormWeightedRcost.getFrequency()) + << NV("Overhead", (unsigned)WeightedOutliningRcost.getFrequency()) << ", savings=" << NV("Savings", (unsigned)NormWeightedSavings.getFrequency()) << ")" << " of making the outlined call is too high"); @@ -495,7 +508,7 @@ bool PartialInlinerImpl::shouldPartialInline( } ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", Call) - << NV("Callee", F) << " can be partially inlined into " + << NV("Callee", Cloner.OrigFunc) << " can be partially inlined into " << NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost()) << " (threshold=" << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")"); @@ -551,50 +564,32 @@ int PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB) { return InlineCost; } -std::tuple PartialInlinerImpl::computeOutliningCosts( - Function *F, const FunctionOutliningInfo *OI, Function *OutlinedFunction, - BasicBlock *OutliningCallBB) { - // First compute the cost of the outlined region 'OI' in the original - // function 'F'. - // FIXME: The code extractor (outliner) can now do code sinking/hoisting - // to reduce outlining cost. The hoisted/sunk code currently do not - // incur any runtime cost so it is still OK to compare the outlined - // function cost with the outlined region in the original function. - // If this ever changes, we will need to introduce new extractor api - // to pass the information. - int OutlinedRegionCost = 0; - for (BasicBlock &BB : *F) { - if (&BB != OI->ReturnBlock && - // Assuming Entry set is small -- do a linear search here: - std::find(OI->Entries.begin(), OI->Entries.end(), &BB) == - OI->Entries.end()) { - OutlinedRegionCost += computeBBInlineCost(&BB); - } - } +std::tuple +PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) { // Now compute the cost of the call sequence to the outlined function // 'OutlinedFunction' in BB 'OutliningCallBB': - int OutliningFuncCallCost = computeBBInlineCost(OutliningCallBB); + int OutliningFuncCallCost = computeBBInlineCost(Cloner.OutliningCallBB); // Now compute the cost of the extracted/outlined function itself: int OutlinedFunctionCost = 0; - for (BasicBlock &BB : *OutlinedFunction) { + for (BasicBlock &BB : *Cloner.OutlinedFunc) { OutlinedFunctionCost += computeBBInlineCost(&BB); } - assert(OutlinedFunctionCost >= OutlinedRegionCost && + assert(OutlinedFunctionCost >= Cloner.OutlinedRegionCost && "Outlined function cost should be no less than the outlined region"); // The code extractor introduces a new root and exit stub blocks with // additional unconditional branches. Those branches will be eliminated // later with bb layout. The cost should be adjusted accordingly: OutlinedFunctionCost -= 2 * InlineConstants::InstrCost; - int OutliningRuntimeOverhead = OutliningFuncCallCost + - (OutlinedFunctionCost - OutlinedRegionCost) + - ExtraOutliningPenalty; + int OutliningRuntimeOverhead = + OutliningFuncCallCost + + (OutlinedFunctionCost - Cloner.OutlinedRegionCost) + + ExtraOutliningPenalty; - return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead, - OutlinedRegionCost); + return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead); } // Create the callsite to profile count map which is @@ -641,42 +636,30 @@ void PartialInlinerImpl::computeCallsiteToProfCountMap( } } -Function *PartialInlinerImpl::unswitchFunction(Function *F) { - - if (F->hasAddressTaken()) - return nullptr; - - // Let inliner handle it - if (F->hasFnAttribute(Attribute::AlwaysInline)) - return nullptr; - - if (F->hasFnAttribute(Attribute::NoInline)) - return nullptr; - - if (PSI->isFunctionEntryCold(F)) - return nullptr; - - if (F->user_begin() == F->user_end()) - return nullptr; - - std::unique_ptr OI = computeOutliningInfo(F); - - if (!OI) - return nullptr; +PartialInlinerImpl::FunctionCloner::FunctionCloner(Function *F, + FunctionOutliningInfo *OI) + : OrigFunc(F) { + ClonedOI = llvm::make_unique(); // Clone the function, so that we can hack away on it. ValueToValueMapTy VMap; - Function *DuplicateFunction = CloneFunction(F, VMap); - BasicBlock *NewReturnBlock = cast(VMap[OI->ReturnBlock]); - BasicBlock *NewNonReturnBlock = cast(VMap[OI->NonReturnBlock]); - DenseSet NewEntries; + ClonedFunc = CloneFunction(F, VMap); + + ClonedOI->ReturnBlock = cast(VMap[OI->ReturnBlock]); + ClonedOI->NonReturnBlock = cast(VMap[OI->NonReturnBlock]); for (BasicBlock *BB : OI->Entries) { - NewEntries.insert(cast(VMap[BB])); + ClonedOI->Entries.push_back(cast(VMap[BB])); + } + for (BasicBlock *E : OI->ReturnBlockPreds) { + BasicBlock *NewE = cast(VMap[E]); + ClonedOI->ReturnBlockPreds.push_back(NewE); } - // Go ahead and update all uses to the duplicate, so that we can just // use the inliner functionality when we're done hacking. - F->replaceAllUsesWith(DuplicateFunction); + F->replaceAllUsesWith(ClonedFunc); +} + +void PartialInlinerImpl::FunctionCloner::NormalizeReturnBlock() { auto getFirstPHI = [](BasicBlock *BB) { BasicBlock::iterator I = BB->begin(); @@ -692,14 +675,19 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) { } return FirstPhi; }; + // Special hackery is needed with PHI nodes that have inputs from more than // one extracted block. For simplicity, just split the PHIs into a two-level // sequence of PHIs, some of which will go in the extracted region, and some // of which will go outside. - BasicBlock *PreReturn = NewReturnBlock; + BasicBlock *PreReturn = ClonedOI->ReturnBlock; // only split block when necessary: PHINode *FirstPhi = getFirstPHI(PreReturn); - unsigned NumPredsFromEntries = OI->ReturnBlockPreds.size(); + unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size(); + + if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1) + return; + auto IsTrivialPhi = [](PHINode *PN) -> Value * { Value *CommonValue = PN->getIncomingValue(0); if (all_of(PN->incoming_values(), @@ -708,143 +696,185 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) { return nullptr; }; - if (FirstPhi && FirstPhi->getNumIncomingValues() > NumPredsFromEntries + 1) { - - NewReturnBlock = NewReturnBlock->splitBasicBlock( - NewReturnBlock->getFirstNonPHI()->getIterator()); - BasicBlock::iterator I = PreReturn->begin(); - Instruction *Ins = &NewReturnBlock->front(); - SmallVector DeadPhis; - while (I != PreReturn->end()) { - PHINode *OldPhi = dyn_cast(I); - if (!OldPhi) - break; - - PHINode *RetPhi = - PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins); - OldPhi->replaceAllUsesWith(RetPhi); - Ins = NewReturnBlock->getFirstNonPHI(); + ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock( + ClonedOI->ReturnBlock->getFirstNonPHI()->getIterator()); + BasicBlock::iterator I = PreReturn->begin(); + Instruction *Ins = &ClonedOI->ReturnBlock->front(); + SmallVector DeadPhis; + while (I != PreReturn->end()) { + PHINode *OldPhi = dyn_cast(I); + if (!OldPhi) + break; - RetPhi->addIncoming(&*I, PreReturn); - for (BasicBlock *E : OI->ReturnBlockPreds) { - BasicBlock *NewE = cast(VMap[E]); - RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(NewE), NewE); - OldPhi->removeIncomingValue(NewE); - } + PHINode *RetPhi = + PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins); + OldPhi->replaceAllUsesWith(RetPhi); + Ins = ClonedOI->ReturnBlock->getFirstNonPHI(); - // After incoming values splitting, the old phi may become trivial. - // Keeping the trivial phi can introduce definition inside the outline - // region which is live-out, causing necessary overhead (load, store - // arg passing etc). - if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) { - OldPhi->replaceAllUsesWith(OldPhiVal); - DeadPhis.push_back(OldPhi); - } - - ++I; + RetPhi->addIncoming(&*I, PreReturn); + for (BasicBlock *E : ClonedOI->ReturnBlockPreds) { + RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(E), E); + OldPhi->removeIncomingValue(E); } + // After incoming values splitting, the old phi may become trivial. + // Keeping the trivial phi can introduce definition inside the outline + // region which is live-out, causing necessary overhead (load, store + // arg passing etc). + if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) { + OldPhi->replaceAllUsesWith(OldPhiVal); + DeadPhis.push_back(OldPhi); + } + ++I; + } for (auto *DP : DeadPhis) DP->eraseFromParent(); - for (auto E : OI->ReturnBlockPreds) { - BasicBlock *NewE = cast(VMap[E]); - NewE->getTerminator()->replaceUsesOfWith(PreReturn, NewReturnBlock); + for (auto E : ClonedOI->ReturnBlockPreds) { + E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock); } - } +} +Function *PartialInlinerImpl::FunctionCloner::doFunctionOutlining() { // Returns true if the block is to be partial inlined into the caller // (i.e. not to be extracted to the out of line function) - auto ToBeInlined = [&](BasicBlock *BB) { - return BB == NewReturnBlock || NewEntries.count(BB); + auto ToBeInlined = [&, this](BasicBlock *BB) { + return BB == ClonedOI->ReturnBlock || + (std::find(ClonedOI->Entries.begin(), ClonedOI->Entries.end(), BB) != + ClonedOI->Entries.end()); }; + // Gather up the blocks that we're going to extract. std::vector ToExtract; - ToExtract.push_back(NewNonReturnBlock); - for (BasicBlock &BB : *DuplicateFunction) - if (!ToBeInlined(&BB) && &BB != NewNonReturnBlock) + ToExtract.push_back(ClonedOI->NonReturnBlock); + OutlinedRegionCost += + PartialInlinerImpl::computeBBInlineCost(ClonedOI->NonReturnBlock); + for (BasicBlock &BB : *ClonedFunc) + if (!ToBeInlined(&BB) && &BB != ClonedOI->NonReturnBlock) { ToExtract.push_back(&BB); + // FIXME: the code extractor may hoist/sink more code + // into the outlined function which may make the outlining + // overhead (the difference of the outlined function cost + // and OutliningRegionCost) look larger. + OutlinedRegionCost += computeBBInlineCost(&BB); + } // The CodeExtractor needs a dominator tree. DominatorTree DT; - DT.recalculate(*DuplicateFunction); + DT.recalculate(*ClonedFunc); // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo. LoopInfo LI(DT); - BranchProbabilityInfo BPI(*DuplicateFunction, LI); - BlockFrequencyInfo BFI(*DuplicateFunction, BPI, LI); + BranchProbabilityInfo BPI(*ClonedFunc, LI); + ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI)); // Extract the body of the if. - Function *OutlinedFunction = - CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false, &BFI, &BPI) - .extractCodeRegion(); + OutlinedFunc = CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false, + ClonedFuncBFI.get(), &BPI) + .extractCodeRegion(); + + if (OutlinedFunc) { + OutliningCallBB = PartialInlinerImpl::getOneCallSiteTo(OutlinedFunc) + .getInstruction() + ->getParent(); + assert(OutliningCallBB->getParent() == ClonedFunc); + } - bool AnyInline = - tryPartialInline(DuplicateFunction, F, OI.get(), OutlinedFunction, &BFI); + return OutlinedFunc; +} +PartialInlinerImpl::FunctionCloner::~FunctionCloner() { // Ditch the duplicate, since we're done with it, and rewrite all remaining // users (function pointers, etc.) back to the original function. - DuplicateFunction->replaceAllUsesWith(F); - DuplicateFunction->eraseFromParent(); + ClonedFunc->replaceAllUsesWith(OrigFunc); + ClonedFunc->eraseFromParent(); + if (!IsFunctionInlined) { + // Remove the function that is speculatively created if there is no + // reference. + if (OutlinedFunc) + OutlinedFunc->eraseFromParent(); + } +} + +Function *PartialInlinerImpl::unswitchFunction(Function *F) { + + if (F->hasAddressTaken()) + return nullptr; + + // Let inliner handle it + if (F->hasFnAttribute(Attribute::AlwaysInline)) + return nullptr; + + if (F->hasFnAttribute(Attribute::NoInline)) + return nullptr; + + if (PSI->isFunctionEntryCold(F)) + return nullptr; + + if (F->user_begin() == F->user_end()) + return nullptr; + + std::unique_ptr OI = computeOutliningInfo(F); + + if (!OI) + return nullptr; + + FunctionCloner Cloner(F, OI.get()); + Cloner.NormalizeReturnBlock(); + Function *OutlinedFunction = Cloner.doFunctionOutlining(); + + bool AnyInline = tryPartialInline(Cloner); if (AnyInline) return OutlinedFunction; - // Remove the function that is speculatively created: - if (OutlinedFunction) - OutlinedFunction->eraseFromParent(); - return nullptr; } -bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction, - Function *F, - FunctionOutliningInfo *OI, - Function *OutlinedFunction, - BlockFrequencyInfo *CalleeBFI) { - if (OutlinedFunction == nullptr) - return false; - +bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) { int NonWeightedRcost; int SizeCost; - int OutlinedRegionSizeCost; - auto OutliningCallBB = - getOneCallSiteTo(OutlinedFunction).getInstruction()->getParent(); + if (Cloner.OutlinedFunc == nullptr) + return false; + + std::tie(SizeCost, NonWeightedRcost) = computeOutliningCosts(Cloner); - std::tie(SizeCost, NonWeightedRcost, OutlinedRegionSizeCost) = - computeOutliningCosts(F, OI, OutlinedFunction, OutliningCallBB); + auto RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner); + auto WeightedRcost = BlockFrequency(NonWeightedRcost) * RelativeToEntryFreq; // The call sequence to the outlined function is larger than the original // outlined region size, it does not increase the chances of inlining - // 'F' with outlining (The inliner usies the size increase to model the - // the cost of inlining a callee). - if (!SkipCostAnalysis && OutlinedRegionSizeCost < SizeCost) { - OptimizationRemarkEmitter ORE(F); + // the function with outlining (The inliner usies the size increase to + // model the cost of inlining a callee). + if (!SkipCostAnalysis && Cloner.OutlinedRegionCost < SizeCost) { + OptimizationRemarkEmitter ORE(Cloner.OrigFunc); DebugLoc DLoc; BasicBlock *Block; - std::tie(DLoc, Block) = getOneDebugLoc(DuplicateFunction); + std::tie(DLoc, Block) = getOneDebugLoc(Cloner.ClonedFunc); ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall", DLoc, Block) - << ore::NV("Function", F) + << ore::NV("Function", Cloner.OrigFunc) << " not partially inlined into callers (Original Size = " - << ore::NV("OutlinedRegionOriginalSize", OutlinedRegionSizeCost) + << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost) << ", Size of call sequence to outlined function = " << ore::NV("NewSize", SizeCost) << ")"); return false; } - assert(F->user_begin() == F->user_end() && + assert(Cloner.OrigFunc->user_begin() == Cloner.OrigFunc->user_end() && "F's users should all be replaced!"); - std::vector Users(DuplicateFunction->user_begin(), - DuplicateFunction->user_end()); + + std::vector Users(Cloner.ClonedFunc->user_begin(), + Cloner.ClonedFunc->user_end()); DenseMap CallSiteToProfCountMap; - if (F->getEntryCount()) - computeCallsiteToProfCountMap(DuplicateFunction, CallSiteToProfCountMap); + if (Cloner.OrigFunc->getEntryCount()) + computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap); - auto CalleeEntryCount = F->getEntryCount(); + auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount(); uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0); + bool AnyInline = false; for (User *User : Users) { CallSite CS = getCallSite(User); @@ -854,13 +884,12 @@ bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction, OptimizationRemarkEmitter ORE(CS.getCaller()); - if (!shouldPartialInline(CS, F, OI, CalleeBFI, OutliningCallBB, - NonWeightedRcost, ORE)) + if (!shouldPartialInline(CS, Cloner, WeightedRcost, ORE)) continue; ORE.emit( OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", CS.getInstruction()) - << ore::NV("Callee", F) << " partially inlined into " + << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into " << ore::NV("Caller", CS.getCaller())); InlineFunctionInfo IFI(nullptr, GetAssumptionCache, PSI); @@ -878,8 +907,11 @@ bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction, NumPartialInlined++; } - if (AnyInline && CalleeEntryCount) - F->setEntryCount(CalleeEntryCountV); + if (AnyInline) { + Cloner.IsFunctionInlined = true; + if (CalleeEntryCount) + Cloner.OrigFunc->setEntryCount(CalleeEntryCountV); + } return AnyInline; } diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp index 16fba32..4bc64ab 100644 --- a/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -141,6 +141,10 @@ static cl::opt PreInlineThreshold( cl::desc("Control the amount of inlining in pre-instrumentation inliner " "(default = 75)")); +static cl::opt EnableEarlyCSEMemSSA( + "enable-earlycse-memssa", cl::init(false), cl::Hidden, + cl::desc("Enable the EarlyCSE w/ MemorySSA pass (default = off)")); + static cl::opt EnableGVNHoist( "enable-gvn-hoist", cl::init(false), cl::Hidden, cl::desc("Enable the GVN hoisting pass (default = off)")); @@ -308,7 +312,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses( // Start of function pass. // Break up aggregate allocas, using SSAUpdater. MPM.add(createSROAPass()); - MPM.add(createEarlyCSEPass()); // Catch trivial redundancies + MPM.add(createEarlyCSEPass(EnableEarlyCSEMemSSA)); // Catch trivial redundancies if (EnableGVNHoist) MPM.add(createGVNHoistPass()); if (EnableGVNSink) { diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index a7bcc7c..802f470 100644 --- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -32,7 +32,8 @@ namespace { // Promote each local-linkage entity defined by ExportM and used by ImportM by // changing visibility and appending the given ModuleId. -void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) { +void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId, + SetVector &PromoteExtra) { DenseMap RenamedComdats; for (auto &ExportGV : ExportM.global_values()) { if (!ExportGV.hasLocalLinkage()) @@ -40,7 +41,7 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) { auto Name = ExportGV.getName(); GlobalValue *ImportGV = ImportM.getNamedValue(Name); - if (!ImportGV || ImportGV->use_empty()) + if ((!ImportGV || ImportGV->use_empty()) && !PromoteExtra.count(&ExportGV)) continue; std::string NewName = (Name + ModuleId).str(); @@ -53,8 +54,10 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) { ExportGV.setLinkage(GlobalValue::ExternalLinkage); ExportGV.setVisibility(GlobalValue::HiddenVisibility); - ImportGV->setName(NewName); - ImportGV->setVisibility(GlobalValue::HiddenVisibility); + if (ImportGV) { + ImportGV->setName(NewName); + ImportGV->setVisibility(GlobalValue::HiddenVisibility); + } } if (!RenamedComdats.empty()) @@ -296,6 +299,11 @@ void splitAndWriteThinLTOBitcode( F.setComdat(nullptr); } + SetVector CfiFunctions; + for (auto &F : M) + if ((!F.hasLocalLinkage() || F.hasAddressTaken()) && HasTypeMetadata(&F)) + CfiFunctions.insert(&F); + // Remove all globals with type metadata, globals with comdats that live in // MergedM, and aliases pointing to such globals from the thin LTO module. filterModule(&M, [&](const GlobalValue *GV) { @@ -308,11 +316,39 @@ void splitAndWriteThinLTOBitcode( return true; }); - promoteInternals(*MergedM, M, ModuleId); - promoteInternals(M, *MergedM, ModuleId); + promoteInternals(*MergedM, M, ModuleId, CfiFunctions); + promoteInternals(M, *MergedM, ModuleId, CfiFunctions); + + SmallVector CfiFunctionMDs; + for (auto V : CfiFunctions) { + Function &F = *cast(V); + SmallVector Types; + F.getMetadata(LLVMContext::MD_type, Types); + + auto &Ctx = MergedM->getContext(); + SmallVector Elts; + Elts.push_back(MDString::get(Ctx, F.getName())); + CfiFunctionLinkage Linkage; + if (!F.isDeclarationForLinker()) + Linkage = CFL_Definition; + else if (F.isWeakForLinker()) + Linkage = CFL_WeakDeclaration; + else + Linkage = CFL_Declaration; + Elts.push_back(ConstantAsMetadata::get( + llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage))); + for (auto Type : Types) + Elts.push_back(Type); + CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts)); + } - simplifyExternals(*MergedM); + if(!CfiFunctionMDs.empty()) { + NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("cfi.functions"); + for (auto MD : CfiFunctionMDs) + NMD->addOperand(MD); + } + simplifyExternals(*MergedM); // FIXME: Try to re-use BSI and PFI from the original module here. ProfileSummaryInfo PSI(M); diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 4fe3225..a881bda 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -763,8 +763,54 @@ foldAndOrOfEqualityCmpsWithConstants(ICmpInst *LHS, ICmpInst *RHS, return nullptr; } +// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2) +// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2) +Value *InstCombiner::foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS, + bool JoinedByAnd, + Instruction &CxtI) { + ICmpInst::Predicate Pred = LHS->getPredicate(); + if (Pred != RHS->getPredicate()) + return nullptr; + if (JoinedByAnd && Pred != ICmpInst::ICMP_NE) + return nullptr; + if (!JoinedByAnd && Pred != ICmpInst::ICMP_EQ) + return nullptr; + + // TODO support vector splats + ConstantInt *LHSC = dyn_cast(LHS->getOperand(1)); + ConstantInt *RHSC = dyn_cast(RHS->getOperand(1)); + if (!LHSC || !RHSC || !LHSC->isZero() || !RHSC->isZero()) + return nullptr; + + Value *A, *B, *C, *D; + if (match(LHS->getOperand(0), m_And(m_Value(A), m_Value(B))) && + match(RHS->getOperand(0), m_And(m_Value(C), m_Value(D)))) { + if (A == D || B == D) + std::swap(C, D); + if (B == C) + std::swap(A, B); + + if (A == C && + isKnownToBeAPowerOfTwo(B, false, 0, &CxtI) && + isKnownToBeAPowerOfTwo(D, false, 0, &CxtI)) { + Value *Mask = Builder->CreateOr(B, D); + Value *Masked = Builder->CreateAnd(A, Mask); + auto NewPred = JoinedByAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE; + return Builder->CreateICmp(NewPred, Masked, Mask); + } + } + + return nullptr; +} + /// Fold (icmp)&(icmp) if possible. -Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { +Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, + Instruction &CxtI) { + // Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2) + // if K1 and K2 are a one-bit mask. + if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, true, CxtI)) + return V; + ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate(); // (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B) @@ -1127,8 +1173,8 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) { ICmpInst *ICmp0 = dyn_cast(Cast0Src); ICmpInst *ICmp1 = dyn_cast(Cast1Src); if (ICmp0 && ICmp1) { - Value *Res = LogicOpc == Instruction::And ? foldAndOfICmps(ICmp0, ICmp1) - : foldOrOfICmps(ICmp0, ICmp1, &I); + Value *Res = LogicOpc == Instruction::And ? foldAndOfICmps(ICmp0, ICmp1, I) + : foldOrOfICmps(ICmp0, ICmp1, I); if (Res) return CastInst::Create(CastOpcode, Res, DestTy); return nullptr; @@ -1426,7 +1472,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { ICmpInst *LHS = dyn_cast(Op0); ICmpInst *RHS = dyn_cast(Op1); if (LHS && RHS) - if (Value *Res = foldAndOfICmps(LHS, RHS)) + if (Value *Res = foldAndOfICmps(LHS, RHS, I)) return replaceInstUsesWith(I, Res); // TODO: Make this recursive; it's a little tricky because an arbitrary @@ -1434,18 +1480,18 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { Value *X, *Y; if (LHS && match(Op1, m_OneUse(m_And(m_Value(X), m_Value(Y))))) { if (auto *Cmp = dyn_cast(X)) - if (Value *Res = foldAndOfICmps(LHS, Cmp)) + if (Value *Res = foldAndOfICmps(LHS, Cmp, I)) return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y)); if (auto *Cmp = dyn_cast(Y)) - if (Value *Res = foldAndOfICmps(LHS, Cmp)) + if (Value *Res = foldAndOfICmps(LHS, Cmp, I)) return replaceInstUsesWith(I, Builder->CreateAnd(Res, X)); } if (RHS && match(Op0, m_OneUse(m_And(m_Value(X), m_Value(Y))))) { if (auto *Cmp = dyn_cast(X)) - if (Value *Res = foldAndOfICmps(Cmp, RHS)) + if (Value *Res = foldAndOfICmps(Cmp, RHS, I)) return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y)); if (auto *Cmp = dyn_cast(Y)) - if (Value *Res = foldAndOfICmps(Cmp, RHS)) + if (Value *Res = foldAndOfICmps(Cmp, RHS, I)) return replaceInstUsesWith(I, Builder->CreateAnd(Res, X)); } } @@ -1591,41 +1637,16 @@ static Value *matchSelectFromAndOr(Value *A, Value *C, Value *B, Value *D, /// Fold (icmp)|(icmp) if possible. Value *InstCombiner::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, - Instruction *CxtI) { - ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate(); - + Instruction &CxtI) { // Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2) // if K1 and K2 are a one-bit mask. - ConstantInt *LHSC = dyn_cast(LHS->getOperand(1)); - ConstantInt *RHSC = dyn_cast(RHS->getOperand(1)); + if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, false, CxtI)) + return V; - if (LHS->getPredicate() == ICmpInst::ICMP_EQ && LHSC && LHSC->isZero() && - RHS->getPredicate() == ICmpInst::ICMP_EQ && RHSC && RHSC->isZero()) { - - BinaryOperator *LAnd = dyn_cast(LHS->getOperand(0)); - BinaryOperator *RAnd = dyn_cast(RHS->getOperand(0)); - if (LAnd && RAnd && LAnd->hasOneUse() && RHS->hasOneUse() && - LAnd->getOpcode() == Instruction::And && - RAnd->getOpcode() == Instruction::And) { - - Value *Mask = nullptr; - Value *Masked = nullptr; - if (LAnd->getOperand(0) == RAnd->getOperand(0) && - isKnownToBeAPowerOfTwo(LAnd->getOperand(1), false, 0, CxtI) && - isKnownToBeAPowerOfTwo(RAnd->getOperand(1), false, 0, CxtI)) { - Mask = Builder->CreateOr(LAnd->getOperand(1), RAnd->getOperand(1)); - Masked = Builder->CreateAnd(LAnd->getOperand(0), Mask); - } else if (LAnd->getOperand(1) == RAnd->getOperand(1) && - isKnownToBeAPowerOfTwo(LAnd->getOperand(0), false, 0, CxtI) && - isKnownToBeAPowerOfTwo(RAnd->getOperand(0), false, 0, CxtI)) { - Mask = Builder->CreateOr(LAnd->getOperand(0), RAnd->getOperand(0)); - Masked = Builder->CreateAnd(LAnd->getOperand(1), Mask); - } + ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate(); - if (Masked) - return Builder->CreateICmp(ICmpInst::ICMP_NE, Masked, Mask); - } - } + ConstantInt *LHSC = dyn_cast(LHS->getOperand(1)); + ConstantInt *RHSC = dyn_cast(RHS->getOperand(1)); // Fold (icmp ult/ule (A + C1), C3) | (icmp ult/ule (A + C2), C3) // --> (icmp ult/ule ((A & ~(C1 ^ C2)) + max(C1, C2)), C3) @@ -2117,12 +2138,16 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { } // (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C + // FIXME: The two hasOneUse calls here are the same call, maybe we were + // supposed to check Op1->operand(0)? if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A)))) if (Op1->hasOneUse() || cast(Op1)->hasOneUse()) return BinaryOperator::CreateOr(Op0, C); // ((A ^ C) ^ B) | (B ^ A) -> (B ^ A) | C + // FIXME: The two hasOneUse calls here are the same call, maybe we were + // supposed to check Op0->operand(0)? if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B)))) if (match(Op1, m_Xor(m_Specific(B), m_Specific(A)))) if (Op0->hasOneUse() || cast(Op0)->hasOneUse()) @@ -2194,7 +2219,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { ICmpInst *LHS = dyn_cast(Op0); ICmpInst *RHS = dyn_cast(Op1); if (LHS && RHS) - if (Value *Res = foldOrOfICmps(LHS, RHS, &I)) + if (Value *Res = foldOrOfICmps(LHS, RHS, I)) return replaceInstUsesWith(I, Res); // TODO: Make this recursive; it's a little tricky because an arbitrary @@ -2202,18 +2227,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { Value *X, *Y; if (LHS && match(Op1, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) { if (auto *Cmp = dyn_cast(X)) - if (Value *Res = foldOrOfICmps(LHS, Cmp, &I)) + if (Value *Res = foldOrOfICmps(LHS, Cmp, I)) return replaceInstUsesWith(I, Builder->CreateOr(Res, Y)); if (auto *Cmp = dyn_cast(Y)) - if (Value *Res = foldOrOfICmps(LHS, Cmp, &I)) + if (Value *Res = foldOrOfICmps(LHS, Cmp, I)) return replaceInstUsesWith(I, Builder->CreateOr(Res, X)); } if (RHS && match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) { if (auto *Cmp = dyn_cast(X)) - if (Value *Res = foldOrOfICmps(Cmp, RHS, &I)) + if (Value *Res = foldOrOfICmps(Cmp, RHS, I)) return replaceInstUsesWith(I, Builder->CreateOr(Res, Y)); if (auto *Cmp = dyn_cast(Y)) - if (Value *Res = foldOrOfICmps(Cmp, RHS, &I)) + if (Value *Res = foldOrOfICmps(Cmp, RHS, I)) return replaceInstUsesWith(I, Builder->CreateOr(Res, X)); } } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index d29ed49..c0830a5 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -94,75 +94,80 @@ static Constant *getNegativeIsTrueBoolVec(ConstantDataVector *V) { return ConstantVector::get(BoolVec); } -Instruction * -InstCombiner::SimplifyElementAtomicMemCpy(ElementAtomicMemCpyInst *AMI) { +Instruction *InstCombiner::SimplifyElementUnorderedAtomicMemCpy( + ElementUnorderedAtomicMemCpyInst *AMI) { // Try to unfold this intrinsic into sequence of explicit atomic loads and // stores. // First check that number of elements is compile time constant. - auto *NumElementsCI = dyn_cast(AMI->getNumElements()); - if (!NumElementsCI) + auto *LengthCI = dyn_cast(AMI->getLength()); + if (!LengthCI) return nullptr; // Check that there are not too many elements. - uint64_t NumElements = NumElementsCI->getZExtValue(); + uint64_t LengthInBytes = LengthCI->getZExtValue(); + uint32_t ElementSizeInBytes = AMI->getElementSizeInBytes(); + uint64_t NumElements = LengthInBytes / ElementSizeInBytes; if (NumElements >= UnfoldElementAtomicMemcpyMaxElements) return nullptr; - // Don't unfold into illegal integers - uint64_t ElementSizeInBytes = AMI->getElementSizeInBytes() * 8; - if (!getDataLayout().isLegalInteger(ElementSizeInBytes)) - return nullptr; + // Only expand if there are elements to copy. + if (NumElements > 0) { + // Don't unfold into illegal integers + uint64_t ElementSizeInBits = ElementSizeInBytes * 8; + if (!getDataLayout().isLegalInteger(ElementSizeInBits)) + return nullptr; - // Cast source and destination to the correct type. Intrinsic input arguments - // are usually represented as i8*. - // Often operands will be explicitly casted to i8* and we can just strip - // those casts instead of inserting new ones. However it's easier to rely on - // other InstCombine rules which will cover trivial cases anyway. - Value *Src = AMI->getRawSource(); - Value *Dst = AMI->getRawDest(); - Type *ElementPointerType = Type::getIntNPtrTy( - AMI->getContext(), ElementSizeInBytes, Src->getType()->getPointerAddressSpace()); - - Value *SrcCasted = Builder->CreatePointerCast(Src, ElementPointerType, - "memcpy_unfold.src_casted"); - Value *DstCasted = Builder->CreatePointerCast(Dst, ElementPointerType, - "memcpy_unfold.dst_casted"); - - for (uint64_t i = 0; i < NumElements; ++i) { - // Get current element addresses - ConstantInt *ElementIdxCI = - ConstantInt::get(AMI->getContext(), APInt(64, i)); - Value *SrcElementAddr = - Builder->CreateGEP(SrcCasted, ElementIdxCI, "memcpy_unfold.src_addr"); - Value *DstElementAddr = - Builder->CreateGEP(DstCasted, ElementIdxCI, "memcpy_unfold.dst_addr"); - - // Load from the source. Transfer alignment information and mark load as - // unordered atomic. - LoadInst *Load = Builder->CreateLoad(SrcElementAddr, "memcpy_unfold.val"); - Load->setOrdering(AtomicOrdering::Unordered); - // We know alignment of the first element. It is also guaranteed by the - // verifier that element size is less or equal than first element alignment - // and both of this values are powers of two. - // This means that all subsequent accesses are at least element size - // aligned. - // TODO: We can infer better alignment but there is no evidence that this - // will matter. - Load->setAlignment(i == 0 ? AMI->getSrcAlignment() - : AMI->getElementSizeInBytes()); - Load->setDebugLoc(AMI->getDebugLoc()); - - // Store loaded value via unordered atomic store. - StoreInst *Store = Builder->CreateStore(Load, DstElementAddr); - Store->setOrdering(AtomicOrdering::Unordered); - Store->setAlignment(i == 0 ? AMI->getDstAlignment() - : AMI->getElementSizeInBytes()); - Store->setDebugLoc(AMI->getDebugLoc()); + // Cast source and destination to the correct type. Intrinsic input + // arguments are usually represented as i8*. Often operands will be + // explicitly casted to i8* and we can just strip those casts instead of + // inserting new ones. However it's easier to rely on other InstCombine + // rules which will cover trivial cases anyway. + Value *Src = AMI->getRawSource(); + Value *Dst = AMI->getRawDest(); + Type *ElementPointerType = + Type::getIntNPtrTy(AMI->getContext(), ElementSizeInBits, + Src->getType()->getPointerAddressSpace()); + + Value *SrcCasted = Builder->CreatePointerCast(Src, ElementPointerType, + "memcpy_unfold.src_casted"); + Value *DstCasted = Builder->CreatePointerCast(Dst, ElementPointerType, + "memcpy_unfold.dst_casted"); + + for (uint64_t i = 0; i < NumElements; ++i) { + // Get current element addresses + ConstantInt *ElementIdxCI = + ConstantInt::get(AMI->getContext(), APInt(64, i)); + Value *SrcElementAddr = + Builder->CreateGEP(SrcCasted, ElementIdxCI, "memcpy_unfold.src_addr"); + Value *DstElementAddr = + Builder->CreateGEP(DstCasted, ElementIdxCI, "memcpy_unfold.dst_addr"); + + // Load from the source. Transfer alignment information and mark load as + // unordered atomic. + LoadInst *Load = Builder->CreateLoad(SrcElementAddr, "memcpy_unfold.val"); + Load->setOrdering(AtomicOrdering::Unordered); + // We know alignment of the first element. It is also guaranteed by the + // verifier that element size is less or equal than first element + // alignment and both of this values are powers of two. This means that + // all subsequent accesses are at least element size aligned. + // TODO: We can infer better alignment but there is no evidence that this + // will matter. + Load->setAlignment(i == 0 ? AMI->getParamAlignment(1) + : ElementSizeInBytes); + Load->setDebugLoc(AMI->getDebugLoc()); + + // Store loaded value via unordered atomic store. + StoreInst *Store = Builder->CreateStore(Load, DstElementAddr); + Store->setOrdering(AtomicOrdering::Unordered); + Store->setAlignment(i == 0 ? AMI->getParamAlignment(0) + : ElementSizeInBytes); + Store->setDebugLoc(AMI->getDebugLoc()); + } } // Set the number of elements of the copy to 0, it will be deleted on the // next iteration. - AMI->setNumElements(Constant::getNullValue(NumElementsCI->getType())); + AMI->setLength(Constant::getNullValue(LengthCI->getType())); return AMI; } @@ -1888,12 +1893,12 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { if (Changed) return II; } - if (auto *AMI = dyn_cast(II)) { - if (Constant *C = dyn_cast(AMI->getNumElements())) + if (auto *AMI = dyn_cast(II)) { + if (Constant *C = dyn_cast(AMI->getLength())) if (C->isNullValue()) return eraseInstFromFunction(*AMI); - if (Instruction *I = SimplifyElementAtomicMemCpy(AMI)) + if (Instruction *I = SimplifyElementUnorderedAtomicMemCpy(AMI)) return I; } diff --git a/lib/Transforms/InstCombine/InstCombineInternal.h b/lib/Transforms/InstCombine/InstCombineInternal.h index fd0a64a..1a7db14 100644 --- a/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/lib/Transforms/InstCombine/InstCombineInternal.h @@ -447,12 +447,14 @@ private: Instruction::CastOps isEliminableCastPair(const CastInst *CI1, const CastInst *CI2); - Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS); + Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI); Value *foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS); - Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction *CxtI); + Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI); Value *foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS); Value *foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS); + Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS, + bool JoinedByAnd, Instruction &CxtI); public: /// \brief Inserts an instruction \p New before instruction \p Old /// @@ -724,7 +726,8 @@ private: Instruction *MatchBSwap(BinaryOperator &I); bool SimplifyStoreAtEndOfBlock(StoreInst &SI); - Instruction *SimplifyElementAtomicMemCpy(ElementAtomicMemCpyInst *AMI); + Instruction * + SimplifyElementUnorderedAtomicMemCpy(ElementUnorderedAtomicMemCpyInst *AMI); Instruction *SimplifyMemTransfer(MemIntrinsic *MI); Instruction *SimplifyMemSet(MemSetInst *MI); diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index 3f2ddca..8cec865 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -682,11 +682,11 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) { return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask)); } - if (match(Op0, m_SExt(m_Value(X)))) { + if (match(Op0, m_SExt(m_Value(X))) && + (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) { // Are we moving the sign bit to the low bit and widening with high zeros? unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits(); - if (ShAmt == BitWidth - 1 && - (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) { + if (ShAmt == BitWidth - 1) { // lshr (sext i1 X to iN), N-1 --> zext X to iN if (SrcTyBitWidth == 1) return new ZExtInst(X, Ty); @@ -698,7 +698,13 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) { } } - // TODO: Convert to ashr+zext if the shift equals the extension amount. + // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN + if (ShAmt == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) { + // The new shift amount can't be more than the narrow source type. + unsigned NewShAmt = std::min(ShAmt, SrcTyBitWidth - 1); + Value *AShr = Builder->CreateAShr(X, NewShAmt); + return new ZExtInst(AShr, Ty); + } } if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) { diff --git a/lib/Transforms/Instrumentation/CMakeLists.txt b/lib/Transforms/Instrumentation/CMakeLists.txt index 7ff69b9..f2806e2 100644 --- a/lib/Transforms/Instrumentation/CMakeLists.txt +++ b/lib/Transforms/Instrumentation/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_library(LLVMInstrumentation Instrumentation.cpp InstrProfiling.cpp PGOInstrumentation.cpp + PGOMemOPSizeOpt.cpp SanitizerCoverage.cpp ThreadSanitizer.cpp EfficiencySanitizer.cpp diff --git a/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp index 96027bc..0d30881 100644 --- a/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp +++ b/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp @@ -56,8 +56,6 @@ using namespace llvm; STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions."); STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites."); -STATISTIC(NumOfPGOMemOPOpt, "Number of memop intrinsics optimized."); -STATISTIC(NumOfPGOMemOPAnnotate, "Number of memop intrinsics annotated."); // Command line option to disable indirect-call promotion with the default as // false. This is for debug purpose. @@ -111,44 +109,6 @@ static cl::opt ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden, cl::desc("Dump IR after transformation happens")); -// The minimum call count to optimize memory intrinsic calls. -static cl::opt - MemOPCountThreshold("pgo-memop-count-threshold", cl::Hidden, cl::ZeroOrMore, - cl::init(1000), - cl::desc("The minimum count to optimize memory " - "intrinsic calls")); - -// Command line option to disable memory intrinsic optimization. The default is -// false. This is for debug purpose. -static cl::opt DisableMemOPOPT("disable-memop-opt", cl::init(false), - cl::Hidden, cl::desc("Disable optimize")); - -// The percent threshold to optimize memory intrinsic calls. -static cl::opt - MemOPPercentThreshold("pgo-memop-percent-threshold", cl::init(40), - cl::Hidden, cl::ZeroOrMore, - cl::desc("The percentage threshold for the " - "memory intrinsic calls optimization")); - -// Maximum number of versions for optimizing memory intrinsic call. -static cl::opt - MemOPMaxVersion("pgo-memop-max-version", cl::init(3), cl::Hidden, - cl::ZeroOrMore, - cl::desc("The max version for the optimized memory " - " intrinsic calls")); - -// Scale the counts from the annotation using the BB count value. -static cl::opt - MemOPScaleCount("pgo-memop-scale-count", cl::init(true), cl::Hidden, - cl::desc("Scale the memop size counts using the basic " - " block count value")); - -// This option sets the rangge of precise profile memop sizes. -extern cl::opt MemOPSizeRange; - -// This option sets the value that groups large memop sizes -extern cl::opt MemOPSizeLarge; - namespace { class PGOIndirectCallPromotionLegacyPass : public ModulePass { public: @@ -173,24 +133,6 @@ private: // the promoted direct call. bool SamplePGO; }; - -class PGOMemOPSizeOptLegacyPass : public FunctionPass { -public: - static char ID; - - PGOMemOPSizeOptLegacyPass() : FunctionPass(ID) { - initializePGOMemOPSizeOptLegacyPassPass(*PassRegistry::getPassRegistry()); - } - - StringRef getPassName() const override { return "PGOMemOPSize"; } - -private: - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addPreserved(); - } -}; } // end anonymous namespace char PGOIndirectCallPromotionLegacyPass::ID = 0; @@ -204,19 +146,6 @@ ModulePass *llvm::createPGOIndirectCallPromotionLegacyPass(bool InLTO, return new PGOIndirectCallPromotionLegacyPass(InLTO, SamplePGO); } -char PGOMemOPSizeOptLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt", - "Optimize memory intrinsic using its size value profile", - false, false) -INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) -INITIALIZE_PASS_END(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt", - "Optimize memory intrinsic using its size value profile", - false, false) - -FunctionPass *llvm::createPGOMemOPSizeOptLegacyPass() { - return new PGOMemOPSizeOptLegacyPass(); -} - namespace { // The class for main data structure to promote indirect calls to conditional // direct calls. @@ -749,285 +678,3 @@ PreservedAnalyses PGOIndirectCallPromotion::run(Module &M, return PreservedAnalyses::none(); } - -namespace { -class MemOPSizeOpt : public InstVisitor { -public: - MemOPSizeOpt(Function &Func, BlockFrequencyInfo &BFI) - : Func(Func), BFI(BFI), Changed(false) { - ValueDataArray = - llvm::make_unique(MemOPMaxVersion + 2); - // Get the MemOPSize range information from option MemOPSizeRange, - getMemOPSizeRangeFromOption(MemOPSizeRange, PreciseRangeStart, - PreciseRangeLast); - } - bool isChanged() const { return Changed; } - void perform() { - WorkList.clear(); - visit(Func); - - for (auto &MI : WorkList) { - ++NumOfPGOMemOPAnnotate; - if (perform(MI)) { - Changed = true; - ++NumOfPGOMemOPOpt; - DEBUG(dbgs() << "MemOP call: " << MI->getCalledFunction()->getName() - << "is Transformed.\n"); - } - } - } - - void visitMemIntrinsic(MemIntrinsic &MI) { - Value *Length = MI.getLength(); - // Not perform on constant length calls. - if (dyn_cast(Length)) - return; - WorkList.push_back(&MI); - } - -private: - Function &Func; - BlockFrequencyInfo &BFI; - bool Changed; - std::vector WorkList; - // Start of the previse range. - int64_t PreciseRangeStart; - // Last value of the previse range. - int64_t PreciseRangeLast; - // The space to read the profile annotation. - std::unique_ptr ValueDataArray; - bool perform(MemIntrinsic *MI); - - // This kind shows which group the value falls in. For PreciseValue, we have - // the profile count for that value. LargeGroup groups the values that are in - // range [LargeValue, +inf). NonLargeGroup groups the rest of values. - enum MemOPSizeKind { PreciseValue, NonLargeGroup, LargeGroup }; - - MemOPSizeKind getMemOPSizeKind(int64_t Value) const { - if (Value == MemOPSizeLarge && MemOPSizeLarge != 0) - return LargeGroup; - if (Value == PreciseRangeLast + 1) - return NonLargeGroup; - return PreciseValue; - } -}; - -static const char *getMIName(const MemIntrinsic *MI) { - switch (MI->getIntrinsicID()) { - case Intrinsic::memcpy: - return "memcpy"; - case Intrinsic::memmove: - return "memmove"; - case Intrinsic::memset: - return "memset"; - default: - return "unknown"; - } -} - -static bool isProfitable(uint64_t Count, uint64_t TotalCount) { - assert(Count <= TotalCount); - if (Count < MemOPCountThreshold) - return false; - if (Count < TotalCount * MemOPPercentThreshold / 100) - return false; - return true; -} - -static inline uint64_t getScaledCount(uint64_t Count, uint64_t Num, - uint64_t Denom) { - if (!MemOPScaleCount) - return Count; - bool Overflowed; - uint64_t ScaleCount = SaturatingMultiply(Count, Num, &Overflowed); - return ScaleCount / Denom; -} - -bool MemOPSizeOpt::perform(MemIntrinsic *MI) { - assert(MI); - if (MI->getIntrinsicID() == Intrinsic::memmove) - return false; - - uint32_t NumVals, MaxNumPromotions = MemOPMaxVersion + 2; - uint64_t TotalCount; - if (!getValueProfDataFromInst(*MI, IPVK_MemOPSize, MaxNumPromotions, - ValueDataArray.get(), NumVals, TotalCount)) - return false; - - uint64_t ActualCount = TotalCount; - uint64_t SavedTotalCount = TotalCount; - if (MemOPScaleCount) { - auto BBEdgeCount = BFI.getBlockProfileCount(MI->getParent()); - if (!BBEdgeCount) - return false; - ActualCount = *BBEdgeCount; - } - - ArrayRef VDs(ValueDataArray.get(), NumVals); - DEBUG(dbgs() << "Read one memory intrinsic profile with count " << ActualCount - << "\n"); - DEBUG( - for (auto &VD - : VDs) { dbgs() << " (" << VD.Value << "," << VD.Count << ")\n"; }); - - if (ActualCount < MemOPCountThreshold) - return false; - // Skip if the total value profiled count is 0, in which case we can't - // scale up the counts properly (and there is no profitable transformation). - if (TotalCount == 0) - return false; - - TotalCount = ActualCount; - if (MemOPScaleCount) - DEBUG(dbgs() << "Scale counts: numerator = " << ActualCount - << " denominator = " << SavedTotalCount << "\n"); - - // Keeping track of the count of the default case: - uint64_t RemainCount = TotalCount; - SmallVector SizeIds; - SmallVector CaseCounts; - uint64_t MaxCount = 0; - unsigned Version = 0; - // Default case is in the front -- save the slot here. - CaseCounts.push_back(0); - for (auto &VD : VDs) { - int64_t V = VD.Value; - uint64_t C = VD.Count; - if (MemOPScaleCount) - C = getScaledCount(C, ActualCount, SavedTotalCount); - - // Only care precise value here. - if (getMemOPSizeKind(V) != PreciseValue) - continue; - - // ValueCounts are sorted on the count. Break at the first un-profitable - // value. - if (!isProfitable(C, RemainCount)) - break; - - SizeIds.push_back(V); - CaseCounts.push_back(C); - if (C > MaxCount) - MaxCount = C; - - assert(RemainCount >= C); - RemainCount -= C; - - if (++Version > MemOPMaxVersion && MemOPMaxVersion != 0) - break; - } - - if (Version == 0) - return false; - - CaseCounts[0] = RemainCount; - if (RemainCount > MaxCount) - MaxCount = RemainCount; - - uint64_t SumForOpt = TotalCount - RemainCount; - - DEBUG(dbgs() << "Optimize one memory intrinsic call to " << Version - << " Versions (covering " << SumForOpt << " out of " - << TotalCount << ")\n"); - - // mem_op(..., size) - // ==> - // switch (size) { - // case s1: - // mem_op(..., s1); - // goto merge_bb; - // case s2: - // mem_op(..., s2); - // goto merge_bb; - // ... - // default: - // mem_op(..., size); - // goto merge_bb; - // } - // merge_bb: - - BasicBlock *BB = MI->getParent(); - DEBUG(dbgs() << "\n\n== Basic Block Before ==\n"); - DEBUG(dbgs() << *BB << "\n"); - auto OrigBBFreq = BFI.getBlockFreq(BB); - - BasicBlock *DefaultBB = SplitBlock(BB, MI); - BasicBlock::iterator It(*MI); - ++It; - assert(It != DefaultBB->end()); - BasicBlock *MergeBB = SplitBlock(DefaultBB, &(*It)); - MergeBB->setName("MemOP.Merge"); - BFI.setBlockFreq(MergeBB, OrigBBFreq.getFrequency()); - DefaultBB->setName("MemOP.Default"); - - auto &Ctx = Func.getContext(); - IRBuilder<> IRB(BB); - BB->getTerminator()->eraseFromParent(); - Value *SizeVar = MI->getLength(); - SwitchInst *SI = IRB.CreateSwitch(SizeVar, DefaultBB, SizeIds.size()); - - // Clear the value profile data. - MI->setMetadata(LLVMContext::MD_prof, nullptr); - - DEBUG(dbgs() << "\n\n== Basic Block After==\n"); - - for (uint64_t SizeId : SizeIds) { - ConstantInt *CaseSizeId = ConstantInt::get(Type::getInt64Ty(Ctx), SizeId); - BasicBlock *CaseBB = BasicBlock::Create( - Ctx, Twine("MemOP.Case.") + Twine(SizeId), &Func, DefaultBB); - Instruction *NewInst = MI->clone(); - // Fix the argument. - dyn_cast(NewInst)->setLength(CaseSizeId); - CaseBB->getInstList().push_back(NewInst); - IRBuilder<> IRBCase(CaseBB); - IRBCase.CreateBr(MergeBB); - SI->addCase(CaseSizeId, CaseBB); - DEBUG(dbgs() << *CaseBB << "\n"); - } - setProfMetadata(Func.getParent(), SI, CaseCounts, MaxCount); - - DEBUG(dbgs() << *BB << "\n"); - DEBUG(dbgs() << *DefaultBB << "\n"); - DEBUG(dbgs() << *MergeBB << "\n"); - - emitOptimizationRemark(Func.getContext(), "memop-opt", Func, - MI->getDebugLoc(), - Twine("optimize ") + getMIName(MI) + " with count " + - Twine(SumForOpt) + " out of " + Twine(TotalCount) + - " for " + Twine(Version) + " versions"); - - return true; -} -} // namespace - -static bool PGOMemOPSizeOptImpl(Function &F, BlockFrequencyInfo &BFI) { - if (DisableMemOPOPT) - return false; - - if (F.hasFnAttribute(Attribute::OptimizeForSize)) - return false; - MemOPSizeOpt MemOPSizeOpt(F, BFI); - MemOPSizeOpt.perform(); - return MemOPSizeOpt.isChanged(); -} - -bool PGOMemOPSizeOptLegacyPass::runOnFunction(Function &F) { - BlockFrequencyInfo &BFI = - getAnalysis().getBFI(); - return PGOMemOPSizeOptImpl(F, BFI); -} - -namespace llvm { -char &PGOMemOPSizeOptID = PGOMemOPSizeOptLegacyPass::ID; - -PreservedAnalyses PGOMemOPSizeOpt::run(Function &F, - FunctionAnalysisManager &FAM) { - auto &BFI = FAM.getResult(F); - bool Changed = PGOMemOPSizeOptImpl(F, BFI); - if (!Changed) - return PreservedAnalyses::all(); - auto PA = PreservedAnalyses(); - PA.preserve(); - return PA; -} -} // namespace llvm diff --git a/lib/Transforms/Instrumentation/InstrProfiling.cpp b/lib/Transforms/Instrumentation/InstrProfiling.cpp index f83c930..37f88d5 100644 --- a/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -343,14 +343,24 @@ static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) { static inline bool shouldRecordFunctionAddr(Function *F) { // Check the linkage + bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage(); if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() && - !F->hasAvailableExternallyLinkage()) + !HasAvailableExternallyLinkage) return true; + + // A function marked 'alwaysinline' with available_externally linkage can't + // have its address taken. Doing so would create an undefined external ref to + // the function, which would fail to link. + if (HasAvailableExternallyLinkage && + F->hasFnAttribute(Attribute::AlwaysInline)) + return false; + // Prohibit function address recording if the function is both internal and // COMDAT. This avoids the profile data variable referencing internal symbols // in COMDAT. if (F->hasLocalLinkage() && F->hasComdat()) return false; + // Check uses of this function for other than direct calls or invokes to it. // Inline virtual functions have linkeOnceODR linkage. When a key method // exists, the vtable will only be emitted in the TU where the key method diff --git a/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp b/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp new file mode 100644 index 0000000..0bc9ddf --- /dev/null +++ b/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp @@ -0,0 +1,419 @@ +//===-- PGOMemOPSizeOpt.cpp - Optimizations based on value profiling ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the transformation that optimizes memory intrinsics +// such as memcpy using the size value profile. When memory intrinsic size +// value profile metadata is available, a single memory intrinsic is expanded +// to a sequence of guarded specialized versions that are called with the +// hottest size(s), for later expansion into more optimal inline sequences. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/InstVisitor.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/Pass.h" +#include "llvm/PassRegistry.h" +#include "llvm/PassSupport.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/PGOInstrumentation.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include +#include +#include + +using namespace llvm; + +#define DEBUG_TYPE "pgo-memop-opt" + +STATISTIC(NumOfPGOMemOPOpt, "Number of memop intrinsics optimized."); +STATISTIC(NumOfPGOMemOPAnnotate, "Number of memop intrinsics annotated."); + +// The minimum call count to optimize memory intrinsic calls. +static cl::opt + MemOPCountThreshold("pgo-memop-count-threshold", cl::Hidden, cl::ZeroOrMore, + cl::init(1000), + cl::desc("The minimum count to optimize memory " + "intrinsic calls")); + +// Command line option to disable memory intrinsic optimization. The default is +// false. This is for debug purpose. +static cl::opt DisableMemOPOPT("disable-memop-opt", cl::init(false), + cl::Hidden, cl::desc("Disable optimize")); + +// The percent threshold to optimize memory intrinsic calls. +static cl::opt + MemOPPercentThreshold("pgo-memop-percent-threshold", cl::init(40), + cl::Hidden, cl::ZeroOrMore, + cl::desc("The percentage threshold for the " + "memory intrinsic calls optimization")); + +// Maximum number of versions for optimizing memory intrinsic call. +static cl::opt + MemOPMaxVersion("pgo-memop-max-version", cl::init(3), cl::Hidden, + cl::ZeroOrMore, + cl::desc("The max version for the optimized memory " + " intrinsic calls")); + +// Scale the counts from the annotation using the BB count value. +static cl::opt + MemOPScaleCount("pgo-memop-scale-count", cl::init(true), cl::Hidden, + cl::desc("Scale the memop size counts using the basic " + " block count value")); + +// This option sets the rangge of precise profile memop sizes. +extern cl::opt MemOPSizeRange; + +// This option sets the value that groups large memop sizes +extern cl::opt MemOPSizeLarge; + +namespace { +class PGOMemOPSizeOptLegacyPass : public FunctionPass { +public: + static char ID; + + PGOMemOPSizeOptLegacyPass() : FunctionPass(ID) { + initializePGOMemOPSizeOptLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { return "PGOMemOPSize"; } + +private: + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addPreserved(); + } +}; +} // end anonymous namespace + +char PGOMemOPSizeOptLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt", + "Optimize memory intrinsic using its size value profile", + false, false) +INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) +INITIALIZE_PASS_END(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt", + "Optimize memory intrinsic using its size value profile", + false, false) + +FunctionPass *llvm::createPGOMemOPSizeOptLegacyPass() { + return new PGOMemOPSizeOptLegacyPass(); +} + +namespace { +class MemOPSizeOpt : public InstVisitor { +public: + MemOPSizeOpt(Function &Func, BlockFrequencyInfo &BFI) + : Func(Func), BFI(BFI), Changed(false) { + ValueDataArray = + llvm::make_unique(MemOPMaxVersion + 2); + // Get the MemOPSize range information from option MemOPSizeRange, + getMemOPSizeRangeFromOption(MemOPSizeRange, PreciseRangeStart, + PreciseRangeLast); + } + bool isChanged() const { return Changed; } + void perform() { + WorkList.clear(); + visit(Func); + + for (auto &MI : WorkList) { + ++NumOfPGOMemOPAnnotate; + if (perform(MI)) { + Changed = true; + ++NumOfPGOMemOPOpt; + DEBUG(dbgs() << "MemOP call: " << MI->getCalledFunction()->getName() + << "is Transformed.\n"); + } + } + } + + void visitMemIntrinsic(MemIntrinsic &MI) { + Value *Length = MI.getLength(); + // Not perform on constant length calls. + if (dyn_cast(Length)) + return; + WorkList.push_back(&MI); + } + +private: + Function &Func; + BlockFrequencyInfo &BFI; + bool Changed; + std::vector WorkList; + // Start of the previse range. + int64_t PreciseRangeStart; + // Last value of the previse range. + int64_t PreciseRangeLast; + // The space to read the profile annotation. + std::unique_ptr ValueDataArray; + bool perform(MemIntrinsic *MI); + + // This kind shows which group the value falls in. For PreciseValue, we have + // the profile count for that value. LargeGroup groups the values that are in + // range [LargeValue, +inf). NonLargeGroup groups the rest of values. + enum MemOPSizeKind { PreciseValue, NonLargeGroup, LargeGroup }; + + MemOPSizeKind getMemOPSizeKind(int64_t Value) const { + if (Value == MemOPSizeLarge && MemOPSizeLarge != 0) + return LargeGroup; + if (Value == PreciseRangeLast + 1) + return NonLargeGroup; + return PreciseValue; + } +}; + +static const char *getMIName(const MemIntrinsic *MI) { + switch (MI->getIntrinsicID()) { + case Intrinsic::memcpy: + return "memcpy"; + case Intrinsic::memmove: + return "memmove"; + case Intrinsic::memset: + return "memset"; + default: + return "unknown"; + } +} + +static bool isProfitable(uint64_t Count, uint64_t TotalCount) { + assert(Count <= TotalCount); + if (Count < MemOPCountThreshold) + return false; + if (Count < TotalCount * MemOPPercentThreshold / 100) + return false; + return true; +} + +static inline uint64_t getScaledCount(uint64_t Count, uint64_t Num, + uint64_t Denom) { + if (!MemOPScaleCount) + return Count; + bool Overflowed; + uint64_t ScaleCount = SaturatingMultiply(Count, Num, &Overflowed); + return ScaleCount / Denom; +} + +bool MemOPSizeOpt::perform(MemIntrinsic *MI) { + assert(MI); + if (MI->getIntrinsicID() == Intrinsic::memmove) + return false; + + uint32_t NumVals, MaxNumPromotions = MemOPMaxVersion + 2; + uint64_t TotalCount; + if (!getValueProfDataFromInst(*MI, IPVK_MemOPSize, MaxNumPromotions, + ValueDataArray.get(), NumVals, TotalCount)) + return false; + + uint64_t ActualCount = TotalCount; + uint64_t SavedTotalCount = TotalCount; + if (MemOPScaleCount) { + auto BBEdgeCount = BFI.getBlockProfileCount(MI->getParent()); + if (!BBEdgeCount) + return false; + ActualCount = *BBEdgeCount; + } + + ArrayRef VDs(ValueDataArray.get(), NumVals); + DEBUG(dbgs() << "Read one memory intrinsic profile with count " << ActualCount + << "\n"); + DEBUG( + for (auto &VD + : VDs) { dbgs() << " (" << VD.Value << "," << VD.Count << ")\n"; }); + + if (ActualCount < MemOPCountThreshold) + return false; + // Skip if the total value profiled count is 0, in which case we can't + // scale up the counts properly (and there is no profitable transformation). + if (TotalCount == 0) + return false; + + TotalCount = ActualCount; + if (MemOPScaleCount) + DEBUG(dbgs() << "Scale counts: numerator = " << ActualCount + << " denominator = " << SavedTotalCount << "\n"); + + // Keeping track of the count of the default case: + uint64_t RemainCount = TotalCount; + uint64_t SavedRemainCount = SavedTotalCount; + SmallVector SizeIds; + SmallVector CaseCounts; + uint64_t MaxCount = 0; + unsigned Version = 0; + // Default case is in the front -- save the slot here. + CaseCounts.push_back(0); + for (auto &VD : VDs) { + int64_t V = VD.Value; + uint64_t C = VD.Count; + if (MemOPScaleCount) + C = getScaledCount(C, ActualCount, SavedTotalCount); + + // Only care precise value here. + if (getMemOPSizeKind(V) != PreciseValue) + continue; + + // ValueCounts are sorted on the count. Break at the first un-profitable + // value. + if (!isProfitable(C, RemainCount)) + break; + + SizeIds.push_back(V); + CaseCounts.push_back(C); + if (C > MaxCount) + MaxCount = C; + + assert(RemainCount >= C); + RemainCount -= C; + assert(SavedRemainCount >= VD.Count); + SavedRemainCount -= VD.Count; + + if (++Version > MemOPMaxVersion && MemOPMaxVersion != 0) + break; + } + + if (Version == 0) + return false; + + CaseCounts[0] = RemainCount; + if (RemainCount > MaxCount) + MaxCount = RemainCount; + + uint64_t SumForOpt = TotalCount - RemainCount; + + DEBUG(dbgs() << "Optimize one memory intrinsic call to " << Version + << " Versions (covering " << SumForOpt << " out of " + << TotalCount << ")\n"); + + // mem_op(..., size) + // ==> + // switch (size) { + // case s1: + // mem_op(..., s1); + // goto merge_bb; + // case s2: + // mem_op(..., s2); + // goto merge_bb; + // ... + // default: + // mem_op(..., size); + // goto merge_bb; + // } + // merge_bb: + + BasicBlock *BB = MI->getParent(); + DEBUG(dbgs() << "\n\n== Basic Block Before ==\n"); + DEBUG(dbgs() << *BB << "\n"); + auto OrigBBFreq = BFI.getBlockFreq(BB); + + BasicBlock *DefaultBB = SplitBlock(BB, MI); + BasicBlock::iterator It(*MI); + ++It; + assert(It != DefaultBB->end()); + BasicBlock *MergeBB = SplitBlock(DefaultBB, &(*It)); + MergeBB->setName("MemOP.Merge"); + BFI.setBlockFreq(MergeBB, OrigBBFreq.getFrequency()); + DefaultBB->setName("MemOP.Default"); + + auto &Ctx = Func.getContext(); + IRBuilder<> IRB(BB); + BB->getTerminator()->eraseFromParent(); + Value *SizeVar = MI->getLength(); + SwitchInst *SI = IRB.CreateSwitch(SizeVar, DefaultBB, SizeIds.size()); + + // Clear the value profile data. + MI->setMetadata(LLVMContext::MD_prof, nullptr); + // If all promoted, we don't need the MD.prof metadata. + if (SavedRemainCount > 0 || Version != NumVals) + // Otherwise we need update with the un-promoted records back. + annotateValueSite(*Func.getParent(), *MI, VDs.slice(Version), + SavedRemainCount, IPVK_MemOPSize, NumVals); + + DEBUG(dbgs() << "\n\n== Basic Block After==\n"); + + for (uint64_t SizeId : SizeIds) { + ConstantInt *CaseSizeId = ConstantInt::get(Type::getInt64Ty(Ctx), SizeId); + BasicBlock *CaseBB = BasicBlock::Create( + Ctx, Twine("MemOP.Case.") + Twine(SizeId), &Func, DefaultBB); + Instruction *NewInst = MI->clone(); + // Fix the argument. + dyn_cast(NewInst)->setLength(CaseSizeId); + CaseBB->getInstList().push_back(NewInst); + IRBuilder<> IRBCase(CaseBB); + IRBCase.CreateBr(MergeBB); + SI->addCase(CaseSizeId, CaseBB); + DEBUG(dbgs() << *CaseBB << "\n"); + } + setProfMetadata(Func.getParent(), SI, CaseCounts, MaxCount); + + DEBUG(dbgs() << *BB << "\n"); + DEBUG(dbgs() << *DefaultBB << "\n"); + DEBUG(dbgs() << *MergeBB << "\n"); + + emitOptimizationRemark(Func.getContext(), "memop-opt", Func, + MI->getDebugLoc(), + Twine("optimize ") + getMIName(MI) + " with count " + + Twine(SumForOpt) + " out of " + Twine(TotalCount) + + " for " + Twine(Version) + " versions"); + + return true; +} +} // namespace + +static bool PGOMemOPSizeOptImpl(Function &F, BlockFrequencyInfo &BFI) { + if (DisableMemOPOPT) + return false; + + if (F.hasFnAttribute(Attribute::OptimizeForSize)) + return false; + MemOPSizeOpt MemOPSizeOpt(F, BFI); + MemOPSizeOpt.perform(); + return MemOPSizeOpt.isChanged(); +} + +bool PGOMemOPSizeOptLegacyPass::runOnFunction(Function &F) { + BlockFrequencyInfo &BFI = + getAnalysis().getBFI(); + return PGOMemOPSizeOptImpl(F, BFI); +} + +namespace llvm { +char &PGOMemOPSizeOptID = PGOMemOPSizeOptLegacyPass::ID; + +PreservedAnalyses PGOMemOPSizeOpt::run(Function &F, + FunctionAnalysisManager &FAM) { + auto &BFI = FAM.getResult(F); + bool Changed = PGOMemOPSizeOptImpl(F, BFI); + if (!Changed) + return PreservedAnalyses::all(); + auto PA = PreservedAnalyses(); + PA.preserve(); + return PA; +} +} // namespace llvm diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp index 8aa40d1..e3c36c9 100644 --- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp +++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp @@ -61,7 +61,7 @@ static const char *const SanCov8bitCountersInitName = "__sanitizer_cov_8bit_counters_init"; static const char *const SanCovGuardsSectionName = "sancov_guards"; -static const char *const SanCovCountersSectionName = "sancov_counters"; +static const char *const SanCovCountersSectionName = "sancov_cntrs"; static cl::opt ClCoverageLevel( "sanitizer-coverage-level", diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 7b625b9..2a4c952 100644 --- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -551,7 +551,7 @@ static bool runImpl(Function &F, LazyValueInfo *LVI, const SimplifyQuery &SQ) { BBChanged = true; } } - }; + } FnChanged |= BBChanged; } diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp index c4f4509..0f92760 100644 --- a/lib/Transforms/Scalar/EarlyCSE.cpp +++ b/lib/Transforms/Scalar/EarlyCSE.cpp @@ -15,6 +15,7 @@ #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/ScopedHashTable.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/GlobalsModRef.h" @@ -506,7 +507,7 @@ private: if (MemoryAccess *MA = MSSA->getMemoryAccess(Inst)) { // Optimize MemoryPhi nodes that may become redundant by having all the // same input values once MA is removed. - SmallVector PhisToCheck; + SmallSetVector PhisToCheck; SmallVector WorkQueue; WorkQueue.push_back(MA); // Process MemoryPhi nodes in FIFO order using a ever-growing vector since @@ -517,7 +518,7 @@ private: for (auto *U : WI->users()) if (MemoryPhi *MP = dyn_cast(U)) - PhisToCheck.push_back(MP); + PhisToCheck.insert(MP); MSSAUpdater->removeMemoryAccess(WI); diff --git a/lib/Transforms/Scalar/GVNSink.cpp b/lib/Transforms/Scalar/GVNSink.cpp index 8634816..5fd2dfc 100644 --- a/lib/Transforms/Scalar/GVNSink.cpp +++ b/lib/Transforms/Scalar/GVNSink.cpp @@ -64,6 +64,17 @@ using namespace llvm; STATISTIC(NumRemoved, "Number of instructions removed"); +namespace llvm { +namespace GVNExpression { + +LLVM_DUMP_METHOD void Expression::dump() const { + print(dbgs()); + dbgs() << "\n"; +} + +} +} + namespace { static bool isMemoryInst(const Instruction *I) { diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index b706152..8b43505 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -983,21 +983,21 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI, const SCEV *NumBytesS = SE->getAddExpr(BECount, SE->getOne(IntPtrTy), SCEV::FlagNUW); + if (StoreSize != 1) + NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(IntPtrTy, StoreSize), + SCEV::FlagNUW); + + Value *NumBytes = + Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator()); + unsigned Align = std::min(SI->getAlignment(), LI->getAlignment()); CallInst *NewCall = nullptr; // Check whether to generate an unordered atomic memcpy: // If the load or store are atomic, then they must neccessarily be unordered // by previous checks. - if (!SI->isAtomic() && !LI->isAtomic()) { - if (StoreSize != 1) - NumBytesS = SE->getMulExpr( - NumBytesS, SE->getConstant(IntPtrTy, StoreSize), SCEV::FlagNUW); - - Value *NumBytes = - Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator()); - + if (!SI->isAtomic() && !LI->isAtomic()) NewCall = Builder.CreateMemCpy(StoreBasePtr, LoadBasePtr, NumBytes, Align); - } else { + else { // We cannot allow unaligned ops for unordered load/store, so reject // anything where the alignment isn't at least the element size. if (Align < StoreSize) @@ -1010,11 +1010,9 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI, if (StoreSize > TTI->getAtomicMemIntrinsicMaxElementSize()) return false; - Value *NumElements = - Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator()); + NewCall = Builder.CreateElementUnorderedAtomicMemCpy( + StoreBasePtr, LoadBasePtr, NumBytes, StoreSize); - NewCall = Builder.CreateElementAtomicMemCpy(StoreBasePtr, LoadBasePtr, - NumElements, StoreSize); // Propagate alignment info onto the pointer args. Note that unordered // atomic loads/stores are *required* by the spec to have an alignment // but non-atomic loads/stores may not. diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp index 6926aae..cbbd555 100644 --- a/lib/Transforms/Scalar/NewGVN.cpp +++ b/lib/Transforms/Scalar/NewGVN.cpp @@ -2195,7 +2195,7 @@ void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, // For a given expression, mark the phi of ops instructions that could have // changed as a result. void NewGVN::markPhiOfOpsChanged(const Expression *E) { - touchAndErase(ExpressionToPhiOfOps, E); + touchAndErase(ExpressionToPhiOfOps, ExactEqualsExpression(*E)); } // Perform congruence finding on a given value numbering expression. @@ -3561,7 +3561,7 @@ bool NewGVN::eliminateInstructions(Function &F) { // TODO: It would be faster to use getNumIncomingBlocks() on a phi node in // the block and subtract the pred count, but it's more complicated. if (ReachablePredCount.lookup(BB) != - std::distance(pred_begin(BB), pred_end(BB))) { + unsigned(std::distance(pred_begin(BB), pred_end(BB)))) { for (auto II = BB->begin(); isa(II); ++II) { auto &PHI = cast(*II); ReplaceUnreachablePHIArgs(PHI, BB); diff --git a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index bae7911..a52739b 100644 --- a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -89,10 +89,10 @@ struct RewriteStatepointsForGC : public ModulePass { Changed |= runOnFunction(F); if (Changed) { - // stripNonValidAttributes asserts that shouldRewriteStatepointsIn + // stripNonValidAttributesAndMetadata asserts that shouldRewriteStatepointsIn // returns true for at least one function in the module. Since at least // one function changed, we know that the precondition is satisfied. - stripNonValidAttributes(M); + stripNonValidAttributesAndMetadata(M); } return Changed; @@ -105,20 +105,24 @@ struct RewriteStatepointsForGC : public ModulePass { AU.addRequired(); } - /// The IR fed into RewriteStatepointsForGC may have had attributes implying - /// dereferenceability that are no longer valid/correct after - /// RewriteStatepointsForGC has run. This is because semantically, after + /// The IR fed into RewriteStatepointsForGC may have had attributes and + /// metadata implying dereferenceability that are no longer valid/correct after + /// RewriteStatepointsForGC has run. This is because semantically, after /// RewriteStatepointsForGC runs, all calls to gc.statepoint "free" the entire - /// heap. stripNonValidAttributes (conservatively) restores correctness - /// by erasing all attributes in the module that externally imply - /// dereferenceability. - /// Similar reasoning also applies to the noalias attributes. gc.statepoint - /// can touch the entire heap including noalias objects. - void stripNonValidAttributes(Module &M); - - // Helpers for stripNonValidAttributes - void stripNonValidAttributesFromBody(Function &F); + /// heap. stripNonValidAttributesAndMetadata (conservatively) restores + /// correctness by erasing all attributes in the module that externally imply + /// dereferenceability. Similar reasoning also applies to the noalias + /// attributes and metadata. gc.statepoint can touch the entire heap including + /// noalias objects. + void stripNonValidAttributesAndMetadata(Module &M); + + // Helpers for stripNonValidAttributesAndMetadata + void stripNonValidAttributesAndMetadataFromBody(Function &F); void stripNonValidAttributesFromPrototype(Function &F); + // Certain metadata on instructions are invalid after running RS4GC. + // Optimizations that run after RS4GC can incorrectly use this metadata to + // optimize functions. We drop such metadata on the instruction. + void stripInvalidMetadataFromInstruction(Instruction &I); }; } // namespace @@ -2306,13 +2310,44 @@ RewriteStatepointsForGC::stripNonValidAttributesFromPrototype(Function &F) { RemoveNonValidAttrAtIndex(Ctx, F, AttributeList::ReturnIndex); } -void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) { +void RewriteStatepointsForGC::stripInvalidMetadataFromInstruction(Instruction &I) { + + if (!isa(I) && !isa(I)) + return; + // These are the attributes that are still valid on loads and stores after + // RS4GC. + // The metadata implying dereferenceability and noalias are (conservatively) + // dropped. This is because semantically, after RewriteStatepointsForGC runs, + // all calls to gc.statepoint "free" the entire heap. Also, gc.statepoint can + // touch the entire heap including noalias objects. Note: The reasoning is + // same as stripping the dereferenceability and noalias attributes that are + // analogous to the metadata counterparts. + // We also drop the invariant.load metadata on the load because that metadata + // implies the address operand to the load points to memory that is never + // changed once it became dereferenceable. This is no longer true after RS4GC. + // Similar reasoning applies to invariant.group metadata, which applies to + // loads within a group. + unsigned ValidMetadataAfterRS4GC[] = {LLVMContext::MD_tbaa, + LLVMContext::MD_range, + LLVMContext::MD_alias_scope, + LLVMContext::MD_nontemporal, + LLVMContext::MD_nonnull, + LLVMContext::MD_align, + LLVMContext::MD_type}; + + // Drops all metadata on the instruction other than ValidMetadataAfterRS4GC. + I.dropUnknownNonDebugMetadata(ValidMetadataAfterRS4GC); + +} + +void RewriteStatepointsForGC::stripNonValidAttributesAndMetadataFromBody(Function &F) { if (F.empty()) return; LLVMContext &Ctx = F.getContext(); MDBuilder Builder(Ctx); + for (Instruction &I : instructions(F)) { if (const MDNode *MD = I.getMetadata(LLVMContext::MD_tbaa)) { assert(MD->getNumOperands() < 5 && "unrecognized metadata shape!"); @@ -2333,6 +2368,8 @@ void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) { I.setMetadata(LLVMContext::MD_tbaa, MutableTBAA); } + stripInvalidMetadataFromInstruction(I); + if (CallSite CS = CallSite(&I)) { for (int i = 0, e = CS.arg_size(); i != e; i++) if (isa(CS.getArgument(i)->getType())) @@ -2357,7 +2394,7 @@ static bool shouldRewriteStatepointsIn(Function &F) { return false; } -void RewriteStatepointsForGC::stripNonValidAttributes(Module &M) { +void RewriteStatepointsForGC::stripNonValidAttributesAndMetadata(Module &M) { #ifndef NDEBUG assert(any_of(M, shouldRewriteStatepointsIn) && "precondition!"); #endif @@ -2366,7 +2403,7 @@ void RewriteStatepointsForGC::stripNonValidAttributes(Module &M) { stripNonValidAttributesFromPrototype(F); for (Function &F : M) - stripNonValidAttributesFromBody(F); + stripNonValidAttributesAndMetadataFromBody(F); } bool RewriteStatepointsForGC::runOnFunction(Function &F) { diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 815492a..c6929c3 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -515,10 +515,6 @@ private: void visitCmpInst(CmpInst &I); void visitExtractValueInst(ExtractValueInst &EVI); void visitInsertValueInst(InsertValueInst &IVI); - void visitLandingPadInst(LandingPadInst &I) { markOverdefined(&I); } - void visitFuncletPadInst(FuncletPadInst &FPI) { - markOverdefined(&FPI); - } void visitCatchSwitchInst(CatchSwitchInst &CPI) { markOverdefined(&CPI); visitTerminatorInst(CPI); @@ -539,13 +535,6 @@ private: void visitResumeInst (TerminatorInst &I) { /*returns void*/ } void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ } void visitFenceInst (FenceInst &I) { /*returns void*/ } - void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { - markOverdefined(&I); - } - void visitAtomicRMWInst (AtomicRMWInst &I) { markOverdefined(&I); } - void visitAllocaInst (Instruction &I) { markOverdefined(&I); } - void visitVAArgInst (Instruction &I) { markOverdefined(&I); } - void visitInstruction(Instruction &I) { // If a new instruction is added to LLVM that we don't handle. DEBUG(dbgs() << "SCCP: Don't know how to handle: " << I << '\n'); diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp index 24d28a6..5d57ed9 100644 --- a/lib/Transforms/Utils/CodeExtractor.cpp +++ b/lib/Transforms/Utils/CodeExtractor.cpp @@ -142,8 +142,139 @@ static bool definedInCaller(const SetVector &Blocks, Value *V) { return false; } -void CodeExtractor::findAllocas(ValueSet &SinkCands) const { +static BasicBlock *getCommonExitBlock(const SetVector &Blocks) { + BasicBlock *CommonExitBlock = nullptr; + auto hasNonCommonExitSucc = [&](BasicBlock *Block) { + for (auto *Succ : successors(Block)) { + // Internal edges, ok. + if (Blocks.count(Succ)) + continue; + if (!CommonExitBlock) { + CommonExitBlock = Succ; + continue; + } + if (CommonExitBlock == Succ) + continue; + + return true; + } + return false; + }; + + if (any_of(Blocks, hasNonCommonExitSucc)) + return nullptr; + + return CommonExitBlock; +} + +bool CodeExtractor::isLegalToShrinkwrapLifetimeMarkers( + Instruction *Addr) const { + AllocaInst *AI = cast(Addr->stripInBoundsConstantOffsets()); + Function *Func = (*Blocks.begin())->getParent(); + for (BasicBlock &BB : *Func) { + if (Blocks.count(&BB)) + continue; + for (Instruction &II : BB) { + + if (isa(II)) + continue; + + unsigned Opcode = II.getOpcode(); + Value *MemAddr = nullptr; + switch (Opcode) { + case Instruction::Store: + case Instruction::Load: { + if (Opcode == Instruction::Store) { + StoreInst *SI = cast(&II); + MemAddr = SI->getPointerOperand(); + } else { + LoadInst *LI = cast(&II); + MemAddr = LI->getPointerOperand(); + } + // Global variable can not be aliased with locals. + if (dyn_cast(MemAddr)) + break; + Value *Base = MemAddr->stripInBoundsConstantOffsets(); + if (!dyn_cast(Base) || Base == AI) + return false; + break; + } + default: { + IntrinsicInst *IntrInst = dyn_cast(&II); + if (IntrInst) { + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start || + IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) + break; + return false; + } + // Treat all the other cases conservatively if it has side effects. + if (II.mayHaveSideEffects()) + return false; + } + } + } + } + + return true; +} + +BasicBlock * +CodeExtractor::findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock) { + BasicBlock *SinglePredFromOutlineRegion = nullptr; + assert(!Blocks.count(CommonExitBlock) && + "Expect a block outside the region!"); + for (auto *Pred : predecessors(CommonExitBlock)) { + if (!Blocks.count(Pred)) + continue; + if (!SinglePredFromOutlineRegion) { + SinglePredFromOutlineRegion = Pred; + } else if (SinglePredFromOutlineRegion != Pred) { + SinglePredFromOutlineRegion = nullptr; + break; + } + } + + if (SinglePredFromOutlineRegion) + return SinglePredFromOutlineRegion; + +#ifndef NDEBUG + auto getFirstPHI = [](BasicBlock *BB) { + BasicBlock::iterator I = BB->begin(); + PHINode *FirstPhi = nullptr; + while (I != BB->end()) { + PHINode *Phi = dyn_cast(I); + if (!Phi) + break; + if (!FirstPhi) { + FirstPhi = Phi; + break; + } + } + return FirstPhi; + }; + // If there are any phi nodes, the single pred either exists or has already + // be created before code extraction. + assert(!getFirstPHI(CommonExitBlock) && "Phi not expected"); +#endif + + BasicBlock *NewExitBlock = CommonExitBlock->splitBasicBlock( + CommonExitBlock->getFirstNonPHI()->getIterator()); + + for (auto *Pred : predecessors(CommonExitBlock)) { + if (Blocks.count(Pred)) + continue; + Pred->getTerminator()->replaceUsesOfWith(CommonExitBlock, NewExitBlock); + } + // Now add the old exit block to the outline region. + Blocks.insert(CommonExitBlock); + return CommonExitBlock; +} + +void CodeExtractor::findAllocas(ValueSet &SinkCands, ValueSet &HoistCands, + BasicBlock *&ExitBlock) const { Function *Func = (*Blocks.begin())->getParent(); + ExitBlock = getCommonExitBlock(Blocks); + for (BasicBlock &BB : *Func) { if (Blocks.count(&BB)) continue; @@ -152,49 +283,96 @@ void CodeExtractor::findAllocas(ValueSet &SinkCands) const { if (!AI) continue; - // Returns true if matching life time markers are found within - // the outlined region. - auto GetLifeTimeMarkers = [&](Instruction *Addr) { + // Find the pair of life time markers for address 'Addr' that are either + // defined inside the outline region or can legally be shrinkwrapped into + // the outline region. If there are not other untracked uses of the + // address, return the pair of markers if found; otherwise return a pair + // of nullptr. + auto GetLifeTimeMarkers = + [&](Instruction *Addr, bool &SinkLifeStart, + bool &HoistLifeEnd) -> std::pair { Instruction *LifeStart = nullptr, *LifeEnd = nullptr; - for (User *U : Addr->users()) { - if (!definedInRegion(Blocks, U)) - return false; + for (User *U : Addr->users()) { IntrinsicInst *IntrInst = dyn_cast(U); if (IntrInst) { - if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) { + // Do not handle the case where AI has multiple start markers. + if (LifeStart) + return std::make_pair(nullptr, nullptr); LifeStart = IntrInst; - if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) + } + if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) { + if (LifeEnd) + return std::make_pair(nullptr, nullptr); LifeEnd = IntrInst; + } + continue; } + // Find untracked uses of the address, bail. + if (!definedInRegion(Blocks, U)) + return std::make_pair(nullptr, nullptr); } - return LifeStart && LifeEnd; + + if (!LifeStart || !LifeEnd) + return std::make_pair(nullptr, nullptr); + + SinkLifeStart = !definedInRegion(Blocks, LifeStart); + HoistLifeEnd = !definedInRegion(Blocks, LifeEnd); + // Do legality Check. + if ((SinkLifeStart || HoistLifeEnd) && + !isLegalToShrinkwrapLifetimeMarkers(Addr)) + return std::make_pair(nullptr, nullptr); + + // Check to see if we have a place to do hoisting, if not, bail. + if (HoistLifeEnd && !ExitBlock) + return std::make_pair(nullptr, nullptr); + + return std::make_pair(LifeStart, LifeEnd); }; - if (GetLifeTimeMarkers(AI)) { + bool SinkLifeStart = false, HoistLifeEnd = false; + auto Markers = GetLifeTimeMarkers(AI, SinkLifeStart, HoistLifeEnd); + + if (Markers.first) { + if (SinkLifeStart) + SinkCands.insert(Markers.first); SinkCands.insert(AI); + if (HoistLifeEnd) + HoistCands.insert(Markers.second); continue; } - // Follow the bitcast: + // Follow the bitcast. Instruction *MarkerAddr = nullptr; for (User *U : AI->users()) { - if (U->stripPointerCasts() == AI) { + + if (U->stripInBoundsConstantOffsets() == AI) { + SinkLifeStart = false; + HoistLifeEnd = false; Instruction *Bitcast = cast(U); - if (GetLifeTimeMarkers(Bitcast)) { + Markers = GetLifeTimeMarkers(Bitcast, SinkLifeStart, HoistLifeEnd); + if (Markers.first) { MarkerAddr = Bitcast; continue; } } + + // Found unknown use of AI. if (!definedInRegion(Blocks, U)) { MarkerAddr = nullptr; break; } } + if (MarkerAddr) { + if (SinkLifeStart) + SinkCands.insert(Markers.first); if (!definedInRegion(Blocks, MarkerAddr)) SinkCands.insert(MarkerAddr); SinkCands.insert(AI); + if (HoistLifeEnd) + HoistCands.insert(Markers.second); } } } @@ -780,7 +958,8 @@ Function *CodeExtractor::extractCodeRegion() { if (!isEligible()) return nullptr; - ValueSet inputs, outputs, SinkingCands; + ValueSet inputs, outputs, SinkingCands, HoistingCands; + BasicBlock *CommonExit = nullptr; // Assumption: this is a single-entry code region, and the header is the first // block in the region. @@ -819,7 +998,8 @@ Function *CodeExtractor::extractCodeRegion() { "newFuncRoot"); newFuncRoot->getInstList().push_back(BranchInst::Create(header)); - findAllocas(SinkingCands); + findAllocas(SinkingCands, HoistingCands, CommonExit); + assert(HoistingCands.empty() || CommonExit); // Find inputs to, outputs from the code region. findInputsOutputs(inputs, outputs, SinkingCands); @@ -829,6 +1009,13 @@ Function *CodeExtractor::extractCodeRegion() { cast(II)->moveBefore(*newFuncRoot, newFuncRoot->getFirstInsertionPt()); + if (!HoistingCands.empty()) { + auto *HoistToBlock = findOrCreateBlockForHoisting(CommonExit); + Instruction *TI = HoistToBlock->getTerminator(); + for (auto *II : HoistingCands) + cast(II)->moveBefore(TI); + } + // Calculate the exit blocks for the extracted region and the total exit // weights for each of those blocks. DenseMap ExitWeights; diff --git a/lib/Transforms/Utils/PredicateInfo.cpp b/lib/Transforms/Utils/PredicateInfo.cpp index 9e71cba..1260e35 100644 --- a/lib/Transforms/Utils/PredicateInfo.cpp +++ b/lib/Transforms/Utils/PredicateInfo.cpp @@ -460,6 +460,9 @@ void PredicateInfo::buildPredicateInfo() { if (auto *BI = dyn_cast(BranchBB->getTerminator())) { if (!BI->isConditional()) continue; + // Can't insert conditional information if they all go to the same place. + if (BI->getSuccessor(0) == BI->getSuccessor(1)) + continue; processBranch(BI, BranchBB, OpsToRename); } else if (auto *SI = dyn_cast(BranchBB->getTerminator())) { processSwitch(SI, BranchBB, OpsToRename); diff --git a/lib/Transforms/Utils/SimplifyIndVar.cpp b/lib/Transforms/Utils/SimplifyIndVar.cpp index 02a5d3d..faa1404 100644 --- a/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -352,7 +352,7 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) { return false; typedef const SCEV *(ScalarEvolution::*OperationFunctionTy)( - const SCEV *, const SCEV *, SCEV::NoWrapFlags); + const SCEV *, const SCEV *, SCEV::NoWrapFlags, unsigned); typedef const SCEV *(ScalarEvolution::*ExtensionFunctionTy)( const SCEV *, Type *); @@ -406,10 +406,11 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) { IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2); const SCEV *A = - (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap), WideTy); + (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0u), + WideTy); const SCEV *B = (SE->*Operation)((SE->*Extension)(LHS, WideTy), - (SE->*Extension)(RHS, WideTy), SCEV::FlagAnyWrap); + (SE->*Extension)(RHS, WideTy), SCEV::FlagAnyWrap, 0u); if (A != B) return false; @@ -530,8 +531,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO, return false; const SCEV *(ScalarEvolution::*GetExprForBO)(const SCEV *, const SCEV *, - SCEV::NoWrapFlags); - + SCEV::NoWrapFlags, unsigned); switch (BO->getOpcode()) { default: return false; @@ -560,7 +560,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO, const SCEV *ExtendAfterOp = SE->getZeroExtendExpr(SE->getSCEV(BO), WideTy); const SCEV *OpAfterExtend = (SE->*GetExprForBO)( SE->getZeroExtendExpr(LHS, WideTy), SE->getZeroExtendExpr(RHS, WideTy), - SCEV::FlagAnyWrap); + SCEV::FlagAnyWrap, 0u); if (ExtendAfterOp == OpAfterExtend) { BO->setHasNoUnsignedWrap(); SE->forgetValue(BO); @@ -572,7 +572,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO, const SCEV *ExtendAfterOp = SE->getSignExtendExpr(SE->getSCEV(BO), WideTy); const SCEV *OpAfterExtend = (SE->*GetExprForBO)( SE->getSignExtendExpr(LHS, WideTy), SE->getSignExtendExpr(RHS, WideTy), - SCEV::FlagAnyWrap); + SCEV::FlagAnyWrap, 0u); if (ExtendAfterOp == OpAfterExtend) { BO->setHasNoSignedWrap(); SE->forgetValue(BO); diff --git a/test/Analysis/ScalarEvolution/limit-depth.ll b/test/Analysis/ScalarEvolution/limit-depth.ll new file mode 100644 index 0000000..5a35bfe --- /dev/null +++ b/test/Analysis/ScalarEvolution/limit-depth.ll @@ -0,0 +1,44 @@ +; RUN: opt -scalar-evolution-max-arith-depth=0 -analyze -scalar-evolution < %s | FileCheck %s + +; Check that depth set to 0 prevents getAddExpr and getMulExpr from making +; transformations in SCEV. We expect the result to be very straightforward. + +define void @test_add(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) { +; CHECK-LABEL: @test_add +; CHECK: %s2 = add i32 %s1, %p3 +; CHECK-NEXT: --> (%a + %a + %b + %b + %c + %c + %d + %d + %e + %e + %f + %f) + %tmp0 = add i32 %a, %b + %tmp1 = add i32 %b, %c + %tmp2 = add i32 %c, %d + %tmp3 = add i32 %d, %e + %tmp4 = add i32 %e, %f + %tmp5 = add i32 %f, %a + + %p1 = add i32 %tmp0, %tmp3 + %p2 = add i32 %tmp1, %tmp4 + %p3 = add i32 %tmp2, %tmp5 + + %s1 = add i32 %p1, %p2 + %s2 = add i32 %s1, %p3 + ret void +} + +define void @test_mul(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) { +; CHECK-LABEL: @test_mul +; CHECK: %s2 = mul i32 %s1, %p3 +; CHECK-NEXT: --> (2 * 3 * 4 * 5 * 6 * 7 * %a * %b * %c * %d * %e * %f) + %tmp0 = mul i32 %a, 2 + %tmp1 = mul i32 %b, 3 + %tmp2 = mul i32 %c, 4 + %tmp3 = mul i32 %d, 5 + %tmp4 = mul i32 %e, 6 + %tmp5 = mul i32 %f, 7 + + %p1 = mul i32 %tmp0, %tmp3 + %p2 = mul i32 %tmp1, %tmp4 + %p3 = mul i32 %tmp2, %tmp5 + + %s1 = mul i32 %p1, %p2 + %s2 = mul i32 %s1, %p3 + ret void +} diff --git a/test/Assembler/diexpression.ll b/test/Assembler/diexpression.ll index c2fa3ee..39f4be7 100644 --- a/test/Assembler/diexpression.ll +++ b/test/Assembler/diexpression.ll @@ -1,18 +1,20 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !1, !2, !3, !4, !5} -!named = !{!0, !1, !2, !3, !4, !5} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6} +!named = !{!0, !1, !2, !3, !4, !5, !6} ; CHECK: !0 = !DIExpression() ; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref) -; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3) +; CHECK-NEXT: !2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus) ; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) -; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) +; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7) ; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) +; CHECK-NEXT: !6 = !DIExpression(DW_OP_plus_uconst, 3) !0 = !DIExpression() !1 = !DIExpression(DW_OP_deref) -!2 = !DIExpression(DW_OP_plus, 3) +!2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus) !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7) -!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7) +!4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7) !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) +!6 = !DIExpression(DW_OP_plus_uconst, 3) diff --git a/test/Bitcode/DIExpression-deref.ll b/test/Bitcode/DIExpression-deref.ll index 3a161b8..a03d601 100644 --- a/test/Bitcode/DIExpression-deref.ll +++ b/test/Bitcode/DIExpression-deref.ll @@ -11,11 +11,11 @@ !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ; DW_OP_deref should be moved to the back of the expression. ; -; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32) +; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32) !6 = !DIExpression(DW_OP_deref, DW_OP_plus, 0, DW_OP_LLVM_fragment, 8, 32) -; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref) +; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref) !7 = !DIExpression(DW_OP_deref, DW_OP_plus, 0) -; CHECK: !DIExpression(DW_OP_plus, 1, DW_OP_deref) +; CHECK: !DIExpression(DW_OP_plus_uconst, 1, DW_OP_deref) !8 = !DIExpression(DW_OP_plus, 1, DW_OP_deref) ; CHECK: !DIExpression(DW_OP_deref) !9 = !DIExpression(DW_OP_deref) diff --git a/test/Bitcode/DIExpression-minus-upgrade.ll b/test/Bitcode/DIExpression-minus-upgrade.ll new file mode 100644 index 0000000..1f26eba --- /dev/null +++ b/test/Bitcode/DIExpression-minus-upgrade.ll @@ -0,0 +1,16 @@ +; RUN: llvm-dis -o - %s.bc | FileCheck %s + +!llvm.dbg.cu = !{!1} +!llvm.module.flags = !{!8, !9} + +!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true) +!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang (llvm/trunk 304286)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4) +!2 = !DIFile(filename: "a.c", directory: "/") +!3 = !{} +!4 = !{!7} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +; CHECK: !DIExpression(DW_OP_constu, 42, DW_OP_minus) +!6 = !DIExpression(DW_OP_minus, 42) +!7 = !DIGlobalVariableExpression(var: !0, expr: !6) +!8 = !{i32 2, !"Dwarf Version", i32 4} +!9 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/test/Bitcode/DIExpression-minus-upgrade.ll.bc b/test/Bitcode/DIExpression-minus-upgrade.ll.bc new file mode 100644 index 0000000..354ba64 Binary files /dev/null and b/test/Bitcode/DIExpression-minus-upgrade.ll.bc differ diff --git a/test/Bitcode/DIGlobalVariableExpression.ll b/test/Bitcode/DIGlobalVariableExpression.ll index f6796bb..31c3fda 100644 --- a/test/Bitcode/DIGlobalVariableExpression.ll +++ b/test/Bitcode/DIGlobalVariableExpression.ll @@ -14,7 +14,7 @@ ; CHECK: ![[HVAR:[0-9]+]] = distinct !DIGlobalVariable(name: "h", ; CHECK: ![[IMPORTS]] = !{![[CIMPORT:[0-9]+]]} ; CHECK: ![[CIMPORT]] = !DIImportedEntity({{.*}}entity: ![[HVAR]] -; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus, 1) +; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus_uconst, 1) ; CHECK: ![[H]] = {{.*}}!DIGlobalVariableExpression(var: ![[HVAR]]) @g = common global i32 0, align 4, !dbg !0 diff --git a/test/Bitcode/upgrade-linker-options.ll b/test/Bitcode/upgrade-linker-options.ll new file mode 100644 index 0000000..6c874fa --- /dev/null +++ b/test/Bitcode/upgrade-linker-options.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as -disable-verify < %s | llvm-dis | FileCheck %s +; RUN: not llvm-as < %s 2>&1 | FileCheck --check-prefix=ERROR %s + +; CHECK: !llvm.linker.options = !{!2, !3} +; CHECK: !2 = !{!"/DEFAULTLIB:libcmtd.lib"} +; CHECK: !3 = !{!"/DEFAULTLIB:oldnames.lib"} + +; ERROR: 'Linker Options' named metadata no longer supported + +!0 = !{i32 6, !"Linker Options", !1} +!1 = !{!2, !3} +!2 = !{!"/DEFAULTLIB:libcmtd.lib"} +!3 = !{!"/DEFAULTLIB:oldnames.lib"} + +!llvm.module.flags = !{!0} diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir index c806b4a..ce913d2 100644 --- a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir +++ b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir @@ -53,9 +53,7 @@ body: | ; CHECK: %7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr) %7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr) - ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0 - ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64) - ; CHECK: [[LOAD0:%[0-9]+]](s64) = G_LOAD [[GEP0]](p0) :: (load 16 from %ir.addr) + ; CHECK: [[LOAD0:%[0-9]+]](s64) = G_LOAD %0(p0) :: (load 16 from %ir.addr) ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8 ; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64) ; CHECK: [[LOAD1:%[0-9]+]](s64) = G_LOAD [[GEP1]](p0) :: (load 16 from %ir.addr) @@ -105,9 +103,7 @@ body: | ; CHECK: G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr) - ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0 - ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64) - ; CHECK: G_STORE %5(s64), [[GEP0]](p0) :: (store 16 into %ir.addr) + ; CHECK: G_STORE %5(s64), %0(p0) :: (store 16 into %ir.addr) ; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8 ; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64) ; CHECK: G_STORE %6(s64), [[GEP1]](p0) :: (store 16 into %ir.addr) diff --git a/test/CodeGen/AArch64/arm64-sincos.ll b/test/CodeGen/AArch64/arm64-sincos.ll index 06157b2..98876db 100644 --- a/test/CodeGen/AArch64/arm64-sincos.ll +++ b/test/CodeGen/AArch64/arm64-sincos.ll @@ -1,7 +1,9 @@ ; RUN: llc < %s -mtriple=arm64-apple-ios7 | FileCheck %s --check-prefix CHECK-IOS ; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s --check-prefix CHECK-LINUX -; Combine sin / cos into a single call. +; Combine sin / cos into a single call unless they may write errno (as +; captured by readnone attrbiute, controlled by clang -fmath-errno +; setting). ; rdar://12856873 define float @test1(float %x) nounwind { @@ -11,11 +13,26 @@ entry: ; CHECK-IOS: fadd s0, s0, s1 ; CHECK-LINUX-LABEL: test1: +; CHECK-LINUX: bl sincosf + + %call = tail call float @sinf(float %x) readnone + %call1 = tail call float @cosf(float %x) readnone + %add = fadd float %call, %call1 + ret float %add +} + +define float @test1_errno(float %x) nounwind { +entry: +; CHECK-IOS-LABEL: test1_errno: +; CHECK-IOS: bl _sinf +; CHECK-IOS: bl _cosf + +; CHECK-LINUX-LABEL: test1_errno: ; CHECK-LINUX: bl sinf ; CHECK-LINUX: bl cosf - %call = tail call float @sinf(float %x) nounwind readnone - %call1 = tail call float @cosf(float %x) nounwind readnone + %call = tail call float @sinf(float %x) + %call1 = tail call float @cosf(float %x) %add = fadd float %call, %call1 ret float %add } @@ -27,16 +44,31 @@ entry: ; CHECK-IOS: fadd d0, d0, d1 ; CHECK-LINUX-LABEL: test2: +; CHECK-LINUX: bl sincos + + %call = tail call double @sin(double %x) readnone + %call1 = tail call double @cos(double %x) readnone + %add = fadd double %call, %call1 + ret double %add +} + +define double @test2_errno(double %x) nounwind { +entry: +; CHECK-IOS-LABEL: test2_errno: +; CHECK-IOS: bl _sin +; CHECK-IOS: bl _cos + +; CHECK-LINUX-LABEL: test2_errno: ; CHECK-LINUX: bl sin ; CHECK-LINUX: bl cos - %call = tail call double @sin(double %x) nounwind readnone - %call1 = tail call double @cos(double %x) nounwind readnone + %call = tail call double @sin(double %x) + %call1 = tail call double @cos(double %x) %add = fadd double %call, %call1 ret double %add } -declare float @sinf(float) readonly -declare double @sin(double) readonly -declare float @cosf(float) readonly -declare double @cos(double) readonly +declare float @sinf(float) +declare double @sin(double) +declare float @cosf(float) +declare double @cos(double) diff --git a/test/CodeGen/AArch64/fast-isel-sp-adjust.ll b/test/CodeGen/AArch64/fast-isel-sp-adjust.ll new file mode 100644 index 0000000..9201d1b --- /dev/null +++ b/test/CodeGen/AArch64/fast-isel-sp-adjust.ll @@ -0,0 +1,288 @@ +; RUN: llc -O0 -mtriple=aarch64-apple-ios -o - %s | FileCheck %s +; RUN: not llc -O0 -mtriple=aarch64-apple-ios -o /dev/null -fast-isel-abort=3 %s 2> %t +; RUN: FileCheck %s --check-prefix=CHECK-ERRORS < %t + +; The issue here is that FastISel cannot emit an ADDrr where one of the inputs +; is SP. This only ever crops up with function calls, and then only if the +; argument is at an offset > 2^12 * size from SP. + +; If FastISel ever starts coping with this and emits an "add xD, sp, xM" it's +; critical to check the encoding as well as the textual assembly. An ADDXrs with +; SP as an operand will still print with SP, but will actually mean XZR. + +; CHECK-ERRORS: LLVM ERROR: FastISel missed call + +; CHECK-LABEL: foo: +; CHECK-DAG: mov x[[SP:[0-9]+]], sp +; CHECK-DAG: mov [[TMP:w[0-9]+]], #4104 +; CHECK: mov w[[OFFSET:[0-9]+]], [[TMP]] +; CHECK: strb w0, [x[[SP]], x[[OFFSET]]] + +define void @foo(i8 %in) { + call void @bar(i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; All regs gone. + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 32 + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 64 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 128 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 256 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 512 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 1024 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 2048 + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, + i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 4096 + i64 undef, ; sp + 4104 (i.e. not uimm12 or uimm12 << 12). + i8 %in) + ret void +} + +declare void @bar(i64, i64, i64, i64, + i64, i64, i64, i64, ; All regs gone. + i64, i64, i64, i64, ; sp + 32 + i64, i64, i64, i64, ; sp + 64 + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 128 + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 256 + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 512 + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 1024 + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 2048 + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, + i64, i64, i64, i64, ; sp + 4096 + i64, + i8) diff --git a/test/CodeGen/AArch64/misched-fusion-aes.ll b/test/CodeGen/AArch64/misched-fusion-aes.ll index bd7c69c..8ee4dbc 100644 --- a/test/CodeGen/AArch64/misched-fusion-aes.ll +++ b/test/CodeGen/AArch64/misched-fusion-aes.ll @@ -1,7 +1,9 @@ -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX -; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX +; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=+fuse-aes,+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=generic -mattr=+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS +; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS ; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=exynos-m1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKM1 declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d, <16 x i8> %k) @@ -74,22 +76,23 @@ define void @aesea(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, ret void ; CHECK-LABEL: aesea: -; CHECKCORTEX: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VA]] -; CHECKCORTEX: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VB]] -; CHECKCORTEX: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VC]] -; CHECKCORTEX: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VD]] -; CHECKCORTEX: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VE]] -; CHECKCORTEX: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VF]] -; CHECKCORTEX: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VG]] -; CHECKCORTEX: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VH]] +; CHECKFUSEALLPAIRS: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VA]] +; CHECKFUSEALLPAIRS: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VB]] +; CHECKFUSEALLPAIRS: aese [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VC]] +; CHECKFUSEALLPAIRS: aese [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VD]] +; CHECKFUSEALLPAIRS: aese [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VE]] +; CHECKFUSEALLPAIRS: aese [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VF]] +; CHECKFUSEALLPAIRS: aese [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VG]] +; CHECKFUSEALLPAIRS: aese [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VH]] +; CHECKFUSEALLPAIRS-NOT: aesmc ; CHECKM1: aese [[VA:v[0-7].16b]], {{v[0-7].16b}} ; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VA]] @@ -175,22 +178,23 @@ define void @aesda(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d, ret void ; CHECK-LABEL: aesda: -; CHECKCORTEX: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VA]] -; CHECKCORTEX: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VB]] -; CHECKCORTEX: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VC]] -; CHECKCORTEX: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VD]] -; CHECKCORTEX: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VE]] -; CHECKCORTEX: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VF]] -; CHECKCORTEX: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VG]] -; CHECKCORTEX: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} -; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VH]] +; CHECKFUSEALLPAIRS: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VA]] +; CHECKFUSEALLPAIRS: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VB]] +; CHECKFUSEALLPAIRS: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VC]] +; CHECKFUSEALLPAIRS: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VD]] +; CHECKFUSEALLPAIRS: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VE]] +; CHECKFUSEALLPAIRS: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VF]] +; CHECKFUSEALLPAIRS: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VG]] +; CHECKFUSEALLPAIRS: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}} +; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VH]] +; CHECKFUSEALLPAIRS-NOT: aesimc ; CHECKM1: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}} ; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VA]] @@ -236,4 +240,5 @@ entry: ; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VA]] ; CHECK: aese [[VB:v[0-7].16b]], {{v[0-7].16b}} ; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VB]] +; CHECK-NOT: aesmc } diff --git a/test/CodeGen/AArch64/sincos-expansion.ll b/test/CodeGen/AArch64/sincos-expansion.ll index c3a172d..41ee403 100644 --- a/test/CodeGen/AArch64/sincos-expansion.ll +++ b/test/CodeGen/AArch64/sincos-expansion.ll @@ -1,8 +1,18 @@ ; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs -o - %s | FileCheck %s define float @test_sincos_f32(float %f) { +; CHECK-LABEL: test_sincos_f32: %sin = call float @sinf(float %f) readnone %cos = call float @cosf(float %f) readnone +; CHECK: bl sincosf + %val = fadd float %sin, %cos + ret float %val +} + +define float @test_sincos_f32_errno(float %f) { +; CHECK-LABEL: test_sincos_f32_errno: + %sin = call float @sinf(float %f) + %cos = call float @cosf(float %f) ; CHECK: bl sinf ; CHECK: bl cosf %val = fadd float %sin, %cos @@ -10,26 +20,46 @@ define float @test_sincos_f32(float %f) { } define double @test_sincos_f64(double %f) { +; CHECK-LABEL: test_sincos_f64: %sin = call double @sin(double %f) readnone %cos = call double @cos(double %f) readnone %val = fadd double %sin, %cos +; CHECK: bl sincos + ret double %val +} + +define double @test_sincos_f64_errno(double %f) { +; CHECK-LABEL: test_sincos_f64_errno: + %sin = call double @sin(double %f) + %cos = call double @cos(double %f) + %val = fadd double %sin, %cos ; CHECK: bl sin ; CHECK: bl cos ret double %val } define fp128 @test_sincos_f128(fp128 %f) { +; CHECK-LABEL: test_sincos_f128: %sin = call fp128 @sinl(fp128 %f) readnone %cos = call fp128 @cosl(fp128 %f) readnone %val = fadd fp128 %sin, %cos +; CHECK: bl sincosl + ret fp128 %val +} + +define fp128 @test_sincos_f128_errno(fp128 %f) { +; CHECK-LABEL: test_sincos_f128_errno: + %sin = call fp128 @sinl(fp128 %f) + %cos = call fp128 @cosl(fp128 %f) + %val = fadd fp128 %sin, %cos ; CHECK: bl sinl ; CHECK: bl cosl ret fp128 %val } -declare float @sinf(float) readonly -declare double @sin(double) readonly -declare fp128 @sinl(fp128) readonly -declare float @cosf(float) readonly -declare double @cos(double) readonly -declare fp128 @cosl(fp128) readonly +declare float @sinf(float) +declare double @sin(double) +declare fp128 @sinl(fp128) +declare float @cosf(float) +declare double @cos(double) +declare fp128 @cosl(fp128) diff --git a/test/CodeGen/AArch64/swifterror.ll b/test/CodeGen/AArch64/swifterror.ll index 69bf351..bc28f47 100644 --- a/test/CodeGen/AArch64/swifterror.ll +++ b/test/CodeGen/AArch64/swifterror.ll @@ -597,3 +597,30 @@ entry: tail call void @acallee(i8* null) ret void } + +declare swiftcc void @foo2(%swift_error** swifterror) + +; Make sure we properly assign registers during fast-isel. +; CHECK-O0-LABEL: testAssign +; CHECK-O0: mov [[TMP:x.*]], xzr +; CHECK-O0: mov x21, [[TMP]] +; CHECK-O0: bl _foo2 +; CHECK-O0: str x21, [s[[STK:.*]]] +; CHECK-O0: ldr x0, [s[[STK]]] + +; CHECK-APPLE-LABEL: testAssign +; CHECK-APPLE: mov x21, xzr +; CHECK-APPLE: bl _foo2 +; CHECK-APPLE: mov x0, x21 + +define swiftcc %swift_error* @testAssign(i8* %error_ref) { +entry: + %error_ptr = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr + call swiftcc void @foo2(%swift_error** swifterror %error_ptr) + br label %a + +a: + %error = load %swift_error*, %swift_error** %error_ptr + ret %swift_error* %error +} diff --git a/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir b/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir index 2a3d388..56a9e70 100644 --- a/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir +++ b/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir @@ -14,7 +14,7 @@ regBankSelected: true # GCN: global_addrspace # GCN: [[PTR:%[0-9]+]] = COPY %vgpr0_vgpr1 -# GCN: FLAT_LOAD_DWORD [[PTR]], 0, 0 +# GCN: FLAT_LOAD_DWORD [[PTR]], 0, 0, 0 body: | bb.0: diff --git a/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir b/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir index 89be3bd..ea43572 100644 --- a/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir +++ b/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir @@ -15,7 +15,7 @@ regBankSelected: true # GCN: global_addrspace # GCN: [[PTR:%[0-9]+]] = COPY %vgpr0_vgpr1 # GCN: [[VAL:%[0-9]+]] = COPY %vgpr2 -# GCN: FLAT_STORE_DWORD [[PTR]], [[VAL]], 0, 0 +# GCN: FLAT_STORE_DWORD [[PTR]], [[VAL]], 0, 0, 0 body: | bb.0: diff --git a/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir b/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir new file mode 100644 index 0000000..f10c896 --- /dev/null +++ b/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir @@ -0,0 +1,22 @@ +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s + +--- | + define void @test_add() { ret void } +... + +--- +name: test_add +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: %vgpr0, %vgpr1 + ; CHECK-LABEL: name: test_add + ; CHECK: %2(s32) = G_ADD %0, %1 + + %0(s32) = COPY %vgpr0 + %1(s32) = COPY %vgpr1 + %2(s32) = G_ADD %0, %1 +... diff --git a/test/CodeGen/AMDGPU/always-uniform.ll b/test/CodeGen/AMDGPU/always-uniform.ll new file mode 100644 index 0000000..4ba57fb --- /dev/null +++ b/test/CodeGen/AMDGPU/always-uniform.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple amdgcn-amdhsa -mcpu=fiji -amdgpu-scalarize-global-loads -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s + +declare i32 @llvm.amdgcn.workitem.id.x() +declare i32 @llvm.amdgcn.readfirstlane(i32) + +; GCN-LABEL: readfirstlane_uniform +; GCN: s_load_dwordx2 s{{\[}}[[IN_ADDR:[0-9]+]]:1{{\]}}, s[4:5], 0x0 +; GCN: v_readfirstlane_b32 s[[SCALAR:[0-9]+]], v0 +; GCN: s_add_u32 s[[LOAD_ADDR:[0-9]+]], s[[IN_ADDR]], s[[SCALAR]] +; GCN: s_load_dword s{{[0-9]+}}, s{{\[}}[[LOAD_ADDR]] + +define amdgpu_kernel void @readfirstlane_uniform(float addrspace(1)* noalias nocapture readonly, float addrspace(1)* noalias nocapture readonly) { + %tid = tail call i32 @llvm.amdgcn.workitem.id.x() + %scalar = tail call i32 @llvm.amdgcn.readfirstlane(i32 %tid) + %idx = zext i32 %scalar to i64 + %gep0 = getelementptr inbounds float, float addrspace(1)* %0, i64 %idx + %val = load float, float addrspace(1)* %gep0, align 4 + %gep1 = getelementptr inbounds float, float addrspace(1)* %1, i64 10 + store float %val, float addrspace(1)* %gep1, align 4 + ret void +} diff --git a/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll b/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll index cbdcf6a..5dec3e3 100644 --- a/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll +++ b/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll @@ -1,12 +1,19 @@ -; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=bonaire < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-CI %s -; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-VI %s -; RUN: llc -march=amdgcn -mcpu=bonaire -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=CI %s -; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s +; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=bonaire < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-CI -check-prefix=OPT-CIVI %s +; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-VI -check-prefix=OPT-CIVI %s +; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=gfx900 -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-GFX9 %s +; RUN: llc -march=amdgcn -mcpu=bonaire -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=CI -check-prefix=CIVI %s +; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=VI -check-prefix=CIVI %s +; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=GFX9 %s ; OPT-LABEL: @test_no_sink_flat_small_offset_i32( -; OPT: getelementptr i32, i32 addrspace(4)* %in -; OPT: br i1 -; OPT-NOT: ptrtoint +; OPT-CIVI: getelementptr i32, i32 addrspace(4)* %in +; OPT-CIVI: br i1 +; OPT-CIVI-NOT: ptrtoint + +; OPT-GFX9: br +; OPT-GFX9: %sunkaddr = getelementptr i8, i8 addrspace(4)* %0, i64 28 +; OPT-GFX9: %1 = bitcast i8 addrspace(4)* %sunkaddr to i32 addrspace(4)* +; OPT-GFX9: load i32, i32 addrspace(4)* %1 ; GCN-LABEL: {{^}}test_no_sink_flat_small_offset_i32: ; GCN: flat_load_dword @@ -96,3 +103,105 @@ endif: done: ret void } + +; OPT-LABEL: @test_sink_flat_small_max_flat_offset( +; OPT-CIVI: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4095 +; OPT-CIVI: br +; OPT-CIVI-NOT: getelementptr +; OPT-CIVI: load i8, i8 addrspace(4)* %in.gep + +; OPT-GFX9: br +; OPT-GFX9: %sunkaddr = getelementptr i8, i8 addrspace(4)* %in, i64 4095 +; OPT-GFX9: load i8, i8 addrspace(4)* %sunkaddr + +; GCN-LABEL: {{^}}test_sink_flat_small_max_flat_offset: +; GFX9: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}} offset:4095{{$}} +; CIVI: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}} +define amdgpu_kernel void @test_sink_flat_small_max_flat_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in) #1 { +entry: + %out.gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024 + %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4095 + %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0 + %tmp0 = icmp eq i32 %tid, 0 + br i1 %tmp0, label %endif, label %if + +if: + %tmp1 = load i8, i8 addrspace(4)* %in.gep + %tmp2 = sext i8 %tmp1 to i32 + br label %endif + +endif: + %x = phi i32 [ %tmp2, %if ], [ 0, %entry ] + store i32 %x, i32 addrspace(4)* %out.gep + br label %done + +done: + ret void +} + +; OPT-LABEL: @test_sink_flat_small_max_plus_1_flat_offset( +; OPT: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4096 +; OPT: br +; OPT-NOT: getelementptr +; OPT: load i8, i8 addrspace(4)* %in.gep + +; GCN-LABEL: {{^}}test_sink_flat_small_max_plus_1_flat_offset: +; GCN: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}} +define amdgpu_kernel void @test_sink_flat_small_max_plus_1_flat_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in) #1 { +entry: + %out.gep = getelementptr i32, i32 addrspace(4)* %out, i64 99999 + %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4096 + %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0 + %tmp0 = icmp eq i32 %tid, 0 + br i1 %tmp0, label %endif, label %if + +if: + %tmp1 = load i8, i8 addrspace(4)* %in.gep + %tmp2 = sext i8 %tmp1 to i32 + br label %endif + +endif: + %x = phi i32 [ %tmp2, %if ], [ 0, %entry ] + store i32 %x, i32 addrspace(4)* %out.gep + br label %done + +done: + ret void +} + +; OPT-LABEL: @test_no_sink_flat_reg_offset( +; OPT: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 %reg +; OPT: br + +; OPT-NOT: getelementptr +; OPT: load i8, i8 addrspace(4)* %in.gep + +; GCN-LABEL: {{^}}test_no_sink_flat_reg_offset: +; GCN: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}} +define amdgpu_kernel void @test_no_sink_flat_reg_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in, i64 %reg) #1 { +entry: + %out.gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024 + %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 %reg + %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0 + %tmp0 = icmp eq i32 %tid, 0 + br i1 %tmp0, label %endif, label %if + +if: + %tmp1 = load i8, i8 addrspace(4)* %in.gep + %tmp2 = sext i8 %tmp1 to i32 + br label %endif + +endif: + %x = phi i32 [ %tmp2, %if ], [ 0, %entry ] + store i32 %x, i32 addrspace(4)* %out.gep + br label %done + +done: + ret void +} + +declare i32 @llvm.amdgcn.mbcnt.lo(i32, i32) #0 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } +attributes #2 = { nounwind argmemonly } diff --git a/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll b/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll index 801029b..0796c24 100644 --- a/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll +++ b/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll @@ -12,7 +12,9 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) ; CHECK: DebugProps: ; CHECK: DebuggerABIVersion: [ 1, 0 ] ; CHECK: ReservedNumVGPRs: 4 -; CHECK: ReservedFirstVGPR: 11 +; GFX700: ReservedFirstVGPR: 11 +; GFX800: ReservedFirstVGPR: 11 +; GFX9: ReservedFirstVGPR: 14 ; CHECK: PrivateSegmentBufferSGPR: 0 ; CHECK: WavefrontPrivateSegmentOffsetSGPR: 11 define amdgpu_kernel void @test(i32 addrspace(1)* %A) #0 !dbg !7 !kernel_arg_addr_space !12 !kernel_arg_access_qual !13 !kernel_arg_type !14 !kernel_arg_base_type !14 !kernel_arg_type_qual !15 { diff --git a/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir b/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir index bc992ed..62b47be 100644 --- a/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir +++ b/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir @@ -219,19 +219,19 @@ body: | %34 = V_MOV_B32_e32 63, implicit %exec %27 = V_AND_B32_e64 %26, %24, implicit %exec - FLAT_STORE_DWORD %37, %27, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %37, %27, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %28 = V_AND_B32_e64 %24, %26, implicit %exec - FLAT_STORE_DWORD %37, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %37, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %29 = V_AND_B32_e32 %26, %24, implicit %exec - FLAT_STORE_DWORD %37, %29, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %37, %29, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %30 = V_AND_B32_e64 %26, %26, implicit %exec - FLAT_STORE_DWORD %37, %30, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %37, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %31 = V_AND_B32_e64 %34, %34, implicit %exec - FLAT_STORE_DWORD %37, %31, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %37, %31, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) S_ENDPGM @@ -407,34 +407,34 @@ body: | %27 = S_MOV_B32 -4 %11 = V_LSHLREV_B32_e64 12, %10, implicit %exec - FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %12 = V_LSHLREV_B32_e64 %7, 12, implicit %exec - FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %13 = V_LSHL_B32_e64 %7, 12, implicit %exec - FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %14 = V_LSHL_B32_e64 12, %7, implicit %exec - FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %15 = V_LSHL_B32_e64 12, %24, implicit %exec - FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %22 = V_LSHL_B32_e64 %6, 12, implicit %exec - FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %23 = V_LSHL_B32_e64 %6, 32, implicit %exec - FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %25 = V_LSHL_B32_e32 %6, %6, implicit %exec - FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %26 = V_LSHLREV_B32_e32 11, %24, implicit %exec - FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %28 = V_LSHL_B32_e32 %27, %6, implicit %exec - FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) S_ENDPGM @@ -615,34 +615,34 @@ body: | %35 = V_MOV_B32_e32 2, implicit %exec %11 = V_ASHRREV_I32_e64 8, %10, implicit %exec - FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %12 = V_ASHRREV_I32_e64 %8, %10, implicit %exec - FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %13 = V_ASHR_I32_e64 %7, 3, implicit %exec - FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %14 = V_ASHR_I32_e64 7, %32, implicit %exec - FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %15 = V_ASHR_I32_e64 %27, %24, implicit %exec - FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %22 = V_ASHR_I32_e64 %6, 4, implicit %exec - FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %23 = V_ASHR_I32_e64 %6, %33, implicit %exec - FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %25 = V_ASHR_I32_e32 %34, %34, implicit %exec - FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %26 = V_ASHRREV_I32_e32 11, %10, implicit %exec - FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %28 = V_ASHR_I32_e32 %27, %35, implicit %exec - FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) S_ENDPGM @@ -824,34 +824,34 @@ body: | %35 = V_MOV_B32_e32 2, implicit %exec %11 = V_LSHRREV_B32_e64 8, %10, implicit %exec - FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %12 = V_LSHRREV_B32_e64 %8, %10, implicit %exec - FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %13 = V_LSHR_B32_e64 %7, 3, implicit %exec - FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %14 = V_LSHR_B32_e64 7, %32, implicit %exec - FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %15 = V_LSHR_B32_e64 %27, %24, implicit %exec - FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %22 = V_LSHR_B32_e64 %6, 4, implicit %exec - FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %23 = V_LSHR_B32_e64 %6, %33, implicit %exec - FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %25 = V_LSHR_B32_e32 %34, %34, implicit %exec - FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %26 = V_LSHRREV_B32_e32 11, %10, implicit %exec - FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) %28 = V_LSHR_B32_e32 %27, %35, implicit %exec - FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) + FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out) S_ENDPGM diff --git a/test/CodeGen/AMDGPU/flat-address-space.ll b/test/CodeGen/AMDGPU/flat-address-space.ll index c867e4f..e486b9c 100644 --- a/test/CodeGen/AMDGPU/flat-address-space.ll +++ b/test/CodeGen/AMDGPU/flat-address-space.ll @@ -1,6 +1,7 @@ -; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=bonaire < %s | FileCheck %s -; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck %s +; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=bonaire < %s | FileCheck -check-prefixes=CHECK,CIVI %s +; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,CIVI %s ; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,HSA %s +; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,HSA,GFX9 %s ; Disable optimizations in case there are optimizations added that ; specialize away generic pointer accesses. @@ -172,6 +173,55 @@ define amdgpu_kernel void @flat_scratch_multidword_store() { ret void } +; CHECK-LABEL: {{^}}store_flat_i8_max_offset: +; CIVI: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}} +; GFX9: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}} offset:4095{{$}} +define amdgpu_kernel void @store_flat_i8_max_offset(i8 addrspace(4)* %fptr, i8 %x) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4095 + store volatile i8 %x, i8 addrspace(4)* %fptr.offset + ret void +} + +; CHECK-LABEL: {{^}}store_flat_i8_max_offset_p1: +; CHECK: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}} +define amdgpu_kernel void @store_flat_i8_max_offset_p1(i8 addrspace(4)* %fptr, i8 %x) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4096 + store volatile i8 %x, i8 addrspace(4)* %fptr.offset + ret void +} + +; CHECK-LABEL: {{^}}store_flat_i8_neg_offset: +; CHECK: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}} +define amdgpu_kernel void @store_flat_i8_neg_offset(i8 addrspace(4)* %fptr, i8 %x) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 -2 + store volatile i8 %x, i8 addrspace(4)* %fptr.offset + ret void +} + +; CHECK-LABEL: {{^}}load_flat_i8_max_offset: +; CIVI: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}} +; GFX9: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}} offset:4095{{$}} +define amdgpu_kernel void @load_flat_i8_max_offset(i8 addrspace(4)* %fptr) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4095 + %val = load volatile i8, i8 addrspace(4)* %fptr.offset + ret void +} + +; CHECK-LABEL: {{^}}load_flat_i8_max_offset_p1: +; CHECK: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}} +define amdgpu_kernel void @load_flat_i8_max_offset_p1(i8 addrspace(4)* %fptr) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4096 + %val = load volatile i8, i8 addrspace(4)* %fptr.offset + ret void +} + +; CHECK-LABEL: {{^}}load_flat_i8_neg_offset: +; CHECK: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}} +define amdgpu_kernel void @load_flat_i8_neg_offset(i8 addrspace(4)* %fptr) #0 { + %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 -2 + %val = load volatile i8, i8 addrspace(4)* %fptr.offset + ret void +} + attributes #0 = { nounwind } attributes #1 = { nounwind convergent } -attributes #3 = { nounwind readnone } diff --git a/test/CodeGen/AMDGPU/flat_atomics.ll b/test/CodeGen/AMDGPU/flat_atomics.ll index cc95d80..8e15318 100644 --- a/test/CodeGen/AMDGPU/flat_atomics.ll +++ b/test/CodeGen/AMDGPU/flat_atomics.ll @@ -1,8 +1,10 @@ -; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s -; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s +; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,CIVI %s +; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,CIVI %s +; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,GFX9 %s ; GCN-LABEL: {{^}}atomic_add_i32_offset: -; GCN: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +; GFX9: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_add_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -10,8 +12,28 @@ entry: ret void } +; GCN-LABEL: {{^}}atomic_add_i32_max_offset: +; CIVI: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +; GFX9: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:4092{{$}} +define amdgpu_kernel void @atomic_add_i32_max_offset(i32 addrspace(4)* %out, i32 %in) { +entry: + %gep = getelementptr i32, i32 addrspace(4)* %out, i32 1023 + %val = atomicrmw volatile add i32 addrspace(4)* %gep, i32 %in seq_cst + ret void +} + +; GCN-LABEL: {{^}}atomic_add_i32_max_offset_p1: +; GCN: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +define amdgpu_kernel void @atomic_add_i32_max_offset_p1(i32 addrspace(4)* %out, i32 %in) { +entry: + %gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024 + %val = atomicrmw volatile add i32 addrspace(4)* %gep, i32 %in seq_cst + ret void +} + ; GCN-LABEL: {{^}}atomic_add_i32_ret_offset: -; GCN: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_add_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -22,7 +44,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_add_i32_addr64_offset: -; GCN: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_add_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -32,7 +55,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_add_i32_ret_addr64_offset: -; GCN: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_add_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -82,7 +106,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_and_i32_offset: -; GCN: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_and_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -91,7 +116,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_and_i32_ret_offset: -; GCN: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_and_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -102,7 +128,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_and_i32_addr64_offset: -; GCN: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_and_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -112,7 +139,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_and_i32_ret_addr64_offset: -; GCN: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_and_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -162,7 +190,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_sub_i32_offset: -; GCN: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_sub_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -171,7 +200,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_sub_i32_ret_offset: -; GCN: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_sub_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -182,7 +212,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_sub_i32_addr64_offset: -; GCN: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_sub_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -192,7 +223,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_sub_i32_ret_addr64_offset: -; GCN: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_sub_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -242,7 +274,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_max_i32_offset: -; GCN: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_max_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -251,7 +284,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_max_i32_ret_offset: -; GCN: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_max_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -262,7 +296,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_max_i32_addr64_offset: -; GCN: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_max_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -272,7 +307,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_max_i32_ret_addr64_offset: -; GCN: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -322,7 +358,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umax_i32_offset: -; GCN: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_umax_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -331,7 +368,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umax_i32_ret_offset: -; GCN: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_umax_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -342,7 +380,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umax_i32_addr64_offset: -; GCN: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_umax_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -352,7 +391,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umax_i32_ret_addr64_offset: -; GCN: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -402,7 +442,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_min_i32_offset: -; GCN: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_min_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -411,7 +452,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_min_i32_ret_offset: -; GCN: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_min_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -422,7 +464,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_min_i32_addr64_offset: -; GCN: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_min_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -432,7 +475,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_min_i32_ret_addr64_offset: -; GCN: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -482,7 +526,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umin_i32_offset: -; GCN: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_umin_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -491,7 +536,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umin_i32_ret_offset: -; GCN: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_umin_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -502,7 +548,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umin_i32_addr64_offset: -; GCN: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_umin_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -512,7 +559,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_umin_i32_ret_addr64_offset: -; GCN: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_umin_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -562,7 +610,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_or_i32_offset: -; GCN: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_or_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -571,7 +620,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_or_i32_ret_offset: -; GCN: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_or_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -582,7 +632,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_or_i32_addr64_offset: -; GCN: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_or_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -592,7 +643,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_or_i32_ret_addr64_offset: -; GCN: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_or_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -642,7 +694,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xchg_i32_offset: -; GCN: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_xchg_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -651,7 +704,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xchg_i32_ret_offset: -; GCN: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_xchg_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -662,7 +716,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xchg_i32_addr64_offset: -; GCN: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_xchg_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -672,7 +727,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xchg_i32_ret_addr64_offset: -; GCN: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_xchg_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -724,7 +780,8 @@ entry: ; CMP_SWAP ; GCN-LABEL: {{^}}atomic_cmpxchg_i32_offset: -; GCN: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}} +; CIVI: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}} +; GFX9: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16{{$}} define amdgpu_kernel void @atomic_cmpxchg_i32_offset(i32 addrspace(4)* %out, i32 %in, i32 %old) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -733,7 +790,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_cmpxchg_i32_ret_offset: -; GCN: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}} +; CIVI: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}} +; GFX9: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, v[[RET]] define amdgpu_kernel void @atomic_cmpxchg_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i32 %old) { entry: @@ -745,7 +803,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_cmpxchg_i32_addr64_offset: -; GCN: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}} +; CIVI: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}} +; GFX9: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16{{$}} define amdgpu_kernel void @atomic_cmpxchg_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index, i32 %old) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -755,7 +814,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_cmpxchg_i32_ret_addr64_offset: -; GCN: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] glc{{$}} +; CIVI: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] glc{{$}} +; GFX9: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, v[[RET]] define amdgpu_kernel void @atomic_cmpxchg_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index, i32 %old) { entry: @@ -808,7 +868,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xor_i32_offset: -; GCN: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +; CIVI: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}} +; GFX9: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_xor_i32_offset(i32 addrspace(4)* %out, i32 %in) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -817,7 +878,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xor_i32_ret_offset: -; GCN: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_xor_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) { entry: @@ -828,7 +890,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xor_i32_addr64_offset: -; GCN: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; CIVI: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}} +; GFX9: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}} define amdgpu_kernel void @atomic_xor_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index @@ -838,7 +901,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_xor_i32_ret_addr64_offset: -; GCN: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; CIVI: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}} +; GFX9: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_xor_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) { entry: @@ -888,7 +952,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_load_i32_offset: -; GCN: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}} +; CIVI: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}} +; GFX9: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_load_i32_offset(i32 addrspace(4)* %in, i32 addrspace(4)* %out) { entry: @@ -909,7 +974,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_load_i32_addr64_offset: -; GCN: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] glc{{$}} +; CIVI: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] glc{{$}} +; GFX9: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] offset:16 glc{{$}} ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]] define amdgpu_kernel void @atomic_load_i32_addr64_offset(i32 addrspace(4)* %in, i32 addrspace(4)* %out, i64 %index) { entry: @@ -932,7 +998,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_store_i32_offset: -; GCN: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}} +; CIVI: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}} +; GFX9: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} offset:16 glc{{$}} define amdgpu_kernel void @atomic_store_i32_offset(i32 %in, i32 addrspace(4)* %out) { entry: %gep = getelementptr i32, i32 addrspace(4)* %out, i32 4 @@ -949,7 +1016,8 @@ entry: } ; GCN-LABEL: {{^}}atomic_store_i32_addr64_offset: -; GCN: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}} +; CIVI: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}} +; GFX9: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} offset:16 glc{{$}} define amdgpu_kernel void @atomic_store_i32_addr64_offset(i32 %in, i32 addrspace(4)* %out, i64 %index) { entry: %ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index diff --git a/test/CodeGen/AMDGPU/global_smrd_cfg.ll b/test/CodeGen/AMDGPU/global_smrd_cfg.ll index a6a0415..be6e3fd 100644 --- a/test/CodeGen/AMDGPU/global_smrd_cfg.ll +++ b/test/CodeGen/AMDGPU/global_smrd_cfg.ll @@ -72,6 +72,39 @@ bb22: ; preds = %bb20, %bb11 br i1 %tmp31, label %bb7, label %bb11 } +; one more test to ensure that aliasing store after the load +; is considered clobbering if load parent block is the same +; as a loop header block. + +; CHECK-LABEL: %bb1 + +; Load from %arg has alias store that is after the load +; but is considered clobbering because of the loop. + +; CHECK: flat_load_dword + +define amdgpu_kernel void @cfg_selfloop(i32 addrspace(1)* nocapture readonly %arg, i32 addrspace(1)* nocapture %arg1, i32 %arg2) #0 { +bb: + br label %bb1 + +bb2: + ret void + +bb1: + %tmp13 = phi i32 [ %tmp25, %bb1 ], [ 0, %bb ] + %tmp14 = srem i32 %tmp13, %arg2 + %tmp15 = sext i32 %tmp14 to i64 + %tmp16 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i64 %tmp15 + %tmp17 = load i32, i32 addrspace(1)* %tmp16, align 4, !tbaa !0 + %tmp19 = sext i32 %tmp13 to i64 + %tmp21 = getelementptr inbounds i32, i32 addrspace(1)* %arg1, i64 %tmp19 + store i32 %tmp17, i32 addrspace(1)* %tmp21, align 4, !tbaa !0 + %tmp25 = add nuw nsw i32 %tmp13, 1 + %tmp31 = icmp eq i32 %tmp25, 100 + br i1 %tmp31, label %bb2, label %bb1 +} + + attributes #0 = { "target-cpu"="fiji" } !0 = !{!1, !1, i64 0} diff --git a/test/CodeGen/AMDGPU/inserted-wait-states.mir b/test/CodeGen/AMDGPU/inserted-wait-states.mir index ff9fcd1..c6fe6de 100644 --- a/test/CodeGen/AMDGPU/inserted-wait-states.mir +++ b/test/CodeGen/AMDGPU/inserted-wait-states.mir @@ -246,15 +246,15 @@ body: | S_BRANCH %bb.1 bb.1: - FLAT_STORE_DWORDX2 %vgpr0_vgpr1, %vgpr2_vgpr3, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX2 %vgpr0_vgpr1, %vgpr2_vgpr3, 0, 0, 0, implicit %exec, implicit %flat_scr %vgpr3 = V_MOV_B32_e32 0, implicit %exec - FLAT_STORE_DWORDX3 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX3 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4, 0, 0, 0, implicit %exec, implicit %flat_scr %vgpr3 = V_MOV_B32_e32 0, implicit %exec - FLAT_STORE_DWORDX4 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX4 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit %exec, implicit %flat_scr %vgpr3 = V_MOV_B32_e32 0, implicit %exec - FLAT_ATOMIC_CMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, implicit %exec, implicit %flat_scr + FLAT_ATOMIC_CMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr %vgpr3 = V_MOV_B32_e32 0, implicit %exec - FLAT_ATOMIC_FCMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, implicit %exec, implicit %flat_scr + FLAT_ATOMIC_FCMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr %vgpr3 = V_MOV_B32_e32 0, implicit %exec S_ENDPGM diff --git a/test/CodeGen/AMDGPU/limit-coalesce.mir b/test/CodeGen/AMDGPU/limit-coalesce.mir index 7d6d8a5..d6b3d7b 100644 --- a/test/CodeGen/AMDGPU/limit-coalesce.mir +++ b/test/CodeGen/AMDGPU/limit-coalesce.mir @@ -57,15 +57,15 @@ body: | %4.sub1 = COPY %3.sub0 undef %5.sub0 = COPY %4.sub1 %5.sub1 = COPY %4.sub0 - FLAT_STORE_DWORDX2 %vgpr0_vgpr1, killed %5, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX2 %vgpr0_vgpr1, killed %5, 0, 0, 0, implicit %exec, implicit %flat_scr %6 = IMPLICIT_DEF undef %7.sub0_sub1 = COPY %6 %7.sub2 = COPY %3.sub0 - FLAT_STORE_DWORDX3 %vgpr0_vgpr1, killed %7, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX3 %vgpr0_vgpr1, killed %7, 0, 0, 0, implicit %exec, implicit %flat_scr %8 = IMPLICIT_DEF undef %9.sub0_sub1_sub2 = COPY %8 %9.sub3 = COPY %3.sub0 - FLAT_STORE_DWORDX4 %vgpr0_vgpr1, killed %9, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX4 %vgpr0_vgpr1, killed %9, 0, 0, 0, implicit %exec, implicit %flat_scr ... diff --git a/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir b/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir index 1a0d68d..3102427 100644 --- a/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir +++ b/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir @@ -58,12 +58,12 @@ body: | bb.3: %1 = COPY killed %17 - FLAT_STORE_DWORD undef %10, %1.sub2, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORD undef %10, %1.sub2, 0, 0, 0, implicit %exec, implicit %flat_scr %14 = COPY %1.sub1 %16 = COPY killed %1.sub0 undef %15.sub0 = COPY killed %16 %15.sub1 = COPY killed %14 - FLAT_STORE_DWORDX2 undef %11, killed %15, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORDX2 undef %11, killed %15, 0, 0, 0, implicit %exec, implicit %flat_scr S_ENDPGM ... diff --git a/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir b/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir index cd0d410..ba937c9 100644 --- a/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir +++ b/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir @@ -214,26 +214,26 @@ body: | %15 = S_ADDC_U32 %7.sub1, %0.sub1, implicit-def dead %scc, implicit %scc %16 = REG_SEQUENCE %14, 1, %15, 2 %18 = COPY %16 - %17 = FLAT_LOAD_DWORD %18, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45) + %17 = FLAT_LOAD_DWORD %18, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45) %60 = V_BFE_U32 %17, 8, 8, implicit %exec %61 = V_LSHLREV_B32_e32 2, killed %60, implicit %exec %70 = V_ADD_I32_e32 %7.sub0, %61, implicit-def %vcc, implicit %exec %66 = COPY %13 %65 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec %67 = REG_SEQUENCE %70, 1, killed %65, 2 - FLAT_STORE_DWORD %67, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9) + FLAT_STORE_DWORD %67, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9) %37 = S_ADD_U32 %14, 4, implicit-def %scc %38 = S_ADDC_U32 %15, 0, implicit-def dead %scc, implicit %scc %71 = COPY killed %37 %72 = COPY killed %38 %41 = REG_SEQUENCE killed %71, 1, killed %72, 2 - %40 = FLAT_LOAD_DWORD killed %41, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep) + %40 = FLAT_LOAD_DWORD killed %41, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep) %73 = V_BFE_U32 %40, 8, 8, implicit %exec %74 = V_LSHLREV_B32_e32 2, killed %73, implicit %exec %83 = V_ADD_I32_e32 %7.sub0, %74, implicit-def %vcc, implicit %exec %78 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec %80 = REG_SEQUENCE %83, 1, killed %78, 2 - FLAT_STORE_DWORD %80, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17) + FLAT_STORE_DWORD %80, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17) %55 = S_ADD_U32 %0.sub0, 8, implicit-def %scc %56 = S_ADDC_U32 %0.sub1, 0, implicit-def dead %scc, implicit %scc %57 = REG_SEQUENCE %55, 1, killed %56, 2 @@ -377,26 +377,26 @@ body: | %15 = S_ADDC_U32 %7.sub1, %0.sub1, implicit-def dead %scc, implicit %scc %16 = REG_SEQUENCE %14, 1, %15, 2 %18 = COPY %16 - %17 = FLAT_LOAD_DWORD %18, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45) + %17 = FLAT_LOAD_DWORD %18, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45) %60 = V_BFE_U32 %17, 8, 8, implicit %exec %61 = V_LSHLREV_B32_e32 %84, killed %60, implicit %exec %70 = V_ADD_I32_e32 %7.sub0, %61, implicit-def %vcc, implicit %exec %66 = COPY %13 %65 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec %67 = REG_SEQUENCE %70, 1, killed %65, 2 - FLAT_STORE_DWORD %67, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9) + FLAT_STORE_DWORD %67, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9) %37 = S_ADD_U32 %14, 4, implicit-def %scc %38 = S_ADDC_U32 %15, 0, implicit-def dead %scc, implicit %scc %71 = COPY killed %37 %72 = COPY killed %38 %41 = REG_SEQUENCE killed %71, 1, killed %72, 2 - %40 = FLAT_LOAD_DWORD killed %41, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep) + %40 = FLAT_LOAD_DWORD killed %41, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep) %73 = V_BFE_U32 %40, 8, 8, implicit %exec %74 = V_LSHLREV_B32_e32 %84, killed %73, implicit %exec %83 = V_ADD_I32_e32 %7.sub0, %74, implicit-def %vcc, implicit %exec %78 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec %80 = REG_SEQUENCE %83, 1, killed %78, 2 - FLAT_STORE_DWORD %80, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17) + FLAT_STORE_DWORD %80, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17) %55 = S_ADD_U32 %0.sub0, 8, implicit-def %scc %56 = S_ADDC_U32 %0.sub1, 0, implicit-def dead %scc, implicit %scc %57 = REG_SEQUENCE %55, 1, killed %56, 2 diff --git a/test/CodeGen/AMDGPU/waitcnt.mir b/test/CodeGen/AMDGPU/waitcnt.mir index f754415..38662e8 100644 --- a/test/CodeGen/AMDGPU/waitcnt.mir +++ b/test/CodeGen/AMDGPU/waitcnt.mir @@ -51,21 +51,21 @@ name: flat_zero_waitcnt body: | bb.0: successors: %bb.1 - %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.global4) - %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16) + %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.global4) + %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16) %vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec S_BRANCH %bb.1 bb.1: successors: %bb.2 - %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr - %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16) + %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr + %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16) %vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec S_BRANCH %bb.2 bb.2: - %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.flat4) - %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.flat16) + %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.flat4) + %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.flat16) %vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec S_ENDPGM ... @@ -86,11 +86,11 @@ name: single_fallthrough_successor_no_end_block_wait body: | bb.0: successors: %bb.1 - %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr + %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr bb.1: %vgpr3_vgpr4 = V_LSHLREV_B64 4, %vgpr7_vgpr8, implicit %exec - FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr S_ENDPGM ... --- @@ -114,15 +114,15 @@ name: single_branch_successor_not_next_block body: | bb.0: successors: %bb.2 - %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr + %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr S_BRANCH %bb.2 bb.1: - FLAT_STORE_DWORD %vgpr8_vgpr9, %vgpr10, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORD %vgpr8_vgpr9, %vgpr10, 0, 0, 0, implicit %exec, implicit %flat_scr S_ENDPGM bb.2: %vgpr3_vgpr4 = V_LSHLREV_B64 4, %vgpr7_vgpr8, implicit %exec - FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, implicit %exec, implicit %flat_scr + FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr S_ENDPGM ... diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll index 05902c2..6663a92 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -621,28 +621,18 @@ define arm_aapcscc [3 x i32] @test_tiny_int_arrays([2 x i32] %arr) { ; CHECK: liveins: %r0, %r1 ; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 -; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0 -; CHECK: [[ARG_ARR2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32 -; CHECK: [[ARG_ARR:%[0-9]+]](s64) = COPY [[ARG_ARR2]] +; CHECK: [[ARG_ARR:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) ; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s64), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s64), 32 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s64) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: BLX @tiny_int_arrays_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1 ; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 ; CHECK: [[R2:%[0-9]+]](s32) = COPY %r2 -; CHECK: [[RES_ARR0:%[0-9]+]](s96) = IMPLICIT_DEF -; CHECK: [[RES_ARR1:%[0-9]+]](s96) = G_INSERT [[RES_ARR0]], [[R0]](s32), 0 -; CHECK: [[RES_ARR2:%[0-9]+]](s96) = G_INSERT [[RES_ARR1]], [[R1]](s32), 32 -; CHECK: [[RES_ARR3:%[0-9]+]](s96) = G_INSERT [[RES_ARR2]], [[R2]](s32), 64 -; CHECK: [[RES_ARR:%[0-9]+]](s96) = COPY [[RES_ARR3]] +; CHECK: [[RES_ARR:%[0-9]+]](s96) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32) ; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 32 -; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 64 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32) = G_UNMERGE_VALUES [[RES_ARR]](s96) ; FIXME: This doesn't seem correct with regard to the AAPCS docs (which say ; that composite types larger than 4 bytes should be passed through memory), ; but it's what DAGISel does. We should fix it in the common code for both. @@ -664,19 +654,11 @@ define arm_aapcscc void @test_multiple_int_arrays([2 x i32] %arr0, [2 x i32] %ar ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 ; CHECK: [[R2:%[0-9]+]](s32) = COPY %r2 ; CHECK: [[R3:%[0-9]+]](s32) = COPY %r3 -; CHECK: [[ARG_ARR0_0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[ARG_ARR0_1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0_0]], [[R0]](s32), 0 -; CHECK: [[ARG_ARR0_2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0_1]], [[R1]](s32), 32 -; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = COPY [[ARG_ARR0_2]] -; CHECK: [[ARG_ARR1_0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[ARG_ARR1_1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1_0]], [[R2]](s32), 0 -; CHECK: [[ARG_ARR1_2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1_1]], [[R3]](s32), 32 -; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = COPY [[ARG_ARR1_2]] +; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) +; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = G_MERGE_VALUES [[R2]](s32), [[R3]](s32) ; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR0]](s64), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR0]](s64), 32 -; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR1]](s64), 0 -; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR1]](s64), 32 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR0]](s64) +; CHECK: [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR1]](s64) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: %r2 = COPY [[R2]] @@ -707,21 +689,9 @@ define arm_aapcscc void @test_large_int_arrays([20 x i32] %arr) { ; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]] -; CHECK: [[ARG_ARR0:%[0-9]+]](s640) = IMPLICIT_DEF -; CHECK: [[ARG_ARR1:%[0-9]+]](s640) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0 -; CHECK: [[ARG_ARR2:%[0-9]+]](s640) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32 -; CHECK: [[ARG_ARR3:%[0-9]+]](s640) = G_INSERT [[ARG_ARR2]], [[R2]](s32), 64 -; CHECK: [[ARG_ARR4:%[0-9]+]](s640) = G_INSERT [[ARG_ARR3]], [[R3]](s32), 96 -; CHECK: [[ARG_ARR5:%[0-9]+]](s640) = G_INSERT [[ARG_ARR4]], [[FIRST_STACK_ELEMENT]](s32), 128 -; CHECK: [[ARG_ARR6:%[0-9]+]](s640) = G_INSERT {{%[0-9]+}}, [[LAST_STACK_ELEMENT]](s32), 608 -; CHECK: [[ARG_ARR:%[0-9]+]](s640) = COPY [[ARG_ARR6]] +; CHECK: [[ARG_ARR:%[0-9]+]](s640) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32), [[FIRST_STACK_ELEMENT]](s32), {{.*}}, [[LAST_STACK_ELEMENT]](s32) ; CHECK: ADJCALLSTACKDOWN 64, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 32 -; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 64 -; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 96 -; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 128 -; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 608 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32), [[FIRST_STACK_ELEMENT:%[0-9]+]](s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s640) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: %r2 = COPY [[R2]] @@ -761,15 +731,9 @@ define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) { ; BIG: [[ARR1:%[0-9]+]](s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32) ; CHECK: [[ARR2_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]] ; CHECK: [[ARR2:%[0-9]+]](s64) = G_LOAD [[ARR2_FI]]{{.*}}load 8 from %fixed-stack.[[ARR2_ID]] -; CHECK: [[ARR_MERGED_0:%[0-9]+]](s192) = IMPLICIT_DEF -; CHECK: [[ARR_MERGED_1:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_0]], [[ARR0]](s64), 0 -; CHECK: [[ARR_MERGED_2:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_1]], [[ARR1]](s64), 64 -; CHECK: [[ARR_MERGED_3:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_2]], [[ARR2]](s64), 128 -; CHECK: [[ARR_MERGED:%[0-9]+]](s192) = COPY [[ARR_MERGED_3]] +; CHECK: [[ARR_MERGED:%[0-9]+]](s192) = G_MERGE_VALUES [[ARR0]](s64), [[ARR1]](s64), [[ARR2]](s64) ; CHECK: ADJCALLSTACKDOWN 8, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[ARR0:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 0 -; CHECK: [[ARR1:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 64 -; CHECK: [[ARR2:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 128 +; CHECK: [[ARR0:%[0-9]+]](s64), [[ARR1:%[0-9]+]](s64), [[ARR2:%[0-9]+]](s64) = G_UNMERGE_VALUES [[ARR_MERGED]](s192) ; CHECK: [[ARR0_0:%[0-9]+]](s32), [[ARR0_1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARR0]](s64) ; LITTLE: %r0 = COPY [[ARR0_0]](s32) ; LITTLE: %r1 = COPY [[ARR0_1]](s32) @@ -787,13 +751,9 @@ define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) { ; CHECK: BLX @fp_arrays_aapcs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1 ; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 -; CHECK: [[R_MERGED_0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[R_MERGED_1:%[0-9]+]](s64) = G_INSERT [[R_MERGED_0]], [[R0]](s32), 0 -; CHECK: [[R_MERGED_2:%[0-9]+]](s64) = G_INSERT [[R_MERGED_1]], [[R1]](s32), 32 -; CHECK: [[R_MERGED:%[0-9]+]](s64) = COPY [[R_MERGED_2]] +; CHECK: [[R_MERGED:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) ; CHECK: ADJCALLSTACKUP 8, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s64), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s64), 32 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R_MERGED]](s64) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: BX_RET 14, _, implicit %r0, implicit %r1 @@ -826,33 +786,13 @@ define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3 ; CHECK: [[Z2:%[0-9]+]](s64) = G_LOAD [[Z2_FI]]{{.*}}load 8 ; CHECK: [[Z3_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]] ; CHECK: [[Z3:%[0-9]+]](s64) = G_LOAD [[Z3_FI]]{{.*}}load 8 -; CHECK: [[X_ARR_0:%[0-9]+]](s192) = IMPLICIT_DEF -; CHECK: [[X_ARR_1:%[0-9]+]](s192) = G_INSERT [[X_ARR_0]], [[X0]](s64), 0 -; CHECK: [[X_ARR_2:%[0-9]+]](s192) = G_INSERT [[X_ARR_1]], [[X1]](s64), 64 -; CHECK: [[X_ARR_3:%[0-9]+]](s192) = G_INSERT [[X_ARR_2]], [[X2]](s64), 128 -; CHECK: [[X_ARR:%[0-9]+]](s192) = COPY [[X_ARR_3]](s192) -; CHECK: [[Y_ARR_0:%[0-9]+]](s96) = IMPLICIT_DEF -; CHECK: [[Y_ARR_1:%[0-9]+]](s96) = G_INSERT [[Y_ARR_0]], [[Y0]](s32), 0 -; CHECK: [[Y_ARR_2:%[0-9]+]](s96) = G_INSERT [[Y_ARR_1]], [[Y1]](s32), 32 -; CHECK: [[Y_ARR_3:%[0-9]+]](s96) = G_INSERT [[Y_ARR_2]], [[Y2]](s32), 64 -; CHECK: [[Y_ARR:%[0-9]+]](s96) = COPY [[Y_ARR_3]](s96) -; CHECK: [[Z_ARR_0:%[0-9]+]](s256) = IMPLICIT_DEF -; CHECK: [[Z_ARR_1:%[0-9]+]](s256) = G_INSERT [[Z_ARR_0]], [[Z0]](s64), 0 -; CHECK: [[Z_ARR_2:%[0-9]+]](s256) = G_INSERT [[Z_ARR_1]], [[Z1]](s64), 64 -; CHECK: [[Z_ARR_3:%[0-9]+]](s256) = G_INSERT [[Z_ARR_2]], [[Z2]](s64), 128 -; CHECK: [[Z_ARR_4:%[0-9]+]](s256) = G_INSERT [[Z_ARR_3]], [[Z3]](s64), 192 -; CHECK: [[Z_ARR:%[0-9]+]](s256) = COPY [[Z_ARR_4]](s256) +; CHECK: [[X_ARR:%[0-9]+]](s192) = G_MERGE_VALUES [[X0]](s64), [[X1]](s64), [[X2]](s64) +; CHECK: [[Y_ARR:%[0-9]+]](s96) = G_MERGE_VALUES [[Y0]](s32), [[Y1]](s32), [[Y2]](s32) +; CHECK: [[Z_ARR:%[0-9]+]](s256) = G_MERGE_VALUES [[Z0]](s64), [[Z1]](s64), [[Z2]](s64), [[Z3]](s64) ; CHECK: ADJCALLSTACKDOWN 32, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[X0:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 0 -; CHECK: [[X1:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 64 -; CHECK: [[X2:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 128 -; CHECK: [[Y0:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 0 -; CHECK: [[Y1:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 32 -; CHECK: [[Y2:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 64 -; CHECK: [[Z0:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 0 -; CHECK: [[Z1:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 64 -; CHECK: [[Z2:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 128 -; CHECK: [[Z3:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 192 +; CHECK: [[X0:%[0-9]+]](s64), [[X1:%[0-9]+]](s64), [[X2:%[0-9]+]](s64) = G_UNMERGE_VALUES [[X_ARR]](s192) +; CHECK: [[Y0:%[0-9]+]](s32), [[Y1:%[0-9]+]](s32), [[Y2:%[0-9]+]](s32) = G_UNMERGE_VALUES [[Y_ARR]](s96) +; CHECK: [[Z0:%[0-9]+]](s64), [[Z1:%[0-9]+]](s64), [[Z2:%[0-9]+]](s64), [[Z3:%[0-9]+]](s64) = G_UNMERGE_VALUES [[Z_ARR]](s256) ; CHECK: %d0 = COPY [[X0]](s64) ; CHECK: %d1 = COPY [[X1]](s64) ; CHECK: %d2 = COPY [[X2]](s64) @@ -880,17 +820,9 @@ define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %s1 ; CHECK: [[R2:%[0-9]+]](s32) = COPY %s2 ; CHECK: [[R3:%[0-9]+]](s32) = COPY %s3 -; CHECK: [[R_MERGED_0:%[0-9]+]](s128) = IMPLICIT_DEF -; CHECK: [[R_MERGED_1:%[0-9]+]](s128) = G_INSERT [[R_MERGED_0]], [[R0]](s32), 0 -; CHECK: [[R_MERGED_2:%[0-9]+]](s128) = G_INSERT [[R_MERGED_1]], [[R1]](s32), 32 -; CHECK: [[R_MERGED_3:%[0-9]+]](s128) = G_INSERT [[R_MERGED_2]], [[R2]](s32), 64 -; CHECK: [[R_MERGED_4:%[0-9]+]](s128) = G_INSERT [[R_MERGED_3]], [[R3]](s32), 96 -; CHECK: [[R_MERGED:%[0-9]+]](s128) = COPY [[R_MERGED_4]] +; CHECK: [[R_MERGED:%[0-9]+]](s128) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32) ; CHECK: ADJCALLSTACKUP 32, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 32 -; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 64 -; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 96 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R_MERGED]](s128) ; CHECK: %s0 = COPY [[R0]] ; CHECK: %s1 = COPY [[R1]] ; CHECK: %s2 = COPY [[R2]] @@ -919,21 +851,9 @@ define arm_aapcscc [2 x i32*] @test_tough_arrays([6 x [4 x i32]] %arr) { ; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]] ; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]] -; CHECK: [[ARG_ARR0:%[0-9]+]](s768) = IMPLICIT_DEF -; CHECK: [[ARG_ARR1:%[0-9]+]](s768) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0 -; CHECK: [[ARG_ARR2:%[0-9]+]](s768) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32 -; CHECK: [[ARG_ARR3:%[0-9]+]](s768) = G_INSERT [[ARG_ARR2]], [[R2]](s32), 64 -; CHECK: [[ARG_ARR4:%[0-9]+]](s768) = G_INSERT [[ARG_ARR3]], [[R3]](s32), 96 -; CHECK: [[ARG_ARR5:%[0-9]+]](s768) = G_INSERT [[ARG_ARR4]], [[FIRST_STACK_ELEMENT]](s32), 128 -; CHECK: [[ARG_ARR6:%[0-9]+]](s768) = G_INSERT {{%[0-9]+}}, [[LAST_STACK_ELEMENT]](s32), 736 -; CHECK: [[ARG_ARR:%[0-9]+]](s768) = COPY [[ARG_ARR6]] +; CHECK: [[ARG_ARR:%[0-9]+]](s768) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32), [[FIRST_STACK_ELEMENT]](s32), {{.*}}, [[LAST_STACK_ELEMENT]](s32) ; CHECK: ADJCALLSTACKDOWN 80, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 32 -; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 64 -; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 96 -; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 128 -; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 736 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32), [[FIRST_STACK_ELEMENT:%[0-9]+]](s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s768) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: %r2 = COPY [[R2]] @@ -951,13 +871,9 @@ define arm_aapcscc [2 x i32*] @test_tough_arrays([6 x [4 x i32]] %arr) { ; CHECK: BLX @tough_arrays_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1 ; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 -; CHECK: [[RES_ARR0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[RES_ARR1:%[0-9]+]](s64) = G_INSERT [[RES_ARR0]], [[R0]](s32), 0 -; CHECK: [[RES_ARR2:%[0-9]+]](s64) = G_INSERT [[RES_ARR1]], [[R1]](s32), 32 -; CHECK: [[RES_ARR:%[0-9]+]](s64) = COPY [[RES_ARR2]] +; CHECK: [[RES_ARR:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) ; CHECK: ADJCALLSTACKUP 80, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s64), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s64), 32 +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[RES_ARR]](s64) ; CHECK: %r0 = COPY [[R0]] ; CHECK: %r1 = COPY [[R1]] ; CHECK: BX_RET 14, _, implicit %r0, implicit %r1 @@ -966,65 +882,28 @@ entry: ret [2 x i32*] %r } -declare arm_aapcscc {i32, i32} @structs_target({i32, i32}, {i32*, float, i32, double}) +declare arm_aapcscc {i32, i32} @structs_target({i32, i32}) -define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x, {i32*, float, i32, double} %y) { +define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x) { ; CHECK-LABEL: test_structs -; CHECK: fixedStack: -; CHECK-DAG: id: [[Y2_ID:[0-9]+]], type: default, offset: 0, size: 4, -; CHECK-DAG: id: [[Y3_ID:[0-9]+]], type: default, offset: 8, size: 8, -; CHECK: liveins: %r0, %r1, %r2, %r3 +; CHECK: liveins: %r0, %r1 ; CHECK-DAG: [[X0:%[0-9]+]](s32) = COPY %r0 ; CHECK-DAG: [[X1:%[0-9]+]](s32) = COPY %r1 -; CHECK-DAG: [[Y0:%[0-9]+]](s32) = COPY %r2 -; CHECK-DAG: [[Y1:%[0-9]+]](s32) = COPY %r3 -; CHECK: [[Y2_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Y2_ID]] -; CHECK: [[Y2:%[0-9]+]](s32) = G_LOAD [[Y2_ADDR]](p0){{.*}}load 4 -; CHECK: [[Y3_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Y3_ID]] -; CHECK: [[Y3:%[0-9]+]](s64) = G_LOAD [[Y3_ADDR]](p0){{.*}}load 8 -; CHECK: [[X_0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[X_1:%[0-9]+]](s64) = G_INSERT [[X_0]], [[X0]](s32), 0 -; CHECK: [[X_2:%[0-9]+]](s64) = G_INSERT [[X_1]], [[X1]](s32), 32 -; CHECK: [[X:%[0-9]+]](s64) = COPY [[X_2]] -; CHECK: [[Y_0:%[0-9]+]](s192) = IMPLICIT_DEF -; CHECK: [[Y_1:%[0-9]+]](s192) = G_INSERT [[Y_0]], [[Y0]](s32), 0 -; CHECK: [[Y_2:%[0-9]+]](s192) = G_INSERT [[Y_1]], [[Y1]](s32), 32 -; CHECK: [[Y_3:%[0-9]+]](s192) = G_INSERT [[Y_2]], [[Y2]](s32), 64 -; CHECK: [[Y_4:%[0-9]+]](s192) = G_INSERT [[Y_3]], [[Y3]](s64), 128 -; CHECK: [[Y:%[0-9]+]](s192) = COPY [[Y_4]] -; CHECK: ADJCALLSTACKDOWN 16, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[X0:%[0-9]+]](s32) = G_EXTRACT [[X]](s64), 0 -; CHECK: [[X1:%[0-9]+]](s32) = G_EXTRACT [[X]](s64), 32 -; CHECK: [[Y0:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 0 -; CHECK: [[Y1:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 32 -; CHECK: [[Y2:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 64 -; CHECK: [[Y3:%[0-9]+]](s64) = G_EXTRACT [[Y]](s192), 128 +; CHECK: [[X:%[0-9]+]](s64) = G_MERGE_VALUES [[X0]](s32), [[X1]](s32) +; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp +; CHECK: [[X0:%[0-9]+]](s32), [[X1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[X]](s64) ; CHECK-DAG: %r0 = COPY [[X0]](s32) ; CHECK-DAG: %r1 = COPY [[X1]](s32) -; CHECK-DAG: %r2 = COPY [[Y0]](s32) -; CHECK-DAG: %r3 = COPY [[Y1]](s32) -; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp -; CHECK: [[Y2_OFF:%[0-9]+]](s32) = G_CONSTANT i32 0 -; CHECK: [[Y2_ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[Y2_OFF]](s32) -; CHECK: G_STORE [[Y2]](s32), [[Y2_ADDR]](p0){{.*}}store 4 -; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp -; CHECK: [[Y3_OFF:%[0-9]+]](s32) = G_CONSTANT i32 8 -; CHECK: [[Y3_ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[Y3_OFF]](s32) -; CHECK: G_STORE [[Y3]](s64), [[Y3_ADDR]](p0){{.*}}store 8 -; CHECK: BLX @structs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1 +; CHECK: BLX @structs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1 ; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0 ; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1 -; CHECK: [[R_0:%[0-9]+]](s64) = IMPLICIT_DEF -; CHECK: [[R_1:%[0-9]+]](s64) = G_INSERT [[R_0]], [[R0]](s32), 0 -; CHECK: [[R_2:%[0-9]+]](s64) = G_INSERT [[R_1]], [[R1]](s32), 32 -; CHECK: [[R:%[0-9]+]](s64) = COPY [[R_2]] -; CHECK: ADJCALLSTACKUP 16, 0, 14, _, implicit-def %sp, implicit %sp -; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R]](s64), 0 -; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R]](s64), 32 +; CHECK: [[R:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32) +; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp +; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R]](s64) ; CHECK: %r0 = COPY [[R0]](s32) ; CHECK: %r1 = COPY [[R1]](s32) ; CHECK: BX_RET 14, _, implicit %r0, implicit %r1 - %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x, {i32*, float, i32, double} %y) + %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x) ret {i32, i32} %r } diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll index 2881740..c778caa 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll @@ -66,3 +66,24 @@ define arm_aapcscc i8 @test_udiv_i8(i8 %a, i8 %b) { ret i8 %r } +define arm_aapcscc i32 @test_srem_i32(i32 %x, i32 %y) { +; CHECK-LABEL: test_srem_i32: +; HWDIV: sdiv [[Q:r[0-9]+]], r0, r1 +; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1 +; HWDIV: sub r0, r0, [[P]] +; SOFT-AEABI: blx __aeabi_idivmod +; SOFT-DEFAULT: blx __modsi3 + %r = srem i32 %x, %y + ret i32 %r +} + +define arm_aapcscc i32 @test_urem_i32(i32 %x, i32 %y) { +; CHECK-LABEL: test_urem_i32: +; HWDIV: udiv [[Q:r[0-9]+]], r0, r1 +; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1 +; HWDIV: sub r0, r0, [[P]] +; SOFT-AEABI: blx __aeabi_uidivmod +; SOFT-DEFAULT: blx __umodsi3 + %r = urem i32 %x, %y + ret i32 %r +} diff --git a/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir index 6f3e09d..c93e7fa 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir @@ -11,6 +11,9 @@ define void @test_sdiv_i8() { ret void } define void @test_udiv_i8() { ret void } + + define void @test_srem_i32() { ret void } + define void @test_urem_i32() { ret void } ... --- name: test_sdiv_i32 @@ -228,3 +231,75 @@ body: | %r0 = COPY %2(s8) BX_RET 14, _, implicit %r0 ... +--- +name: test_srem_i32 +# CHECK-LABEL: name: test_srem_i32 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: %r0, %r1 + + ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0 + ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1 + %0(s32) = COPY %r0 + %1(s32) = COPY %r1 + ; HWDIV: [[Q:%[0-9]+]](s32) = G_SDIV [[X]], [[Y]] + ; HWDIV: [[P:%[0-9]+]](s32) = G_MUL [[Q]], [[Y]] + ; HWDIV: [[R:%[0-9]+]](s32) = G_SUB [[X]], [[P]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X]] + ; SOFT-DAG: %r1 = COPY [[Y]] + ; SOFT-AEABI: BLX $__aeabi_idivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1 + ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r1 + ; SOFT-DEFAULT: BLX $__modsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + %2(s32) = G_SREM %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s32) + BX_RET 14, _, implicit %r0 +... +--- +name: test_urem_i32 +# CHECK-LABEL: name: test_urem_i32 +legalized: false +# CHECK: legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0: + liveins: %r0, %r1 + + ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0 + ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1 + %0(s32) = COPY %r0 + %1(s32) = COPY %r1 + ; HWDIV: [[Q:%[0-9]+]](s32) = G_UDIV [[X]], [[Y]] + ; HWDIV: [[P:%[0-9]+]](s32) = G_MUL [[Q]], [[Y]] + ; HWDIV: [[R:%[0-9]+]](s32) = G_SUB [[X]], [[P]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X]] + ; SOFT-DAG: %r1 = COPY [[Y]] + ; SOFT-AEABI: BLX $__aeabi_uidivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1 + ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r1 + ; SOFT-DEFAULT: BLX $__umodsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + %2(s32) = G_UREM %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s32) + BX_RET 14, _, implicit %r0 +... diff --git a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll index 34f00ae..f2f9c5d 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -65,6 +65,14 @@ define %large.struct @test_large_struct_return() { ret %large.struct %r } +%mixed.struct = type {i32*, float, i32} + +define %mixed.struct @test_mixed_struct(%mixed.struct %x) { +; CHECK: remark: {{.*}} unable to lower arguments: %mixed.struct (%mixed.struct)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_mixed_struct + ret %mixed.struct %x +} + define void @test_vararg_definition(i32 %a, ...) { ; CHECK: remark: {{.*}} unable to lower arguments: void (i32, ...)* ; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_definition diff --git a/test/CodeGen/ARM/cortex-a57-misched-vfma.ll b/test/CodeGen/ARM/cortex-a57-misched-vfma.ll index 5f91432..e234e17 100644 --- a/test/CodeGen/ARM/cortex-a57-misched-vfma.ll +++ b/test/CodeGen/ARM/cortex-a57-misched-vfma.ll @@ -156,3 +156,41 @@ define <2 x float> @Test4(<2 x float> %f1, <2 x float> %f2, <2 x float> %f3, <2 %sub2 = fsub <2 x float> %sub1, %mul3 ret <2 x float> %sub2 } + +define float @Test5(float %f1, float %f2, float %f3) { +; CHECK: ********** MI Scheduling ********** +; CHECK: Test5:BB#0 + +; CHECK-DEFAULT: VNMLS +; CHECK-FAST: VFNMS +; CHECK: Latency : 9 +; CHECK: Successors: +; CHECK: data +; > VMLAS not-optimized latency to VMOVRS = 9 +; CHECK-SAME: Latency=9 + +; f1 * f2 - f3 ==> VNMLS/VFNMS + %mul = fmul float %f1, %f2 + %sub = fsub float %mul, %f3 + ret float %sub +} + + +define float @Test6(float %f1, float %f2, float %f3) { +; CHECK: ********** MI Scheduling ********** +; CHECK: Test6:BB#0 + +; CHECK-DEFAULT: VNMLA +; CHECK-FAST: VFNMA +; CHECK: Latency : 9 +; CHECK: Successors: +; CHECK: data +; > VMLAS not-optimized latency to VMOVRS = 9 +; CHECK-SAME: Latency=9 + +; f1 * f2 - f3 ==> VNMLA/VFNMA + %mul = fmul float %f1, %f2 + %sub1 = fsub float -0.0, %mul + %sub2 = fsub float %sub1, %f2 + ret float %sub2 +} diff --git a/test/CodeGen/ARM/debug-info-blocks.ll b/test/CodeGen/ARM/debug-info-blocks.ll index 1e9d890..6019a94 100644 --- a/test/CodeGen/ARM/debug-info-blocks.ll +++ b/test/CodeGen/ARM/debug-info-blocks.ll @@ -273,6 +273,6 @@ define hidden void @foobar_func_block_invoke_0(i8* %.block_descriptor, %0* %load !160 = !DIFile(filename: "header.h", directory: "/Volumes/Sandbox/llvm") !161 = !{!"header2.h", !"/Volumes/Sandbox/llvm"} !162 = !{i32 1, !"Debug Info Version", i32 3} -!163 = !DIExpression(DW_OP_plus, 20, DW_OP_deref, DW_OP_plus, 4, DW_OP_deref, DW_OP_plus, 24) -!164 = !DIExpression(DW_OP_deref, DW_OP_plus, 24) -!165 = !DIExpression(DW_OP_deref, DW_OP_plus, 28) +!163 = !DIExpression(DW_OP_plus_uconst, 20, DW_OP_deref, DW_OP_plus_uconst, 4, DW_OP_deref, DW_OP_plus_uconst, 24) +!164 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24) +!165 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 28) diff --git a/test/CodeGen/ARM/sincos.ll b/test/CodeGen/ARM/sincos.ll index 5be0044..42a834d 100644 --- a/test/CodeGen/ARM/sincos.ll +++ b/test/CodeGen/ARM/sincos.ll @@ -1,10 +1,12 @@ ; RUN: llc < %s -mtriple=armv7-apple-ios6 -mcpu=cortex-a8 | FileCheck %s --check-prefix=NOOPT ; RUN: llc < %s -mtriple=armv7-apple-ios7 -mcpu=cortex-a8 | FileCheck %s --check-prefix=SINCOS -; RUN: llc < %s -mtriple=armv7-linux-gnu -mcpu=cortex-a8 | FileCheck %s --check-prefix=NOOPT-GNU +; RUN: llc < %s -mtriple=armv7-linux-gnu -mcpu=cortex-a8 | FileCheck %s --check-prefix=SINCOS-GNU ; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a8 \ ; RUN: --enable-unsafe-fp-math | FileCheck %s --check-prefix=SINCOS-GNU -; Combine sin / cos into a single call. +; Combine sin / cos into a single call unless they may write errno (as +; captured by readnone attrbiute, controlled by clang -fmath-errno +; setting). ; rdar://12856873 define float @test1(float %x) nounwind { @@ -19,12 +21,28 @@ entry: ; NOOPT: bl _sinf ; NOOPT: bl _cosf -; NOOPT-GNU-LABEL: test1: -; NOOPT-GNU: bl sinf -; NOOPT-GNU: bl cosf + %call = tail call float @sinf(float %x) readnone + %call1 = tail call float @cosf(float %x) readnone + %add = fadd float %call, %call1 + ret float %add +} + +define float @test1_errno(float %x) nounwind { +entry: +; SINCOS-LABEL: test1_errno: +; SINCOS: bl _sinf +; SINCOS: bl _cosf - %call = tail call float @sinf(float %x) nounwind readnone - %call1 = tail call float @cosf(float %x) nounwind readnone +; SINCOS-GNU-LABEL: test1_errno: +; SINCOS-GNU: bl sinf +; SINCOS-GNU: bl cosf + +; NOOPT-LABEL: test1_errno: +; NOOPT: bl _sinf +; NOOPT: bl _cosf + + %call = tail call float @sinf(float %x) + %call1 = tail call float @cosf(float %x) %add = fadd float %call, %call1 ret float %add } @@ -41,16 +59,33 @@ entry: ; NOOPT: bl _sin ; NOOPT: bl _cos -; NOOPT-GNU-LABEL: test2: -; NOOPT-GNU: bl sin -; NOOPT-GNU: bl cos - %call = tail call double @sin(double %x) nounwind readnone - %call1 = tail call double @cos(double %x) nounwind readnone + %call = tail call double @sin(double %x) readnone + %call1 = tail call double @cos(double %x) readnone + %add = fadd double %call, %call1 + ret double %add +} + +define double @test2_errno(double %x) nounwind { +entry: +; SINCOS-LABEL: test2_errno: +; SINCOS: bl _sin +; SINCOS: bl _cos + +; SINCOS-GNU-LABEL: test2_errno: +; SINCOS-GNU: bl sin +; SINCOS-GNU: bl cos + +; NOOPT-LABEL: test2_errno: +; NOOPT: bl _sin +; NOOPT: bl _cos + + %call = tail call double @sin(double %x) + %call1 = tail call double @cos(double %x) %add = fadd double %call, %call1 ret double %add } -declare float @sinf(float) readonly -declare double @sin(double) readonly -declare float @cosf(float) readonly -declare double @cos(double) readonly +declare float @sinf(float) +declare double @sin(double) +declare float @cosf(float) +declare double @cos(double) diff --git a/test/CodeGen/ARM/swifterror.ll b/test/CodeGen/ARM/swifterror.ll index 7876420..3fd57c5 100644 --- a/test/CodeGen/ARM/swifterror.ll +++ b/test/CodeGen/ARM/swifterror.ll @@ -528,3 +528,31 @@ entry: tail call void @acallee(i8* null) ret void } + + +declare swiftcc void @foo2(%swift_error** swifterror) + +; Make sure we properly assign registers during fast-isel. +; CHECK-O0-LABEL: testAssign +; CHECK-O0: mov r8, #0 +; CHECK-O0: bl _foo2 +; CHECK-O0: str r8, [s[[STK:p.*]]] +; CHECK-O0: ldr r0, [s[[STK]]] +; CHECK-O0: pop + +; CHECK-APPLE-LABEL: testAssign +; CHECK-APPLE: mov r8, #0 +; CHECK-APPLE: bl _foo2 +; CHECK-APPLE: mov r0, r8 + +define swiftcc %swift_error* @testAssign(i8* %error_ref) { +entry: + %error_ptr = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr + call swiftcc void @foo2(%swift_error** swifterror %error_ptr) + br label %a + +a: + %error = load %swift_error*, %swift_error** %error_ptr + ret %swift_error* %error +} diff --git a/test/CodeGen/BPF/rodata_1.ll b/test/CodeGen/BPF/rodata_1.ll new file mode 100644 index 0000000..5566f76 --- /dev/null +++ b/test/CodeGen/BPF/rodata_1.ll @@ -0,0 +1,52 @@ +; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s + +; Source code: +; struct test_t1 { +; char a, b, c; +; }; +; struct test_t2 { +; int a, b, c, d, e; +; }; +; +; struct test_t1 g1; +; struct test_t2 g2; +; int test() +; { +; struct test_t1 t1 = {.c = 1}; +; struct test_t2 t2 = {.c = 1}; +; g1 = t1; +; g2 = t2; +; return 0; +; } + +%struct.test_t1 = type { i8, i8, i8 } +%struct.test_t2 = type { i32, i32, i32, i32, i32 } + +@test.t1 = private unnamed_addr constant %struct.test_t1 { i8 0, i8 0, i8 1 }, align 1 +@test.t2 = private unnamed_addr constant %struct.test_t2 { i32 0, i32 0, i32 1, i32 0, i32 0 }, align 4 +@g1 = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 1 +@g2 = common local_unnamed_addr global %struct.test_t2 zeroinitializer, align 4 + +; Function Attrs: nounwind +define i32 @test() local_unnamed_addr #0 { +; CHECK-LABEL: test: + +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @g1, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @test.t1, i64 0, i32 0), i64 3, i32 1, i1 false) + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.test_t2* @g2 to i8*), i8* bitcast (%struct.test_t2* @test.t2 to i8*), i64 20, i32 4, i1 false) +; CHECK: r1 = ll +; CHECK: r2 = 0 +; CHECK: *(u8 *)(r1 + 1) = r2 +; CHECK: r3 = 1 +; CHECK: *(u8 *)(r1 + 2) = r3 +; CHECK: r1 = ll +; CHECK: *(u32 *)(r1 + 8) = r3 + ret i32 0 +} +; CHECK: .section .rodata,"a",@progbits + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1 + +attributes #0 = { nounwind } +attributes #1 = { argmemonly nounwind } diff --git a/test/CodeGen/BPF/rodata_2.ll b/test/CodeGen/BPF/rodata_2.ll new file mode 100644 index 0000000..74b3c36 --- /dev/null +++ b/test/CodeGen/BPF/rodata_2.ll @@ -0,0 +1,51 @@ +; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s + +; Source code: +; struct test_t1 { +; char a; +; int b; +; }; +; struct test_t2 { +; char a, b; +; struct test_t1 c[2]; +; int d[2]; +; int e; +; }; +; struct test_t2 g; +; int test() +; { +; struct test_t2 t2 = {.c = {{}, {.b = 1}}, .d = {2, 3}}; +; g = t2; +; return 0; +; } + +%struct.test_t2 = type { i8, i8, [2 x %struct.test_t1], [2 x i32], i32 } +%struct.test_t1 = type { i8, i32 } + +@test.t2 = private unnamed_addr constant %struct.test_t2 { i8 0, i8 0, [2 x %struct.test_t1] [%struct.test_t1 zeroinitializer, %struct.test_t1 { i8 0, i32 1 }], [2 x i32] [i32 2, i32 3], i32 0 }, align 4 +@g = common local_unnamed_addr global %struct.test_t2 zeroinitializer, align 4 + +; Function Attrs: nounwind +define i32 @test() local_unnamed_addr #0 { +; CHECK-LABEL: test: + +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t2, %struct.test_t2* @g, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t2, %struct.test_t2* @test.t2, i64 0, i32 0), i64 32, i32 4, i1 false) +; CHECK: r1 = ll +; CHECK: r2 = 0 +; CHECK: *(u32 *)(r1 + 28) = r2 +; CHECK: r3 = 3 +; CHECK: *(u32 *)(r1 + 24) = r3 +; CHECK: r3 = 2 +; CHECK: *(u32 *)(r1 + 20) = r3 +; CHECK: r3 = 1 +; CHECK: *(u32 *)(r1 + 16) = r3 + ret i32 0 +} +; CHECK: .section .rodata.cst32,"aM",@progbits,32 + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1 + +attributes #0 = { nounwind } +attributes #1 = { argmemonly nounwind } diff --git a/test/CodeGen/BPF/rodata_3.ll b/test/CodeGen/BPF/rodata_3.ll new file mode 100644 index 0000000..814ce76 --- /dev/null +++ b/test/CodeGen/BPF/rodata_3.ll @@ -0,0 +1,41 @@ +; REQUIRES: x86_64-linux +; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck --check-prefix=CHECK-EL %s +; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck --check-prefix=CHECK-EB %s +; +; This test requires little-endian host, so we specific x86_64-linux here. +; Source code: +; struct test_t1 { +; char a; +; int b, c, d; +; }; +; +; struct test_t1 g; +; int test() +; { +; struct test_t1 t1 = {.a = 1}; +; g = t1; +; return 0; +; } + +%struct.test_t1 = type { i8, i32, i32, i32 } + +@test.t1 = private unnamed_addr constant %struct.test_t1 { i8 1, i32 0, i32 0, i32 0 }, align 4 +@g = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 4 + +; Function Attrs: nounwind +define i32 @test() local_unnamed_addr #0 { +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @g, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @test.t1, i64 0, i32 0), i64 16, i32 4, i1 false) +; CHECK-EL: r2 = 1 +; CHECK-EL: *(u32 *)(r1 + 0) = r2 +; CHECK-EB: r2 = 16777216 +; CHECK-EB: *(u32 *)(r1 + 0) = r2 + ret i32 0 +} +; CHECK-EL: .section .rodata.cst16,"aM",@progbits,16 +; CHECK-EB: .section .rodata.cst16,"aM",@progbits,16 + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1 + +attributes #0 = { nounwind } +attributes #1 = { argmemonly nounwind } diff --git a/test/CodeGen/BPF/rodata_4.ll b/test/CodeGen/BPF/rodata_4.ll new file mode 100644 index 0000000..d6b9fba --- /dev/null +++ b/test/CodeGen/BPF/rodata_4.ll @@ -0,0 +1,43 @@ +; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s + +; Source code: +; struct test_t1 +; { +; short a; +; short b; +; char c; +; }; +; +; struct test_t1 g; +; int test() +; { +; struct test_t1 t1[] = {{50, 500, 5}, {60, 600, 6}, {70, 700, 7}, {80, 800, 8} }; +; +; g = t1[1]; +; return 0; +; } + +%struct.test_t1 = type { i16, i16, i8 } + +@test.t1 = private unnamed_addr constant [4 x %struct.test_t1] [%struct.test_t1 { i16 50, i16 500, i8 5 }, %struct.test_t1 { i16 60, i16 600, i8 6 }, %struct.test_t1 { i16 70, i16 700, i8 7 }, %struct.test_t1 { i16 80, i16 800, i8 8 }], align 2 +@g = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 2 + +; Function Attrs: nounwind +define i32 @test() local_unnamed_addr #0 { +; CHECK-LABEL: test: +entry: + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.test_t1* @g to i8*), i8* bitcast (%struct.test_t1* getelementptr inbounds ([4 x %struct.test_t1], [4 x %struct.test_t1]* @test.t1, i64 0, i64 1) to i8*), i64 6, i32 2, i1 false) +; CHECK: r2 = 600 +; CHECK: *(u16 *)(r1 + 2) = r2 +; CHECK: r2 = 60 +; CHECK: *(u16 *)(r1 + 0) = r2 + ret i32 0 +} +; CHECK .section .rodata,"a",@progbits + +; Function Attrs: argmemonly nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1 + +attributes #0 = { nounwind } +attributes #1 = { argmemonly nounwind } diff --git a/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll b/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll new file mode 100644 index 0000000..0abf8f8 --- /dev/null +++ b/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll @@ -0,0 +1,48 @@ +; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s +; REQUIRES: asserts +; +; Check for sane output, this used to crash. +; CHECK: define void @fred + +; The conversion of shifts from right to left failed, but the return +; code was not checked and the transformation proceeded. + +target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" +target triple = "hexagon" + +@A = common global [256 x i32] zeroinitializer, align 8 + +; Function Attrs: noinline nounwind +define void @fred() local_unnamed_addr #0 { +b0: + br label %b1 + +b1: ; preds = %b13, %b0 + %v2 = phi i32 [ 0, %b0 ], [ %v16, %b13 ] + br label %b3 + +b3: ; preds = %b3, %b1 + %v4 = phi i32 [ %v2, %b1 ], [ %v10, %b3 ] + %v5 = phi i32 [ 0, %b1 ], [ %v11, %b3 ] + %v6 = and i32 %v4, 1 + %v7 = icmp ne i32 %v6, 0 + %v8 = lshr i32 %v4, 1 + %v9 = xor i32 %v8, 123456789 + %v10 = select i1 %v7, i32 %v9, i32 %v8 + %v11 = add nuw nsw i32 %v5, 1 + %v12 = icmp ne i32 %v11, 8 + br i1 %v12, label %b3, label %b13 + +b13: ; preds = %b3 + %v14 = phi i32 [ %v10, %b3 ] + %v15 = getelementptr inbounds [256 x i32], [256 x i32]* @A, i32 0, i32 %v2 + store i32 %v14, i32* %v15, align 4 + %v16 = add nuw nsw i32 %v2, 1 + %v17 = icmp ne i32 %v16, 256 + br i1 %v17, label %b1, label %b18 + +b18: ; preds = %b13 + ret void +} + +attributes #0 = { noinline nounwind "target-cpu"="hexagonv60" } diff --git a/test/CodeGen/Hexagon/mulh.ll b/test/CodeGen/Hexagon/mulh.ll new file mode 100644 index 0000000..0442e28 --- /dev/null +++ b/test/CodeGen/Hexagon/mulh.ll @@ -0,0 +1,27 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s + +target triple = "hexagon" + +; CHECK-LABEL: danny: +; CHECK: r{{[0-9]+}} = mpy(r0,r1) +define i32 @danny(i32 %a0, i32 %a1) { +b2: + %v3 = sext i32 %a0 to i64 + %v4 = sext i32 %a1 to i64 + %v5 = mul nsw i64 %v3, %v4 + %v6 = ashr i64 %v5, 32 + %v7 = trunc i64 %v6 to i32 + ret i32 %v7 +} + +; CHECK-LABEL: sammy: +; CHECK: r{{[0-9]+}} = mpy(r0,r1) +define i32 @sammy(i32 %a0, i32 %a1) { +b2: + %v3 = sext i32 %a0 to i64 + %v4 = sext i32 %a1 to i64 + %v5 = mul nsw i64 %v3, %v4 + %v6 = lshr i64 %v5, 32 + %v7 = trunc i64 %v6 to i32 + ret i32 %v7 +} diff --git a/test/CodeGen/Hexagon/mux-kill.mir b/test/CodeGen/Hexagon/mux-kill.mir new file mode 100644 index 0000000..6944050 --- /dev/null +++ b/test/CodeGen/Hexagon/mux-kill.mir @@ -0,0 +1,15 @@ +# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - %s -verify-machineinstrs | FileCheck %s +# CHECK: %r2 = C2_mux %p0, %r0, %r1 +--- +name: fred +tracksRegLiveness: true + +body: | + bb.0: + liveins: %d0, %p0 + + %r2 = A2_tfrt %p0, %r0 + %r0 = A2_tfr %r1 + %r2 = A2_tfrf %p0, killed %r1 +... + diff --git a/test/CodeGen/Hexagon/mux-kill2.mir b/test/CodeGen/Hexagon/mux-kill2.mir new file mode 100644 index 0000000..5f34097 --- /dev/null +++ b/test/CodeGen/Hexagon/mux-kill2.mir @@ -0,0 +1,17 @@ +# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - -verify-machineinstrs %s | FileCheck %s +# CHECK: %r1 = C2_muxri %p0, 123, %r0 +# CHECK: %r2 = C2_muxir %p0, killed %r0, 321 +--- +name: fred +tracksRegLiveness: true + +body: | + bb.0: + liveins: %r0, %p0 + + %r2 = A2_tfrt %p0, %r0 + %r1 = C2_cmoveit %p0, 123 + %r1 = A2_tfrf %p0, killed %r0, implicit killed %r1 + %r2 = C2_cmoveif killed %p0, 321, implicit killed %r2 +... + diff --git a/test/CodeGen/Hexagon/store-imm-stack-object.ll b/test/CodeGen/Hexagon/store-imm-stack-object.ll new file mode 100644 index 0000000..8de3109 --- /dev/null +++ b/test/CodeGen/Hexagon/store-imm-stack-object.ll @@ -0,0 +1,86 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s + +target triple = "hexagon" + +; CHECK-LABEL: test1: +; CHECK: [[REG1:(r[0-9]+)]] = ##875770417 +; CHECK-DAG: memw(r29+#4) = [[REG1]] +; CHECK-DAG: memw(r29+#8) = #51 +; CHECK-DAG: memh(r29+#12) = #50 +; CHECK-DAG: memb(r29+#15) = #49 +define void @test1() { +b0: + %v1 = alloca [1 x i8], align 1 + %v2 = alloca i16, align 2 + %v3 = alloca i32, align 4 + %v4 = alloca i32, align 4 + %v5 = getelementptr inbounds [1 x i8], [1 x i8]* %v1, i32 0, i32 0 + call void @llvm.lifetime.start(i64 1, i8* %v5) + store i8 49, i8* %v5, align 1 + %v6 = bitcast i16* %v2 to i8* + call void @llvm.lifetime.start(i64 2, i8* %v6) + store i16 50, i16* %v2, align 2 + %v7 = bitcast i32* %v3 to i8* + call void @llvm.lifetime.start(i64 4, i8* %v7) + store i32 51, i32* %v3, align 4 + %v8 = bitcast i32* %v4 to i8* + call void @llvm.lifetime.start(i64 4, i8* %v8) + store i32 875770417, i32* %v4, align 4 + call void @test4(i8* %v5, i8* %v6, i8* %v7, i8* %v8) + call void @llvm.lifetime.end(i64 4, i8* %v8) + call void @llvm.lifetime.end(i64 4, i8* %v7) + call void @llvm.lifetime.end(i64 2, i8* %v6) + call void @llvm.lifetime.end(i64 1, i8* %v5) + ret void +} + +; CHECK-LABEL: test2: +; CHECK-DAG: memw(r29+#208) = #51 +; CHECK-DAG: memh(r29+#212) = r{{[0-9]+}} +; CHECK-DAG: memb(r29+#215) = r{{[0-9]+}} +define void @test2() { +b0: + %v1 = alloca [1 x i8], align 1 + %v2 = alloca i16, align 2 + %v3 = alloca i32, align 4 + %v4 = alloca i32, align 4 + %v5 = alloca [100 x i8], align 8 + %v6 = alloca [101 x i8], align 8 + %v7 = getelementptr inbounds [1 x i8], [1 x i8]* %v1, i32 0, i32 0 + call void @llvm.lifetime.start(i64 1, i8* %v7) + store i8 49, i8* %v7, align 1 + %v8 = bitcast i16* %v2 to i8* + call void @llvm.lifetime.start(i64 2, i8* %v8) + store i16 50, i16* %v2, align 2 + %v9 = bitcast i32* %v3 to i8* + call void @llvm.lifetime.start(i64 4, i8* %v9) + store i32 51, i32* %v3, align 4 + %v10 = bitcast i32* %v4 to i8* + call void @llvm.lifetime.start(i64 4, i8* %v10) + store i32 875770417, i32* %v4, align 4 + %v11 = getelementptr inbounds [100 x i8], [100 x i8]* %v5, i32 0, i32 0 + call void @llvm.lifetime.start(i64 100, i8* %v11) + call void @llvm.memset.p0i8.i32(i8* %v11, i8 0, i32 100, i32 8, i1 false) + store i8 50, i8* %v11, align 8 + %v12 = getelementptr inbounds [101 x i8], [101 x i8]* %v6, i32 0, i32 0 + call void @llvm.lifetime.start(i64 101, i8* %v12) + call void @llvm.memset.p0i8.i32(i8* %v12, i8 0, i32 101, i32 8, i1 false) + store i8 49, i8* %v12, align 8 + call void @test3(i8* %v7, i8* %v8, i8* %v9, i8* %v10, i8* %v11, i8* %v12) + call void @llvm.lifetime.end(i64 101, i8* %v12) + call void @llvm.lifetime.end(i64 100, i8* %v11) + call void @llvm.lifetime.end(i64 4, i8* %v10) + call void @llvm.lifetime.end(i64 4, i8* %v9) + call void @llvm.lifetime.end(i64 2, i8* %v8) + call void @llvm.lifetime.end(i64 1, i8* %v7) + ret void +} + +declare void @llvm.lifetime.start(i64, i8* nocapture) #0 +declare void @llvm.lifetime.end(i64, i8* nocapture) #0 +declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i32, i1) #0 + +declare void @test3(i8*, i8*, i8*, i8*, i8*, i8*) +declare void @test4(i8*, i8*, i8*, i8*) + +attributes #0 = { argmemonly nounwind "target-cpu"="hexagonv60" } diff --git a/test/CodeGen/Mips/2008-06-05-Carry.ll b/test/CodeGen/Mips/2008-06-05-Carry.ll index c61e1cd..5e6092f 100644 --- a/test/CodeGen/Mips/2008-06-05-Carry.ll +++ b/test/CodeGen/Mips/2008-06-05-Carry.ll @@ -2,20 +2,21 @@ define i64 @add64(i64 %u, i64 %v) nounwind { entry: +; CHECK-LABEL: add64: ; CHECK: addu -; CHECK: sltu +; CHECK-DAG: sltu +; CHECK-DAG: addu ; CHECK: addu -; CHECK: addu - %tmp2 = add i64 %u, %v + %tmp2 = add i64 %u, %v ret i64 %tmp2 } define i64 @sub64(i64 %u, i64 %v) nounwind { entry: -; CHECK: sub64 +; CHECK-LABEL: sub64 +; CHECK-DAG: sltu +; CHECK-DAG: subu ; CHECK: subu -; CHECK: sltu -; CHECK: addu ; CHECK: subu %tmp2 = sub i64 %u, %v ret i64 %tmp2 diff --git a/test/CodeGen/Mips/brundef.ll b/test/CodeGen/Mips/brundef.ll new file mode 100644 index 0000000..802556c --- /dev/null +++ b/test/CodeGen/Mips/brundef.ll @@ -0,0 +1,26 @@ +; RUN: llc -march=mips -mcpu=mips32 -verify-machineinstrs -o /dev/null < %s +; Confirm that MachineInstr branch simplification preserves +; register operand flags, such as the flag. + +define void @ham() { +bb: + %tmp = alloca i32, align 4 + %tmp13 = ptrtoint i32* %tmp to i32 + %tmp70 = icmp eq i32 undef, -1 + br i1 %tmp70, label %bb72, label %bb40 + +bb72: ; preds = %bb72, %bb + br i1 undef, label %bb40, label %bb72 + +bb40: ; preds = %bb72, %bb + %tmp41 = phi i32 [ %tmp13, %bb72 ], [ %tmp13, %bb ] + %tmp55 = inttoptr i32 %tmp41 to i32* + %tmp58 = insertelement <2 x i32*> undef, i32* %tmp55, i32 1 + br label %bb59 + +bb59: ; preds = %bb59, %bb40 + %tmp60 = phi <2 x i32*> [ %tmp61, %bb59 ], [ %tmp58, %bb40 ] + %tmp61 = getelementptr i32, <2 x i32*> %tmp60, <2 x i32> + %tmp62 = extractelement <2 x i32*> %tmp61, i32 1 + br label %bb59 +} diff --git a/test/CodeGen/Mips/dsp-patterns.ll b/test/CodeGen/Mips/dsp-patterns.ll index 837c0d8..250d3ef 100644 --- a/test/CodeGen/Mips/dsp-patterns.ll +++ b/test/CodeGen/Mips/dsp-patterns.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=mips -mattr=dsp < %s | FileCheck %s -check-prefix=R1 -; RUN: llc -march=mips -mattr=dspr2 < %s | FileCheck %s -check-prefix=R2 +; RUN: llc -march=mips -mcpu=mips32r2 -mattr=dsp < %s | FileCheck %s -check-prefix=R1 +; RUN: llc -march=mips -mcpu=mips32r2 -mattr=dspr2 < %s | FileCheck %s -check-prefix=R2 ; R1-LABEL: test_lbux: ; R1: lbux ${{[0-9]+}} diff --git a/test/CodeGen/Mips/llcarry.ll b/test/CodeGen/Mips/llcarry.ll index fcf1294..b7cc6fc 100644 --- a/test/CodeGen/Mips/llcarry.ll +++ b/test/CodeGen/Mips/llcarry.ll @@ -14,9 +14,9 @@ entry: %add = add nsw i64 %1, %0 store i64 %add, i64* @k, align 8 ; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} -; 16: sltu ${{[0-9]+}}, ${{[0-9]+}} -; 16: move ${{[0-9]+}}, $t8 ; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} +; 16: sltu ${{[0-9]+}}, ${{[0-9]+}} +; 16: move ${{[0-9]+}}, $24 ; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} ret void } @@ -28,8 +28,8 @@ entry: %sub = sub nsw i64 %0, %1 ; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} ; 16: sltu ${{[0-9]+}}, ${{[0-9]+}} -; 16: move ${{[0-9]+}}, $t8 -; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} +; 16: move ${{[0-9]+}}, $24 +; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} ; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} store i64 %sub, i64* @l, align 8 ret void @@ -41,8 +41,7 @@ entry: %add = add nsw i64 %0, 15 ; 16: addiu ${{[0-9]+}}, 15 ; 16: sltu ${{[0-9]+}}, ${{[0-9]+}} -; 16: move ${{[0-9]+}}, $t8 -; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} +; 16: move ${{[0-9]+}}, $24 ; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}} store i64 %add, i64* @m, align 8 ret void diff --git a/test/CodeGen/Mips/llvm-ir/add.ll b/test/CodeGen/Mips/llvm-ir/add.ll index a5ecdda..63884eb 100644 --- a/test/CodeGen/Mips/llvm-ir/add.ll +++ b/test/CodeGen/Mips/llvm-ir/add.ll @@ -1,35 +1,35 @@ ; RUN: llc < %s -march=mips -mcpu=mips2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32 +; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32,PRE4 ; RUN: llc < %s -march=mips -mcpu=mips32 | FileCheck %s \ -; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32 +; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32,GP32-CMOV ; RUN: llc < %s -march=mips -mcpu=mips32r2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP32 +; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV ; RUN: llc < %s -march=mips -mcpu=mips32r3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP32 +; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV ; RUN: llc < %s -march=mips -mcpu=mips32r5 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP32 +; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV ; RUN: llc < %s -march=mips -mcpu=mips32r6 | FileCheck %s \ ; RUN: -check-prefixes=ALL,R2-R6,GP32 ; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64 +; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips4 | FileCheck %s \ -; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64 +; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips64 | FileCheck %s \ -; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64 +; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips64r2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP64 +; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips64r3 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP64 +; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips64r5 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP64 +; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6 ; RUN: llc < %s -march=mips64 -mcpu=mips64r6 | FileCheck %s \ -; RUN: -check-prefixes=ALL,R2-R6,GP64 +; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6 ; RUN: llc < %s -march=mips -mcpu=mips32r3 -mattr=+micromips -O2 -verify-machineinstrs | FileCheck %s \ -; RUN: -check-prefixes=ALL,MMR6,MM32 +; RUN: -check-prefixes=ALL,MMR3,MM32 ; RUN: llc < %s -march=mips -mcpu=mips32r6 -mattr=+micromips -O2 | FileCheck %s \ ; RUN: -check-prefixes=ALL,MMR6,MM32 ; RUN: llc < %s -march=mips -mcpu=mips64r6 -target-abi n64 -mattr=+micromips -O2 | FileCheck %s \ -; RUN: -check-prefixes=ALL,MMR6,MM64 +; RUN: -check-prefixes=ALL,MM64 ; FIXME: This code sequence is inefficient as it should be 'subu $[[T0]], $zero, $[[T0]'. @@ -110,17 +110,17 @@ define signext i64 @add_i64(i64 signext %a, i64 signext %b) { entry: ; ALL-LABEL: add_i64: - ; GP32: addu $3, $5, $7 - ; GP32: sltu $[[T0:[0-9]+]], $3, $7 - ; GP32: addu $[[T1:[0-9]+]], $[[T0]], $6 - ; GP32: addu $2, $4, $[[T1]] + ; GP32-DAG: addu $[[T0:[0-9]+]], $4, $6 + ; GP32-DAG: addu $3, $5, $7 + ; GP32: sltu $[[T1:[0-9]+]], $3, $5 + ; GP32: addu $2, $[[T0]], $[[T1]] ; GP64: daddu $2, $4, $5 - ; MM32: addu16 $3, $5, $7 - ; MM32: sltu $[[T0:[0-9]+]], $3, $7 - ; MM32: addu $[[T1:[0-9]+]], $[[T0]], $6 - ; MM32: addu $2, $4, $[[T1]] + ; MM32-DAG: addu16 $3, $5, $7 + ; MM32-DAG: addu16 $[[T0:[0-9]+]], $4, $6 + ; MM32: sltu $[[T1:[0-9]+]], $3, $5 + ; MM32: addu16 $2, $[[T0]], $[[T1]] ; MM64: daddu $2, $4, $5 @@ -132,49 +132,108 @@ define signext i128 @add_i128(i128 signext %a, i128 signext %b) { entry: ; ALL-LABEL: add_i128: - ; GP32: lw $[[T0:[0-9]+]], 28($sp) - ; GP32: addu $[[T1:[0-9]+]], $7, $[[T0]] - ; GP32: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]] - ; GP32: lw $[[T3:[0-9]+]], 24($sp) - ; GP32: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]] - ; GP32: addu $[[T5:[0-9]+]], $6, $[[T4]] - ; GP32: sltu $[[T6:[0-9]+]], $[[T5]], $[[T3]] - ; GP32: lw $[[T7:[0-9]+]], 20($sp) - ; GP32: addu $[[T8:[0-9]+]], $[[T6]], $[[T7]] - ; GP32: lw $[[T9:[0-9]+]], 16($sp) - ; GP32: addu $3, $5, $[[T8]] - ; GP32: sltu $[[T10:[0-9]+]], $3, $[[T7]] - ; GP32: addu $[[T11:[0-9]+]], $[[T10]], $[[T9]] - ; GP32: addu $2, $4, $[[T11]] - ; GP32: move $4, $[[T5]] - ; GP32: move $5, $[[T1]] - - ; GP64: daddu $3, $5, $7 - ; GP64: sltu $[[T0:[0-9]+]], $3, $7 - ; GP64: daddu $[[T1:[0-9]+]], $[[T0]], $6 - ; GP64: daddu $2, $4, $[[T1]] - - ; MM32: lw $[[T0:[0-9]+]], 28($sp) - ; MM32: addu $[[T1:[0-9]+]], $7, $[[T0]] - ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]] - ; MM32: lw $[[T3:[0-9]+]], 24($sp) - ; MM32: addu16 $[[T4:[0-9]+]], $[[T2]], $[[T3]] - ; MM32: addu16 $[[T5:[0-9]+]], $6, $[[T4]] - ; MM32: sltu $[[T6:[0-9]+]], $[[T5]], $[[T3]] - ; MM32: lw $[[T7:[0-9]+]], 20($sp) - ; MM32: addu16 $[[T8:[0-9]+]], $[[T6]], $[[T7]] - ; MM32: lw $[[T9:[0-9]+]], 16($sp) - ; MM32: addu16 $[[T10:[0-9]+]], $5, $[[T8]] - ; MM32: sltu $[[T11:[0-9]+]], $[[T10]], $[[T7]] - ; MM32: addu $[[T12:[0-9]+]], $[[T11]], $[[T9]] - ; MM32: addu16 $[[T13:[0-9]+]], $4, $[[T12]] - ; MM32: move $4, $[[T5]] - ; MM32: move $5, $[[T1]] - + ; PRE4: move $[[R1:[0-9]+]], $5 + ; PRE4: move $[[R2:[0-9]+]], $4 + ; PRE4: lw $[[R3:[0-9]+]], 24($sp) + ; PRE4: addu $[[R4:[0-9]+]], $6, $[[R3]] + ; PRE4: lw $[[R5:[0-9]+]], 28($sp) + ; PRE4: addu $[[R6:[0-9]+]], $7, $[[R5]] + ; PRE4: sltu $[[R7:[0-9]+]], $[[R6]], $7 + ; PRE4: addu $[[R8:[0-9]+]], $[[R4]], $[[R7]] + ; PRE4: xor $[[R9:[0-9]+]], $[[R8]], $6 + ; PRE4: sltiu $[[R10:[0-9]+]], $[[R9]], 1 + ; PRE4: bnez $[[R10]], $BB5_2 + ; PRE4: sltu $[[R7]], $[[R8]], $6 + ; PRE4: lw $[[R12:[0-9]+]], 20($sp) + ; PRE4: addu $[[R13:[0-9]+]], $[[R1]], $[[R12]] + ; PRE4: lw $[[R14:[0-9]+]], 16($sp) + ; PRE4: addu $[[R15:[0-9]+]], $[[R13]], $[[R7]] + ; PRE4: addu $[[R16:[0-9]+]], $[[R2]], $[[R14]] + ; PRE4: sltu $[[R17:[0-9]+]], $[[R15]], $[[R13]] + ; PRE4: sltu $[[R18:[0-9]+]], $[[R13]], $[[R1]] + ; PRE4: addu $[[R19:[0-9]+]], $[[R16]], $[[R18]] + ; PRE4: addu $2, $[[R19]], $[[R17]] + + ; GP32-CMOV: lw $[[T0:[0-9]+]], 24($sp) + ; GP32-CMOV: addu $[[T1:[0-9]+]], $6, $[[T0]] + ; GP32-CMOV: lw $[[T2:[0-9]+]], 28($sp) + ; GP32-CMOV: addu $[[T3:[0-9]+]], $7, $[[T2]] + ; GP32-CMOV: sltu $[[T4:[0-9]+]], $[[T3]], $7 + ; GP32-CMOV: addu $[[T5:[0-9]+]], $[[T1]], $[[T4]] + ; GP32-CMOV: sltu $[[T6:[0-9]+]], $[[T5]], $6 + ; GP32-CMOV: xor $[[T7:[0-9]+]], $[[T5]], $6 + ; GP32-CMOV: movz $[[T8:[0-9]+]], $[[T4]], $[[T7]] + ; GP32-CMOV: lw $[[T9:[0-9]+]], 20($sp) + ; GP32-CMOV: addu $[[T10:[0-9]+]], $5, $[[T4]] + ; GP32-CMOV: addu $[[T11:[0-9]+]], $[[T10]], $[[T8]] + ; GP32-CMOV: lw $[[T12:[0-9]+]], 16($sp) + ; GP32-CMOV: sltu $[[T13:[0-9]+]], $[[T11]], $[[T10]] + ; GP32-CMOV: addu $[[T14:[0-9]+]], $4, $[[T12]] + ; GP32-CMOV: sltu $[[T15:[0-9]+]], $[[T10]], $5 + ; GP32-CMOV: addu $[[T16:[0-9]+]], $[[T14]], $[[T15]] + ; GP32-CMOV: addu $[[T17:[0-9]+]], $[[T16]], $[[T13]] + ; GP32-CMOV: move $4, $[[T5]] + ; GP32-CMOV: move $5, $[[T3]] + + ; GP64: daddu $[[T0:[0-9]+]], $4, $6 + ; GP64: daddu $[[T1:[0-9]+]], $5, $7 + ; GP64: sltu $[[T2:[0-9]+]], $[[T1]], $5 + ; GP64-NOT-R2-R6: dsll $[[T3:[0-9]+]], $[[T2]], 32 + ; GP64-NOT-R2-R6: dsrl $[[T4:[0-9]+]], $[[T3]], 32 + ; GP64-R2-R6: dext $[[T4:[0-9]+]], $[[T2]], 0, 32 + + ; GP64: daddu $2, $[[T0]], $[[T4]] + + ; MMR3: move $[[T1:[0-9]+]], $5 + ; MMR3-DAG: lw $[[T2:[0-9]+]], 32($sp) + ; MMR3: addu16 $[[T3:[0-9]+]], $6, $[[T2]] + ; MMR3-DAG: lw $[[T4:[0-9]+]], 36($sp) + ; MMR3: addu16 $[[T5:[0-9]+]], $7, $[[T4]] + ; MMR3: sltu $[[T6:[0-9]+]], $[[T5]], $7 + ; MMR3: addu16 $[[T7:[0-9]+]], $[[T3]], $[[T6]] + ; MMR3: sltu $[[T8:[0-9]+]], $[[T7]], $6 + ; MMR3: xor $[[T9:[0-9]+]], $[[T7]], $6 + ; MMR3: movz $[[T8]], $[[T6]], $[[T9]] + ; MMR3: lw $[[T10:[0-9]+]], 28($sp) + ; MMR3: addu16 $[[T11:[0-9]+]], $[[T1]], $[[T10]] + ; MMR3: addu16 $[[T12:[0-9]+]], $[[T11]], $[[T8]] + ; MMR3: lw $[[T13:[0-9]+]], 24($sp) + ; MMR3: sltu $[[T14:[0-9]+]], $[[T12]], $[[T11]] + ; MMR3: addu16 $[[T15:[0-9]+]], $4, $[[T13]] + ; MMR3: sltu $[[T16:[0-9]+]], $[[T11]], $[[T1]] + ; MMR3: addu16 $[[T17:[0-9]+]], $[[T15]], $[[T16]] + ; MMR3: addu16 $2, $2, $[[T14]] + + ; MMR6: move $[[T1:[0-9]+]], $5 + ; MMR6: move $[[T2:[0-9]+]], $4 + ; MMR6: lw $[[T3:[0-9]+]], 32($sp) + ; MMR6: addu16 $[[T4:[0-9]+]], $6, $[[T3]] + ; MMR6: lw $[[T5:[0-9]+]], 36($sp) + ; MMR6: addu16 $[[T6:[0-9]+]], $7, $[[T5]] + ; MMR6: sltu $[[T7:[0-9]+]], $[[T6]], $7 + ; MMR6: addu16 $[[T8:[0-9]+]], $[[T4]], $7 + ; MMR6: sltu $[[T9:[0-9]+]], $[[T8]], $6 + ; MMR6: xor $[[T10:[0-9]+]], $[[T4]], $6 + ; MMR6: sltiu $[[T11:[0-9]+]], $[[T10]], 1 + ; MMR6: seleqz $[[T12:[0-9]+]], $[[T9]], $[[T11]] + ; MMR6: selnez $[[T13:[0-9]+]], $[[T7]], $[[T11]] + ; MMR6: lw $[[T14:[0-9]+]], 24($sp) + ; MMR6: or $[[T15:[0-9]+]], $[[T13]], $[[T12]] + ; MMR6: addu16 $[[T16:[0-9]+]], $[[T2]], $[[T14]] + ; MMR6: lw $[[T17:[0-9]+]], 28($sp) + ; MMR6: addu16 $[[T18:[0-9]+]], $[[T1]], $[[T17]] + ; MMR6: addu16 $[[T19:[0-9]+]], $[[T18]], $[[T15]] + ; MMR6: sltu $[[T20:[0-9]+]], $[[T18]], $[[T1]] + ; MMR6: sltu $[[T21:[0-9]+]], $[[T17]], $[[T18]] + ; MMR6: addu16 $2, $[[T16]], $[[T20]] + ; MMR6: addu16 $2, $[[T20]], $[[T21]] + + ; MM64: daddu $[[T0:[0-9]+]], $4, $6 ; MM64: daddu $3, $5, $7 - ; MM64: sltu $[[T0:[0-9]+]], $3, $7 - ; MM64: daddu $[[T1:[0-9]+]], $[[T0]], $6 - ; MM64: daddu $2, $4, $[[T1]] + ; MM64: sltu $[[T1:[0-9]+]], $3, $5 + ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32 + ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32 + ; MM64: daddu $2, $[[T0]], $[[T3]] %r = add i128 %a, %b ret i128 %r @@ -249,17 +308,16 @@ define signext i32 @add_i32_4(i32 signext %a) { define signext i64 @add_i64_4(i64 signext %a) { ; ALL-LABEL: add_i64_4: - ; GP32: addiu $[[T0:[0-9]+]], $5, 4 - ; GP32: addiu $[[T1:[0-9]+]], $zero, 4 - ; GP32: sltu $[[T1]], $[[T0]], $[[T1]] - ; GP32: addu $2, $4, $[[T1]] + ; GP32: addiu $3, $5, 4 + ; GP32: sltu $[[T0:[0-9]+]], $3, $5 + ; GP32: addu $2, $4, $[[T0]] + + ; MM32: addiur2 $[[T1:[0-9]+]], $5, 4 + ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $5 + ; MM32: addu16 $2, $4, $[[T2]] ; GP64: daddiu $2, $4, 4 - ; MM32: addiu $[[T0:[0-9]+]], $5, 4 - ; MM32: li16 $[[T1:[0-9]+]], 4 - ; MM32: sltu $[[T2:[0-9]+]], $[[T0]], $[[T1]] - ; MM32: addu $2, $4, $[[T2]] ; MM64: daddiu $2, $4, 4 @@ -270,38 +328,67 @@ define signext i64 @add_i64_4(i64 signext %a) { define signext i128 @add_i128_4(i128 signext %a) { ; ALL-LABEL: add_i128_4: - ; GP32: addiu $[[T0:[0-9]+]], $7, 4 - ; GP32: addiu $[[T1:[0-9]+]], $zero, 4 - ; GP32: sltu $[[T1]], $[[T0]], $[[T1]] - ; GP32: addu $[[T2:[0-9]+]], $6, $[[T1]] - ; GP32: sltu $[[T1]], $[[T2]], $zero - ; GP32: addu $[[T3:[0-9]+]], $5, $[[T1]] - ; GP32: sltu $[[T1]], $[[T3]], $zero - ; GP32: addu $[[T1]], $4, $[[T1]] - ; GP32: move $4, $[[T2]] - ; GP32: move $5, $[[T0]] - - ; GP64: daddiu $[[T0:[0-9]+]], $5, 4 - ; GP64: daddiu $[[T1:[0-9]+]], $zero, 4 - ; GP64: sltu $[[T1]], $[[T0]], $[[T1]] - ; GP64: daddu $2, $4, $[[T1]] - - ; MM32: addiu $[[T0:[0-9]+]], $7, 4 - ; MM32: li16 $[[T1:[0-9]+]], 4 - ; MM32: sltu $[[T1]], $[[T0]], $[[T1]] - ; MM32: addu16 $[[T2:[0-9]+]], $6, $[[T1]] - ; MM32: li16 $[[T1]], 0 - ; MM32: sltu $[[T3:[0-9]+]], $[[T2]], $[[T1]] - ; MM32: addu16 $[[T3]], $5, $[[T3]] - ; MM32: sltu $[[T1]], $[[T3]], $[[T1]] - ; MM32: addu16 $[[T1]], $4, $[[T1]] - ; MM32: move $4, $[[T2]] - ; MM32: move $5, $[[T0]] + ; PRE4: move $[[T0:[0-9]+]], $5 + ; PRE4: addiu $[[T1:[0-9]+]], $7, 4 + ; PRE4: sltu $[[T2:[0-9]+]], $[[T1]], $7 + ; PRE4: xori $[[T3:[0-9]+]], $[[T2]], 1 + ; PRE4: bnez $[[T3]], $BB[[BB0:[0-9_]+]] + ; PRE4: addu $[[T4:[0-9]+]], $6, $[[T2]] + ; PRE4: sltu $[[T5:[0-9]+]], $[[T4]], $6 + ; PRE4; $BB[[BB0:[0-9]+]]: + ; PRE4: addu $[[T6:[0-9]+]], $[[T0]], $[[T5]] + ; PRE4: sltu $[[T7:[0-9]+]], $[[T6]], $[[T0]] + ; PRE4: addu $[[T8:[0-9]+]], $4, $[[T7]] + ; PRE4: move $4, $[[T4]] + + ; GP32-CMOV: addiu $[[T0:[0-9]+]], $7, 4 + ; GP32-CMOV: sltu $[[T1:[0-9]+]], $[[T0]], $7 + ; GP32-CMOV: addu $[[T2:[0-9]+]], $6, $[[T1]] + ; GP32-CMOV: sltu $[[T3:[0-9]+]], $[[T2]], $6 + ; GP32-CMOV: movz $[[T3]], $[[T1]], $[[T1]] + ; GP32-CMOV: addu $[[T4:[0-9]+]], $5, $[[T3]] + ; GP32-CMOV: sltu $[[T5:[0-9]+]], $[[T4]], $5 + ; GP32-CMOV: addu $[[T7:[0-9]+]], $4, $[[T5]] + ; GP32-CMOV: move $4, $[[T2]] + ; GP32-CMOV: move $5, $[[T0]] + + ; GP64: daddiu $[[T0:[0-9]+]], $5, 4 + ; GP64: sltu $[[T1:[0-9]+]], $[[T0]], $5 + ; GP64-NOT-R2-R6: dsll $[[T2:[0-9]+]], $[[T1]], 32 + ; GP64-NOT-R2-R6: dsrl $[[T3:[0-9]+]], $[[T2]], 32 + ; GP64-R2-R6: dext $[[T3:[0-9]+]], $[[T1]], 0, 32 + + ; GP64: daddu $2, $4, $[[T3]] + + ; MMR3: addiur2 $[[T0:[0-9]+]], $7, 4 + ; MMR3: sltu $[[T1:[0-9]+]], $[[T0]], $7 + ; MMR3: sltu $[[T2:[0-9]+]], $[[T0]], $7 + ; MMR3: addu16 $[[T3:[0-9]+]], $6, $[[T2]] + ; MMR3: sltu $[[T4:[0-9]+]], $[[T3]], $6 + ; MMR3: movz $[[T4]], $[[T2]], $[[T1]] + ; MMR3: addu16 $[[T6:[0-9]+]], $5, $[[T4]] + ; MMR3: sltu $[[T7:[0-9]+]], $[[T6]], $5 + ; MMR3: addu16 $2, $4, $[[T7]] + + ; MMR6: addiur2 $[[T1:[0-9]+]], $7, 4 + ; MMR6: sltu $[[T2:[0-9]+]], $[[T1]], $7 + ; MMR6: xori $[[T3:[0-9]+]], $[[T2]], 1 + ; MMR6: selnez $[[T4:[0-9]+]], $[[T2]], $[[T3]] + ; MMR6: addu16 $[[T5:[0-9]+]], $6, $[[T2]] + ; MMR6: sltu $[[T6:[0-9]+]], $[[T5]], $6 + ; MMR6: seleqz $[[T7:[0-9]+]], $[[T6]], $[[T3]] + ; MMR6: or $[[T8:[0-9]+]], $[[T4]], $[[T7]] + ; MMR6: addu16 $[[T9:[0-9]+]], $5, $[[T8]] + ; MMR6: sltu $[[T10:[0-9]+]], $[[T9]], $5 + ; MMR6: addu16 $[[T11:[0-9]+]], $4, $[[T10]] + ; MMR6: move $4, $7 + ; MMR6: move $5, $[[T1]] ; MM64: daddiu $[[T0:[0-9]+]], $5, 4 - ; MM64: daddiu $[[T1:[0-9]+]], $zero, 4 - ; MM64: sltu $[[T1]], $[[T0]], $[[T1]] - ; MM64: daddu $2, $4, $[[T1]] + ; MM64: sltu $[[T1:[0-9]+]], $[[T0]], $5 + ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32 + ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32 + ; MM64: daddu $2, $4, $[[T3]] %r = add i128 4, %a ret i128 %r @@ -380,16 +467,15 @@ define signext i64 @add_i64_3(i64 signext %a) { ; ALL-LABEL: add_i64_3: ; GP32: addiu $[[T0:[0-9]+]], $5, 3 - ; GP32: addiu $[[T1:[0-9]+]], $zero, 3 - ; GP32: sltu $[[T1]], $[[T0]], $[[T1]] + ; GP32: sltu $[[T1:[0-9]+]], $[[T0]], $5 ; GP32: addu $2, $4, $[[T1]] ; GP64: daddiu $2, $4, 3 - ; MM32: addiu $[[T0:[0-9]+]], $5, 3 - ; MM32: li16 $[[T1:[0-9]+]], 3 - ; MM32: sltu $[[T2:[0-9]+]], $[[T0]], $[[T1]] - ; MM32: addu $2, $4, $[[T2]] + ; MM32: move $[[T1:[0-9]+]], $5 + ; MM32: addius5 $[[T1]], 3 + ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $5 + ; MM32: addu16 $2, $4, $[[T2]] ; MM64: daddiu $2, $4, 3 @@ -400,38 +486,70 @@ define signext i64 @add_i64_3(i64 signext %a) { define signext i128 @add_i128_3(i128 signext %a) { ; ALL-LABEL: add_i128_3: - ; GP32: addiu $[[T0:[0-9]+]], $7, 3 - ; GP32: addiu $[[T1:[0-9]+]], $zero, 3 - ; GP32: sltu $[[T1]], $[[T0]], $[[T1]] - ; GP32: addu $[[T2:[0-9]+]], $6, $[[T1]] - ; GP32: sltu $[[T3:[0-9]+]], $[[T2]], $zero - ; GP32: addu $[[T4:[0-9]+]], $5, $[[T3]] - ; GP32: sltu $[[T5:[0-9]+]], $[[T4]], $zero - ; GP32: addu $[[T5]], $4, $[[T5]] - ; GP32: move $4, $[[T2]] - ; GP32: move $5, $[[T0]] - - ; GP64: daddiu $[[T0:[0-9]+]], $5, 3 - ; GP64: daddiu $[[T1:[0-9]+]], $zero, 3 - ; GP64: sltu $[[T1]], $[[T0]], $[[T1]] - ; GP64: daddu $2, $4, $[[T1]] - - ; MM32: addiu $[[T0:[0-9]+]], $7, 3 - ; MM32: li16 $[[T1:[0-9]+]], 3 - ; MM32: sltu $[[T1]], $[[T0]], $[[T1]] - ; MM32: addu16 $[[T2:[0-9]+]], $6, $[[T1]] - ; MM32: li16 $[[T3:[0-9]+]], 0 - ; MM32: sltu $[[T4:[0-9]+]], $[[T2]], $[[T3]] - ; MM32: addu16 $[[T4]], $5, $[[T4]] - ; MM32: sltu $[[T5:[0-9]+]], $[[T4]], $[[T3]] - ; MM32: addu16 $[[T5]], $4, $[[T5]] - ; MM32: move $4, $[[T2]] - ; MM32: move $5, $[[T0]] + ; PRE4: move $[[T0:[0-9]+]], $5 + ; PRE4: addiu $[[T1:[0-9]+]], $7, 3 + ; PRE4: sltu $[[T2:[0-9]+]], $[[T1]], $7 + ; PRE4: xori $[[T3:[0-9]+]], $[[T2]], 1 + ; PRE4: bnez $[[T3]], $BB[[BB0:[0-9_]+]] + ; PRE4: addu $[[T4:[0-9]+]], $6, $[[T2]] + ; PRE4: sltu $[[T5:[0-9]+]], $[[T4]], $6 + ; PRE4; $BB[[BB0:[0-9]+]]: + ; PRE4: addu $[[T6:[0-9]+]], $[[T0]], $[[T5]] + ; PRE4: sltu $[[T7:[0-9]+]], $[[T6]], $[[T0]] + ; PRE4: addu $[[T8:[0-9]+]], $4, $[[T7]] + ; PRE4: move $4, $[[T4]] + + ; GP32-CMOV: addiu $[[T0:[0-9]+]], $7, 3 + ; GP32-CMOV: sltu $[[T1:[0-9]+]], $[[T0]], $7 + ; GP32-CMOV: addu $[[T2:[0-9]+]], $6, $[[T1]] + ; GP32-CMOV: sltu $[[T3:[0-9]+]], $[[T2]], $6 + ; GP32-CMOV: movz $[[T3]], $[[T1]], $[[T1]] + ; GP32-CMOV: addu $[[T4:[0-9]+]], $5, $[[T3]] + ; GP32-CMOV: sltu $[[T5:[0-9]+]], $[[T4]], $5 + ; GP32-CMOV: addu $[[T7:[0-9]+]], $4, $[[T5]] + ; GP32-CMOV: move $4, $[[T2]] + ; GP32-CMOV: move $5, $[[T0]] + + ; GP64: daddiu $[[T0:[0-9]+]], $5, 3 + ; GP64: sltu $[[T1:[0-9]+]], $[[T0]], $5 + + ; GP64-NOT-R2-R6: dsll $[[T2:[0-9]+]], $[[T1]], 32 + ; GP64-NOT-R2-R6: dsrl $[[T3:[0-9]+]], $[[T2]], 32 + ; GP64-R2-R6: dext $[[T3:[0-9]+]], $[[T1]], 0, 32 + + ; GP64: daddu $2, $4, $[[T3]] + + ; MMR3: move $[[T1:[0-9]+]], $7 + ; MMR3: addius5 $[[T1]], 3 + ; MMR3: sltu $[[T2:[0-9]+]], $[[T1]], $7 + ; MMR3: sltu $[[T3:[0-9]+]], $[[T1]], $7 + ; MMR3: addu16 $[[T4:[0-9]+]], $6, $[[T3]] + ; MMR3: sltu $[[T5:[0-9]+]], $[[T4]], $6 + ; MMR3: movz $[[T5]], $[[T3]], $[[T2]] + ; MMR3: addu16 $[[T6:[0-9]+]], $5, $[[T5]] + ; MMR3: sltu $[[T7:[0-9]+]], $[[T6]], $5 + ; MMR3: addu16 $2, $4, $[[T7]] + + ; MMR6: move $[[T1:[0-9]+]], $7 + ; MMR6: addius5 $[[T1]], 3 + ; MMR6: sltu $[[T2:[0-9]+]], $[[T1]], $7 + ; MMR6: xori $[[T3:[0-9]+]], $[[T2]], 1 + ; MMR6: selnez $[[T4:[0-9]+]], $[[T2]], $[[T3]] + ; MMR6: addu16 $[[T5:[0-9]+]], $6, $[[T2]] + ; MMR6: sltu $[[T6:[0-9]+]], $[[T5]], $6 + ; MMR6: seleqz $[[T7:[0-9]+]], $[[T6]], $[[T3]] + ; MMR6: or $[[T8:[0-9]+]], $[[T4]], $[[T7]] + ; MMR6: addu16 $[[T9:[0-9]+]], $5, $[[T8]] + ; MMR6: sltu $[[T10:[0-9]+]], $[[T9]], $5 + ; MMR6: addu16 $[[T11:[0-9]+]], $4, $[[T10]] + ; MMR6: move $4, $[[T5]] + ; MMR6: move $5, $[[T1]] ; MM64: daddiu $[[T0:[0-9]+]], $5, 3 - ; MM64: daddiu $[[T1:[0-9]+]], $zero, 3 - ; MM64: sltu $[[T1]], $[[T0]], $[[T1]] - ; MM64: daddu $2, $4, $[[T1]] + ; MM64: sltu $[[T1:[0-9]+]], $[[T0]], $5 + ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32 + ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32 + ; MM64: daddu $2, $4, $[[T3]] %r = add i128 3, %a ret i128 %r diff --git a/test/CodeGen/Mips/llvm-ir/sub.ll b/test/CodeGen/Mips/llvm-ir/sub.ll index a730063..655addb 100644 --- a/test/CodeGen/Mips/llvm-ir/sub.ll +++ b/test/CodeGen/Mips/llvm-ir/sub.ll @@ -1,5 +1,5 @@ ; RUN: llc < %s -march=mips -mcpu=mips2 | FileCheck %s \ -; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM +; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM,PRE4 ; RUN: llc < %s -march=mips -mcpu=mips32 | FileCheck %s \ ; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM ; RUN: llc < %s -march=mips -mcpu=mips32r2 | FileCheck %s \ @@ -11,25 +11,25 @@ ; RUN: llc < %s -march=mips -mcpu=mips32r6 | FileCheck %s \ ; RUN: -check-prefixes=R2-R6,GP32,GP32-NOT-MM,NOT-MM ; RUN: llc < %s -march=mips -mcpu=mips32r3 -mattr=+micromips -verify-machineinstrs | FileCheck %s \ -; RUN: -check-prefixes=GP32-MM,GP32,MM +; RUN: -check-prefixes=GP32-MM,GP32,MM32,MMR3 ; RUN: llc < %s -march=mips -mcpu=mips32r6 -mattr=+micromips | FileCheck %s \ -; RUN: -check-prefixes=GP32-MM,GP32,MM +; RUN: -check-prefixes=GP32-MM,GP32,MM32,MMR6 ; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s \ -; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips4 | FileCheck %s \ -; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64 | FileCheck %s \ -; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64r2 | FileCheck %s \ -; RUN: -check-prefixes=R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64r3 | FileCheck %s \ -; RUN: -check-prefixes=R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64r5 | FileCheck %s \ -; RUN: -check-prefixes=R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64r6 | FileCheck %s \ -; RUN: -check-prefixes=R2-R6,GP64,NOT-MM +; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2 ; RUN: llc < %s -march=mips64 -mcpu=mips64r6 -mattr=+micromips | FileCheck %s \ -; RUN: -check-prefixes=GP64,MM +; RUN: -check-prefixes=GP64,MM64 define signext i1 @sub_i1(i1 signext %a, i1 signext %b) { entry: @@ -100,10 +100,15 @@ define signext i64 @sub_i64(i64 signext %a, i64 signext %b) { entry: ; ALL-LABEL: sub_i64: - ; GP32-NOT-MM subu $3, $5, $7 - ; GP32: sltu $[[T0:[0-9]+]], $5, $7 - ; GP32: addu $[[T1:[0-9]+]], $[[T0]], $6 - ; GP32: subu $2, $4, $[[T1]] + ; GP32-NOT-MM: sltu $[[T0:[0-9]+]], $5, $7 + ; GP32-NOT-MM: subu $2, $4, $6 + ; GP32-NOT-MM: subu $2, $2, $[[T0]] + ; GP32-NOT-MM: subu $3, $5, $7 + + ; MM32: sltu $[[T0:[0-9]+]], $5, $7 + ; MM32: subu16 $3, $4, $6 + ; MM32: subu16 $2, $3, $[[T0]] + ; MM32: subu16 $3, $5, $7 ; GP64: dsubu $2, $4, $5 @@ -115,42 +120,109 @@ define signext i128 @sub_i128(i128 signext %a, i128 signext %b) { entry: ; ALL-LABEL: sub_i128: - ; GP32-NOT-MM: lw $[[T0:[0-9]+]], 20($sp) - ; GP32-NOT-MM: sltu $[[T1:[0-9]+]], $5, $[[T0]] - ; GP32-NOT-MM: lw $[[T2:[0-9]+]], 16($sp) - ; GP32-NOT-MM: addu $[[T3:[0-9]+]], $[[T1]], $[[T2]] - ; GP32-NOT-MM: lw $[[T4:[0-9]+]], 24($sp) - ; GP32-NOT-MM: lw $[[T5:[0-9]+]], 28($sp) - ; GP32-NOT-MM: subu $[[T6:[0-9]+]], $7, $[[T5]] - ; GP32-NOT-MM: subu $2, $4, $[[T3]] - ; GP32-NOT-MM: sltu $[[T8:[0-9]+]], $6, $[[T4]] - ; GP32-NOT-MM: addu $[[T9:[0-9]+]], $[[T8]], $[[T0]] - ; GP32-NOT-MM: subu $3, $5, $[[T9]] - ; GP32-NOT-MM: sltu $[[T10:[0-9]+]], $7, $[[T5]] - ; GP32-NOT-MM: addu $[[T11:[0-9]+]], $[[T10]], $[[T4]] - ; GP32-NOT-MM: subu $4, $6, $[[T11]] - ; GP32-NOT-MM: move $5, $[[T6]] - - ; GP32-MM: lw $[[T0:[0-9]+]], 20($sp) - ; GP32-MM: sltu $[[T1:[0-9]+]], $[[T2:[0-9]+]], $[[T0]] - ; GP32-MM: lw $[[T3:[0-9]+]], 16($sp) - ; GP32-MM: addu $[[T3]], $[[T1]], $[[T3]] - ; GP32-MM: lw $[[T4:[0-9]+]], 24($sp) - ; GP32-MM: lw $[[T5:[0-9]+]], 28($sp) - ; GP32-MM: subu $[[T1]], $7, $[[T5]] - ; GP32-MM: subu16 $[[T3]], $[[T6:[0-9]+]], $[[T3]] - ; GP32-MM: sltu $[[T6]], $6, $[[T4]] - ; GP32-MM: addu16 $[[T0]], $[[T6]], $[[T0]] - ; GP32-MM: subu16 $[[T0]], $5, $[[T0]] - ; GP32-MM: sltu $[[T6]], $7, $[[T5]] - ; GP32-MM: addu $[[T6]], $[[T6]], $[[T4]] - ; GP32-MM: subu16 $[[T6]], $6, $[[T6]] - ; GP32-MM: move $[[T2]], $[[T1]] - - ; GP64: dsubu $3, $5, $7 - ; GP64: sltu $[[T0:[0-9]+]], $5, $7 - ; GP64: daddu $[[T1:[0-9]+]], $[[T0]], $6 - ; GP64: dsubu $2, $4, $[[T1]] +; PRE4: lw $[[T0:[0-9]+]], 24($sp) +; PRE4: lw $[[T1:[0-9]+]], 28($sp) +; PRE4: sltu $[[T2:[0-9]+]], $7, $[[T1]] +; PRE4: xor $[[T3:[0-9]+]], $6, $[[T0]] +; PRE4: sltiu $[[T4:[0-9]+]], $[[T3]], 1 +; PRE4: bnez $[[T4]] +; PRE4: move $[[T5:[0-9]+]], $[[T2]] +; PRE4: sltu $[[T5]], $6, $[[T0]] + +; PRE4: lw $[[T6:[0-9]+]], 20($sp) +; PRE4: subu $[[T7:[0-9]+]], $5, $[[T6]] +; PRE4: subu $[[T8:[0-9]+]], $[[T7]], $[[T5]] +; PRE4: sltu $[[T9:[0-9]+]], $[[T7]], $[[T5]] +; PRE4: sltu $[[T10:[0-9]+]], $5, $[[T6]] +; PRE4: lw $[[T11:[0-9]+]], 16($sp) +; PRE4: subu $[[T12:[0-9]+]], $4, $[[T11]] +; PRE4: subu $[[T13:[0-9]+]], $[[T12]], $[[T10]] +; PRE4: subu $[[T14:[0-9]+]], $[[T13]], $[[T9]] +; PRE4: subu $[[T15:[0-9]+]], $6, $[[T0]] +; PRE4: subu $[[T16:[0-9]+]], $[[T15]], $[[T2]] +; PRE4: subu $5, $7, $[[T1]] + +; MMR3: lw $[[T1:[0-9]+]], 48($sp) +; MMR3: sltu $[[T2:[0-9]+]], $6, $[[T1]] +; MMR3: xor $[[T3:[0-9]+]], $6, $[[T1]] +; MMR3: lw $[[T4:[0-9]+]], 52($sp) +; MMR3: sltu $[[T5:[0-9]+]], $7, $[[T4]] +; MMR3: movz $[[T6:[0-9]+]], $[[T5]], $[[T3]] +; MMR3: lw $[[T7:[0-8]+]], 44($sp) +; MMR3: subu16 $[[T8:[0-9]+]], $5, $[[T7]] +; MMR3: subu16 $[[T9:[0-9]+]], $[[T8]], $[[T6]] +; MMR3: sltu $[[T10:[0-9]+]], $[[T8]], $[[T2]] +; MMR3: sltu $[[T11:[0-9]+]], $5, $[[T7]] +; MMR3: lw $[[T12:[0-9]+]], 40($sp) +; MMR3: lw $[[T13:[0-9]+]], 12($sp) +; MMR3: subu16 $[[T14:[0-9]+]], $[[T13]], $[[T12]] +; MMR3: subu16 $[[T15:[0-9]+]], $[[T14]], $[[T11]] +; MMR3: subu16 $[[T16:[0-9]+]], $[[T15]], $[[T10]] +; MMR3: subu16 $[[T17:[0-9]+]], $6, $[[T1]] +; MMR3: subu16 $[[T18:[0-9]+]], $[[T17]], $7 +; MMR3: lw $[[T19:[0-9]+]], 8($sp) +; MMR3: lw $[[T20:[0-9]+]], 0($sp) +; MMR3: subu16 $5, $[[T19]], $[[T20]] + +; MMR6: move $[[T0:[0-9]+]], $7 +; MMR6: sw $[[T0]], 8($sp) +; MMR6: move $[[T1:[0-9]+]], $5 +; MMR6: sw $4, 12($sp) +; MMR6: lw $[[T2:[0-9]+]], 48($sp) +; MMR6: sltu $[[T3:[0-9]+]], $6, $[[T2]] +; MMR6: xor $[[T4:[0-9]+]], $6, $[[T2]] +; MMR6: sltiu $[[T5:[0-9]+]], $[[T4]], 1 +; MMR6: seleqz $[[T6:[0-9]+]], $[[T3]], $[[T5]] +; MMR6: lw $[[T7:[0-9]+]], 52($sp) +; MMR6: sltu $[[T8:[0-9]+]], $[[T0]], $[[T7]] +; MMR6: selnez $[[T9:[0-9]+]], $[[T8]], $[[T5]] +; MMR6: or $[[T10:[0-9]+]], $[[T9]], $[[T6]] +; MMR6: lw $[[T11:[0-9]+]], 44($sp) +; MMR6: subu16 $[[T12:[0-9]+]], $[[T1]], $[[T11]] +; MMR6: subu16 $[[T13:[0-9]+]], $[[T12]], $[[T7]] +; MMR6: sltu $[[T16:[0-9]+]], $[[T12]], $[[T7]] +; MMR6: sltu $[[T17:[0-9]+]], $[[T1]], $[[T11]] +; MMR6: lw $[[T18:[0-9]+]], 40($sp) +; MMR6: lw $[[T19:[0-9]+]], 12($sp) +; MMR6: subu16 $[[T20:[0-9]+]], $[[T19]], $[[T18]] +; MMR6: subu16 $[[T21:[0-9]+]], $[[T20]], $[[T17]] +; MMR6: subu16 $[[T22:[0-9]+]], $[[T21]], $[[T16]] +; MMR6: subu16 $[[T23:[0-9]+]], $6, $[[T2]] +; MMR6: subu16 $4, $[[T23]], $5 +; MMR6: lw $[[T24:[0-9]+]], 8($sp) +; MMR6: lw $[[T25:[0-9]+]], 0($sp) +; MMR6: subu16 $5, $[[T24]], $[[T25]] +; MMR6: lw $3, 4($sp) + +; FIXME: The sltu, dsll, dsrl pattern here occurs when an i32 is zero +; extended to 64 bits. Fortunately slt(i)(u) actually gives an i1. +; These should be combined away. + +; GP64-NOT-R2: dsubu $1, $4, $6 +; GP64-NOT-R2: sltu $[[T0:[0-9]+]], $5, $7 +; GP64-NOT-R2: dsll $[[T1:[0-9]+]], $[[T0]], 32 +; GP64-NOT-R2: dsrl $[[T2:[0-9]+]], $[[T1]], 32 +; GP64-NOT-R2: dsubu $2, $1, $[[T2]] +; GP64-NOT-R2: dsubu $3, $5, $7 + +; FIXME: Likewise for the sltu, dext here. + +; GP64-R2: dsubu $1, $4, $6 +; GP64-R2: sltu $[[T0:[0-9]+]], $5, $7 +; GP64-R2: dext $[[T1:[0-9]+]], $[[T0]], 0, 32 +; GP64-R2: dsubu $2, $1, $[[T1]] +; GP64-R2: dsubu $3, $5, $7 + +; FIXME: Again, redundant sign extension. Also, microMIPSR6 has the +; dext instruction which should be used here. + +; MM64: dsubu $[[T0:[0-9]+]], $4, $6 +; MM64: sltu $[[T1:[0-9]+]], $5, $7 +; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32 +; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32 +; MM64: dsubu $2, $[[T0]], $[[T3]] +; MM64: dsubu $3, $5, $7 +; MM64: jr $ra %r = sub i128 %a, %b ret i128 %r diff --git a/test/CodeGen/Mips/longbranch.ll b/test/CodeGen/Mips/longbranch.ll index 11bc6d3..c616089 100644 --- a/test/CodeGen/Mips/longbranch.ll +++ b/test/CodeGen/Mips/longbranch.ll @@ -1,17 +1,17 @@ -; RUN: llc -march=mipsel -relocation-model=pic < %s | FileCheck %s -; RUN: llc -march=mipsel -force-mips-long-branch -O3 -relocation-model=pic < %s \ +; RUN: llc -march=mipsel -relocation-model=pic < %s -verify-machineinstrs | FileCheck %s +; RUN: llc -march=mipsel -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs \ ; RUN: | FileCheck %s -check-prefix=O32 ; RUN: llc -march=mipsel -mcpu=mips32r6 -force-mips-long-branch -O3 \ -; RUN: -relocation-model=pic -asm-show-inst < %s | FileCheck %s -check-prefix=O32-R6 +; RUN: -relocation-model=pic -asm-show-inst < %s -verify-machineinstrs | FileCheck %s -check-prefix=O32-R6 ; RUN: llc -march=mips64el -mcpu=mips4 -target-abi=n64 -force-mips-long-branch -O3 -relocation-model=pic \ -; RUN: < %s | FileCheck %s -check-prefix=N64 +; RUN: < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64 ; RUN: llc -march=mips64el -mcpu=mips64 -target-abi=n64 -force-mips-long-branch -O3 -relocation-model=pic \ -; RUN: < %s | FileCheck %s -check-prefix=N64 +; RUN: < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64 ; RUN: llc -march=mips64el -mcpu=mips64r6 -target-abi=n64 -force-mips-long-branch -O3 \ -; RUN: -relocation-model=pic -asm-show-inst < %s | FileCheck %s -check-prefix=N64-R6 +; RUN: -relocation-model=pic -asm-show-inst < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64-R6 ; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=micromips \ -; RUN: -force-mips-long-branch -O3 -relocation-model=pic < %s | FileCheck %s -check-prefix=MICROMIPS -; RUN: llc -mtriple=mipsel-none-nacl -force-mips-long-branch -O3 -relocation-model=pic < %s \ +; RUN: -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs | FileCheck %s -check-prefix=MICROMIPS +; RUN: llc -mtriple=mipsel-none-nacl -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs \ ; RUN: | FileCheck %s -check-prefix=NACL @@ -59,9 +59,9 @@ end: ; Check for long branch expansion: ; O32: addiu $sp, $sp, -8 ; O32-NEXT: sw $ra, 0($sp) -; O32-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]])) +; O32-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]])) ; O32-NEXT: bal $[[BB1]] -; O32-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]])) +; O32-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]])) ; O32-NEXT: $[[BB1]]: ; O32-NEXT: addu $1, $ra, $1 ; O32-NEXT: lw $ra, 0($sp) @@ -72,7 +72,7 @@ end: ; O32: lw $[[R1:[0-9]+]], %got(x)($[[GP]]) ; O32: addiu $[[R2:[0-9]+]], $zero, 1 ; O32: sw $[[R2]], 0($[[R1]]) -; O32: $[[BB2]]: +; O32: # BB#[[BB2]]: ; O32: jr $ra ; O32: nop @@ -90,10 +90,10 @@ end: ; Check for long branch expansion: ; N64: daddiu $sp, $sp, -16 ; N64-NEXT: sd $ra, 0($sp) -; N64-NEXT: daddiu $1, $zero, %hi([[BB2:\.LBB[0-9_]+]]-[[BB1:\.LBB[0-9_]+]]) +; N64-NEXT: daddiu $1, $zero, %hi(.LBB0_[[BB2:[0-9_]+]]-[[BB1:\.LBB[0-9_]+]]) ; N64-NEXT: dsll $1, $1, 16 ; N64-NEXT: bal [[BB1]] -; N64-NEXT: daddiu $1, $1, %lo([[BB2]]-[[BB1]]) +; N64-NEXT: daddiu $1, $1, %lo(.LBB0_[[BB2]]-[[BB1]]) ; N64-NEXT: [[BB1]]: ; N64-NEXT: daddu $1, $ra, $1 ; N64-NEXT: ld $ra, 0($sp) @@ -105,7 +105,7 @@ end: ; N64: addiu $[[R3:[0-9]+]], $zero, 1 ; N64: ld $[[R2:[0-9]+]], %got_disp(x)($[[GP]]) ; N64: sw $[[R3]], 0($[[R2]]) -; N64: [[BB2]]: +; N64: # BB#[[BB2]]: ; N64: jr $ra ; N64: nop @@ -125,9 +125,9 @@ end: ; Check for long branch expansion: ; MICROMIPS: addiu $sp, $sp, -8 ; MICROMIPS-NEXT: sw $ra, 0($sp) -; MICROMIPS-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]])) +; MICROMIPS-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]])) ; MICROMIPS-NEXT: bal $[[BB1]] -; MICROMIPS-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]])) +; MICROMIPS-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]])) ; MICROMIPS-NEXT: $[[BB1]]: ; MICROMIPS-NEXT: addu $1, $ra, $1 ; MICROMIPS-NEXT: lw $ra, 0($sp) @@ -138,7 +138,7 @@ end: ; MICROMIPS: lw $[[R1:[0-9]+]], %got(x)($[[GP]]) ; MICROMIPS: li16 $[[R2:[0-9]+]], 1 ; MICROMIPS: sw16 $[[R2]], 0($[[R1]]) -; MICROMIPS: $[[BB2]]: +; MICROMIPS: # BB#[[BB2]]: ; MICROMIPS: jrc $ra @@ -154,9 +154,9 @@ end: ; Check for long branch expansion: ; NACL: addiu $sp, $sp, -8 ; NACL-NEXT: sw $ra, 0($sp) -; NACL-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]])) +; NACL-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]])) ; NACL-NEXT: bal $[[BB1]] -; NACL-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]])) +; NACL-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]])) ; NACL-NEXT: $[[BB1]]: ; NACL-NEXT: addu $1, $ra, $1 ; NACL-NEXT: lw $ra, 0($sp) @@ -169,7 +169,7 @@ end: ; NACL: addiu $[[R2:[0-9]+]], $zero, 1 ; NACL: sw $[[R2]], 0($[[R1]]) ; NACL: .p2align 4 -; NACL-NEXT: $[[BB2]]: +; NACL-NEXT: # BB#[[BB2]]: ; NACL: jr $ra ; NACL: nop } diff --git a/test/CodeGen/Mips/madd-msub.ll b/test/CodeGen/Mips/madd-msub.ll index 7baba00..3e1a2e8 100644 --- a/test/CodeGen/Mips/madd-msub.ll +++ b/test/CodeGen/Mips/madd-msub.ll @@ -25,11 +25,11 @@ ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 -; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 -; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31 -; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]] -; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: addu $2, $[[T5]], $[[T4]] +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]] +; 32R6-DAG: muh $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sra $[[T4:[0-9]+]], $6, 31 +; 32R6-DAG: addu $[[T5:[0-9]+]], $[[T3]], $[[T4]] +; 32R6-DAG: addu $2, $[[T5]], $[[T2]] ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 @@ -71,7 +71,7 @@ entry: ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6 -; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6 +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]] ; FIXME: There's a redundant move here. We should remove it ; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} ; 32R6-DAG: addu $2, $[[T3]], $[[T2]] @@ -109,10 +109,10 @@ entry: ; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} ; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $7 -; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $7 -; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $6 -; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: addu $2, $[[T5]], $[[T4]] +; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $1 +; 32R6-DAG: muh $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $6 +; 32R6-DAG: addu $2, $[[T4]], $[[T2]] ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 @@ -134,6 +134,17 @@ entry: ret i64 %add } +; ALL-LABEL: madd4 +; ALL-NOT: madd ${{[0-9]+}}, ${{[0-9]+}} + +define i32 @madd4(i32 %a, i32 %b, i32 %c) { +entry: + %mul = mul nsw i32 %a, %b + %add = add nsw i32 %c, %mul + + ret i32 %add +} + ; ALL-LABEL: msub1: ; 32-DAG: sra $[[T0:[0-9]+]], $6, 31 @@ -148,13 +159,13 @@ entry: ; DSP-DAG: mfhi $2, $[[AC]] ; DSP-DAG: mflo $3, $[[AC]] -; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: sltu $[[T3:[0-9]+]], $6, $[[T1]] -; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $[[T0]] -; 32R6-DAG: sra $[[T5:[0-9]+]], $6, 31 -; 32R6-DAG: subu $2, $[[T5]], $[[T4]] -; 32R6-DAG: subu $3, $6, $[[T1]] +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sltu $[[T1:[0-9]+]], $6, $[[T0]] +; 32R6-DAG: muh $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31 +; 32R6-DAG: subu $[[T4:[0-9]+]], $[[T3]], $[[T2]] +; 32R6-DAG: subu $2, $[[T4]], $[[T1]] +; 32R6-DAG: subu $3, $6, $[[T0]] ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 @@ -194,13 +205,12 @@ entry: ; DSP-DAG: mfhi $2, $[[AC]] ; DSP-DAG: mflo $3, $[[AC]] -; 32R6-DAG: muhu $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} - -; 32R6-DAG: sltu $[[T2:[0-9]+]], $6, $[[T1]] -; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] -; 32R6-DAG: negu $2, $[[T3]] -; 32R6-DAG: subu $3, $6, $[[T1]] +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sltu $[[T1:[0-9]+]], $6, $[[T0]] +; 32R6-DAG: muhu $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: negu $[[T3:[0-9]+]], $[[T2]] +; 32R6-DAG: subu $2, $[[T3]], $[[T1]] +; 32R6-DAG: subu $3, $6, $[[T0]] ; 64-DAG: d[[m:m]]ult $5, $4 ; 64-DAG: [[m]]flo $[[T0:[0-9]+]] @@ -234,12 +244,12 @@ entry: ; DSP-DAG: mfhi $2, $[[AC]] ; DSP-DAG: mflo $3, $[[AC]] -; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}} -; 32R6-DAG: sltu $[[T2:[0-9]+]], $7, $[[T1]] -; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]] -; 32R6-DAG: subu $2, $6, $[[T3]] -; 32R6-DAG: subu $3, $7, $[[T1]] +; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: sltu $[[T1:[0-9]+]], $7, $[[T0]] +; 32R6-DAG: muh $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}} +; 32R6-DAG: subu $[[T3:[0-9]+]], $6, $[[T2]] +; 32R6-DAG: subu $2, $[[T3]], $[[T1]] +; 32R6-DAG: subu $3, $7, $[[T0]] ; 64-DAG: sll $[[T0:[0-9]+]], $4, 0 ; 64-DAG: sll $[[T1:[0-9]+]], $5, 0 @@ -260,3 +270,14 @@ entry: %sub = sub nsw i64 %c, %mul ret i64 %sub } + +; ALL-LABEL: msub4 +; ALL-NOT: msub ${{[0-9]+}}, ${{[0-9]+}} + +define i32 @msub4(i32 %a, i32 %b, i32 %c) { +entry: + %mul = mul nsw i32 %a, %b + %sub = sub nsw i32 %c, %mul + + ret i32 %sub +} diff --git a/test/CodeGen/PowerPC/atomic-2.ll b/test/CodeGen/PowerPC/atomic-2.ll index 2039c1f..f402cb7 100644 --- a/test/CodeGen/PowerPC/atomic-2.ll +++ b/test/CodeGen/PowerPC/atomic-2.ll @@ -109,7 +109,7 @@ entry: %tmp = load atomic i64, i64* %mem acquire, align 64 ; CHECK-NOT: ldarx ; CHECK: ld [[VAL:r[0-9]+]] -; CHECK: cmpw [[CR:cr[0-9]+]], [[VAL]], [[VAL]] +; CHECK: cmpd [[CR:cr[0-9]+]], [[VAL]], [[VAL]] ; CHECK: bne- [[CR]], .+4 ; CHECK: isync ret i64 %tmp diff --git a/test/CodeGen/PowerPC/atomics-constant.ll b/test/CodeGen/PowerPC/atomics-constant.ll index a92ca81..77825c6 100644 --- a/test/CodeGen/PowerPC/atomics-constant.ll +++ b/test/CodeGen/PowerPC/atomics-constant.ll @@ -11,7 +11,7 @@ define i64 @foo() { ; CHECK-NEXT: addis 3, 2, .LC0@toc@ha ; CHECK-NEXT: li 4, 0 ; CHECK-NEXT: ld 3, .LC0@toc@l(3) -; CHECK-NEXT: cmpw 7, 4, 4 +; CHECK-NEXT: cmpd 7, 4, 4 ; CHECK-NEXT: ld 3, 0(3) ; CHECK-NEXT: bne- 7, .+4 ; CHECK-NEXT: isync diff --git a/test/CodeGen/PowerPC/atomics-regression.ll b/test/CodeGen/PowerPC/atomics-regression.ll index 054d3a4..d57b3a2 100644 --- a/test/CodeGen/PowerPC/atomics-regression.ll +++ b/test/CodeGen/PowerPC/atomics-regression.ll @@ -23,7 +23,7 @@ define i8 @test2(i8* %ptr) { ; PPC64LE-LABEL: test2: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: lbz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -37,7 +37,7 @@ define i8 @test3(i8* %ptr) { ; PPC64LE-NEXT: sync ; PPC64LE-NEXT: ori 2, 2, 0 ; PPC64LE-NEXT: lbz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -67,7 +67,7 @@ define i16 @test6(i16* %ptr) { ; PPC64LE-LABEL: test6: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: lhz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -81,7 +81,7 @@ define i16 @test7(i16* %ptr) { ; PPC64LE-NEXT: sync ; PPC64LE-NEXT: ori 2, 2, 0 ; PPC64LE-NEXT: lhz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -111,7 +111,7 @@ define i32 @test10(i32* %ptr) { ; PPC64LE-LABEL: test10: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: lwz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -125,7 +125,7 @@ define i32 @test11(i32* %ptr) { ; PPC64LE-NEXT: sync ; PPC64LE-NEXT: ori 2, 2, 0 ; PPC64LE-NEXT: lwz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -155,7 +155,7 @@ define i64 @test14(i64* %ptr) { ; PPC64LE-LABEL: test14: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: ld 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -169,7 +169,7 @@ define i64 @test15(i64* %ptr) { ; PPC64LE-NEXT: sync ; PPC64LE-NEXT: ori 2, 2, 0 ; PPC64LE-NEXT: ld 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: blr @@ -9566,7 +9566,7 @@ define i32 @test_ordering0(i32* %ptr1, i32* %ptr2) { ; PPC64LE-LABEL: test_ordering0: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: lwz 4, 0(3) -; PPC64LE-NEXT: cmpw 7, 4, 4 +; PPC64LE-NEXT: cmpd 7, 4, 4 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: lwz 3, 0(3) @@ -9583,7 +9583,7 @@ define i32 @test_ordering1(i32* %ptr1, i32 %val1, i32* %ptr2) { ; PPC64LE-LABEL: test_ordering1: ; PPC64LE: # BB#0: ; PPC64LE-NEXT: lwz 3, 0(3) -; PPC64LE-NEXT: cmpw 7, 3, 3 +; PPC64LE-NEXT: cmpd 7, 3, 3 ; PPC64LE-NEXT: bne- 7, .+4 ; PPC64LE-NEXT: isync ; PPC64LE-NEXT: stw 4, 0(5) diff --git a/test/CodeGen/PowerPC/licm-tocReg.ll b/test/CodeGen/PowerPC/licm-tocReg.ll new file mode 100644 index 0000000..ecdfcba --- /dev/null +++ b/test/CodeGen/PowerPC/licm-tocReg.ll @@ -0,0 +1,110 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s + +; The instructions ADDIStocHA/LDtocL are used to calculate the address of +; globals. The ones that are in bb.3.if.end could not be hoisted by Machine +; LICM due to BCTRL_LDinto_toc in bb2.if.then. This call causes the compiler +; to insert a save TOC to stack before the call and load into X2 to restore TOC +; after. By communicating to Machine LICM that X2 is guaranteed to have the +; same value before and after BCTRL_LDinto_toc, these instructions can be +; hoisted out of bb.3.if.end to outside of the loop. + +; Pre Machine LICM MIR +; +;body: +; bb.0.entry: +; successors: %bb.2.if.then(0x40000000), %bb.3.if.end(0x40000000) +; liveins: %x3 +; +; %4 = COPY %x3 +; %5 = ADDIStocHA %x2, @ga +; %6 = LDtocL @ga, killed %5 :: (load 8 from got) +; %7 = LWZ 0, %6 :: (volatile dereferenceable load 4 from @ga) +; %8 = ADDIStocHA %x2, @gb +; %9 = LDtocL @gb, killed %8 :: (load 8 from got) +; %10 = LWZ 0, killed %9 :: (volatile dereferenceable load 4 from @gb) +; %0 = LWZ 0, %6 :: (volatile dereferenceable load 4 from @ga) +; %11 = CMPW killed %7, killed %10 +; BCC 44, killed %11, %bb.2.if.then +; B %bb.3.if.end +; +; bb.2.if.then: +; %1 = PHI %0, %bb.0.entry, %3, %bb.3.if.end +; ADJCALLSTACKDOWN 32, 0, implicit-def dead %r1, implicit %r1 +; %20 = COPY %x2 +; STD %20, 24, %x1 :: (store 8 into stack + 24) +; %21 = EXTSW_32_64 %1 +; %x3 = COPY %21 +; %x12 = COPY %4 +; MTCTR8 %4, implicit-def %ctr8 +; BCTRL8_LDinto_toc 24, %x1, csr_svr464_altivec, implicit-def dead %lr8, implicit-def dead %x2, implicit %ctr8, implicit %rm, implicit %x3, implicit %x12, implicit %x2, implicit-def %r1, implicit-def %x3 +; ADJCALLSTACKUP 32, 0, implicit-def dead %r1, implicit %r1 +; %22 = COPY %x3 +; %x3 = COPY %22 +; BLR8 implicit %lr8, implicit %rm, implicit %x3 +; +; bb.3.if.end: +; successors: %bb.2.if.then(0x04000000), %bb.3.if.end(0x7c000000) +; +; %2 = PHI %0, %bb.0.entry, %3, %bb.3.if.end +; %12 = ADDI %2, 1 +; %13 = ADDIStocHA %x2, @ga +; %14 = LDtocL @ga, killed %13 :: (load 8 from got) +; STW killed %12, 0, %14 :: (volatile store 4 into @ga) +; %15 = LWZ 0, %14 :: (volatile dereferenceable load 4 from @ga) +; %16 = ADDIStocHA %x2, @gb +; %17 = LDtocL @gb, killed %16 :: (load 8 from got) +; %18 = LWZ 0, killed %17 :: (volatile dereferenceable load 4 from @gb) +; %3 = LWZ 0, %14 :: (volatile dereferenceable load 4 from @ga) +; %19 = CMPW killed %15, killed %18 +; BCC 44, killed %19, %bb.2.if.then +; B %bb.3.if.end + +@ga = external global i32, align 4 +@gb = external global i32, align 4 + +; Function Attrs: nounwind +define signext i32 @test(i32 (i32)* nocapture %FP) local_unnamed_addr #0 { +; CHECK-LABEL: test: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: addis 4, 2, .LC0@toc@ha +; CHECK-NEXT: addis 5, 2, .LC1@toc@ha +; CHECK-NEXT: ld 4, .LC0@toc@l(4) +; CHECK-NEXT: ld 5, .LC1@toc@l(5) +; CHECK-NEXT: lwz 6, 0(4) +; CHECK-NEXT: lwz 5, 0(5) +; CHECK-NEXT: cmpw 6, 5 +; CHECK-NEXT: lwz 5, 0(4) +; CHECK-NEXT: mr 4, 3 +; CHECK-NEXT: bgt 0, .LBB0_3 +; CHECK-NEXT: # BB#1: +; CHECK-NEXT: addis 3, 2, .LC0@toc@ha +; CHECK-NEXT: addis 6, 2, .LC1@toc@ha +; CHECK-NEXT: ld 3, .LC0@toc@l(3) +; CHECK-NEXT: ld 6, .LC1@toc@l(6) +; CHECK-NEXT: .p2align 5 +; CHECK-NEXT: .LBB0_2: # %if.end +; CHECK-NOT: addis {{[0-9]+}}, 2, .LC0@toc@ha +; CHECK-NOT: addis {{[0-9]+}}, 2, .LC1@toc@ha +; CHECK: blr +entry: + %0 = load volatile i32, i32* @ga, align 4 + %1 = load volatile i32, i32* @gb, align 4 + %cmp1 = icmp sgt i32 %0, %1 + %2 = load volatile i32, i32* @ga, align 4 + br i1 %cmp1, label %if.then, label %if.end + +if.then: ; preds = %if.end, %entry + %.lcssa = phi i32 [ %2, %entry ], [ %6, %if.end ] + %call = tail call signext i32 %FP(i32 signext %.lcssa) #1 + ret i32 %call + +if.end: ; preds = %entry, %if.end + %3 = phi i32 [ %6, %if.end ], [ %2, %entry ] + %inc = add nsw i32 %3, 1 + store volatile i32 %inc, i32* @ga, align 4 + %4 = load volatile i32, i32* @ga, align 4 + %5 = load volatile i32, i32* @gb, align 4 + %cmp = icmp sgt i32 %4, %5 + %6 = load volatile i32, i32* @ga, align 4 + br i1 %cmp, label %if.then, label %if.end +} diff --git a/test/CodeGen/PowerPC/logic-ops-on-compares.ll b/test/CodeGen/PowerPC/logic-ops-on-compares.ll index 5a507e9..df021c2 100644 --- a/test/CodeGen/PowerPC/logic-ops-on-compares.ll +++ b/test/CodeGen/PowerPC/logic-ops-on-compares.ll @@ -40,8 +40,8 @@ return: ; preds = %if.end, %if.then ret i32 %retval.0 } -define void @neg_truncate_i32_eq(i32 *%ptr) { -; CHECK-LABEL: neg_truncate_i32_eq: +define void @neg_truncate_i32(i32 *%ptr) { +; CHECK-LABEL: neg_truncate_i32: ; CHECK: # BB#0: # %entry ; CHECK-NEXT: lwz r3, 0(r3) ; CHECK-NEXT: rldicl. r3, r3, 0, 63 @@ -66,8 +66,8 @@ if.end29: ; preds = %if.else } ; Function Attrs: nounwind -define i64 @logic_eq_64(i64 %a, i64 %b, i64 %c) { -; CHECK-LABEL: logic_eq_64: +define i64 @logic_ne_64(i64 %a, i64 %b, i64 %c) { +; CHECK-LABEL: logic_ne_64: ; CHECK: xor r7, r3, r4 ; CHECK-NEXT: li r6, 55 ; CHECK-NEXT: xor r5, r5, r6 @@ -99,8 +99,8 @@ return: ; preds = %if.end, %if.then ret i64 %retval.0 } -define void @neg_truncate_i64_eq(i64 *%ptr) { -; CHECK-LABEL: neg_truncate_i64_eq: +define void @neg_truncate_i64(i64 *%ptr) { +; CHECK-LABEL: neg_truncate_i64: ; CHECK: # BB#0: # %entry ; CHECK-NEXT: ld r3, 0(r3) ; CHECK-NEXT: rldicl. r3, r3, 0, 63 @@ -124,67 +124,6 @@ if.end29: ; preds = %if.else } -; Function Attrs: nounwind -define i64 @logic_ne_64(i64 %a, i64 %b, i64 %c) { -; CHECK-LABEL: logic_ne_64: -; CHECK: xor r7, r3, r4 -; CHECK-NEXT: li r6, 55 -; CHECK-NEXT: addic r8, r7, -1 -; CHECK-NEXT: xor r5, r5, r6 -; CHECK-NEXT: subfe r7, r8, r7 -; CHECK-NEXT: cntlzd r5, r5 -; CHECK-NEXT: addic r12, r4, -1 -; CHECK-NEXT: rldicl r5, r5, 58, 63 -; CHECK-NEXT: subfe r6, r12, r4 -; CHECK-NEXT: and r6, r7, r6 -; CHECK-NEXT: or. r5, r6, r5 -; CHECK-NEXT: bc 4, 1 -entry: - %tobool = icmp ne i64 %a, %b - %tobool1 = icmp ne i64 %b, 0 - %or.cond = and i1 %tobool, %tobool1 - %tobool3 = icmp eq i64 %c, 55 - %or.cond5 = or i1 %or.cond, %tobool3 - br i1 %or.cond5, label %if.end, label %if.then - -if.then: ; preds = %entry - %call = tail call i64 @foo64(i64 %a) #2 - br label %return - -if.end: ; preds = %entry - %call4 = tail call i64 @bar64(i64 %b) #2 - br label %return - -return: ; preds = %if.end, %if.then - %retval.0 = phi i64 [ %call4, %if.end ], [ %call, %if.then ] - ret i64 %retval.0 -} - -define void @neg_truncate_i64_ne(i64 *%ptr) { -; CHECK-LABEL: neg_truncate_i64_ne: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: ld r3, 0(r3) -; CHECK-NEXT: andi. r3, r3, 1 -; CHECK-NEXT: bclr 12, 1, 0 -; CHECK-NEXT: # BB#1: # %if.end29.thread136 -; CHECK-NEXT: .LBB5_2: # %if.end29 -entry: - %0 = load i64, i64* %ptr, align 4 - %rem17127 = and i64 %0, 1 - %cmp18 = icmp ne i64 %rem17127, 0 - br label %if.else - -if.else: ; preds = %entry - br i1 %cmp18, label %if.end29, label %if.end29.thread136 - -if.end29.thread136: ; preds = %if.else - unreachable - -if.end29: ; preds = %if.else - ret void - -} - declare signext i32 @foo(i32 signext) declare signext i32 @bar(i32 signext) declare i64 @foo64(i64) diff --git a/test/CodeGen/PowerPC/ppc64-P9-mod.ll b/test/CodeGen/PowerPC/ppc64-P9-mod.ll new file mode 100644 index 0000000..46e347b --- /dev/null +++ b/test/CodeGen/PowerPC/ppc64-P9-mod.ll @@ -0,0 +1,263 @@ +; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-PWR8 -implicit-check-not mod[us][wd] + +@mod_resultsw = common local_unnamed_addr global i32 0, align 4 +@mod_resultud = common local_unnamed_addr global i64 0, align 8 +@div_resultsw = common local_unnamed_addr global i32 0, align 4 +@mod_resultuw = common local_unnamed_addr global i32 0, align 4 +@div_resultuw = common local_unnamed_addr global i32 0, align 4 +@div_resultsd = common local_unnamed_addr global i64 0, align 8 +@mod_resultsd = common local_unnamed_addr global i64 0, align 8 +@div_resultud = common local_unnamed_addr global i64 0, align 8 + +; Function Attrs: norecurse nounwind +define void @modulo_sw(i32 signext %a, i32 signext %b) local_unnamed_addr { +entry: + %rem = srem i32 %a, %b + store i32 %rem, i32* @mod_resultsw, align 4 + ret void +; CHECK-LABEL: modulo_sw +; CHECK: modsw {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_sw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind readnone +define zeroext i32 @modulo_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr { +entry: + %rem = urem i32 %a, %b + ret i32 %rem +; CHECK-LABEL: modulo_uw +; CHECK: moduw {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_uw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind readnone +define i64 @modulo_sd(i64 %a, i64 %b) local_unnamed_addr { +entry: + %rem = srem i64 %a, %b + ret i64 %rem +; CHECK-LABEL: modulo_sd +; CHECK: modsd {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_sd +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_ud(i64 %a, i64 %b) local_unnamed_addr { +entry: + %rem = urem i64 %a, %b + store i64 %rem, i64* @mod_resultud, align 8 + ret void +; CHECK-LABEL: modulo_ud +; CHECK: modud {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_ud +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_div_sw(i32 signext %a, i32 signext %b) local_unnamed_addr { +entry: + %rem = srem i32 %a, %b + store i32 %rem, i32* @mod_resultsw, align 4 + %div = sdiv i32 %a, %b + store i32 %div, i32* @div_resultsw, align 4 + ret void +; CHECK-LABEL: modulo_div_sw +; CHECK-NOT: modsw +; CHECK: div +; CHECK-NOT: modsw +; CHECK: mull +; CHECK-NOT: modsw +; CHECK: sub +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_div_sw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_div_abc_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr { +entry: + %rem = srem i32 %a, %c + store i32 %rem, i32* @mod_resultsw, align 4 + %div = sdiv i32 %b, %c + store i32 %div, i32* @div_resultsw, align 4 + ret void +; CHECK-LABEL: modulo_div_abc_sw +; CHECK: modsw {{[0-9]+}}, 3, 5 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_div_abc_sw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_div_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr { +entry: + %rem = urem i32 %a, %b + store i32 %rem, i32* @mod_resultuw, align 4 + %div = udiv i32 %a, %b + store i32 %div, i32* @div_resultuw, align 4 + ret void +; CHECK-LABEL: modulo_div_uw +; CHECK-NOT: modsw +; CHECK: div +; CHECK-NOT: modsw +; CHECK: mull +; CHECK-NOT: modsw +; CHECK: sub +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_div_uw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_div_swuw(i32 signext %a, i32 signext %b) local_unnamed_addr { +entry: + %rem = srem i32 %a, %b + store i32 %rem, i32* @mod_resultsw, align 4 + %div = udiv i32 %a, %b + store i32 %div, i32* @div_resultsw, align 4 + ret void +; CHECK-LABEL: modulo_div_swuw +; CHECK: modsw {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_div_swuw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_div_udsd(i64 %a, i64 %b) local_unnamed_addr { +entry: + %rem = urem i64 %a, %b + store i64 %rem, i64* @mod_resultud, align 8 + %div = sdiv i64 %a, %b + store i64 %div, i64* @div_resultsd, align 8 + ret void +; CHECK-LABEL: modulo_div_udsd +; CHECK: modud {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_div_udsd +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +define void @modulo_const32_sw(i32 signext %a) local_unnamed_addr { +entry: + %rem = srem i32 %a, 32 + store i32 %rem, i32* @mod_resultsw, align 4 + ret void +; CHECK-LABEL: modulo_const32_sw +; CHECK-NOT: modsw +; CHECK: srawi +; CHECK-NOT: modsw +; CHECK: addze +; CHECK-NOT: modsw +; CHECK: slwi +; CHECK-NOT: modsw +; CHECK: subf +; CHECK-NOT: modsw +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_const32_sw +; CHECK-PWR8: srawi +; CHECK-PWR8: addze +; CHECK-PWR8: slwi +; CHECK-PWR8: subf +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @modulo_const3_sw(i32 signext %a) local_unnamed_addr { +entry: + %rem = srem i32 %a, 3 + ret i32 %rem +; CHECK-LABEL: modulo_const3_sw +; CHECK-NOT: modsw +; CHECK: mull +; CHECK-NOT: modsw +; CHECK: sub +; CHECK-NOT: modsw +; CHECK: blr +; CHECK-PWR8-LABEL: modulo_const3_sw +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind readnone +define signext i32 @const2_modulo_sw(i32 signext %a) local_unnamed_addr { +entry: + %rem = srem i32 2, %a + ret i32 %rem +; CHECK-LABEL: const2_modulo_sw +; CHECK: modsw {{[0-9]+}}, {{[0-9]+}}, 3 +; CHECK: blr +; CHECK-PWR8-LABEL: const2_modulo_sw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + +; Function Attrs: norecurse nounwind +; FIXME On power 9 this test will still produce modsw because the divide is in +; a different block than the remainder. Due to the nature of the SDAG we cannot +; see the div in the other block. +define void @blocks_modulo_div_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr { +entry: + %div = sdiv i32 %a, %b + store i32 %div, i32* @div_resultsw, align 4 + %cmp = icmp sgt i32 %c, 0 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + %rem = srem i32 %a, %b + store i32 %rem, i32* @mod_resultsw, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +; CHECK-LABEL: blocks_modulo_div_sw +; CHECK: div +; CHECK: modsw {{[0-9]+}}, 3, 4 +; CHECK: blr +; CHECK-PWR8-LABEL: blocks_modulo_div_sw +; CHECK-PWR8: div +; CHECK-PWR8: mull +; CHECK-PWR8: sub +; CHECK-PWR8: blr +} + + diff --git a/test/CodeGen/PowerPC/testComparesinesll.ll b/test/CodeGen/PowerPC/testComparesinesll.ll deleted file mode 100644 index 9e93694..0000000 --- a/test/CodeGen/PowerPC/testComparesinesll.ll +++ /dev/null @@ -1,125 +0,0 @@ -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py - -@glob = common local_unnamed_addr global i64 0, align 8 - -define signext i32 @test_inesll(i64 %a, i64 %b) { -; CHECK-LABEL: test_inesll: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv = zext i1 %cmp to i32 - ret i32 %conv -} - -define signext i32 @test_inesll_sext(i64 %a, i64 %b) { -; CHECK-LABEL: test_inesll_sext: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %sub = sext i1 %cmp to i32 - ret i32 %sub -} - -define signext i32 @test_inesll_z(i64 %a) { -; CHECK-LABEL: test_inesll_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv = zext i1 %cmp to i32 - ret i32 %conv -} - -define signext i32 @test_inesll_sext_z(i64 %a) { -; CHECK-LABEL: test_inesll_sext_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %sub = sext i1 %cmp to i32 - ret i32 %sub -} - -define void @test_inesll_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_inesll_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_inesll_sext_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_inesll_sext_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_inesll_z_store(i64 %a) { -; CHECK-LABEL: test_inesll_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_inesll_sext_z_store(i64 %a) { -; CHECK-LABEL: test_inesll_sext_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} diff --git a/test/CodeGen/PowerPC/testComparesineull.ll b/test/CodeGen/PowerPC/testComparesineull.ll deleted file mode 100644 index 7f0fed1..0000000 --- a/test/CodeGen/PowerPC/testComparesineull.ll +++ /dev/null @@ -1,125 +0,0 @@ -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py - -@glob = common local_unnamed_addr global i64 0, align 8 - -define signext i32 @test_ineull(i64 %a, i64 %b) { -; CHECK-LABEL: test_ineull: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv = zext i1 %cmp to i32 - ret i32 %conv -} - -define signext i32 @test_ineull_sext(i64 %a, i64 %b) { -; CHECK-LABEL: test_ineull_sext: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %sub = sext i1 %cmp to i32 - ret i32 %sub -} - -define signext i32 @test_ineull_z(i64 %a) { -; CHECK-LABEL: test_ineull_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv = zext i1 %cmp to i32 - ret i32 %conv -} - -define signext i32 @test_ineull_sext_z(i64 %a) { -; CHECK-LABEL: test_ineull_sext_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %sub = sext i1 %cmp to i32 - ret i32 %sub -} - -define void @test_ineull_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_ineull_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_ineull_sext_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_ineull_sext_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_ineull_z_store(i64 %a) { -; CHECK-LABEL: test_ineull_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_ineull_sext_z_store(i64 %a) { -; CHECK-LABEL: test_ineull_sext_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} diff --git a/test/CodeGen/PowerPC/testComparesllnesll.ll b/test/CodeGen/PowerPC/testComparesllnesll.ll deleted file mode 100644 index d87ff55..0000000 --- a/test/CodeGen/PowerPC/testComparesllnesll.ll +++ /dev/null @@ -1,125 +0,0 @@ -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py - -@glob = common local_unnamed_addr global i64 0, align 8 - -define i64 @test_llnesll(i64 %a, i64 %b) { -; CHECK-LABEL: test_llnesll: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llnesll_sext(i64 %a, i64 %b) { -; CHECK-LABEL: test_llnesll_sext: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llnesll_z(i64 %a) { -; CHECK-LABEL: test_llnesll_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llnesll_sext_z(i64 %a) { -; CHECK-LABEL: test_llnesll_sext_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - ret i64 %conv1 -} - -define void @test_llnesll_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_llnesll_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llnesll_sext_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_llnesll_sext_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llnesll_z_store(i64 %a) { -; CHECK-LABEL: test_llnesll_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llnesll_sext_z_store(i64 %a) { -; CHECK-LABEL: test_llnesll_sext_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} diff --git a/test/CodeGen/PowerPC/testComparesllneull.ll b/test/CodeGen/PowerPC/testComparesllneull.ll deleted file mode 100644 index 7309d58..0000000 --- a/test/CodeGen/PowerPC/testComparesllneull.ll +++ /dev/null @@ -1,125 +0,0 @@ -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \ -; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \ -; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py - -@glob = common local_unnamed_addr global i64 0, align 8 - -define i64 @test_llneull(i64 %a, i64 %b) { -; CHECK-LABEL: test_llneull: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llneull_sext(i64 %a, i64 %b) { -; CHECK-LABEL: test_llneull_sext: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llneull_z(i64 %a) { -; CHECK-LABEL: test_llneull_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addic r4, r3, -1 -; CHECK-NEXT: subfe r3, r4, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - ret i64 %conv1 -} - -define i64 @test_llneull_sext_z(i64 %a) { -; CHECK-LABEL: test_llneull_sext_z: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - ret i64 %conv1 -} - -define void @test_llneull_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_llneull_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llneull_sext_store(i64 %a, i64 %b) { -; CHECK-LABEL: test_llneull_sext_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r5, r2, .LC0@toc@ha -; CHECK-NEXT: xor r3, r3, r4 -; CHECK-NEXT: ld r12, .LC0@toc@l(r5) -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r12) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, %b - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llneull_z_store(i64 %a) { -; CHECK-LABEL: test_llneull_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: addic r5, r3, -1 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r5, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = zext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} - -define void @test_llneull_sext_z_store(i64 %a) { -; CHECK-LABEL: test_llneull_sext_z_store: -; CHECK: # BB#0: # %entry -; CHECK-NEXT: addis r4, r2, .LC0@toc@ha -; CHECK-NEXT: subfic r3, r3, 0 -; CHECK-NEXT: ld r4, .LC0@toc@l(r4) -; CHECK-NEXT: subfe r3, r3, r3 -; CHECK-NEXT: std r3, 0(r4) -; CHECK-NEXT: blr -entry: - %cmp = icmp ne i64 %a, 0 - %conv1 = sext i1 %cmp to i64 - store i64 %conv1, i64* @glob, align 8 - ret void -} diff --git a/test/CodeGen/PowerPC/vec_revb.ll b/test/CodeGen/PowerPC/vec_revb.ll new file mode 100644 index 0000000..c09164b --- /dev/null +++ b/test/CodeGen/PowerPC/vec_revb.ll @@ -0,0 +1,54 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s + +define <8 x i16> @testXXBRH(<8 x i16> %a) { +; CHECK-LABEL: testXXBRH: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: xxbrh 34, 34 +; CHECK-NEXT: blr + +entry: + %0 = bitcast <8 x i16> %a to <16 x i8> + %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> + %2 = bitcast <16 x i8> %1 to <8 x i16> + ret <8 x i16> %2 +} + +define <4 x i32> @testXXBRW(<4 x i32> %a) { +; CHECK-LABEL: testXXBRW: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: xxbrw 34, 34 +; CHECK-NEXT: blr + +entry: + %0 = bitcast <4 x i32> %a to <16 x i8> + %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> + %2 = bitcast <16 x i8> %1 to <4 x i32> + ret <4 x i32> %2 +} + +define <2 x double> @testXXBRD(<2 x double> %a) { +; CHECK-LABEL: testXXBRD: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: xxbrd 34, 34 +; CHECK-NEXT: blr + +entry: + %0 = bitcast <2 x double> %a to <16 x i8> + %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> + %2 = bitcast <16 x i8> %1 to <2 x double> + ret <2 x double> %2 +} + +define <1 x i128> @testXXBRQ(<1 x i128> %a) { +; CHECK-LABEL: testXXBRQ: +; CHECK: # BB#0: # %entry +; CHECK-NEXT: xxbrq 34, 34 +; CHECK-NEXT: blr + +entry: + %0 = bitcast <1 x i128> %a to <16 x i8> + %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> + %2 = bitcast <16 x i8> %1 to <1 x i128> + ret <1 x i128> %2 +} diff --git a/test/CodeGen/SystemZ/fp-sincos-01.ll b/test/CodeGen/SystemZ/fp-sincos-01.ll index cd182a5..4a38d7a 100644 --- a/test/CodeGen/SystemZ/fp-sincos-01.ll +++ b/test/CodeGen/SystemZ/fp-sincos-01.ll @@ -1,6 +1,6 @@ ; Test that combined sin/cos library call is emitted when appropriate -; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK-NOOPT +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK-OPT ; RUN: llc < %s -mtriple=s390x-linux-gnu -enable-unsafe-fp-math | FileCheck %s --check-prefix=CHECK-OPT define float @f1(float %x) { @@ -8,10 +8,18 @@ define float @f1(float %x) { ; CHECK-OPT: brasl %r14, sincosf@PLT ; CHECK-OPT: le %f0, 164(%r15) ; CHECK-OPT: aeb %f0, 160(%r15) + %tmp1 = call float @sinf(float %x) readnone + %tmp2 = call float @cosf(float %x) readnone + %add = fadd float %tmp1, %tmp2 + ret float %add +} -; CHECK-NOOPT-LABEL: f1: -; CHECK-NOOPT: brasl %r14, sinf@PLT -; CHECK-NOOPT: brasl %r14, cosf@PLT +define float @f1_errno(float %x) { +; CHECK-OPT-LABEL: f1_errno: +; CHECK-OPT: brasl %r14, sinf@PLT +; CHECK-OPT: ler %f9, %f0 +; CHECK-OPT: brasl %r14, cosf@PLT +; CHECK-OPT: aebr %f0, %f9 %tmp1 = call float @sinf(float %x) %tmp2 = call float @cosf(float %x) %add = fadd float %tmp1, %tmp2 @@ -23,10 +31,18 @@ define double @f2(double %x) { ; CHECK-OPT: brasl %r14, sincos@PLT ; CHECK-OPT: ld %f0, 168(%r15) ; CHECK-OPT: adb %f0, 160(%r15) + %tmp1 = call double @sin(double %x) readnone + %tmp2 = call double @cos(double %x) readnone + %add = fadd double %tmp1, %tmp2 + ret double %add +} -; CHECK-NOOPT-LABEL: f2: -; CHECK-NOOPT: brasl %r14, sin@PLT -; CHECK-NOOPT: brasl %r14, cos@PLT +define double @f2_errno(double %x) { +; CHECK-OPT-LABEL: f2_errno: +; CHECK-OPT: brasl %r14, sin@PLT +; CHECK-OPT: ldr %f9, %f0 +; CHECK-OPT: brasl %r14, cos@PLT +; CHECK-OPT: adbr %f0, %f9 %tmp1 = call double @sin(double %x) %tmp2 = call double @cos(double %x) %add = fadd double %tmp1, %tmp2 @@ -37,20 +53,27 @@ define fp128 @f3(fp128 %x) { ; CHECK-OPT-LABEL: f3: ; CHECK-OPT: brasl %r14, sincosl@PLT ; CHECK-OPT: axbr + %tmp1 = call fp128 @sinl(fp128 %x) readnone + %tmp2 = call fp128 @cosl(fp128 %x) readnone + %add = fadd fp128 %tmp1, %tmp2 + ret fp128 %add +} -; CHECK-NOOPT-LABEL: f3: -; CHECK-NOOPT: brasl %r14, sinl@PLT -; CHECK-NOOPT: brasl %r14, cosl@PLT +define fp128 @f3_errno(fp128 %x) { +; CHECK-OPT-LABEL: f3_errno: +; CHECK-OPT: brasl %r14, sinl@PLT +; CHECK-OPT: brasl %r14, cosl@PLT +; CHECK-OPT: axbr %tmp1 = call fp128 @sinl(fp128 %x) %tmp2 = call fp128 @cosl(fp128 %x) %add = fadd fp128 %tmp1, %tmp2 ret fp128 %add } -declare float @sinf(float) readonly -declare double @sin(double) readonly -declare fp128 @sinl(fp128) readonly -declare float @cosf(float) readonly -declare double @cos(double) readonly -declare fp128 @cosl(fp128) readonly +declare float @sinf(float) +declare double @sin(double) +declare fp128 @sinl(fp128) +declare float @cosf(float) +declare double @cos(double) +declare fp128 @cosl(fp128) diff --git a/test/CodeGen/X86/2012-01-11-split-cv.ll b/test/CodeGen/X86/2012-01-11-split-cv.ll index 212aced..34ec48a 100644 --- a/test/CodeGen/X86/2012-01-11-split-cv.ll +++ b/test/CodeGen/X86/2012-01-11-split-cv.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mattr=+avx -mtriple=i686-unknown-unknown | FileCheck %s define void @add18i16(<18 x i16>* nocapture sret %ret, <18 x i16>* %bp) nounwind { @@ -12,7 +12,6 @@ define void @add18i16(<18 x i16>* nocapture sret %ret, <18 x i16>* %bp) nounwind ; CHECK-NEXT: vmovups %ymm0, (%eax) ; CHECK-NEXT: vzeroupper ; CHECK-NEXT: retl $4 -; %b = load <18 x i16>, <18 x i16>* %bp, align 16 %x = add <18 x i16> zeroinitializer, %b store <18 x i16> %x, <18 x i16>* %ret, align 16 diff --git a/test/CodeGen/X86/StackColoring.ll b/test/CodeGen/X86/StackColoring.ll index 93888c4..47c7417 100644 --- a/test/CodeGen/X86/StackColoring.ll +++ b/test/CodeGen/X86/StackColoring.ll @@ -582,12 +582,76 @@ if.end: ; preds = %if.then, %entry ret i32 %x.addr.0 } +;CHECK-LABEL: multi_segment: +;YESCOLOR: subq $256, %rsp +;NOFIRSTUSE: subq $256, %rsp +;NOCOLOR: subq $512, %rsp +define i1 @multi_segment(i1, i1) +{ +entry-block: + %foo = alloca [32 x i64] + %bar = alloca [32 x i64] + %foo_i8 = bitcast [32 x i64]* %foo to i8* + %bar_i8 = bitcast [32 x i64]* %bar to i8* + call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8) + call void @baz([32 x i64]* %bar, i32 1) + call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8) + call void @llvm.lifetime.start.p0i8(i64 256, i8* %foo_i8) + call void @baz([32 x i64]* %foo, i32 1) + call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8) + call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8) + call void @baz([32 x i64]* %bar, i32 1) + call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8) + ret i1 true +} + +;CHECK-LABEL: pr32488: +;YESCOLOR: subq $256, %rsp +;NOFIRSTUSE: subq $256, %rsp +;NOCOLOR: subq $512, %rsp +define i1 @pr32488(i1, i1) +{ +entry-block: + %foo = alloca [32 x i64] + %bar = alloca [32 x i64] + %foo_i8 = bitcast [32 x i64]* %foo to i8* + %bar_i8 = bitcast [32 x i64]* %bar to i8* + br i1 %0, label %if_false, label %if_true +if_false: + call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8) + call void @baz([32 x i64]* %bar, i32 0) + br i1 %1, label %if_false.1, label %onerr +if_false.1: + call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8) + br label %merge +if_true: + call void @llvm.lifetime.start.p0i8(i64 256, i8* %foo_i8) + call void @baz([32 x i64]* %foo, i32 1) + br i1 %1, label %if_true.1, label %onerr +if_true.1: + call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8) + br label %merge +merge: + ret i1 false +onerr: + call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8) + call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8) + call void @destructor() + ret i1 true +} + +%Data = type { [32 x i64] } + +declare void @destructor() + declare void @inita(i32*) declare void @initb(i32*,i32*,i32*) declare void @bar([100 x i32]* , [100 x i32]*) nounwind +declare void @baz([32 x i64]*, i32) + declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind diff --git a/test/CodeGen/X86/add-sub-nsw-nuw.ll b/test/CodeGen/X86/add-sub-nsw-nuw.ll index f5bffb2..d02736d 100644 --- a/test/CodeGen/X86/add-sub-nsw-nuw.ll +++ b/test/CodeGen/X86/add-sub-nsw-nuw.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=i386-apple-darwin < %s | FileCheck %s ; PR30841: https://llvm.org/bugs/show_bug.cgi?id=30841 @@ -12,7 +12,6 @@ define i8 @PR30841(i64 %argc) { ; CHECK-NEXT: negl %eax ; CHECK-NEXT: ## kill: %AL %AL %EAX ; CHECK-NEXT: retl -; entry: %or = or i64 %argc, -4294967296 br label %end diff --git a/test/CodeGen/X86/addcarry.ll b/test/CodeGen/X86/addcarry.ll index 3c84af4..cffcfd8 100644 --- a/test/CodeGen/X86/addcarry.ll +++ b/test/CodeGen/X86/addcarry.ll @@ -81,6 +81,30 @@ entry: ret void } +define i8 @e(i32* nocapture %a, i32 %b) nounwind { +; CHECK-LABEL: e: +; CHECK: # BB#0: +; CHECK-NEXT: # kill: %ESI %ESI %RSI +; CHECK-NEXT: movl (%rdi), %ecx +; CHECK-NEXT: leal (%rsi,%rcx), %edx +; CHECK-NEXT: addl %esi, %edx +; CHECK-NEXT: setb %al +; CHECK-NEXT: addl %esi, %ecx +; CHECK-NEXT: movl %edx, (%rdi) +; CHECK-NEXT: adcb $0, %al +; CHECK-NEXT: retq + %1 = load i32, i32* %a, align 4 + %2 = add i32 %1, %b + %3 = icmp ult i32 %2, %b + %4 = zext i1 %3 to i8 + %5 = add i32 %2, %b + store i32 %5, i32* %a, align 4 + %6 = icmp ult i32 %5, %b + %7 = zext i1 %6 to i8 + %8 = add nuw nsw i8 %7, %4 + ret i8 %8 +} + %scalar = type { [4 x i64] } define %scalar @pr31719(%scalar* nocapture readonly %this, %scalar %arg.b) { diff --git a/test/CodeGen/X86/avx-vperm2x128.ll b/test/CodeGen/X86/avx-vperm2x128.ll index f4a77c3..9a21f4b 100644 --- a/test/CodeGen/X86/avx-vperm2x128.ll +++ b/test/CodeGen/X86/avx-vperm2x128.ll @@ -50,16 +50,10 @@ entry: } define <8 x float> @shuffle_v8f32_01230123_mem(<8 x float>* %pa, <8 x float>* %pb) nounwind uwtable readnone ssp { -; AVX1-LABEL: shuffle_v8f32_01230123_mem: -; AVX1: ## BB#0: ## %entry -; AVX1-NEXT: vmovaps (%rdi), %ymm0 -; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0 -; AVX1-NEXT: retq -; -; AVX2-LABEL: shuffle_v8f32_01230123_mem: -; AVX2: ## BB#0: ## %entry -; AVX2-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1,0,1] -; AVX2-NEXT: retq +; ALL-LABEL: shuffle_v8f32_01230123_mem: +; ALL: ## BB#0: ## %entry +; ALL-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1,0,1] +; ALL-NEXT: retq entry: %a = load <8 x float>, <8 x float>* %pa %b = load <8 x float>, <8 x float>* %pb @@ -195,17 +189,15 @@ define <16 x i16> @shuffle_v16i16_4501_mem(<16 x i16>* %a, <16 x i16>* %b) nounw ; AVX1-LABEL: shuffle_v16i16_4501_mem: ; AVX1: ## BB#0: ## %entry ; AVX1-NEXT: vmovdqa (%rdi), %ymm0 -; AVX1-NEXT: vmovaps (%rsi), %ymm1 ; AVX1-NEXT: vpaddw {{.*}}(%rip), %xmm0, %xmm0 -; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1],ymm0[0,1] ; AVX1-NEXT: retq ; ; AVX2-LABEL: shuffle_v16i16_4501_mem: ; AVX2: ## BB#0: ## %entry ; AVX2-NEXT: vmovdqa (%rdi), %ymm0 -; AVX2-NEXT: vmovdqa (%rsi), %ymm1 ; AVX2-NEXT: vpaddw {{.*}}(%rip), %ymm0, %ymm0 -; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm0 = mem[0,1],ymm0[0,1] ; AVX2-NEXT: retq entry: %c = load <16 x i16>, <16 x i16>* %a diff --git a/test/CodeGen/X86/bt.ll b/test/CodeGen/X86/bt.ll index cebcba3..0640581 100644 --- a/test/CodeGen/X86/bt.ll +++ b/test/CodeGen/X86/bt.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s ; PR3253 @@ -24,7 +24,12 @@ define void @test2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB0_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB0_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -44,7 +49,13 @@ define void @test2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB1_1 -; +; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB1_1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -64,7 +75,12 @@ define void @atest2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB2_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB2_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -84,7 +100,13 @@ define void @atest2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB3_1 -; +; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB3_1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -104,7 +126,13 @@ define void @test3(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB4_1 -; +; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB4_1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -124,7 +152,13 @@ define void @test3b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB5_1 -; +; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB5_1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -144,7 +178,12 @@ define void @testne2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB6_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB6_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -164,7 +203,12 @@ define void @testne2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB7_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB7_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -184,7 +228,12 @@ define void @atestne2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB8_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB8_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -204,7 +253,12 @@ define void @atestne2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB9_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB9_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -224,7 +278,12 @@ define void @testne3(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB10_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB10_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -244,7 +303,12 @@ define void @testne3b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB11_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB11_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -264,7 +328,12 @@ define void @query2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB12_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB12_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -284,7 +353,12 @@ define void @query2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB13_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB13_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -304,7 +378,12 @@ define void @aquery2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB14_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB14_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -324,7 +403,12 @@ define void @aquery2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB15_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB15_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -344,7 +428,12 @@ define void @query3(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB16_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB16_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -364,7 +453,12 @@ define void @query3b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB17_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB17_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -384,7 +478,12 @@ define void @query3x(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB18_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB18_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -404,7 +503,12 @@ define void @query3bx(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jae .LBB19_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB19_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -424,7 +528,12 @@ define void @queryne2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB20_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB20_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -444,7 +553,12 @@ define void @queryne2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB21_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB21_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = lshr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -464,7 +578,12 @@ define void @aqueryne2(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB22_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB22_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 %tmp29, 1 @@ -484,7 +603,12 @@ define void @aqueryne2b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB23_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB23_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = ashr i32 %x, %n %tmp3 = and i32 1, %tmp29 @@ -504,7 +628,12 @@ define void @queryne3(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB24_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB24_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -524,7 +653,12 @@ define void @queryne3b(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB25_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB25_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -544,7 +678,12 @@ define void @queryne3x(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB26_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB26_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %tmp29, %x @@ -564,7 +703,12 @@ define void @queryne3bx(i32 %x, i32 %n) nounwind { ; CHECK: # BB#0: # %entry ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: jb .LBB27_2 -; +; CHECK-NEXT: # BB#1: # %bb +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: callq foo +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .LBB27_2: # %UnifiedReturnBlock +; CHECK-NEXT: retq entry: %tmp29 = shl i32 1, %n %tmp3 = and i32 %x, %tmp29 @@ -588,7 +732,6 @@ define zeroext i1 @invert(i32 %flags, i32 %flag) nounwind { ; CHECK-NEXT: btl %esi, %edi ; CHECK-NEXT: setb %al ; CHECK-NEXT: retq -; %neg = xor i32 %flags, -1 %shl = shl i32 1, %flag %and = and i32 %shl, %neg @@ -598,8 +741,10 @@ define zeroext i1 @invert(i32 %flags, i32 %flag) nounwind { define zeroext i1 @extend(i32 %bit, i64 %bits) { ; CHECK-LABEL: extend: -; CHECK: # BB#0: -; CHECK-NEXT: btl %edi, %esi +; CHECK: # BB#0: # %entry +; CHECK-NEXT: btl %edi, %esi +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq entry: %and = and i32 %bit, 31 %sh_prom = zext i32 %and to i64 diff --git a/test/CodeGen/X86/cmov-into-branch.ll b/test/CodeGen/X86/cmov-into-branch.ll index 6e4762b..e380395 100644 --- a/test/CodeGen/X86/cmov-into-branch.ll +++ b/test/CodeGen/X86/cmov-into-branch.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s ; cmp with single-use load, should not form branch. @@ -9,7 +9,6 @@ define i32 @test1(double %a, double* nocapture %b, i32 %x, i32 %y) { ; CHECK-NEXT: cmovbel %edx, %esi ; CHECK-NEXT: movl %esi, %eax ; CHECK-NEXT: retq -; %load = load double, double* %b, align 8 %cmp = fcmp olt double %load, %a %cond = select i1 %cmp, i32 %x, i32 %y @@ -24,7 +23,6 @@ define i32 @test2(double %a, double %b, i32 %x, i32 %y) { ; CHECK-NEXT: cmovbel %esi, %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %cmp = fcmp ogt double %a, %b %cond = select i1 %cmp, i32 %x, i32 %y ret i32 %cond @@ -39,7 +37,6 @@ define i32 @test4(i32 %a, i32* nocapture %b, i32 %x, i32 %y) { ; CHECK-NEXT: cmovael %ecx, %edx ; CHECK-NEXT: addl %edx, %eax ; CHECK-NEXT: retq -; %load = load i32, i32* %b, align 4 %cmp = icmp ult i32 %load, %a %cond = select i1 %cmp, i32 %x, i32 %y @@ -56,7 +53,6 @@ define i32 @test5(i32 %a, i32* nocapture %b, i32 %x, i32 %y) { ; CHECK-NEXT: cmovael %edx, %ecx ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: retq -; %load = load i32, i32* %b, align 4 %cmp = icmp ult i32 %load, %a %cmp1 = icmp ugt i32 %load, %a @@ -73,7 +69,6 @@ define i32 @weighted_select1(i32 %a, i32 %b) { ; CHECK-NEXT: cmovnel %edi, %esi ; CHECK-NEXT: movl %esi, %eax ; CHECK-NEXT: retq -; %cmp = icmp ne i32 %a, 0 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !0 ret i32 %sel @@ -84,12 +79,12 @@ define i32 @weighted_select2(i32 %a, i32 %b) { ; CHECK-LABEL: weighted_select2: ; CHECK: # BB#0: ; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: jne [[LABEL_BB5:.*]] -; CHECK: movl %esi, %edi -; CHECK-NEXT: [[LABEL_BB5]] +; CHECK-NEXT: jne .LBB5_2 +; CHECK-NEXT: # BB#1: # %select.false +; CHECK-NEXT: movl %esi, %edi +; CHECK-NEXT: .LBB5_2: # %select.end ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %cmp = icmp ne i32 %a, 0 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !1 ret i32 %sel @@ -103,14 +98,14 @@ define i32 @weighted_select3(i32 %a, i32 %b) { ; CHECK-LABEL: weighted_select3: ; CHECK: # BB#0: ; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je [[LABEL_BB6:.*]] -; CHECK: movl %edi, %eax +; CHECK-NEXT: je .LBB6_1 +; CHECK-NEXT: # BB#2: # %select.end +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; CHECK: [[LABEL_BB6]] +; CHECK-NEXT: .LBB6_1: # %select.false ; CHECK-NEXT: movl %esi, %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %cmp = icmp ne i32 %a, 0 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !2 ret i32 %sel @@ -124,7 +119,6 @@ define i32 @unweighted_select(i32 %a, i32 %b) { ; CHECK-NEXT: cmovnel %edi, %esi ; CHECK-NEXT: movl %esi, %eax ; CHECK-NEXT: retq -; %cmp = icmp ne i32 %a, 0 %sel = select i1 %cmp, i32 %a, i32 %b, !prof !3 ret i32 %sel diff --git a/test/CodeGen/X86/combine-64bit-vec-binop.ll b/test/CodeGen/X86/combine-64bit-vec-binop.ll index 2842cb1..2935a20 100644 --- a/test/CodeGen/X86/combine-64bit-vec-binop.ll +++ b/test/CodeGen/X86/combine-64bit-vec-binop.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefix=SSE41 define double @test1_add(double %A, double %B) { @@ -6,7 +6,6 @@ define double @test1_add(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: paddd %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %add = add <2 x i32> %1, %2 @@ -19,7 +18,6 @@ define double @test2_add(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: paddw %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %add = add <4 x i16> %1, %2 @@ -32,7 +30,6 @@ define double @test3_add(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: paddb %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %add = add <8 x i8> %1, %2 @@ -45,7 +42,6 @@ define double @test1_sub(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: psubd %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %sub = sub <2 x i32> %1, %2 @@ -58,7 +54,6 @@ define double @test2_sub(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: psubw %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %sub = sub <4 x i16> %1, %2 @@ -71,7 +66,6 @@ define double @test3_sub(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: psubb %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %sub = sub <8 x i8> %1, %2 @@ -84,7 +78,6 @@ define double @test1_mul(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: pmulld %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %mul = mul <2 x i32> %1, %2 @@ -97,7 +90,6 @@ define double @test2_mul(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: pmullw %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %mul = mul <4 x i16> %1, %2 @@ -114,7 +106,6 @@ define double @test3_mul(double %A, double %B) { ; SSE41-NEXT: pmullw %xmm2, %xmm0 ; SSE41-NEXT: pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u] ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %mul = mul <8 x i8> %1, %2 @@ -127,7 +118,6 @@ define double @test1_and(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: andps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %and = and <2 x i32> %1, %2 @@ -140,7 +130,6 @@ define double @test2_and(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: andps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %and = and <4 x i16> %1, %2 @@ -153,7 +142,6 @@ define double @test3_and(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: andps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %and = and <8 x i8> %1, %2 @@ -166,7 +154,6 @@ define double @test1_or(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: orps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %or = or <2 x i32> %1, %2 @@ -179,7 +166,6 @@ define double @test2_or(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: orps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %or = or <4 x i16> %1, %2 @@ -192,7 +178,6 @@ define double @test3_or(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: orps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %or = or <8 x i8> %1, %2 @@ -205,7 +190,6 @@ define double @test1_xor(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: xorps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x i32> %2 = bitcast double %B to <2 x i32> %xor = xor <2 x i32> %1, %2 @@ -218,7 +202,6 @@ define double @test2_xor(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: xorps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <4 x i16> %2 = bitcast double %B to <4 x i16> %xor = xor <4 x i16> %1, %2 @@ -231,7 +214,6 @@ define double @test3_xor(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: xorps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <8 x i8> %2 = bitcast double %B to <8 x i8> %xor = xor <8 x i8> %1, %2 @@ -244,7 +226,6 @@ define double @test_fadd(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: addps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x float> %2 = bitcast double %B to <2 x float> %add = fadd <2 x float> %1, %2 @@ -257,7 +238,6 @@ define double @test_fsub(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: subps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x float> %2 = bitcast double %B to <2 x float> %sub = fsub <2 x float> %1, %2 @@ -270,7 +250,6 @@ define double @test_fmul(double %A, double %B) { ; SSE41: # BB#0: ; SSE41-NEXT: mulps %xmm1, %xmm0 ; SSE41-NEXT: retq -; %1 = bitcast double %A to <2 x float> %2 = bitcast double %B to <2 x float> %mul = fmul <2 x float> %1, %2 diff --git a/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll b/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll index 4dc5b1b..9dd184c 100644 --- a/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll +++ b/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll @@ -2,47 +2,47 @@ define i8* @test_memcpy1(i8* %P, i8* %Q) { ; CHECK: test_memcpy - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 1, i32 1) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 1) ret i8* %P + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $1, %edx - ; CHECK-DAG: movl $1, %ecx - ; CHECK: __llvm_memcpy_element_atomic_1 + ; CHECK: __llvm_memcpy_element_unordered_atomic_1 } define i8* @test_memcpy2(i8* %P, i8* %Q) { ; CHECK: test_memcpy2 - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 2, i32 2) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 2, i32 2) ret i8* %P + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $2, %edx - ; CHECK-DAG: movl $2, %ecx - ; CHECK: __llvm_memcpy_element_atomic_2 + ; CHECK: __llvm_memcpy_element_unordered_atomic_2 } define i8* @test_memcpy4(i8* %P, i8* %Q) { ; CHECK: test_memcpy4 - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 4, i32 4) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 4, i32 4) ret i8* %P + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $4, %edx - ; CHECK-DAG: movl $4, %ecx - ; CHECK: __llvm_memcpy_element_atomic_4 + ; CHECK: __llvm_memcpy_element_unordered_atomic_4 } define i8* @test_memcpy8(i8* %P, i8* %Q) { ; CHECK: test_memcpy8 - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 8 %P, i8* align 8 %Q, i64 8, i32 8) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %P, i8* align 8 %Q, i32 8, i32 8) ret i8* %P + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $8, %edx - ; CHECK-DAG: movl $8, %ecx - ; CHECK: __llvm_memcpy_element_atomic_8 + ; CHECK: __llvm_memcpy_element_unordered_atomic_8 } define i8* @test_memcpy16(i8* %P, i8* %Q) { ; CHECK: test_memcpy16 - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %P, i8* align 16 %Q, i64 16, i32 16) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 16 %P, i8* align 16 %Q, i32 16, i32 16) ret i8* %P + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $16, %edx - ; CHECK-DAG: movl $16, %ecx - ; CHECK: __llvm_memcpy_element_atomic_16 + ; CHECK: __llvm_memcpy_element_unordered_atomic_16 } define void @test_memcpy_args(i8** %Storage) { @@ -51,18 +51,15 @@ define void @test_memcpy_args(i8** %Storage) { %Src.addr = getelementptr i8*, i8** %Storage, i64 1 %Src = load i8*, i8** %Src.addr - ; First argument + ; 1st arg (%rdi) ; CHECK-DAG: movq (%rdi), [[REG1:%r.+]] ; CHECK-DAG: movq [[REG1]], %rdi - ; Second argument + ; 2nd arg (%rsi) ; CHECK-DAG: movq 8(%rdi), %rsi - ; Third argument + ; 3rd arg (%edx) -- length ; CHECK-DAG: movl $4, %edx - ; Fourth argument - ; CHECK-DAG: movl $4, %ecx - ; CHECK: __llvm_memcpy_element_atomic_4 - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 4 %Src, i64 4, i32 4) - ret void + ; CHECK: __llvm_memcpy_element_unordered_atomic_4 + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %Dst, i8* align 4 %Src, i32 4, i32 4) ret void } -declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* nocapture, i8* nocapture, i64, i32) nounwind +declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind diff --git a/test/CodeGen/X86/fast-isel-select-sse.ll b/test/CodeGen/X86/fast-isel-select-sse.ll index 499fe5b..1b6bb36 100644 --- a/test/CodeGen/X86/fast-isel-select-sse.ll +++ b/test/CodeGen/X86/fast-isel-select-sse.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefix=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefix=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -mattr=avx | FileCheck %s --check-prefix=AVX @@ -29,7 +29,6 @@ define float @select_fcmp_oeq_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp oeq float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -56,7 +55,6 @@ define double @select_fcmp_oeq_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp oeq double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -84,7 +82,6 @@ define float @select_fcmp_ogt_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ogt float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -112,7 +109,6 @@ define double @select_fcmp_ogt_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ogt double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -140,7 +136,6 @@ define float @select_fcmp_oge_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp oge float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -168,7 +163,6 @@ define double @select_fcmp_oge_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp oge double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -195,7 +189,6 @@ define float @select_fcmp_olt_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp olt float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -222,7 +215,6 @@ define double @select_fcmp_olt_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp olt double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -249,7 +241,6 @@ define float @select_fcmp_ole_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ole float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -276,7 +267,6 @@ define double @select_fcmp_ole_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ole double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -303,7 +293,6 @@ define float @select_fcmp_ord_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ord float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -330,7 +319,6 @@ define double @select_fcmp_ord_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ord double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -357,7 +345,6 @@ define float @select_fcmp_uno_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp uno float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -384,7 +371,6 @@ define double @select_fcmp_uno_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp uno double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -411,7 +397,6 @@ define float @select_fcmp_ugt_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ugt float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -438,7 +423,6 @@ define double @select_fcmp_ugt_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ugt double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -465,7 +449,6 @@ define float @select_fcmp_uge_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp uge float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -492,7 +475,6 @@ define double @select_fcmp_uge_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp uge double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -520,7 +502,6 @@ define float @select_fcmp_ult_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ult float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -548,7 +529,6 @@ define double @select_fcmp_ult_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ult double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -576,7 +556,6 @@ define float @select_fcmp_ule_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ule float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -604,7 +583,6 @@ define double @select_fcmp_ule_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp ule double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 @@ -631,7 +609,6 @@ define float @select_fcmp_une_f32(float %a, float %b, float %c, float %d) { ; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovaps %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp une float %a, %b %2 = select i1 %1, float %c, float %d ret float %2 @@ -658,7 +635,6 @@ define double @select_fcmp_une_f64(double %a, double %b, double %c, double %d) { ; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1} ; AVX512-NEXT: vmovapd %xmm3, %xmm0 ; AVX512-NEXT: retq -; %1 = fcmp une double %a, %b %2 = select i1 %1, double %c, double %d ret double %2 diff --git a/test/CodeGen/X86/fp-logic-replace.ll b/test/CodeGen/X86/fp-logic-replace.ll index 308b42e..e62b2f3 100644 --- a/test/CodeGen/X86/fp-logic-replace.ll +++ b/test/CodeGen/X86/fp-logic-replace.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+sse2 | FileCheck %s --check-prefix=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+avx | FileCheck %s --check-prefix=AVX ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+avx512dq,+avx512vl | FileCheck %s --check-prefix=AVX512DQ diff --git a/test/CodeGen/X86/fp-logic.ll b/test/CodeGen/X86/fp-logic.ll index 973e064..976470a 100644 --- a/test/CodeGen/X86/fp-logic.ll +++ b/test/CodeGen/X86/fp-logic.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s ; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428 @@ -22,7 +22,6 @@ define i32 @f1(float %x, i32 %y) { ; CHECK-NEXT: movd %xmm0, %eax ; CHECK-NEXT: andl %edi, %eax ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %bc1, %y ret i32 %and @@ -36,7 +35,6 @@ define i32 @f2(float %x, i32 %y) { ; CHECK-NEXT: movd %xmm0, %eax ; CHECK-NEXT: andl %edi, %eax ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %y, %bc1 ret i32 %and @@ -50,7 +48,6 @@ define i32 @f3(float %x) { ; CHECK-NEXT: movd %xmm0, %eax ; CHECK-NEXT: andl $1, %eax ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %bc1, 1 ret i32 %and @@ -64,7 +61,6 @@ define i32 @f4(float %x) { ; CHECK-NEXT: movd %xmm0, %eax ; CHECK-NEXT: andl $2, %eax ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 2, %bc1 ret i32 %and @@ -78,7 +74,6 @@ define float @f5(float %x, i32 %y) { ; CHECK-NEXT: movd %edi, %xmm1 ; CHECK-NEXT: pand %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %bc1, %y %bc2 = bitcast i32 %and to float @@ -93,7 +88,6 @@ define float @f6(float %x, i32 %y) { ; CHECK-NEXT: movd %edi, %xmm1 ; CHECK-NEXT: pand %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %y, %bc1 %bc2 = bitcast i32 %and to float @@ -108,7 +102,6 @@ define float @f7(float %x) { ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %bc1, 3 %bc2 = bitcast i32 %and to float @@ -123,7 +116,6 @@ define float @f8(float %x) { ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 4, %bc1 %bc2 = bitcast i32 %and to float @@ -138,7 +130,6 @@ define i32 @f9(float %x, float %y) { ; CHECK-NEXT: pand %xmm1, %xmm0 ; CHECK-NEXT: movd %xmm0, %eax ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %bc2 = bitcast float %y to i32 %and = and i32 %bc1, %bc2 @@ -152,7 +143,6 @@ define float @f10(float %x, float %y) { ; CHECK: # BB#0: ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %bc2 = bitcast float %y to i32 %and = and i32 %bc1, %bc2 @@ -165,7 +155,6 @@ define float @or(float %x, float %y) { ; CHECK: # BB#0: ; CHECK-NEXT: orps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %bc2 = bitcast float %y to i32 %and = or i32 %bc1, %bc2 @@ -178,7 +167,6 @@ define float @xor(float %x, float %y) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %bc2 = bitcast float %y to i32 %and = xor i32 %bc1, %bc2 @@ -192,7 +180,6 @@ define float @f7_or(float %x) { ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; CHECK-NEXT: orps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = or i32 %bc1, 3 %bc2 = bitcast i32 %and to float @@ -205,7 +192,6 @@ define float @f7_xor(float %x) { ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; CHECK-NEXT: xorps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = xor i32 %bc1, 3 %bc2 = bitcast i32 %and to float @@ -219,7 +205,6 @@ define double @doubles(double %x, double %y) { ; CHECK: # BB#0: ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast double %x to i64 %bc2 = bitcast double %y to i64 %and = and i64 %bc1, %bc2 @@ -233,7 +218,6 @@ define double @f7_double(double %x) { ; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast double %x to i64 %and = and i64 %bc1, 3 %bc2 = bitcast i64 %and to double @@ -250,7 +234,6 @@ define float @movmsk(float %x) { ; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %and = and i32 %bc1, 2147483648 %bc2 = bitcast i32 %and to float @@ -262,7 +245,6 @@ define double @bitcast_fabs(double %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast double %x to i64 %and = and i64 %bc1, 9223372036854775807 %bc2 = bitcast i64 %and to double @@ -274,7 +256,6 @@ define float @bitcast_fneg(float %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast float %x to i32 %xor = xor i32 %bc1, 2147483648 %bc2 = bitcast i32 %xor to float @@ -286,7 +267,6 @@ define <2 x double> @bitcast_fabs_vec(<2 x double> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast <2 x double> %x to <2 x i64> %and = and <2 x i64> %bc1, %bc2 = bitcast <2 x i64> %and to <2 x double> @@ -298,7 +278,6 @@ define <4 x float> @bitcast_fneg_vec(<4 x float> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %bc1 = bitcast <4 x float> %x to <4 x i32> %xor = xor <4 x i32> %bc1, %bc2 = bitcast <4 x i32> %xor to <4 x float> diff --git a/test/CodeGen/X86/fp-select-cmp-and.ll b/test/CodeGen/X86/fp-select-cmp-and.ll index e012809..651d7a3 100644 --- a/test/CodeGen/X86/fp-select-cmp-and.ll +++ b/test/CodeGen/X86/fp-select-cmp-and.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.2 | FileCheck %s define double @test1(double %a, double %b, double %eps) { @@ -7,7 +7,6 @@ define double @test1(double %a, double %b, double %eps) { ; CHECK-NEXT: cmpltsd %xmm2, %xmm0 ; CHECK-NEXT: andpd %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp olt double %a, %eps %cond = select i1 %cmp, double %b, double 0.000000e+00 ret double %cond @@ -19,7 +18,6 @@ define double @test2(double %a, double %b, double %eps) { ; CHECK-NEXT: cmplesd %xmm2, %xmm0 ; CHECK-NEXT: andpd %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ole double %a, %eps %cond = select i1 %cmp, double %b, double 0.000000e+00 ret double %cond @@ -32,7 +30,6 @@ define double @test3(double %a, double %b, double %eps) { ; CHECK-NEXT: andpd %xmm1, %xmm2 ; CHECK-NEXT: movapd %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ogt double %a, %eps %cond = select i1 %cmp, double %b, double 0.000000e+00 ret double %cond @@ -45,7 +42,6 @@ define double @test4(double %a, double %b, double %eps) { ; CHECK-NEXT: andpd %xmm1, %xmm2 ; CHECK-NEXT: movapd %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge double %a, %eps %cond = select i1 %cmp, double %b, double 0.000000e+00 ret double %cond @@ -57,7 +53,6 @@ define double @test5(double %a, double %b, double %eps) { ; CHECK-NEXT: cmpltsd %xmm2, %xmm0 ; CHECK-NEXT: andnpd %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp olt double %a, %eps %cond = select i1 %cmp, double 0.000000e+00, double %b ret double %cond @@ -69,7 +64,6 @@ define double @test6(double %a, double %b, double %eps) { ; CHECK-NEXT: cmplesd %xmm2, %xmm0 ; CHECK-NEXT: andnpd %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ole double %a, %eps %cond = select i1 %cmp, double 0.000000e+00, double %b ret double %cond @@ -82,7 +76,6 @@ define double @test7(double %a, double %b, double %eps) { ; CHECK-NEXT: andnpd %xmm1, %xmm2 ; CHECK-NEXT: movapd %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ogt double %a, %eps %cond = select i1 %cmp, double 0.000000e+00, double %b ret double %cond @@ -95,7 +88,6 @@ define double @test8(double %a, double %b, double %eps) { ; CHECK-NEXT: andnpd %xmm1, %xmm2 ; CHECK-NEXT: movapd %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge double %a, %eps %cond = select i1 %cmp, double 0.000000e+00, double %b ret double %cond @@ -107,7 +99,6 @@ define float @test9(float %a, float %b, float %eps) { ; CHECK-NEXT: cmpltss %xmm2, %xmm0 ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp olt float %a, %eps %cond = select i1 %cmp, float %b, float 0.000000e+00 ret float %cond @@ -119,7 +110,6 @@ define float @test10(float %a, float %b, float %eps) { ; CHECK-NEXT: cmpless %xmm2, %xmm0 ; CHECK-NEXT: andps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ole float %a, %eps %cond = select i1 %cmp, float %b, float 0.000000e+00 ret float %cond @@ -132,7 +122,6 @@ define float @test11(float %a, float %b, float %eps) { ; CHECK-NEXT: andps %xmm1, %xmm2 ; CHECK-NEXT: movaps %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ogt float %a, %eps %cond = select i1 %cmp, float %b, float 0.000000e+00 ret float %cond @@ -145,7 +134,6 @@ define float @test12(float %a, float %b, float %eps) { ; CHECK-NEXT: andps %xmm1, %xmm2 ; CHECK-NEXT: movaps %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge float %a, %eps %cond = select i1 %cmp, float %b, float 0.000000e+00 ret float %cond @@ -157,7 +145,6 @@ define float @test13(float %a, float %b, float %eps) { ; CHECK-NEXT: cmpltss %xmm2, %xmm0 ; CHECK-NEXT: andnps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp olt float %a, %eps %cond = select i1 %cmp, float 0.000000e+00, float %b ret float %cond @@ -169,7 +156,6 @@ define float @test14(float %a, float %b, float %eps) { ; CHECK-NEXT: cmpless %xmm2, %xmm0 ; CHECK-NEXT: andnps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ole float %a, %eps %cond = select i1 %cmp, float 0.000000e+00, float %b ret float %cond @@ -182,7 +168,6 @@ define float @test15(float %a, float %b, float %eps) { ; CHECK-NEXT: andnps %xmm1, %xmm2 ; CHECK-NEXT: movaps %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp ogt float %a, %eps %cond = select i1 %cmp, float 0.000000e+00, float %b ret float %cond @@ -195,7 +180,6 @@ define float @test16(float %a, float %b, float %eps) { ; CHECK-NEXT: andnps %xmm1, %xmm2 ; CHECK-NEXT: movaps %xmm2, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge float %a, %eps %cond = select i1 %cmp, float 0.000000e+00, float %b ret float %cond @@ -210,7 +194,6 @@ define float @test17(float %a, float %b, float %c, float %eps) { ; CHECK-NEXT: orps %xmm2, %xmm3 ; CHECK-NEXT: movaps %xmm3, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge float %a, %eps %cond = select i1 %cmp, float %c, float %b ret float %cond @@ -225,7 +208,6 @@ define double @test18(double %a, double %b, double %c, double %eps) { ; CHECK-NEXT: orpd %xmm2, %xmm3 ; CHECK-NEXT: movapd %xmm3, %xmm0 ; CHECK-NEXT: retq -; %cmp = fcmp oge double %a, %eps %cond = select i1 %cmp, double %c, double %b ret double %cond diff --git a/test/CodeGen/X86/immediate_merging64.ll b/test/CodeGen/X86/immediate_merging64.ll index ea8ace1..4bc9d4a 100644 --- a/test/CodeGen/X86/immediate_merging64.ll +++ b/test/CodeGen/X86/immediate_merging64.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; Check that multiple instances of 64-bit constants encodable as @@ -14,7 +14,6 @@ define i1 @imm_multiple_users(i64 %a, i64* %b) optsize { ; CHECK-NEXT: cmpq %rax, %rdi ; CHECK-NEXT: sete %al ; CHECK-NEXT: retq -; store i64 -1, i64* %b, align 8 %cmp = icmp eq i64 %a, -1 ret i1 %cmp @@ -32,7 +31,6 @@ define void @memset_zero(i8* noalias nocapture %D) optsize { ; CHECK-NEXT: movq %rax, 7(%rdi) ; CHECK-NEXT: movq %rax, (%rdi) ; CHECK-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %D, i8 0, i64 15, i32 1, i1 false) ret void } diff --git a/test/CodeGen/X86/lea-opt-with-debug.mir b/test/CodeGen/X86/lea-opt-with-debug.mir index 0a47770..03a7458 100644 --- a/test/CodeGen/X86/lea-opt-with-debug.mir +++ b/test/CodeGen/X86/lea-opt-with-debug.mir @@ -49,7 +49,7 @@ !5 = !{i32 2, !"Dwarf Version", i32 4} !6 = !{i32 2, !"Debug Info Version", i32 3} !7 = !{i32 1, !"PIC Level", i32 2} - !8 = !DIExpression(DW_OP_plus, 8, DW_OP_stack_value) + !8 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value) !9 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 7, type: !10, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: true, unit: !0, variables: !11) !10 = !DISubroutineType(types: !3) !11 = !{!12} diff --git a/test/CodeGen/X86/loop-search.ll b/test/CodeGen/X86/loop-search.ll index 6b29a72..fda4ece 100644 --- a/test/CodeGen/X86/loop-search.ll +++ b/test/CodeGen/X86/loop-search.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s ; This test comes from PR27136 @@ -35,7 +35,6 @@ define zeroext i1 @search(i32 %needle, i32* nocapture readonly %haystack, i32 %c ; CHECK-NEXT: movb $1, %al ; CHECK-NEXT: ## kill: %AL %AL %EAX ; CHECK-NEXT: retq -; entry: %cmp5 = icmp sgt i32 %count, 0 br i1 %cmp5, label %for.body.preheader, label %cleanup diff --git a/test/CodeGen/X86/mask-negated-bool.ll b/test/CodeGen/X86/mask-negated-bool.ll index c5c121c..779641c 100644 --- a/test/CodeGen/X86/mask-negated-bool.ll +++ b/test/CodeGen/X86/mask-negated-bool.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s define i32 @mask_negated_zext_bool1(i1 %x) { @@ -7,7 +7,6 @@ define i32 @mask_negated_zext_bool1(i1 %x) { ; CHECK-NEXT: andl $1, %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %ext = zext i1 %x to i32 %neg = sub i32 0, %ext %and = and i32 %neg, 1 @@ -19,7 +18,6 @@ define i32 @mask_negated_zext_bool2(i1 zeroext %x) { ; CHECK: # BB#0: ; CHECK-NEXT: movzbl %dil, %eax ; CHECK-NEXT: retq -; %ext = zext i1 %x to i32 %neg = sub i32 0, %ext %and = and i32 %neg, 1 @@ -31,7 +29,6 @@ define <4 x i32> @mask_negated_zext_bool_vec(<4 x i1> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %ext = zext <4 x i1> %x to <4 x i32> %neg = sub <4 x i32> zeroinitializer, %ext %and = and <4 x i32> %neg, @@ -44,7 +41,6 @@ define i32 @mask_negated_sext_bool1(i1 %x) { ; CHECK-NEXT: andl $1, %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %ext = sext i1 %x to i32 %neg = sub i32 0, %ext %and = and i32 %neg, 1 @@ -56,7 +52,6 @@ define i32 @mask_negated_sext_bool2(i1 zeroext %x) { ; CHECK: # BB#0: ; CHECK-NEXT: movzbl %dil, %eax ; CHECK-NEXT: retq -; %ext = sext i1 %x to i32 %neg = sub i32 0, %ext %and = and i32 %neg, 1 @@ -68,7 +63,6 @@ define <4 x i32> @mask_negated_sext_bool_vec(<4 x i1> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %ext = sext <4 x i1> %x to <4 x i32> %neg = sub <4 x i32> zeroinitializer, %ext %and = and <4 x i32> %neg, diff --git a/test/CodeGen/X86/memset-2.ll b/test/CodeGen/X86/memset-2.ll index a02ef29..1ac9720 100644 --- a/test/CodeGen/X86/memset-2.ll +++ b/test/CodeGen/X86/memset-2.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=i386-apple-darwin9 -mcpu=yonah < %s | FileCheck %s define fastcc void @t1() nounwind { @@ -10,7 +10,6 @@ define fastcc void @t1() nounwind { ; CHECK-NEXT: pushl $0 ; CHECK-NEXT: calll _memset ; CHECK-NEXT: addl $16, %esp -; entry: call void @llvm.memset.p0i8.i32(i8* null, i8 0, i32 188, i32 1, i1 false) unreachable @@ -23,7 +22,6 @@ define fastcc void @t2(i8 signext %c) nounwind { ; CHECK-NEXT: movl %ecx, {{[0-9]+}}(%esp) ; CHECK-NEXT: movl $76, {{[0-9]+}}(%esp) ; CHECK-NEXT: calll _memset -; entry: call void @llvm.memset.p0i8.i32(i8* undef, i8 %c, i32 76, i32 1, i1 false) unreachable @@ -40,7 +38,6 @@ define void @t3(i8* nocapture %s, i8 %a) nounwind { ; CHECK-NEXT: movl %ecx, 4(%eax) ; CHECK-NEXT: movl %ecx, (%eax) ; CHECK-NEXT: retl -; entry: tail call void @llvm.memset.p0i8.i32(i8* %s, i8 %a, i32 8, i32 1, i1 false) ret void @@ -58,7 +55,6 @@ define void @t4(i8* nocapture %s, i8 %a) nounwind { ; CHECK-NEXT: movw %cx, 12(%eax) ; CHECK-NEXT: movb %cl, 14(%eax) ; CHECK-NEXT: retl -; entry: tail call void @llvm.memset.p0i8.i32(i8* %s, i8 %a, i32 15, i32 1, i1 false) ret void diff --git a/test/CodeGen/X86/memset-nonzero.ll b/test/CodeGen/X86/memset-nonzero.ll index 769fe87..13258fd 100644 --- a/test/CodeGen/X86/memset-nonzero.ll +++ b/test/CodeGen/X86/memset-nonzero.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse | FileCheck %s --check-prefix=SSE ; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse2 | FileCheck %s --check-prefix=SSE ; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse2,-slow-unaligned-mem-16 | FileCheck %s --check-prefix=SSE2FAST @@ -26,7 +26,6 @@ define void @memset_16_nonzero_bytes(i8* %x) { ; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42] ; AVX-NEXT: vmovups %xmm0, (%rdi) ; AVX-NEXT: retq -; %call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 16, i64 -1) ret void } @@ -54,7 +53,6 @@ define void @memset_32_nonzero_bytes(i8* %x) { ; AVX-NEXT: vmovups %ymm0, (%rdi) ; AVX-NEXT: vzeroupper ; AVX-NEXT: retq -; %call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 32, i64 -1) ret void } @@ -89,7 +87,6 @@ define void @memset_64_nonzero_bytes(i8* %x) { ; AVX-NEXT: vmovups %ymm0, (%rdi) ; AVX-NEXT: vzeroupper ; AVX-NEXT: retq -; %call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 64, i64 -1) ret void } @@ -138,7 +135,6 @@ define void @memset_128_nonzero_bytes(i8* %x) { ; AVX-NEXT: vmovups %ymm0, (%rdi) ; AVX-NEXT: vzeroupper ; AVX-NEXT: retq -; %call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 128, i64 -1) ret void } @@ -189,7 +185,6 @@ define void @memset_256_nonzero_bytes(i8* %x) { ; AVX-NEXT: vmovups %ymm0, (%rdi) ; AVX-NEXT: vzeroupper ; AVX-NEXT: retq -; %call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 256, i64 -1) ret void } @@ -231,7 +226,6 @@ define void @memset_16_nonconst_bytes(i8* %x, i8 %c) { ; AVX2-NEXT: vpbroadcastb %xmm0, %xmm0 ; AVX2-NEXT: vmovdqu %xmm0, (%rdi) ; AVX2-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 16, i32 1, i1 false) ret void } @@ -275,7 +269,6 @@ define void @memset_32_nonconst_bytes(i8* %x, i8 %c) { ; AVX2-NEXT: vmovdqu %ymm0, (%rdi) ; AVX2-NEXT: vzeroupper ; AVX2-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 32, i32 1, i1 false) ret void } @@ -327,7 +320,6 @@ define void @memset_64_nonconst_bytes(i8* %x, i8 %c) { ; AVX2-NEXT: vmovdqu %ymm0, (%rdi) ; AVX2-NEXT: vzeroupper ; AVX2-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 64, i32 1, i1 false) ret void } @@ -395,7 +387,6 @@ define void @memset_128_nonconst_bytes(i8* %x, i8 %c) { ; AVX2-NEXT: vmovdqu %ymm0, (%rdi) ; AVX2-NEXT: vzeroupper ; AVX2-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 128, i32 1, i1 false) ret void } @@ -461,7 +452,6 @@ define void @memset_256_nonconst_bytes(i8* %x, i8 %c) { ; AVX2-NEXT: vmovdqu %ymm0, (%rdi) ; AVX2-NEXT: vzeroupper ; AVX2-NEXT: retq -; tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 256, i32 1, i1 false) ret void } diff --git a/test/CodeGen/X86/memset64-on-x86-32.ll b/test/CodeGen/X86/memset64-on-x86-32.ll index 861cb88..a7a3c61 100644 --- a/test/CodeGen/X86/memset64-on-x86-32.ll +++ b/test/CodeGen/X86/memset64-on-x86-32.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i386-unknown-unknown -mattr=sse4.2 | FileCheck %s --check-prefix=FAST ; RUN: llc < %s -mtriple=i386-unknown-unknown -mattr=ssse3 | FileCheck %s --check-prefix=SLOW_32 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=ssse3 | FileCheck %s --check-prefix=SLOW_64 @@ -51,7 +51,6 @@ define void @bork() nounwind { ; SLOW_64-NEXT: movq $0, 8 ; SLOW_64-NEXT: movq $0, 0 ; SLOW_64-NEXT: retq -; call void @llvm.memset.p0i8.i64(i8* null, i8 0, i64 80, i32 4, i1 false) ret void } diff --git a/test/CodeGen/X86/negate-i1.ll b/test/CodeGen/X86/negate-i1.ll index f1678a1..13f831f 100644 --- a/test/CodeGen/X86/negate-i1.ll +++ b/test/CodeGen/X86/negate-i1.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 ; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s --check-prefix=X32 @@ -16,7 +16,6 @@ define i8 @select_i8_neg1_or_0(i1 %a) { ; X32-NEXT: andb $1, %al ; X32-NEXT: negb %al ; X32-NEXT: retl -; %b = sext i1 %a to i8 ret i8 %b } @@ -33,7 +32,6 @@ define i8 @select_i8_neg1_or_0_zeroext(i1 zeroext %a) { ; X32-NEXT: movb {{[0-9]+}}(%esp), %al ; X32-NEXT: negb %al ; X32-NEXT: retl -; %b = sext i1 %a to i8 ret i8 %b } @@ -53,7 +51,6 @@ define i16 @select_i16_neg1_or_0(i1 %a) { ; X32-NEXT: negl %eax ; X32-NEXT: # kill: %AX %AX %EAX ; X32-NEXT: retl -; %b = sext i1 %a to i16 ret i16 %b } @@ -72,7 +69,6 @@ define i16 @select_i16_neg1_or_0_zeroext(i1 zeroext %a) { ; X32-NEXT: negl %eax ; X32-NEXT: # kill: %AX %AX %EAX ; X32-NEXT: retl -; %b = sext i1 %a to i16 ret i16 %b } @@ -91,7 +87,6 @@ define i32 @select_i32_neg1_or_0(i1 %a) { ; X32-NEXT: andl $1, %eax ; X32-NEXT: negl %eax ; X32-NEXT: retl -; %b = sext i1 %a to i32 ret i32 %b } @@ -108,7 +103,6 @@ define i32 @select_i32_neg1_or_0_zeroext(i1 zeroext %a) { ; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax ; X32-NEXT: negl %eax ; X32-NEXT: retl -; %b = sext i1 %a to i32 ret i32 %b } @@ -129,7 +123,6 @@ define i64 @select_i64_neg1_or_0(i1 %a) { ; X32-NEXT: negl %eax ; X32-NEXT: movl %eax, %edx ; X32-NEXT: retl -; %b = sext i1 %a to i64 ret i64 %b } @@ -147,7 +140,6 @@ define i64 @select_i64_neg1_or_0_zeroext(i1 zeroext %a) { ; X32-NEXT: negl %eax ; X32-NEXT: movl %eax, %edx ; X32-NEXT: retl -; %b = sext i1 %a to i64 ret i64 %b } diff --git a/test/CodeGen/X86/negate-shift.ll b/test/CodeGen/X86/negate-shift.ll index 54ffc8e..cbe2f94 100644 --- a/test/CodeGen/X86/negate-shift.ll +++ b/test/CodeGen/X86/negate-shift.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 define i32 @neg_lshr_signbit(i32 %x) { @@ -7,7 +7,6 @@ define i32 @neg_lshr_signbit(i32 %x) { ; X64-NEXT: sarl $31, %edi ; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq -; %sh = lshr i32 %x, 31 %neg = sub i32 0, %sh ret i32 %neg @@ -19,7 +18,6 @@ define i64 @neg_ashr_signbit(i64 %x) { ; X64-NEXT: shrq $63, %rdi ; X64-NEXT: movq %rdi, %rax ; X64-NEXT: retq -; %sh = ashr i64 %x, 63 %neg = sub i64 0, %sh ret i64 %neg @@ -30,7 +28,6 @@ define <4 x i32> @neg_ashr_signbit_vec(<4 x i32> %x) { ; X64: # BB#0: ; X64-NEXT: psrld $31, %xmm0 ; X64-NEXT: retq -; %sh = ashr <4 x i32> %x, %neg = sub <4 x i32> zeroinitializer, %sh ret <4 x i32> %neg @@ -41,7 +38,6 @@ define <8 x i16> @neg_lshr_signbit_vec(<8 x i16> %x) { ; X64: # BB#0: ; X64-NEXT: psraw $15, %xmm0 ; X64-NEXT: retq -; %sh = lshr <8 x i16> %x, %neg = sub <8 x i16> zeroinitializer, %sh ret <8 x i16> %neg diff --git a/test/CodeGen/X86/negate.ll b/test/CodeGen/X86/negate.ll index 6f07378..5bdb114 100644 --- a/test/CodeGen/X86/negate.ll +++ b/test/CodeGen/X86/negate.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s define i32 @negate_nuw(i32 %x) { @@ -6,7 +6,6 @@ define i32 @negate_nuw(i32 %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: retq -; %neg = sub nuw i32 0, %x ret i32 %neg } @@ -16,7 +15,6 @@ define <4 x i32> @negate_nuw_vec(<4 x i32> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq -; %neg = sub nuw <4 x i32> zeroinitializer, %x ret <4 x i32> %neg } @@ -26,7 +24,6 @@ define i8 @negate_zero_or_minsigned_nsw(i8 %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: retq -; %signbit = and i8 %x, 128 %neg = sub nsw i8 0, %signbit ret i8 %neg @@ -37,7 +34,6 @@ define <4 x i32> @negate_zero_or_minsigned_nsw_vec(<4 x i32> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq -; %signbit = shl <4 x i32> %x, %neg = sub nsw <4 x i32> zeroinitializer, %signbit ret <4 x i32> %neg @@ -49,7 +45,6 @@ define i8 @negate_zero_or_minsigned(i8 %x) { ; CHECK-NEXT: shlb $7, %dil ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %signbit = shl i8 %x, 7 %neg = sub i8 0, %signbit ret i8 %neg @@ -60,7 +55,6 @@ define <4 x i32> @negate_zero_or_minsigned_vec(<4 x i32> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %signbit = and <4 x i32> %x, %neg = sub <4 x i32> zeroinitializer, %signbit ret <4 x i32> %neg diff --git a/test/CodeGen/X86/negative-sin.ll b/test/CodeGen/X86/negative-sin.ll index bc38021..94369e3 100644 --- a/test/CodeGen/X86/negative-sin.ll +++ b/test/CodeGen/X86/negative-sin.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s declare double @sin(double %f) @@ -16,7 +16,6 @@ define double @strict(double %e) nounwind { ; CHECK-NEXT: vsubsd %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; %f = fsub double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub double 0.0, %g @@ -29,8 +28,7 @@ define double @strict(double %e) nounwind { define double @fast(double %e) nounwind { ; CHECK-LABEL: fast: ; CHECK: # BB#0: -; CHECK-NEXT: jmp sin -; +; CHECK-NEXT: jmp sin # TAILCALL %f = fsub fast double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub fast double 0.0, %g @@ -42,8 +40,7 @@ define double @fast(double %e) nounwind { define double @nsz(double %e) nounwind { ; CHECK-LABEL: nsz: ; CHECK: # BB#0: -; CHECK-NEXT: jmp sin -; +; CHECK-NEXT: jmp sin # TAILCALL %f = fsub nsz double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub nsz double 0.0, %g @@ -62,7 +59,6 @@ define double @semi_strict1(double %e) nounwind { ; CHECK-NEXT: vxorpd {{.*}}(%rip), %xmm0, %xmm0 ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; %f = fsub double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub nsz double 0.0, %g @@ -80,7 +76,6 @@ define double @semi_strict2(double %e) nounwind { ; CHECK-NEXT: vaddsd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; %f = fsub nsz double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub double 0.0, %g @@ -93,8 +88,7 @@ define double @semi_strict2(double %e) nounwind { define double @fn_attr(double %e) nounwind #0 { ; CHECK-LABEL: fn_attr: ; CHECK: # BB#0: -; CHECK-NEXT: jmp sin -; +; CHECK-NEXT: jmp sin # TAILCALL %f = fsub double 0.0, %e %g = call double @sin(double %f) readonly %h = fsub double 0.0, %g diff --git a/test/CodeGen/X86/no-sse2-avg.ll b/test/CodeGen/X86/no-sse2-avg.ll index 0ed0a7f..e4b97c1 100644 --- a/test/CodeGen/X86/no-sse2-avg.ll +++ b/test/CodeGen/X86/no-sse2-avg.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; REQUIRES: asserts ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-sse2 | FileCheck %s @@ -23,7 +23,6 @@ define <16 x i8> @PR27973() { ; CHECK-NEXT: movb $0, (%rdi) ; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq -; %t0 = zext <16 x i8> zeroinitializer to <16 x i32> %t1 = add nuw nsw <16 x i32> %t0, %t2 = lshr <16 x i32> %t1, diff --git a/test/CodeGen/X86/not-and-simplify.ll b/test/CodeGen/X86/not-and-simplify.ll index 83b2be8..87aa10a 100644 --- a/test/CodeGen/X86/not-and-simplify.ll +++ b/test/CodeGen/X86/not-and-simplify.ll @@ -1,5 +1,4 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-bmi | FileCheck %s --check-prefix=ALL --check-prefix=NO_BMI ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=ALL --check-prefix=BMI diff --git a/test/CodeGen/X86/pr13577.ll b/test/CodeGen/X86/pr13577.ll index 1b16225..665df2c 100644 --- a/test/CodeGen/X86/pr13577.ll +++ b/test/CodeGen/X86/pr13577.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-darwin | FileCheck %s ; CHECK-LABEL: LCPI0_0: @@ -12,12 +12,11 @@ define x86_fp80 @foo(x86_fp80 %a) { ; CHECK-NEXT: fldt {{[0-9]+}}(%rsp) ; CHECK-NEXT: fstpt -{{[0-9]+}}(%rsp) ; CHECK-NEXT: testb $-128, -{{[0-9]+}}(%rsp) -; CHECK-NEXT: flds LCPI0_0(%rip) -; CHECK-NEXT: flds LCPI0_1(%rip) +; CHECK-NEXT: flds {{.*}}(%rip) +; CHECK-NEXT: flds {{.*}}(%rip) ; CHECK-NEXT: fcmovne %st(1), %st(0) ; CHECK-NEXT: fstp %st(1) ; CHECK-NEXT: retq -; %1 = tail call x86_fp80 @copysignl(x86_fp80 0xK7FFF8000000000000000, x86_fp80 %a) nounwind readnone ret x86_fp80 %1 } @@ -34,7 +33,6 @@ define float @pr26070() { ; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,0,0,0] ; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %c = call float @copysignf(float 1.0, float undef) readnone ret float %c } diff --git a/test/CodeGen/X86/pr18014.ll b/test/CodeGen/X86/pr18014.ll index bb3b9c2..cba0650 100644 --- a/test/CodeGen/X86/pr18014.ll +++ b/test/CodeGen/X86/pr18014.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s ; Ensure PSRAD is generated as the condition is consumed by both PADD and @@ -14,7 +14,6 @@ define <4 x i32> @foo(<4 x i32>* %p, <4 x i1> %cond, <4 x i32> %v1, <4 x i32> %v ; CHECK-NEXT: movaps %xmm2, (%rdi) ; CHECK-NEXT: movdqa %xmm1, %xmm0 ; CHECK-NEXT: retq -; %sext_cond = sext <4 x i1> %cond to <4 x i32> %t1 = add <4 x i32> %v1, %sext_cond %t2 = select <4 x i1> %cond, <4 x i32> %v1, <4 x i32> %v2 diff --git a/test/CodeGen/X86/pr32368.ll b/test/CodeGen/X86/pr32368.ll new file mode 100644 index 0000000..b0f0b12 --- /dev/null +++ b/test/CodeGen/X86/pr32368.ll @@ -0,0 +1,153 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK --check-prefix=SSE +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=CHECK --check-prefix=AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=CHECK --check-prefix=AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 + +define <4 x float> @PR32368_128(<4 x float>) { +; SSE-LABEL: PR32368_128: +; SSE: # BB#0: +; SSE-NEXT: andps {{.*}}(%rip), %xmm0 +; SSE-NEXT: addps %xmm0, %xmm0 +; SSE-NEXT: andps {{.*}}(%rip), %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: PR32368_128: +; AVX1: # BB#0: +; AVX1-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vaddps %xmm0, %xmm0, %xmm0 +; AVX1-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: PR32368_128: +; AVX2: # BB#0: +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 +; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vaddps %xmm0, %xmm0, %xmm0 +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 +; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: PR32368_128: +; AVX512: # BB#0: +; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 +; AVX512-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vaddps %xmm0, %xmm0, %xmm0 +; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %xmm1 +; AVX512-NEXT: vandps %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: retq + %2 = bitcast <4 x float> %0 to <4 x i32> + %3 = and <4 x i32> %2, + %4 = bitcast <4 x i32> %3 to <4 x float> + %5 = fmul <4 x float> %4, + %6 = bitcast <4 x float> %5 to <4 x i32> + %7 = and <4 x i32> %6, + %8 = bitcast <4 x i32> %7 to <4 x float> + ret <4 x float> %8 +} + +define <8 x float> @PR32368_256(<8 x float>) { +; SSE-LABEL: PR32368_256: +; SSE: # BB#0: +; SSE-NEXT: movaps {{.*#+}} xmm2 = [4294967004,4294967004,4294967004,4294967004] +; SSE-NEXT: andps %xmm2, %xmm0 +; SSE-NEXT: andps %xmm2, %xmm1 +; SSE-NEXT: addps %xmm1, %xmm1 +; SSE-NEXT: addps %xmm0, %xmm0 +; SSE-NEXT: movaps {{.*#+}} xmm2 = [291,291,291,291] +; SSE-NEXT: andps %xmm2, %xmm0 +; SSE-NEXT: andps %xmm2, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: PR32368_256: +; AVX1: # BB#0: +; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: vaddps %ymm0, %ymm0, %ymm0 +; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: PR32368_256: +; AVX2: # BB#0: +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm1 +; AVX2-NEXT: vandps %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vaddps %ymm0, %ymm0, %ymm0 +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm1 +; AVX2-NEXT: vandps %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: PR32368_256: +; AVX512: # BB#0: +; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %ymm1 +; AVX512-NEXT: vandps %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vaddps %ymm0, %ymm0, %ymm0 +; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %ymm1 +; AVX512-NEXT: vandps %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %2 = bitcast <8 x float> %0 to <8 x i32> + %3 = and <8 x i32> %2, + %4 = bitcast <8 x i32> %3 to <8 x float> + %5 = fmul <8 x float> %4, + %6 = bitcast <8 x float> %5 to <8 x i32> + %7 = and <8 x i32> %6, + %8 = bitcast <8 x i32> %7 to <8 x float> + ret <8 x float> %8 +} + +define <16 x float> @PR32368_512(<16 x float>) { +; SSE-LABEL: PR32368_512: +; SSE: # BB#0: +; SSE-NEXT: movaps {{.*#+}} xmm4 = [4294967004,4294967004,4294967004,4294967004] +; SSE-NEXT: andps %xmm4, %xmm0 +; SSE-NEXT: andps %xmm4, %xmm1 +; SSE-NEXT: andps %xmm4, %xmm2 +; SSE-NEXT: andps %xmm4, %xmm3 +; SSE-NEXT: addps %xmm3, %xmm3 +; SSE-NEXT: addps %xmm2, %xmm2 +; SSE-NEXT: addps %xmm1, %xmm1 +; SSE-NEXT: addps %xmm0, %xmm0 +; SSE-NEXT: movaps {{.*#+}} xmm4 = [291,291,291,291] +; SSE-NEXT: andps %xmm4, %xmm0 +; SSE-NEXT: andps %xmm4, %xmm1 +; SSE-NEXT: andps %xmm4, %xmm2 +; SSE-NEXT: andps %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: PR32368_512: +; AVX1: # BB#0: +; AVX1-NEXT: vmovaps {{.*#+}} ymm2 = [4294967004,4294967004,4294967004,4294967004,4294967004,4294967004,4294967004,4294967004] +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm0 +; AVX1-NEXT: vandps %ymm2, %ymm1, %ymm1 +; AVX1-NEXT: vaddps %ymm1, %ymm1, %ymm1 +; AVX1-NEXT: vaddps %ymm0, %ymm0, %ymm0 +; AVX1-NEXT: vmovaps {{.*#+}} ymm2 = [291,291,291,291,291,291,291,291] +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm0 +; AVX1-NEXT: vandps %ymm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: PR32368_512: +; AVX2: # BB#0: +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm2 +; AVX2-NEXT: vandps %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vandps %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vaddps %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vaddps %ymm0, %ymm0, %ymm0 +; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm2 +; AVX2-NEXT: vandps %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vandps %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: PR32368_512: +; AVX512: # BB#0: +; AVX512-NEXT: vpandd {{.*}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: vaddps %zmm0, %zmm0, %zmm0 +; AVX512-NEXT: vpandd {{.*}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: retq + %2 = bitcast <16 x float> %0 to <16 x i32> + %3 = and <16 x i32> %2, + %4 = bitcast <16 x i32> %3 to <16 x float> + %5 = fmul <16 x float> %4, + %6 = bitcast <16 x float> %5 to <16 x i32> + %7 = and <16 x i32> %6, + %8 = bitcast <16 x i32> %7 to <16 x float> + ret <16 x float> %8 +} diff --git a/test/CodeGen/X86/rem.ll b/test/CodeGen/X86/rem.ll index cc591e5..7b138f0 100644 --- a/test/CodeGen/X86/rem.ll +++ b/test/CodeGen/X86/rem.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s define i32 @test1(i32 %X) { @@ -19,7 +19,6 @@ define i32 @test1(i32 %X) { ; CHECK-NEXT: subl %eax, %ecx ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: retl -; %tmp1 = srem i32 %X, 255 ret i32 %tmp1 } @@ -35,7 +34,6 @@ define i32 @test2(i32 %X) { ; CHECK-NEXT: andl $-256, %ecx ; CHECK-NEXT: subl %ecx, %eax ; CHECK-NEXT: retl -; %tmp1 = srem i32 %X, 256 ret i32 %tmp1 } @@ -54,7 +52,6 @@ define i32 @test3(i32 %X) { ; CHECK-NEXT: subl %eax, %ecx ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: retl -; %tmp1 = urem i32 %X, 255 ret i32 %tmp1 } @@ -64,7 +61,6 @@ define i32 @test4(i32 %X) { ; CHECK: # BB#0: ; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %eax ; CHECK-NEXT: retl -; %tmp1 = urem i32 %X, 256 ret i32 %tmp1 } @@ -77,8 +73,8 @@ define i32 @test5(i32 %X) nounwind readnone { ; CHECK-NEXT: idivl {{[0-9]+}}(%esp) ; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: retl -; entry: %0 = srem i32 41, %X ret i32 %0 } + diff --git a/test/CodeGen/X86/sar_fold64.ll b/test/CodeGen/X86/sar_fold64.ll index 213ca95..66ad8c3 100644 --- a/test/CodeGen/X86/sar_fold64.ll +++ b/test/CodeGen/X86/sar_fold64.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s define i32 @shl48sar47(i64 %a) #0 { @@ -8,7 +8,6 @@ define i32 @shl48sar47(i64 %a) #0 { ; CHECK-NEXT: addl %eax, %eax ; CHECK-NEXT: # kill: %EAX %EAX %RAX ; CHECK-NEXT: retq -; %1 = shl i64 %a, 48 %2 = ashr exact i64 %1, 47 %3 = trunc i64 %2 to i32 @@ -22,7 +21,6 @@ define i32 @shl48sar49(i64 %a) #0 { ; CHECK-NEXT: shrq %rax ; CHECK-NEXT: # kill: %EAX %EAX %RAX ; CHECK-NEXT: retq -; %1 = shl i64 %a, 48 %2 = ashr exact i64 %1, 49 %3 = trunc i64 %2 to i32 @@ -36,7 +34,6 @@ define i32 @shl56sar55(i64 %a) #0 { ; CHECK-NEXT: addl %eax, %eax ; CHECK-NEXT: # kill: %EAX %EAX %RAX ; CHECK-NEXT: retq -; %1 = shl i64 %a, 56 %2 = ashr exact i64 %1, 55 %3 = trunc i64 %2 to i32 @@ -50,7 +47,6 @@ define i32 @shl56sar57(i64 %a) #0 { ; CHECK-NEXT: shrq %rax ; CHECK-NEXT: # kill: %EAX %EAX %RAX ; CHECK-NEXT: retq -; %1 = shl i64 %a, 56 %2 = ashr exact i64 %1, 57 %3 = trunc i64 %2 to i32 @@ -64,7 +60,6 @@ define i8 @all_sign_bit_ashr(i8 %x) { ; CHECK-NEXT: negb %dil ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq -; %and = and i8 %x, 1 %neg = sub i8 0, %and %sar = ashr i8 %neg, 6 @@ -79,7 +74,6 @@ define <4 x i32> @all_sign_bit_ashr_vec(<4 x i32> %x) { ; CHECK-NEXT: psubd %xmm0, %xmm1 ; CHECK-NEXT: movdqa %xmm1, %xmm0 ; CHECK-NEXT: retq -; %and = and <4 x i32> %x, %neg = sub <4 x i32> zeroinitializer, %and %sar = ashr <4 x i32> %neg, diff --git a/test/CodeGen/X86/select-with-and-or.ll b/test/CodeGen/X86/select-with-and-or.ll index f49da85..45e4384 100644 --- a/test/CodeGen/X86/select-with-and-or.ll +++ b/test/CodeGen/X86/select-with-and-or.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s define <4 x i32> @test1(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { @@ -7,7 +7,6 @@ define <4 x i32> @test1(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vandps %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %r = select <4 x i1> %f, <4 x i32> %c, <4 x i32> zeroinitializer ret <4 x i32> %r @@ -19,7 +18,6 @@ define <4 x i32> @test2(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vorps %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %r = select <4 x i1> %f, <4 x i32> , <4 x i32> %c ret <4 x i32> %r @@ -31,7 +29,6 @@ define <4 x i32> @test3(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vandps %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %r = select <4 x i1> %f, <4 x i32> zeroinitializer, <4 x i32> %c ret <4 x i32> %r @@ -43,7 +40,6 @@ define <4 x i32> @test4(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vorps %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %r = select <4 x i1> %f, <4 x i32> %c, <4 x i32> ret <4 x i32> %r @@ -54,7 +50,6 @@ define <4 x i32> @test5(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK: # BB#0: ; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %r = sext <4 x i1> %f to <4 x i32> ret <4 x i32> %r @@ -65,7 +60,6 @@ define <4 x i32> @test6(<4 x float> %a, <4 x float> %b, <4 x i32> %c) { ; CHECK: # BB#0: ; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: retq -; %not.f = fcmp oge <4 x float> %a, %b %r = sext <4 x i1> %not.f to <4 x i32> ret <4 x i32> %r @@ -77,7 +71,6 @@ define <4 x i32> @test7(<4 x float> %a, <4 x float> %b, <4 x i32>* %p) { ; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vandps (%rdi), %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ult <4 x float> %a, %b %l = load <4 x i32>, <4 x i32>* %p, align 16 %r = select <4 x i1> %f, <4 x i32> %l, <4 x i32> zeroinitializer @@ -92,7 +85,6 @@ define <2 x double> @test1f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK-NEXT: vcmpltpd %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vandpd %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ogt <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> %c, <2 x double> zeroinitializer ret <2 x double> %r @@ -104,7 +96,6 @@ define <2 x double> @test2f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK-NEXT: vcmplepd %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: vorpd %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp oge <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> , <2 x double> %c ret <2 x double> %r @@ -116,7 +107,6 @@ define <2 x double> @test3f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK-NEXT: vcmpnltpd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vandpd %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp olt <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> zeroinitializer, <2 x double> %c ret <2 x double> %r @@ -128,7 +118,6 @@ define <2 x double> @test4f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK-NEXT: vcmpnlepd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vorpd %xmm2, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ole <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> %c, <2 x double> ret <2 x double> %r @@ -139,7 +128,6 @@ define <2 x double> @test5f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK: # BB#0: ; CHECK-NEXT: vcmpnlepd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ugt <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> , <2 x double> zeroinitializer ret <2 x double> %r @@ -150,7 +138,6 @@ define <2 x double> @test6f(<2 x double> %a, <2 x double> %b, <2 x double> %c) { ; CHECK: # BB#0: ; CHECK-NEXT: vcmpltpd %xmm0, %xmm1, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp ule <2 x double> %a, %b %r = select <2 x i1> %f, <2 x double> zeroinitializer, <2 x double> ret <2 x double> %r @@ -162,7 +149,6 @@ define <2 x double> @test7f(<2 x double> %a, <2 x double> %b, <2 x double>* %p) ; CHECK-NEXT: vcmpeqpd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vandpd (%rdi), %xmm0, %xmm0 ; CHECK-NEXT: retq -; %f = fcmp oeq <2 x double> %a, %b %l = load <2 x double>, <2 x double>* %p, align 16 %r = select <2 x i1> %f, <2 x double> %l, <2 x double> zeroinitializer diff --git a/test/CodeGen/X86/sext-setcc-self.ll b/test/CodeGen/X86/sext-setcc-self.ll index e739d21..9cbd3d8 100644 --- a/test/CodeGen/X86/sext-setcc-self.ll +++ b/test/CodeGen/X86/sext-setcc-self.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s define <4 x i32> @test_ueq(<4 x float> %in) { @@ -6,7 +6,6 @@ define <4 x i32> @test_ueq(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: pcmpeqd %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp ueq <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 @@ -17,7 +16,6 @@ define <4 x i32> @test_uge(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: pcmpeqd %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp uge <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 @@ -28,7 +26,6 @@ define <4 x i32> @test_ule(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: pcmpeqd %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp ule <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 @@ -39,7 +36,6 @@ define <4 x i32> @test_one(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp one <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 @@ -50,7 +46,6 @@ define <4 x i32> @test_ogt(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp ogt <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 @@ -61,7 +56,6 @@ define <4 x i32> @test_olt(<4 x float> %in) { ; CHECK: # BB#0: ; CHECK-NEXT: xorps %xmm0, %xmm0 ; CHECK-NEXT: retq -; %t0 = fcmp olt <4 x float> %in, %in %t1 = sext <4 x i1> %t0 to <4 x i32> ret <4 x i32> %t1 diff --git a/test/CodeGen/X86/shift-pcmp.ll b/test/CodeGen/X86/shift-pcmp.ll index adfd2f1..f509da2 100644 --- a/test/CodeGen/X86/shift-pcmp.ll +++ b/test/CodeGen/X86/shift-pcmp.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -o - -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=SSE ; RUN: llc < %s -o - -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=AVX @@ -14,7 +14,6 @@ define <8 x i16> @foo(<8 x i16> %a, <8 x i16> %b) { ; AVX-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm0 ; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX-NEXT: retq -; %icmp = icmp eq <8 x i16> %a, %b %zext = zext <8 x i1> %icmp to <8 x i16> %shl = shl nuw nsw <8 x i16> %zext, @@ -34,7 +33,6 @@ define <8 x i16> @bar(<8 x i16> %a, <8 x i16> %b) { ; AVX-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm0 ; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX-NEXT: retq -; %icmp = icmp eq <8 x i16> %a, %b %zext = zext <8 x i1> %icmp to <8 x i16> %shl = shl nuw nsw <8 x i16> %zext, diff --git a/test/CodeGen/X86/sincos-opt.ll b/test/CodeGen/X86/sincos-opt.ll index f0dff3b..e2fd63e 100644 --- a/test/CodeGen/X86/sincos-opt.ll +++ b/test/CodeGen/X86/sincos-opt.ll @@ -1,10 +1,12 @@ ; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9.0 -mcpu=core2 | FileCheck %s --check-prefix=OSX_SINCOS ; RUN: llc < %s -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core2 | FileCheck %s --check-prefix=OSX_NOOPT -; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 | FileCheck %s --check-prefix=GNU_NOOPT -; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS -; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNUX32_SINCOS +; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 | FileCheck %s --check-prefix=GNU_SINCOS +; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS_FASTMATH +; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS_FASTMATH -; Combine sin / cos into a single call. +; Combine sin / cos into a single call unless they may write errno (as +; captured by readnone attrbiute, controlled by clang -fmath-errno +; setting). ; rdar://13087969 ; rdar://13599493 @@ -15,25 +17,44 @@ entry: ; GNU_SINCOS: movss 4(%rsp), %xmm0 ; GNU_SINCOS: addss (%rsp), %xmm0 -; GNUX32_SINCOS-LABEL: test1: -; GNUX32_SINCOS: callq sincosf -; GNUX32_SINCOS: movss 4(%esp), %xmm0 -; GNUX32_SINCOS: addss (%esp), %xmm0 - -; GNU_NOOPT: test1 -; GNU_NOOPT: callq sinf -; GNU_NOOPT: callq cosf +; GNU_SINCOS_FASTMATH-LABEL: test1: +; GNU_SINCOS_FASTMATH: callq sincosf +; GNU_SINCOS_FASTMATH: movss 4(%{{[re]}}sp), %xmm0 +; GNU_SINCOS_FASTMATH: addss (%{{[re]}}sp), %xmm0 ; OSX_SINCOS-LABEL: test1: ; OSX_SINCOS: callq ___sincosf_stret ; OSX_SINCOS: movshdup {{.*}} xmm1 = xmm0[1,1,3,3] ; OSX_SINCOS: addss %xmm1, %xmm0 -; OSX_NOOPT: test1 +; OSX_NOOPT-LABEL: test1: ; OSX_NOOPT: callq _sinf ; OSX_NOOPT: callq _cosf - %call = tail call float @sinf(float %x) nounwind readnone - %call1 = tail call float @cosf(float %x) nounwind readnone + %call = tail call float @sinf(float %x) readnone + %call1 = tail call float @cosf(float %x) readnone + %add = fadd float %call, %call1 + ret float %add +} + +define float @test1_errno(float %x) nounwind { +entry: +; GNU_SINCOS-LABEL: test1_errno: +; GNU_SINCOS: callq sinf +; GNU_SINCOS: callq cosf + +; GNU_SINCOS_FASTMATH-LABEL: test1_errno: +; GNU_SINCOS_FASTMATH: callq sinf +; GNU_SINCOS_FASTMATH: callq cosf + +; OSX_SINCOS-LABEL: test1_errno: +; OSX_SINCOS: callq _sinf +; OSX_SINCOS: callq _cosf + +; OSX_NOOPT-LABEL: test1_errno: +; OSX_NOOPT: callq _sinf +; OSX_NOOPT: callq _cosf + %call = tail call float @sinf(float %x) + %call1 = tail call float @cosf(float %x) %add = fadd float %call, %call1 ret float %add } @@ -45,24 +66,43 @@ entry: ; GNU_SINCOS: movsd 16(%rsp), %xmm0 ; GNU_SINCOS: addsd 8(%rsp), %xmm0 -; GNUX32_SINCOS-LABEL: test2: -; GNUX32_SINCOS: callq sincos -; GNUX32_SINCOS: movsd 16(%esp), %xmm0 -; GNUX32_SINCOS: addsd 8(%esp), %xmm0 - -; GNU_NOOPT: test2: -; GNU_NOOPT: callq sin -; GNU_NOOPT: callq cos +; GNU_SINCOS_FASTMATH-LABEL: test2: +; GNU_SINCOS_FASTMATH: callq sincos +; GNU_SINCOS_FASTMATH: movsd 16(%{{[re]}}sp), %xmm0 +; GNU_SINCOS_FASTMATH: addsd 8(%{{[re]}}sp), %xmm0 ; OSX_SINCOS-LABEL: test2: ; OSX_SINCOS: callq ___sincos_stret ; OSX_SINCOS: addsd %xmm1, %xmm0 -; OSX_NOOPT: test2 +; OSX_NOOPT-LABEL: test2: +; OSX_NOOPT: callq _sin +; OSX_NOOPT: callq _cos + %call = tail call double @sin(double %x) readnone + %call1 = tail call double @cos(double %x) readnone + %add = fadd double %call, %call1 + ret double %add +} + +define double @test2_errno(double %x) nounwind { +entry: +; GNU_SINCOS-LABEL: test2_errno: +; GNU_SINCOS: callq sin +; GNU_SINCOS: callq cos + +; GNU_SINCOS_FASTMATH-LABEL: test2_errno: +; GNU_SINCOS_FASTMATH: callq sin +; GNU_SINCOS_FASTMATH: callq cos + +; OSX_SINCOS-LABEL: test2_errno: +; OSX_SINCOS: callq _sin +; OSX_SINCOS: callq _cos + +; OSX_NOOPT-LABEL: test2_errno: ; OSX_NOOPT: callq _sin ; OSX_NOOPT: callq _cos - %call = tail call double @sin(double %x) nounwind readnone - %call1 = tail call double @cos(double %x) nounwind readnone + %call = tail call double @sin(double %x) + %call1 = tail call double @cos(double %x) %add = fadd double %call, %call1 ret double %add } @@ -70,29 +110,40 @@ entry: define x86_fp80 @test3(x86_fp80 %x) nounwind { entry: ; GNU_SINCOS-LABEL: test3: +; GNU_SINCOS: callq sincosl +; GNU_SINCOS: fldt 16(%rsp) +; GNU_SINCOS: fldt 32(%rsp) +; GNU_SINCOS: faddp %st(1) + +; GNU_SINCOS_FASTMATH-LABEL: test3: +; GNU_SINCOS_FASTMATH: fsin +; GNU_SINCOS_FASTMATH: fcos +; GNU_SINCOS_FASTMATH: faddp %st(1) +; GNU_SINCOS_FASTMATH: ret + %call = tail call x86_fp80 @sinl(x86_fp80 %x) readnone + %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) readnone + %add = fadd x86_fp80 %call, %call1 + ret x86_fp80 %add +} + +define x86_fp80 @test3_errno(x86_fp80 %x) nounwind { +entry: +; GNU_SINCOS-LABEL: test3_errno: ; GNU_SINCOS: callq sinl ; GNU_SINCOS: callq cosl -; GNU_SINCOS: ret -; GNUX32_SINCOS-LABEL: test3: -; GNUX32_SINCOS: callq sinl -; GNUX32_SINCOS: callq cosl -; GNUX32_SINCOS: ret - -; GNU_NOOPT: test3: -; GNU_NOOPT: callq sinl -; GNU_NOOPT: callq cosl - - %call = tail call x86_fp80 @sinl(x86_fp80 %x) nounwind - %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) nounwind +; GNU_SINCOS_FASTMATH-LABEL: test3_errno: +; GNU_SINCOS_FASTMATH: callq sinl +; GNU_SINCOS_FASTMATH: callq cosl + %call = tail call x86_fp80 @sinl(x86_fp80 %x) + %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) %add = fadd x86_fp80 %call, %call1 ret x86_fp80 %add } -declare float @sinf(float) readonly -declare double @sin(double) readonly -declare float @cosf(float) readonly -declare double @cos(double) readonly - +declare float @sinf(float) +declare double @sin(double) +declare float @cosf(float) +declare double @cos(double) declare x86_fp80 @sinl(x86_fp80) declare x86_fp80 @cosl(x86_fp80) diff --git a/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll b/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll index 77497d3..2ecba88 100644 --- a/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll +++ b/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i686-apple-darwin -mattr=+sse2 | FileCheck %s define void @test_x86_sse_storeu_ps(i8* %a0, <4 x float> %a1) { diff --git a/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll b/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll index 26af37e..9bda90a 100644 --- a/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll +++ b/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i386-apple-darwin -mattr=+sse4.1 | FileCheck %s ; This test works just like the non-upgrade one except that it only checks @@ -230,7 +230,6 @@ define <16 x i8> @max_epi8(<16 x i8> %a0, <16 x i8> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pmaxsb %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <16 x i8> @llvm.x86.sse41.pmaxsb(<16 x i8> %a0, <16 x i8> %a1) ret <16 x i8> %res } @@ -241,7 +240,6 @@ define <16 x i8> @min_epi8(<16 x i8> %a0, <16 x i8> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pminsb %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <16 x i8> @llvm.x86.sse41.pminsb(<16 x i8> %a0, <16 x i8> %a1) ret <16 x i8> %res } @@ -252,7 +250,6 @@ define <8 x i16> @max_epu16(<8 x i16> %a0, <8 x i16> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pmaxuw %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <8 x i16> @llvm.x86.sse41.pmaxuw(<8 x i16> %a0, <8 x i16> %a1) ret <8 x i16> %res } @@ -263,7 +260,6 @@ define <8 x i16> @min_epu16(<8 x i16> %a0, <8 x i16> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pminuw %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <8 x i16> @llvm.x86.sse41.pminuw(<8 x i16> %a0, <8 x i16> %a1) ret <8 x i16> %res } @@ -274,7 +270,6 @@ define <4 x i32> @max_epi32(<4 x i32> %a0, <4 x i32> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pmaxsd %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a0, <4 x i32> %a1) ret <4 x i32> %res } @@ -285,7 +280,6 @@ define <4 x i32> @min_epi32(<4 x i32> %a0, <4 x i32> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pminsd %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <4 x i32> @llvm.x86.sse41.pminsd(<4 x i32> %a0, <4 x i32> %a1) ret <4 x i32> %res } @@ -296,7 +290,6 @@ define <4 x i32> @max_epu32(<4 x i32> %a0, <4 x i32> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pmaxud %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <4 x i32> @llvm.x86.sse41.pmaxud(<4 x i32> %a0, <4 x i32> %a1) ret <4 x i32> %res } @@ -307,7 +300,6 @@ define <4 x i32> @min_epu32(<4 x i32> %a0, <4 x i32> %a1) { ; CHECK: ## BB#0: ; CHECK-NEXT: pminud %xmm1, %xmm0 ; CHECK-NEXT: retl -; %res = call <4 x i32> @llvm.x86.sse41.pminud(<4 x i32> %a0, <4 x i32> %a1) ret <4 x i32> %res } diff --git a/test/CodeGen/X86/stack-folding-int-avx512.ll b/test/CodeGen/X86/stack-folding-int-avx512.ll index 38e19ef..362e656 100644 --- a/test/CodeGen/X86/stack-folding-int-avx512.ll +++ b/test/CodeGen/X86/stack-folding-int-avx512.ll @@ -1,4 +1,4 @@ -; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512bw,+avx512dq,+avx512vbmi < %s | FileCheck %s +; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512bw,+avx512dq,+avx512vbmi,+avx512cd < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-unknown" @@ -450,6 +450,24 @@ define <64 x i8> @stack_fold_palignr_maskz(<64 x i8> %a0, <64 x i8> %a1, i64 %ma ret <64 x i8> %4 } +define <16 x i32> @stack_fold_vpconflictd(<16 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictd + ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <16 x i32> @llvm.x86.avx512.mask.conflict.d.512(<16 x i32> %a0, <16 x i32> undef, i16 -1) + ret <16 x i32> %2 +} +declare <16 x i32> @llvm.x86.avx512.mask.conflict.d.512(<16 x i32>, <16 x i32>, i16) nounwind readonly + +define <8 x i64> @stack_fold_vpconflictq(<8 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictq + ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <8 x i64> @llvm.x86.avx512.mask.conflict.q.512(<8 x i64> %a0, <8 x i64> undef, i8 -1) + ret <8 x i64> %2 +} +declare <8 x i64> @llvm.x86.avx512.mask.conflict.q.512(<8 x i64>, <8 x i64>, i8) nounwind readnone + define i64 @stack_fold_pcmpeqb(<64 x i8> %a0, <64 x i8> %a1) { ;CHECK-LABEL: stack_fold_pcmpeqb ;CHECK: vpcmpeqb {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{.*#+}} 64-byte Folded Reload @@ -486,6 +504,61 @@ define i32 @stack_fold_pcmpeqw(<32 x i16> %a0, <32 x i16> %a1) { ret i32 %3 } +define i16 @stack_fold_pcmpeqd_mask(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) { + ;CHECK-LABEL: stack_fold_pcmpeqd_mask + ;CHECK: vpcmpeqd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load + %2 = load <16 x i32>, <16 x i32>* %a2 + %3 = add <16 x i32> %a1, %2 + %4 = bitcast i16 %mask to <16 x i1> + %5 = icmp eq <16 x i32> %3, %a0 + %6 = and <16 x i1> %4, %5 + %7 = bitcast <16 x i1> %6 to i16 + ret i16 %7 +} + +define i16 @stack_fold_pcmpeqd_mask_commuted(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) { + ;CHECK-LABEL: stack_fold_pcmpeqd_mask_commuted + ;CHECK: vpcmpeqd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load + %2 = load <16 x i32>, <16 x i32>* %a2 + %3 = add <16 x i32> %a1, %2 + %4 = bitcast i16 %mask to <16 x i1> + %5 = icmp eq <16 x i32> %a0, %3 + %6 = and <16 x i1> %4, %5 + %7 = bitcast <16 x i1> %6 to i16 + ret i16 %7 +} + +define i16 @stack_fold_pcmpled_mask(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) { + ;CHECK-LABEL: stack_fold_pcmpled_mask + ;CHECK: vpcmpled {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load + %2 = load <16 x i32>, <16 x i32>* %a2 + %3 = add <16 x i32> %a1, %2 + %4 = bitcast i16 %mask to <16 x i1> + %5 = icmp sge <16 x i32> %a0, %3 + %6 = and <16 x i1> %4, %5 + %7 = bitcast <16 x i1> %6 to i16 + ret i16 %7 +} + +define i16 @stack_fold_pcmpleud(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) { + ;CHECK-LABEL: stack_fold_pcmpleud + ;CHECK: vpcmpleud {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = load <16 x i32>, <16 x i32>* %a2 + %3 = add <16 x i32> %a1, %2 + %4 = bitcast i16 %mask to <16 x i1> + %5 = icmp uge <16 x i32> %a0, %3 + %6 = and <16 x i1> %5, %4 + %7 = bitcast <16 x i1> %6 to i16 + ret i16 %7 +} + define <64 x i8> @stack_fold_permbvar(<64 x i8> %a0, <64 x i8> %a1) { ;CHECK-LABEL: stack_fold_permbvar ;CHECK: vpermb {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload @@ -740,6 +813,24 @@ define <8 x i16> @stack_fold_pinsrw(<8 x i16> %a0, i16 %a1) { ret <8 x i16> %2 } +define <16 x i32> @stack_fold_vplzcntd(<16 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntd + ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <16 x i32> @llvm.ctlz.v16i32(<16 x i32> %a0) + ret <16 x i32> %2 +} +declare <16 x i32> @llvm.ctlz.v16i32(<16 x i32>) nounwind readonly + +define <8 x i64> @stack_fold_vplzcntq(<8 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntq + ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <8 x i64> @llvm.ctlz.v8i64(<8 x i64> %a0) + ret <8 x i64> %2 +} +declare <8 x i64> @llvm.ctlz.v8i64(<8 x i64>) nounwind readnone + define <32 x i16> @stack_fold_pmaddubsw_zmm(<64 x i8> %a0, <64 x i8> %a1) { ;CHECK-LABEL: stack_fold_pmaddubsw_zmm ;CHECK: vpmaddubsw {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload diff --git a/test/CodeGen/X86/stack-folding-int-avx512vl.ll b/test/CodeGen/X86/stack-folding-int-avx512vl.ll index 7ce798f..26e97ea 100644 --- a/test/CodeGen/X86/stack-folding-int-avx512vl.ll +++ b/test/CodeGen/X86/stack-folding-int-avx512vl.ll @@ -1,4 +1,4 @@ -; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512vl,+avx512bw,+avx512dq,+avx512vbmi < %s | FileCheck %s +; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512vl,+avx512bw,+avx512dq,+avx512vbmi,+avx512cd < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-unknown" @@ -81,6 +81,42 @@ define <16 x i16> @stack_fold_pavgw_ymm(<16 x i16> %a0, <16 x i16> %a1) { } declare <16 x i16> @llvm.x86.avx2.pavg.w(<16 x i16>, <16 x i16>) nounwind readnone +define <4 x i32> @stack_fold_vpconflictd(<4 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictd + ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <4 x i32> @llvm.x86.avx512.mask.conflict.d.128(<4 x i32> %a0, <4 x i32> undef, i8 -1) + ret <4 x i32> %2 +} +declare <4 x i32> @llvm.x86.avx512.mask.conflict.d.128(<4 x i32>, <4 x i32>, i8) nounwind readonly + +define <8 x i32> @stack_fold_vpconflictd_ymm(<8 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictd_ymm + ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <8 x i32> @llvm.x86.avx512.mask.conflict.d.256(<8 x i32> %a0, <8 x i32> undef, i8 -1) + ret <8 x i32> %2 +} +declare <8 x i32> @llvm.x86.avx512.mask.conflict.d.256(<8 x i32>, <8 x i32>, i8) nounwind readonly + +define <2 x i64> @stack_fold_vpconflictq(<2 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictq + ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <2 x i64> @llvm.x86.avx512.mask.conflict.q.128(<2 x i64> %a0, <2 x i64> undef, i8 -1) + ret <2 x i64> %2 +} +declare <2 x i64> @llvm.x86.avx512.mask.conflict.q.128(<2 x i64>, <2 x i64>, i8) nounwind readnone + +define <4 x i64> @stack_fold_vpconflictq_ymm(<4 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vpconflictq_ymm + ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <4 x i64> @llvm.x86.avx512.mask.conflict.q.256(<4 x i64> %a0, <4 x i64> undef, i8 -1) + ret <4 x i64> %2 +} +declare <4 x i64> @llvm.x86.avx512.mask.conflict.q.256(<4 x i64>, <4 x i64>, i8) nounwind readnone + define <4 x i32> @stack_fold_extracti32x4(<8 x i32> %a0, <8 x i32> %a1) { ;CHECK-LABEL: stack_fold_extracti32x4 ;CHECK: vextracti128 $1, {{%ymm[0-9][0-9]*}}, {{-?[0-9]*}}(%rsp) {{.*#+}} 16-byte Folded Spill @@ -708,6 +744,42 @@ define <16 x i16> @stack_fold_permwvar(<16 x i16> %a0, <16 x i16> %a1) { } declare <16 x i16> @llvm.x86.avx512.mask.permvar.hi.256(<16 x i16>, <16 x i16>, <16 x i16>, i16) nounwind readonly +define <4 x i32> @stack_fold_vplzcntd(<4 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntd + ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a0) + ret <4 x i32> %2 +} +declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>) nounwind readonly + +define <8 x i32> @stack_fold_vplzcntd_ymm(<8 x i32> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntd_ymm + ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <8 x i32> @llvm.ctlz.v8i32(<8 x i32> %a0) + ret <8 x i32> %2 +} +declare <8 x i32> @llvm.ctlz.v8i32(<8 x i32>) nounwind readonly + +define <2 x i64> @stack_fold_vplzcntq(<2 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntq + ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %a0) + ret <2 x i64> %2 +} +declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>) nounwind readnone + +define <4 x i64> @stack_fold_vplzcntq_ymm(<4 x i64> %a0) { + ;CHECK-LABEL: stack_fold_vplzcntq_ymm + ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload + %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"() + %2 = call <4 x i64> @llvm.ctlz.v4i64(<4 x i64> %a0) + ret <4 x i64> %2 +} +declare <4 x i64> @llvm.ctlz.v4i64(<4 x i64>) nounwind readnone + define <8 x i16> @stack_fold_pmaddubsw(<16 x i8> %a0, <16 x i8> %a1) { ;CHECK-LABEL: stack_fold_pmaddubsw ;CHECK: vpmaddubsw {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}}, {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload diff --git a/test/CodeGen/X86/statepoint-live-in.ll b/test/CodeGen/X86/statepoint-live-in.ll index aaa4d7c..0179d37 100644 --- a/test/CodeGen/X86/statepoint-live-in.ll +++ b/test/CodeGen/X86/statepoint-live-in.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -verify-machineinstrs -O3 < %s | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" @@ -16,7 +16,6 @@ define void @test1(i32 %a) gc "statepoint-example" { ; CHECK-NEXT: Ltmp0: ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; entry: ; We expect the argument to be passed in an extra register to bar %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a) @@ -49,7 +48,6 @@ define void @test2(i32 %a, i32 %b) gc "statepoint-example" { ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: popq %rbp ; CHECK-NEXT: retq -; entry: ; Because the first call clobbers esi, we have to move the values into ; new registers. Note that they stay in the registers for both calls. @@ -68,7 +66,6 @@ define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 % ; CHECK-NEXT: Ltmp3: ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; entry: ; We directly reference the argument slot %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 9, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i) @@ -89,7 +86,6 @@ define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 % ; CHECK-NEXT: Ltmp4: ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq -; entry: %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 26, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) ret void @@ -111,7 +107,6 @@ define i32 addrspace(1)* @test5(i32 %a, i32 addrspace(1)* %p) gc "statepoint-ex ; CHECK-NEXT: movq (%rsp), %rax ; CHECK-NEXT: popq %rcx ; CHECK-NEXT: retq -; entry: %token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a, i32 addrspace(1)* %p, i32 addrspace(1)* %p) %p2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 9, i32 9) @@ -139,7 +134,6 @@ define void @test6(i32 %a) gc "statepoint-example" { ; CHECK-NEXT: addq $16, %rsp ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: retq -; entry: call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 %a) call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a) diff --git a/test/CodeGen/X86/swifterror.ll b/test/CodeGen/X86/swifterror.ll index 5704d19..1ecd337 100644 --- a/test/CodeGen/X86/swifterror.ll +++ b/test/CodeGen/X86/swifterror.ll @@ -712,3 +712,111 @@ trueBB: falseBB: ret void } + + +declare swiftcc void @foo2(%swift_error** swifterror) + +; Make sure we properly assign registers during fast-isel. +; CHECK-O0-LABEL: testAssign +; CHECK-O0: pushq %r12 +; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]] +; CHECK-O0: movl [[ZERO]], %r12d +; CHECK-O0: callq _foo2 +; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] +; +; CHECK-O0: movq [[SLOT]], %rax +; CHECK-O0: popq %r12 +; CHECK-O0: retq + +; CHECK-APPLE-LABEL: testAssign +; CHECK-APPLE: pushq %r12 +; CHECK-APPLE: xorl %r12d, %r12d +; CHECK-APPLE: callq _foo2 +; CHECK-APPLE: movq %r12, %rax +; CHECK-APPLE: popq %r12 +; CHECK-APPLE: retq + +define swiftcc %swift_error* @testAssign(i8* %error_ref) { +entry: + %error_ptr = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr + call swiftcc void @foo2(%swift_error** swifterror %error_ptr) + br label %a + +a: + %error = load %swift_error*, %swift_error** %error_ptr + ret %swift_error* %error +} + +; CHECK-O0-LABEL: testAssign2 +; CHECK-O0: movq %r12, {{.*}} +; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] +; CHECK-O0: jmp +; CHECK-O0: movq [[SLOT]], %rax +; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] +; CHECK-O0: movq [[SLOT2]], %r12 +; CHECK-O0: retq + +; CHECK-APPLE-LABEL: testAssign2 +; CHECK-APPLE: movq %r12, %rax +; CHECK-APPLE: retq +define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) { +entry: + br label %a + +a: + %error = load %swift_error*, %swift_error** %err + ret %swift_error* %error +} + +; CHECK-O0-LABEL: testAssign3 +; CHECK-O0: callq _foo2 +; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]] +; CHECK-O0: movq [[SLOT]], %rax +; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] +; CHECK-O0: movq [[SLOT2]], %r12 +; CHECK-O0: addq $24, %rsp +; CHECK-O0: retq + +; CHECK-APPLE-LABEL: testAssign3 +; CHECK-APPLE: callq _foo2 +; CHECK-APPLE: movq %r12, %rax +; CHECK-APPLE: retq + +define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) { +entry: + call swiftcc void @foo2(%swift_error** swifterror %err) + br label %a + +a: + %error = load %swift_error*, %swift_error** %err + ret %swift_error* %error +} + + +; CHECK-O0-LABEL: testAssign4 +; CHECK-O0: callq _foo2 +; CHECK-O0: xorl %ecx, %ecx +; CHECK-O0: movl %ecx, %eax +; CHECK-O0: movq %rax, [[SLOT:[-a-z0-9\(\)\%]*]] +; CHECK-O0: movq [[SLOT]], %rax +; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]] +; CHECK-O0: movq [[SLOT2]], %r12 +; CHECK-O0: retq + +; CHECK-APPLE-LABEL: testAssign4 +; CHECK-APPLE: callq _foo2 +; CHECK-APPLE: xorl %eax, %eax +; CHECK-APPLE: xorl %r12d, %r12d +; CHECK-APPLE: retq + +define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) { +entry: + call swiftcc void @foo2(%swift_error** swifterror %err) + store %swift_error* null, %swift_error** %err + br label %a + +a: + %error = load %swift_error*, %swift_error** %err + ret %swift_error* %error +} diff --git a/test/CodeGen/X86/urem-i8-constant.ll b/test/CodeGen/X86/urem-i8-constant.ll index 45717f9..2a659b2 100644 --- a/test/CodeGen/X86/urem-i8-constant.ll +++ b/test/CodeGen/X86/urem-i8-constant.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s define i8 @foo(i8 %tmp325) { @@ -14,7 +14,6 @@ define i8 @foo(i8 %tmp325) { ; CHECK-NEXT: subb %al, %cl ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: retl -; %t546 = urem i8 %tmp325, 37 ret i8 %t546 } diff --git a/test/CodeGen/X86/urem-power-of-two.ll b/test/CodeGen/X86/urem-power-of-two.ll index 469c573..1b56c87 100644 --- a/test/CodeGen/X86/urem-power-of-two.ll +++ b/test/CodeGen/X86/urem-power-of-two.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s ; The easy case: a constant power-of-2 divisor. @@ -9,7 +9,6 @@ define i64 @const_pow_2(i64 %x) { ; CHECK-NEXT: andl $31, %edi ; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq -; %urem = urem i64 %x, 32 ret i64 %urem } @@ -25,7 +24,6 @@ define i25 @shift_left_pow_2(i25 %x, i25 %y) { ; CHECK-NEXT: addl $33554431, %eax # imm = 0x1FFFFFF ; CHECK-NEXT: andl %edi, %eax ; CHECK-NEXT: retq -; %shl = shl i25 1, %y %urem = urem i25 %x, %shl ret i25 %urem @@ -43,7 +41,6 @@ define i16 @shift_right_pow_2(i16 %x, i16 %y) { ; CHECK-NEXT: andl %edi, %eax ; CHECK-NEXT: # kill: %AX %AX %EAX ; CHECK-NEXT: retq -; %shr = lshr i16 -32768, %y %urem = urem i16 %x, %shr ret i16 %urem @@ -61,7 +58,6 @@ define i8 @and_pow_2(i8 %x, i8 %y) { ; CHECK-NEXT: movzbl %ah, %eax # NOREX ; CHECK-NEXT: # kill: %AL %AL %EAX ; CHECK-NEXT: retq -; %and = and i8 %y, 4 %urem = urem i8 %x, %and ret i8 %urem @@ -74,7 +70,6 @@ define <4 x i32> @vec_const_pow_2(<4 x i32> %x) { ; CHECK: # BB#0: ; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 ; CHECK-NEXT: retq -; %urem = urem <4 x i32> %x, ret <4 x i32> %urem } diff --git a/test/CodeGen/X86/vec3.ll b/test/CodeGen/X86/vec3.ll index 8eaf9f4..e9c47ff 100644 --- a/test/CodeGen/X86/vec3.ll +++ b/test/CodeGen/X86/vec3.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse | FileCheck %s define <3 x float> @fadd(<3 x float> %v, float %d) { @@ -7,7 +7,6 @@ define <3 x float> @fadd(<3 x float> %v, float %d) { ; CHECK-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,0,0,3] ; CHECK-NEXT: addps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %ins = insertelement <3 x float> undef, float %d, i32 0 %splat = shufflevector <3 x float> %ins, <3 x float> undef, <3 x i32> zeroinitializer %add = fadd <3 x float> %splat, %v @@ -23,7 +22,6 @@ define <3 x float> @fdiv(<3 x float> %v, float %d) { ; CHECK-NEXT: divps %xmm0, %xmm1 ; CHECK-NEXT: movaps %xmm1, %xmm0 ; CHECK-NEXT: retq -; %ins = insertelement <3 x float> undef, float %d, i32 0 %splat = shufflevector <3 x float> %ins, <3 x float> undef, <3 x i32> zeroinitializer %div = fdiv <3 x float> %splat, %v diff --git a/test/CodeGen/X86/vector-compare-combines.ll b/test/CodeGen/X86/vector-compare-combines.ll index c25474d..bd7cbfb 100644 --- a/test/CodeGen/X86/vector-compare-combines.ll +++ b/test/CodeGen/X86/vector-compare-combines.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.2 | FileCheck %s --check-prefix=SSE --check-prefix=SSE42 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=AVX --check-prefix=AVX1 @@ -17,7 +17,6 @@ define <4 x i32> @PR27924_cmpeq(<4 x i32> %a, <4 x i32> %b) { ; AVX: # BB#0: ; AVX-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0 ; AVX-NEXT: retq -; %cmp = icmp sgt <4 x i32> %a, %b %max = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> %b %sse_max = tail call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a, <4 x i32> %b) @@ -36,7 +35,6 @@ define <4 x i32> @PR27924_cmpgt(<4 x i32> %a, <4 x i32> %b) { ; AVX: # BB#0: ; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 ; AVX-NEXT: retq -; %cmp = icmp sgt <4 x i32> %a, %b %max = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> %b %sse_max = tail call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a, <4 x i32> %b) diff --git a/test/CodeGen/X86/vector-shuffle-256-v16.ll b/test/CodeGen/X86/vector-shuffle-256-v16.ll index fad5586..d34728d 100644 --- a/test/CodeGen/X86/vector-shuffle-256-v16.ll +++ b/test/CodeGen/X86/vector-shuffle-256-v16.ll @@ -1559,6 +1559,24 @@ define <16 x i16> @shuffle_v16i16_17_18_19_20_21_22_23_zz_25_26_27_28_29_30_31_z ret <16 x i16> %shuffle } +define <16 x i16> @shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13(<16 x i16> %a) { +; AVX1-LABEL: shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13: +; AVX1: # BB#0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [12,13,14,15,2,3,4,5,14,15,0,1,8,9,10,11] +; AVX1-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpshufb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2OR512VL-LABEL: shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13: +; AVX2OR512VL: # BB#0: +; AVX2OR512VL-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[12,13,14,15,2,3,4,5,14,15,0,1,8,9,10,11,28,29,30,31,18,19,20,21,30,31,16,17,24,25,26,27] +; AVX2OR512VL-NEXT: retq + %1 = shufflevector <16 x i16> %a, <16 x i16> undef, <16 x i32> + ret <16 x i16> %1 +} + ; ; Shuffle to logical bit shifts ; diff --git a/test/CodeGen/X86/vzero-excess.ll b/test/CodeGen/X86/vzero-excess.ll index 0ed9074..9ddafec 100644 --- a/test/CodeGen/X86/vzero-excess.ll +++ b/test/CodeGen/X86/vzero-excess.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s ; In the following 4 tests, the existing call to VZU/VZA ensures clean state before diff --git a/test/CodeGen/X86/x86-interleaved-access.ll b/test/CodeGen/X86/x86-interleaved-access.ll index 74214aa..ec8bce1 100644 --- a/test/CodeGen/X86/x86-interleaved-access.ll +++ b/test/CodeGen/X86/x86-interleaved-access.ll @@ -9,8 +9,8 @@ define <4 x double> @load_factorf64_4(<16 x double>* %ptr) { ; AVX-NEXT: vmovupd 32(%rdi), %ymm1 ; AVX-NEXT: vmovupd 64(%rdi), %ymm2 ; AVX-NEXT: vmovupd 96(%rdi), %ymm3 -; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4 -; AVX-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5 +; AVX-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1] +; AVX-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1] ; AVX-NEXT: vhaddpd %ymm5, %ymm4, %ymm4 ; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3] ; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3] @@ -37,8 +37,8 @@ define <4 x double> @load_factorf64_2(<16 x double>* %ptr) { ; AVX-NEXT: vmovupd 32(%rdi), %ymm1 ; AVX-NEXT: vmovupd 64(%rdi), %ymm2 ; AVX-NEXT: vmovupd 96(%rdi), %ymm3 -; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4 -; AVX-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5 +; AVX-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1] +; AVX-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1] ; AVX-NEXT: vunpcklpd {{.*#+}} ymm4 = ymm4[0],ymm5[0],ymm4[2],ymm5[2] ; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3] ; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3] @@ -53,25 +53,15 @@ define <4 x double> @load_factorf64_2(<16 x double>* %ptr) { } define <4 x double> @load_factorf64_1(<16 x double>* %ptr) { -; AVX1-LABEL: load_factorf64_1: -; AVX1: # BB#0: -; AVX1-NEXT: vmovups (%rdi), %ymm0 -; AVX1-NEXT: vmovups 32(%rdi), %ymm1 -; AVX1-NEXT: vinsertf128 $1, 64(%rdi), %ymm0, %ymm0 -; AVX1-NEXT: vinsertf128 $1, 96(%rdi), %ymm1, %ymm1 -; AVX1-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2] -; AVX1-NEXT: vmulpd %ymm0, %ymm0, %ymm0 -; AVX1-NEXT: retq -; -; AVX2-LABEL: load_factorf64_1: -; AVX2: # BB#0: -; AVX2-NEXT: vmovupd (%rdi), %ymm0 -; AVX2-NEXT: vmovupd 32(%rdi), %ymm1 -; AVX2-NEXT: vinsertf128 $1, 64(%rdi), %ymm0, %ymm0 -; AVX2-NEXT: vinsertf128 $1, 96(%rdi), %ymm1, %ymm1 -; AVX2-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2] -; AVX2-NEXT: vmulpd %ymm0, %ymm0, %ymm0 -; AVX2-NEXT: retq +; AVX-LABEL: load_factorf64_1: +; AVX: # BB#0: +; AVX-NEXT: vmovupd (%rdi), %ymm0 +; AVX-NEXT: vmovupd 32(%rdi), %ymm1 +; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[0,1],mem[0,1] +; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[0,1],mem[0,1] +; AVX-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2] +; AVX-NEXT: vmulpd %ymm0, %ymm0, %ymm0 +; AVX-NEXT: retq %wide.vec = load <16 x double>, <16 x double>* %ptr, align 16 %strided.v0 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> %strided.v3 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> @@ -86,8 +76,8 @@ define <4 x i64> @load_factori64_4(<16 x i64>* %ptr) { ; AVX1-NEXT: vmovupd 32(%rdi), %ymm1 ; AVX1-NEXT: vmovupd 64(%rdi), %ymm2 ; AVX1-NEXT: vmovupd 96(%rdi), %ymm3 -; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4 -; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5 +; AVX1-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1] +; AVX1-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1] ; AVX1-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3] ; AVX1-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3] ; AVX1-NEXT: vunpcklpd {{.*#+}} ymm2 = ymm4[0],ymm5[0],ymm4[2],ymm5[2] @@ -113,8 +103,8 @@ define <4 x i64> @load_factori64_4(<16 x i64>* %ptr) { ; AVX2-NEXT: vmovdqu 32(%rdi), %ymm1 ; AVX2-NEXT: vmovdqu 64(%rdi), %ymm2 ; AVX2-NEXT: vmovdqu 96(%rdi), %ymm3 -; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm4 -; AVX2-NEXT: vinserti128 $1, %xmm3, %ymm1, %ymm5 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1] +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1] ; AVX2-NEXT: vperm2i128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3] ; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3] ; AVX2-NEXT: vpunpcklqdq {{.*#+}} ymm2 = ymm4[0],ymm5[0],ymm4[2],ymm5[2] diff --git a/test/DebugInfo/COFF/array-odr-violation.ll b/test/DebugInfo/COFF/array-odr-violation.ll index 471c18f..1041a90 100644 --- a/test/DebugInfo/COFF/array-odr-violation.ll +++ b/test/DebugInfo/COFF/array-odr-violation.ll @@ -65,7 +65,7 @@ attributes #1 = { nounwind readnone } !llvm.dbg.cu = !{!2, !11} !llvm.ident = !{!13, !13} -!llvm.module.flags = !{!14, !18, !19, !20} +!llvm.module.flags = !{!18, !19, !20} !0 = !DIGlobalVariableExpression(var: !1) !1 = distinct !DIGlobalVariable(name: "a", linkageName: "\01?a@@3TYYSTYPE@@A", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) @@ -81,10 +81,6 @@ attributes #1 = { nounwind readnone } !11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !12, producer: "clang version 5.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4) !12 = !DIFile(filename: "b.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "9cfd390d8827beab36769147bb037abc") !13 = !{!"clang version 5.0.0 "} -!14 = !{i32 6, !"Linker Options", !15} -!15 = !{!16, !17} -!16 = !{!"/DEFAULTLIB:libcmt.lib"} -!17 = !{!"/DEFAULTLIB:oldnames.lib"} !18 = !{i32 2, !"CodeView", i32 1} !19 = !{i32 2, !"Debug Info Version", i32 3} !20 = !{i32 1, !"PIC Level", i32 2} diff --git a/test/DebugInfo/COFF/inlining-same-name.ll b/test/DebugInfo/COFF/inlining-same-name.ll index fda5a6d..4a9c992 100644 --- a/test/DebugInfo/COFF/inlining-same-name.ll +++ b/test/DebugInfo/COFF/inlining-same-name.ll @@ -39,12 +39,11 @@ define void @main(i32* %i.i) !dbg !16 { ret void } -!llvm.module.flags = !{!0, !1, !2} +!llvm.module.flags = !{!0, !1} !llvm.dbg.cu = !{!4} !0 = !{i32 2, !"CodeView", i32 1} !1 = !{i32 2, !"Debug Info Version", i32 3} -!2 = !{i32 6, !"Linker Options", !{}} !4 = distinct !DICompileUnit(language: DW_LANG_D, file: !5, producer: "LDC (http://wiki.dlang.org/LDC)", isOptimized: false, runtimeVersion: 1, emissionKind: FullDebug) !5 = !DIFile(filename: "opover2.d", directory: "C:\5CLDC\5Cninja-ldc\5C..\5Cldc\5Ctests\5Cd2\5Cdmd-testsuite\5Crunnable") !6 = !DILocation(line: 302, column: 9, scope: !7, inlinedAt: !15) diff --git a/test/DebugInfo/Generic/block-asan.ll b/test/DebugInfo/Generic/block-asan.ll index f1f8b35..73df59b 100644 --- a/test/DebugInfo/Generic/block-asan.ll +++ b/test/DebugInfo/Generic/block-asan.ll @@ -13,7 +13,7 @@ ; Check that the location of the ASAN instrumented __block variable is ; correct. -; CHECK: !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24) +; CHECK: !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24) target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" @@ -79,7 +79,7 @@ attributes #3 = { nounwind } !19 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !20 = !DIDerivedType(tag: DW_TAG_member, name: "__size", size: 32, align: 32, offset: 160, file: !1, scope: !5, baseType: !19) !21 = !DIDerivedType(tag: DW_TAG_member, name: "x", size: 32, align: 32, offset: 192, file: !1, scope: !5, baseType: !19) -!22 = !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24) +!22 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24) !23 = !DILocation(line: 4, column: 15, scope: !4) !24 = !DILocation(line: 4, column: 3, scope: !4) !25 = !DILocation(line: 5, column: 3, scope: !4) diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o b/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o new file mode 100644 index 0000000..b3c73f7 Binary files /dev/null and b/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o differ diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s index e0a634c..f395f4b 100644 --- a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s +++ b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s @@ -248,253 +248,3 @@ TU_split_5_type: .byte 0 # NULL .byte 0 # NULL TU_split_5_end: -# Test object to verify dwarfdump handles v5 string offset tables. -# We have 2 v5 CUs, a v5 TU, and a split v5 CU and TU. -# -# To generate the test object: -# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets.s -filetype=obj \ -# -o dwarfdump-str-offsets.elf-x86-64 - - .section .debug_str,"MS",@progbits,1 -str_producer: - .asciz "Handmade DWARF producer" -str_CU1: - .asciz "Compile_Unit_1" -str_CU1_dir: - .asciz "/home/test/CU1" -str_CU2: - .asciz "Compile_Unit_2" -str_CU2_dir: - .asciz "/home/test/CU2" -str_TU: - .asciz "Type_Unit" -str_TU_type: - .asciz "MyStruct" - -# Every unit contributes to the string_offsets table. - .section .debug_str_offsets,"",@progbits -# CU1's contribution - .long .debug_str_offsets_segment0_end-.debug_str_offsets_base0 - .short 5 # DWARF version - .short 0 # Padding -.debug_str_offsets_base0: - .long str_producer - .long str_CU1 - .long str_CU1_dir -.debug_str_offsets_segment0_end: -# CU2's contribution - .long .debug_str_offsets_segment1_end-.debug_str_offsets_base1 - .short 5 # DWARF version - .short 0 # Padding -.debug_str_offsets_base1: - .long str_producer - .long str_CU2 - .long str_CU2_dir -.debug_str_offsets_segment1_end: -# The TU's contribution - .long .debug_str_offsets_segment2_end-.debug_str_offsets_base2 - .short 5 # DWARF version - .short 0 # Padding -.debug_str_offsets_base2: - .long str_TU - .long str_TU_type -.debug_str_offsets_segment2_end: - - .section .debug_str.dwo,"MS",@progbits,1 -dwo_str_CU_5_producer: - .asciz "Handmade split DWARF producer" -dwo_str_CU_5_name: - .asciz "V5_split_compile_unit" -dwo_str_CU_5_comp_dir: - .asciz "/home/test/splitCU" -dwo_str_TU_5: - .asciz "V5_split_type_unit" -dwo_str_TU_5_type: - .asciz "V5_split_Mystruct" - - .section .debug_str_offsets.dwo,"",@progbits -# The split CU's contribution - .long .debug_dwo_str_offsets_segment0_end-.debug_dwo_str_offsets_base0 - .short 5 # DWARF version - .short 0 # Padding -.debug_dwo_str_offsets_base0: - .long dwo_str_CU_5_producer-.debug_str.dwo - .long dwo_str_CU_5_name-.debug_str.dwo - .long dwo_str_CU_5_comp_dir-.debug_str.dwo -.debug_dwo_str_offsets_segment0_end: -# The split TU's contribution - .long .debug_dwo_str_offsets_segment1_end-.debug_dwo_str_offsets_base1 - .short 5 # DWARF version - .short 0 # Padding -.debug_dwo_str_offsets_base1: - .long dwo_str_TU_5-.debug_str.dwo - .long dwo_str_TU_5_type-.debug_str.dwo -.debug_dwo_str_offsets_segment1_end: - -# All CUs/TUs use the same abbrev section for simplicity. - .section .debug_abbrev,"",@progbits - .byte 0x01 # Abbrev code - .byte 0x11 # DW_TAG_compile_unit - .byte 0x00 # DW_CHILDREN_no - .byte 0x25 # DW_AT_producer - .byte 0x1a # DW_FORM_strx - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset - .byte 0x1b # DW_AT_comp_dir - .byte 0x1a # DW_FORM_strx - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x02 # Abbrev code - .byte 0x41 # DW_TAG_type_unit - .byte 0x01 # DW_CHILDREN_yes - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x03 # Abbrev code - .byte 0x13 # DW_TAG_structure_type - .byte 0x00 # DW_CHILDREN_no (no members) - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x00 # EOM(3) - -# And a .dwo copy for the .dwo sections. - .section .debug_abbrev.dwo,"",@progbits - .byte 0x01 # Abbrev code - .byte 0x11 # DW_TAG_compile_unit - .byte 0x00 # DW_CHILDREN_no - .byte 0x25 # DW_AT_producer - .byte 0x1a # DW_FORM_strx - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset - .byte 0x1b # DW_AT_comp_dir - .byte 0x1a # DW_FORM_strx - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x02 # Abbrev code - .byte 0x41 # DW_TAG_type_unit - .byte 0x01 # DW_CHILDREN_yes - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x03 # Abbrev code - .byte 0x13 # DW_TAG_structure_type - .byte 0x00 # DW_CHILDREN_no (no members) - .byte 0x03 # DW_AT_name - .byte 0x1a # DW_FORM_strx - .byte 0x00 # EOM(1) - .byte 0x00 # EOM(2) - .byte 0x00 # EOM(3) - - .section .debug_info,"",@progbits - -# DWARF v5 CU header. - .long CU1_5_end-CU1_5_version # Length of Unit -CU1_5_version: - .short 5 # DWARF version number - .byte 1 # DWARF Unit Type - .byte 8 # Address Size (in bytes) - .long .debug_abbrev # Offset Into Abbrev. Section -# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, -# DW_AT_str_offsets and DW_AT_compdir. - .byte 1 # Abbreviation code - .byte 0 # The index of the producer string - .byte 1 # The index of the CU name string - .long .debug_str_offsets_base0 - .byte 2 # The index of the comp dir string - .byte 0 # NULL -CU1_5_end: - -# DWARF v5 CU header - .long CU2_5_end-CU2_5_version # Length of Unit -CU2_5_version: - .short 5 # DWARF version number - .byte 1 # DWARF Unit Type - .byte 8 # Address Size (in bytes) - .long .debug_abbrev # Offset Into Abbrev. Section -# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, -# DW_AT_str_offsets and DW_AT_compdir. - .byte 1 # Abbreviation code - .byte 0 # The index of the producer string - .byte 1 # The index of the CU name string - .long .debug_str_offsets_base1 - .byte 2 # The index of the comp dir string - .byte 0 # NULL -CU2_5_end: - - .section .debug_types,"",@progbits -# DWARF v5 Type unit header. -TU_5_start: - .long TU_5_end-TU_5_version # Length of Unit -TU_5_version: - .short 5 # DWARF version number - .byte 2 # DWARF Unit Type - .byte 8 # Address Size (in bytes) - .long .debug_abbrev # Offset Into Abbrev. Section - .quad 0x0011223344556677 # Type Signature - .long TU_5_type-TU_5_start # Type offset -# The type-unit DIE, which has a name. - .byte 2 # Abbreviation code - .byte 0 # Index of the unit type name string - .long .debug_str_offsets_base2 # offset into the str_offsets section -# The type DIE, which has a name. -TU_5_type: - .byte 3 # Abbreviation code - .byte 1 # Index of the type name string - .byte 0 # NULL - .byte 0 # NULL -TU_5_end: - - .section .debug_info.dwo,"",@progbits - -# DWARF v5 split CU header. - .long CU_split_5_end-CU_split_5_version # Length of Unit -CU_split_5_version: - .short 5 # DWARF version number - .byte 1 # DWARF Unit Type - .byte 8 # Address Size (in bytes) - .long .debug_abbrev.dwo # Offset Into Abbrev Section -# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, -# DW_AT_str_offsets and DW_AT_compdir. - .byte 1 # Abbreviation code - .byte 0 # The index of the producer string - .byte 1 # The index of the CU name string - .long .debug_dwo_str_offsets_base0-.debug_str_offsets.dwo - .byte 2 # The index of the comp dir string - .byte 0 # NULL -CU_split_5_end: - - .section .debug_types.dwo,"",@progbits - -# DWARF v5 split type unit header. -TU_split_5_start: - .long TU_split_5_end-TU_split_5_version # Length of Unit -TU_split_5_version: - .short 5 # DWARF version number - .byte 6 # DWARF Unit Type - .byte 8 # Address Size (in bytes) - .long .debug_abbrev.dwo # Offset Into Abbrev Section - .quad 0x8899aabbccddeeff # Type Signature - .long TU_split_5_type-TU_split_5_start # Type offset -# The type-unit DIE, which has a name. - .byte 2 # Abbreviation code - .byte 0 # The index of the type unit name string - .long .debug_dwo_str_offsets_base1-.debug_str_offsets.dwo -# The type DIE, which has a name. -TU_split_5_type: - .byte 3 # Abbreviation code - .byte 1 # The index of the type name string - .byte 0 # NULL - .byte 0 # NULL -TU_split_5_end: diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc index 966a465..6c50638 100644 --- a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc +++ b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc @@ -22,6 +22,7 @@ int main() { // $ cp dwarfdump-test-zlib.cc /tmp/dbginfo // $ cd /tmp/dbginfo // $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib -o dwarfdump-test-zlib.elf-x86-64 +// $ clang++ -g dwarfdump-test-zlib.cc -Wa,--compress-debug-sections=zlib -c -o dwarfdump-test-zlib.o.elf-x86-64 // $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib-gnu -o dwarfdump-test-zlibgnu.elf-x86-64 // llvm-readobj -sections can be used to see that outputs really contain the compressed sections, also output in both -// cases is slightly smaller, that is because of compression. \ No newline at end of file +// cases is slightly smaller, that is because of compression. diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64 new file mode 100644 index 0000000..55f5cb0 Binary files /dev/null and b/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64 differ diff --git a/test/DebugInfo/MIR/ARM/split-superreg-complex.mir b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir index 2e8d997..0ebde3c 100644 --- a/test/DebugInfo/MIR/ARM/split-superreg-complex.mir +++ b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir @@ -57,7 +57,7 @@ !17 = !{!18} !18 = !DISubrange(count: 4) !19 = !DILocation(line: 4, column: 13, scope: !9) - !20 = !DIExpression(DW_OP_plus, 1, DW_OP_minus, 1) + !20 = !DIExpression(DW_OP_plus_uconst, 1, DW_OP_constu, 1, DW_OP_minus) !21 = !DILocation(line: 4, column: 7, scope: !9) !22 = !DILocation(line: 5, column: 9, scope: !9) !23 = !DILocation(line: 5, column: 18, scope: !9) diff --git a/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml b/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml new file mode 100644 index 0000000..a2966c4 --- /dev/null +++ b/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml @@ -0,0 +1,10 @@ +--- +DbiStream: + Modules: + - Module: unknown-symbol.yaml + Modi: + Records: + - Kind: S_ANNOTATION + UnknownSym: + Data: 123456789ABCDEF0 +... diff --git a/test/DebugInfo/PDB/pdb-unknown-symbol.test b/test/DebugInfo/PDB/pdb-unknown-symbol.test new file mode 100644 index 0000000..3d2547e --- /dev/null +++ b/test/DebugInfo/PDB/pdb-unknown-symbol.test @@ -0,0 +1,6 @@ +; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/unknown-symbol.yaml +; RUN: llvm-pdbutil pdb2yaml -minimal -module-syms -no-file-headers %t.pdb | FileCheck %s + +CHECK: - Kind: S_ANNOTATION +CHECK: UnknownSym: +CHECK: Data: 123456789ABCDEF0 diff --git a/test/DebugInfo/PDB/pdb-yaml-types.test b/test/DebugInfo/PDB/pdb-yaml-types.test deleted file mode 100644 index f65d9ed..0000000 --- a/test/DebugInfo/PDB/pdb-yaml-types.test +++ /dev/null @@ -1,74 +0,0 @@ -RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml -RUN: FileCheck -check-prefix=YAML %s < %t.yaml -RUN: llvm-pdbutil yaml2pdb %t.yaml -pdb %t.pdb -RUN: llvm-pdbutil raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB - -Only verify the beginning of the type stream. - -YAML: TpiStream: -YAML-NEXT: Version: VC80 -YAML-NEXT: Records: -YAML-NEXT: - Kind: LF_ARGLIST -YAML-NEXT: ArgList: -YAML-NEXT: ArgIndices: [ ] -YAML-NEXT: - Kind: LF_PROCEDURE -YAML-NEXT: Procedure: -YAML-NEXT: ReturnType: 3 -YAML-NEXT: CallConv: NearC -YAML-NEXT: Options: [ None ] -YAML-NEXT: ParameterCount: 0 -YAML-NEXT: ArgumentList: 4096 -YAML-NEXT: - Kind: LF_PROCEDURE -YAML-NEXT: Procedure: -YAML-NEXT: ReturnType: 116 -YAML-NEXT: CallConv: NearC -YAML-NEXT: Options: [ None ] -YAML-NEXT: ParameterCount: 0 -YAML-NEXT: ArgumentList: 4096 - -This test is mostly checking to make sure we include the type index offset -table, and eventually hash codes. The type index offsets should be similar to -what are already present in big-read.pdb. - -PDB: Type Info Stream (TPI) { -PDB-NEXT: TPI Version: 20040203 -PDB-NEXT: Record count: 728 -PDB-NEXT: Records [ -PDB-NEXT: { -PDB-NEXT: ArgList (0x1000) { -PDB-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) -PDB-NEXT: NumArgs: 0 -PDB-NEXT: Arguments [ -PDB-NEXT: ] -PDB-NEXT: } -PDB-NEXT: } -PDB-NEXT: { -PDB-NEXT: Procedure (0x1001) { -PDB-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -PDB-NEXT: ReturnType: void (0x3) -PDB-NEXT: CallingConvention: NearC (0x0) -PDB-NEXT: FunctionOptions [ (0x0) -PDB-NEXT: ] -PDB-NEXT: NumParameters: 0 -PDB-NEXT: ArgListType: () (0x1000) -PDB-NEXT: } -PDB-NEXT: } -PDB-NEXT: { -PDB-NEXT: Procedure (0x1002) { -PDB-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -PDB-NEXT: ReturnType: int (0x74) -PDB-NEXT: CallingConvention: NearC (0x0) -PDB-NEXT: FunctionOptions [ (0x0) -PDB-NEXT: ] -PDB-NEXT: NumParameters: 0 -PDB-NEXT: ArgListType: () (0x1000) -PDB-NEXT: } -PDB-NEXT: } -... -PDB: TypeIndexOffsets [ -PDB-NEXT: Index: 0x1000, Offset: 0 -PDB-NEXT: Index: 0x106c, Offset: 8,116 -PDB-NEXT: Index: 0x1118, Offset: 16,372 -PDB-NEXT: Index: 0x11df, Offset: 24,564 -PDB-NEXT: Index: 0x128e, Offset: 32,752 -PDB-NEXT: ] diff --git a/test/DebugInfo/PDB/pdbdump-debug-subsections.test b/test/DebugInfo/PDB/pdbdump-debug-subsections.test index 52f7bb5..4338f11 100644 --- a/test/DebugInfo/PDB/pdbdump-debug-subsections.test +++ b/test/DebugInfo/PDB/pdbdump-debug-subsections.test @@ -1,6 +1,5 @@ ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml ; RUN: llvm-pdbutil pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s -; RUN: llvm-pdbutil raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s YAML: Modules: YAML-NEXT: - Module: Foo.obj @@ -61,150 +60,7 @@ YAML-NEXT: EndDelta: 0 YAML-NEXT: Columns: YAML-NEXT: - !InlineeLines YAML-NEXT: HasExtraFiles: false -YAML-NEXT: Sites: +YAML-NEXT: Sites: YAML-NEXT: - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h' YAML-NEXT: LineNum: 26950 YAML-NEXT: Inlinee: 22767 - - -RAW: DBI Stream { -RAW: Modules [ -RAW-NEXT: { -RAW-NEXT: Name: Foo.obj -RAW: Subsections [ -RAW-NEXT: CrossModuleExports [ -RAW-NEXT: Export { -RAW-NEXT: Local: 0x12F4 -RAW-NEXT: Global: 0x2443 -RAW-NEXT: } -RAW-NEXT: Export { -RAW-NEXT: Local: 0x80001083 -RAW-NEXT: Global: 0x23A3 -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: { -RAW-NEXT: Name: Bar.obj -RAW: Subsections [ -RAW-NEXT: CrossModuleExports [ -RAW-NEXT: Export { -RAW-NEXT: Local: 0x10A9 -RAW-NEXT: Global: 0x17D1 -RAW-NEXT: } -RAW-NEXT: Export { -RAW-NEXT: Local: 0x10C9 -RAW-NEXT: Global: 0x1245 -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: CrossModuleImports [ -RAW-NEXT: ModuleImport { -RAW-NEXT: Module: Foo.obj -RAW-NEXT: Imports: [0x12F4, 0x80001083] -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: { -RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -RAW: Subsections [ -RAW-NEXT: FileChecksums { -RAW-NEXT: Checksum { -RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -RAW-NEXT: Kind: MD5 (0x1) -RAW-NEXT: Checksum ( -RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| -RAW-NEXT: ) -RAW-NEXT: } -RAW-NEXT: Checksum { -RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h -RAW-NEXT: Kind: MD5 (0x1) -RAW-NEXT: Checksum ( -RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k| -RAW-NEXT: ) -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: Lines { -RAW-NEXT: RelocSegment: 1 -RAW-NEXT: RelocOffset: 100016 -RAW-NEXT: CodeSize: 10 -RAW-NEXT: HasColumns: No -RAW-NEXT: FileEntry { -RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -RAW-NEXT: Line { -RAW-NEXT: Offset: 0 -RAW-NEXT: LineNumberStart: 5 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: Line { -RAW-NEXT: Offset: 3 -RAW-NEXT: LineNumberStart: 6 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: Line { -RAW-NEXT: Offset: 8 -RAW-NEXT: LineNumberStart: 7 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: InlineeLines { -RAW-NEXT: HasExtraFiles: No -RAW-NEXT: Lines [ -RAW-NEXT: Inlinee { -RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h -RAW-NEXT: Function { -RAW-NEXT: Index: 0x58ef (unknown function) -RAW-NEXT: } -RAW-NEXT: SourceLine: 26950 -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: { -RAW-NEXT: Name: ObjFileSubsections -RAW-NEXT: Debug Stream Index: 11 -RAW-NEXT: Object File Name: ObjFileSubsections -RAW-NEXT: Num Files: 0 -RAW-NEXT: Source File Name Idx: 0 -RAW-NEXT: Pdb File Name Idx: 0 -RAW-NEXT: Line Info Byte Size: 0 -RAW-NEXT: C13 Line Info Byte Size: 116 -RAW-NEXT: Symbol Byte Size: 4 -RAW-NEXT: Type Server Index: 0 -RAW-NEXT: Has EC Info: No -RAW-NEXT: Subsections [ -RAW-NEXT: String Table [ -RAW-NEXT: String1 -RAW-NEXT: String2 -RAW-NEXT: String3 -RAW-NEXT: ] -RAW-NEXT: Symbols [ -RAW-NEXT: { -RAW-NEXT: ObjectName { -RAW-NEXT: Signature: 0x0 -RAW-NEXT: ObjectName: ObjFileSubsections -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: FrameData [ -RAW-NEXT: Frame { -RAW-NEXT: Rva: 6 -RAW-NEXT: CodeSize: 1 -RAW-NEXT: LocalSize: 2 -RAW-NEXT: ParamsSize: 4 -RAW-NEXT: MaxStackSize: 3 -RAW-NEXT: FrameFunc: MyFunc -RAW-NEXT: PrologSize: 5 -RAW-NEXT: SavedRegsSize: 7 -RAW-NEXT: Flags: 0 -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: } diff --git a/test/DebugInfo/PDB/pdbdump-headers.test b/test/DebugInfo/PDB/pdbdump-headers.test index 82fe91d..fa9a251 100644 --- a/test/DebugInfo/PDB/pdbdump-headers.test +++ b/test/DebugInfo/PDB/pdbdump-headers.test @@ -1,2901 +1,1082 @@ -; RUN: llvm-pdbutil raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \ -; RUN: -sym-record-bytes -globals -publics -module-files \ -; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \ -; RUN: -section-contribs -section-map -section-headers -subsections=all \ -; RUN: -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s ; RUN: llvm-pdbutil raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s -; RUN: llvm-pdbutil raw -headers -modules -module-files \ +; RUN: llvm-pdbutil raw -summary -modules -files \ ; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s -; RUN: not llvm-pdbutil raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s +; RUN: not llvm-pdbutil raw -summary %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s -; EMPTY: FileHeaders { -; EMPTY-NEXT: BlockSize: 4096 -; EMPTY-NEXT: FreeBlockMap: 2 -; EMPTY-NEXT: NumBlocks: 25 -; EMPTY-NEXT: NumDirectoryBytes: 136 -; EMPTY-NEXT: Unknown1: 0 -; EMPTY-NEXT: BlockMapAddr: 24 -; EMPTY-NEXT: NumDirectoryBlocks: 1 -; EMPTY-NEXT: DirectoryBlocks: [23] -; EMPTY-NEXT: NumStreams: 17 -; EMPTY-NEXT: } -; EMPTY-NEXT: Streams [ -; EMPTY-NEXT: Stream 0: [Old MSF Directory] (40 bytes) -; EMPTY-NEXT: Stream 1: [PDB Stream] (118 bytes) -; EMPTY-NEXT: Stream 2: [TPI Stream] (5392 bytes) -; EMPTY-NEXT: Stream 3: [DBI Stream] (739 bytes) -; EMPTY-NEXT: Stream 4: [IPI Stream] (784 bytes) -; EMPTY-NEXT: Stream 5: [Named Stream "/LinkInfo"] (0 bytes) -; EMPTY-NEXT: Stream 6: [Global Symbol Hash] (556 bytes) -; EMPTY-NEXT: Stream 7: [Public Symbol Hash] (604 bytes) -; EMPTY-NEXT: Stream 8: [Public Symbol Records] (104 bytes) -; EMPTY-NEXT: Stream 9: [Named Stream "/src/headerblock"] (0 bytes) -; EMPTY-NEXT: Stream 10: [Section Header Data] (160 bytes) -; EMPTY-NEXT: Stream 11: [New FPO Data] (32 bytes) -; EMPTY-NEXT: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes) -; EMPTY-NEXT: Stream 13: [Named Stream "/names"] (239 bytes) -; EMPTY-NEXT: Stream 14: [Module "* Linker *"] (520 bytes) -; EMPTY-NEXT: Stream 15: [TPI Hash] (308 bytes) -; EMPTY-NEXT: Stream 16: [IPI Hash] (68 bytes) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Msf Free Pages: [3, 4, 5, 8, 9] -; EMPTY-NEXT: Orphaned Pages: [] -; EMPTY-NEXT: Multiply Used Pages: [] -; EMPTY-NEXT: Use After Free Pages: [] -; EMPTY-NEXT: StreamBlocks [ -; EMPTY-NEXT: Stream 0: [8] -; EMPTY-NEXT: Stream 1: [19] -; EMPTY-NEXT: Stream 2: [18, 17] -; EMPTY-NEXT: Stream 3: [14] -; EMPTY-NEXT: Stream 4: [20] -; EMPTY-NEXT: Stream 5: [] -; EMPTY-NEXT: Stream 6: [11] -; EMPTY-NEXT: Stream 7: [13] -; EMPTY-NEXT: Stream 8: [12] -; EMPTY-NEXT: Stream 9: [] -; EMPTY-NEXT: Stream 10: [10] -; EMPTY-NEXT: Stream 11: [15] -; EMPTY-NEXT: Stream 12: [6] -; EMPTY-NEXT: Stream 13: [16] -; EMPTY-NEXT: Stream 14: [7] -; EMPTY-NEXT: Stream 15: [21] -; EMPTY-NEXT: Stream 16: [22] -; EMPTY-NEXT: ] -; EMPTY-NEXT: String Table { -; EMPTY-NEXT: 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)' -; EMPTY-NEXT: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' -; EMPTY-NEXT: '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = ' -; EMPTY-NEXT: } -; EMPTY-NEXT: PDB Stream { -; EMPTY-NEXT: Version: 20000404 -; EMPTY-NEXT: Signature: 0x54E507E2 -; EMPTY-NEXT: Age: 1 -; EMPTY-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0} -; EMPTY-NEXT: Features: 0x1 -; EMPTY-NEXT: Named Streams { -; EMPTY-NEXT: /names: 13 -; EMPTY-NEXT: /LinkInfo: 5 -; EMPTY-NEXT: /src/headerblock: 9 -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: Type Info Stream (TPI) { -; EMPTY-NEXT: TPI Version: 20040203 -; EMPTY-NEXT: Record count: 75 -; EMPTY-NEXT: Records [ -; EMPTY-NEXT: { -; EMPTY-NEXT: ArgList (0x1000) { -; EMPTY-NEXT: TypeLeafKind: LF_ARGLIST (0x1201) -; EMPTY-NEXT: NumArgs: 0 -; EMPTY-NEXT: Arguments [ -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 |....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Procedure (0x1001) { -; EMPTY-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008) -; EMPTY-NEXT: ReturnType: int (0x74) -; EMPTY-NEXT: CallingConvention: NearC (0x0) -; EMPTY-NEXT: FunctionOptions [ (0x0) -; EMPTY-NEXT: ] -; EMPTY-NEXT: NumParameters: 0 -; EMPTY-NEXT: ArgListType: () (0x1000) -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 74000000 00000000 00100000 |t...........| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: FieldList (0x1002) { -; EMPTY-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203) -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 1 -; EMPTY-NEXT: Name: apartment -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 2 -; EMPTY-NEXT: Name: single -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 3 -; EMPTY-NEXT: Name: free -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 4 -; EMPTY-NEXT: Name: neutral -; EMPTY-NEXT: } -; EMPTY-NEXT: Enumerator { -; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502) -; EMPTY-NEXT: AccessSpecifier: Public (0x3) -; EMPTY-NEXT: EnumValue: 5 -; EMPTY-NEXT: Name: both -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 02150300 01006170 6172746D 656E7400 |......apartment.| -; EMPTY-NEXT: 0010: 02150300 02007369 6E676C65 00F3F2F1 |......single....| -; EMPTY-NEXT: 0020: 02150300 03006672 656500F1 02150300 |......free......| -; EMPTY-NEXT: 0030: 04006E65 75747261 6C00F2F1 02150300 |..neutral.......| -; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY: Hash { -; EMPTY-NEXT: Number of Hash Buckets: 262143 -; EMPTY-NEXT: Hash Key Size: 4 -; EMPTY-NEXT: Values: [205956, 163561, 59811, 208239, 16377, 247078, 194342, 254156, 194536, 167492, 185421, 119540, 261871, 198119, 48056, 251486, 134580, 148190, 113636, 53336, 55779, 220695, 198114, 148734, 81128, 60158, 217249, 174209, 159978, 249504, 141941, 238785, 6214, 94935, 151449, 135589, 73373, 96512, 254299, 17744, 239514, 173189, 130544, 204437, 238560, 144673, 115151, 197306, 256035, 101096, 231280, 52156, 48854, 170035, 177041, 102745, 16947, 183703, 98548, 35693, 171328, 203640, 139292, 49018, 43821, 202555, 165040, 215835, 142625, 52534, 44186, 103930, 110942, 17991, 213215] -; EMPTY-NEXT: Adjusters [ -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: TypeIndexOffsets [ -; EMPTY-NEXT: Index: 0x1000, Offset: 0 -; EMPTY-NEXT: ] -; EMPTY: Type Info Stream (IPI) { -; EMPTY-NEXT: IPI Version: 20040203 -; EMPTY-NEXT: Record count: 15 -; EMPTY-NEXT: Records [ -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1000) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::threadingAttribute (0x100B) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 481 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 0B100000 01000000 E1010000 0100F2F1 |................| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1001) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::event_receiverAttribute (0x1017) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 194 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 17100000 01000000 C2000000 0100F2F1 |................| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1002) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::aggregatableAttribute (0x1021) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 603 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 21100000 01000000 5B020000 0100F2F1 |!.......[.......| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1003) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::event_sourceAttribute (0x102C) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 1200 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 2C100000 01000000 B0040000 0100F2F1 |,...............| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1004) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::moduleAttribute (0x103A) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 540 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 3A100000 01000000 1C020000 0100F2F1 |:...............| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1005) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::helper_attributes::usageAttribute (0x1042) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 108 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 42100000 01000000 6C000000 0100F2F1 |B.......l.......| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: UdtModSourceLine (0x1006) { -; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; EMPTY-NEXT: UDT: __vc_attributes::helper_attributes::v1_alttypeAttribute (0x104A) -; EMPTY-NEXT: SourceFile: (0x1) -; EMPTY-NEXT: LineNumber: 96 -; EMPTY-NEXT: Module: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 4A100000 01000000 60000000 0100F2F1 |J.......`.......| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x1007) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: 0x0 -; EMPTY-NEXT: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\| -; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P| -; EMPTY-NEXT: 0020: 44425C49 6E707574 7300F2F1 |DB\Inputs...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x1008) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: 0x0 -; EMPTY-NEXT: StringData: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 433A5C50 726F6772 616D2046 |....C:\Program F| -; EMPTY-NEXT: 0010: 696C6573 20287838 36295C4D 6963726F |iles (x86)\Micro| -; EMPTY-NEXT: 0020: 736F6674 20566973 75616C20 53747564 |soft Visual Stud| -; EMPTY-NEXT: 0030: 696F2031 322E305C 56435C42 494E5C63 |io 12.0\VC\BIN\c| -; EMPTY-NEXT: 0040: 6C2E6578 6500F2F1 |l.exe...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x1009) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: 0x0 -; EMPTY-NEXT: StringData: empty.cpp -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 656D7074 792E6370 7000F2F1 |....empty.cpp...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x100A) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: 0x0 -; EMPTY-NEXT: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\| -; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P| -; EMPTY-NEXT: 0020: 44425C49 6E707574 735C7663 3132302E |DB\Inputs\vc120.| -; EMPTY-NEXT: 0030: 70646200 |pdb.| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x100B) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: 0x0 -; EMPTY-NEXT: StringData: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 2D5A6920 2D4D5420 2D492243 |....-Zi -MT -I"C| -; EMPTY-NEXT: 0010: 3A5C5072 6F677261 6D204669 6C657320 |:\Program Files | -; EMPTY-NEXT: 0020: 28783836 295C4D69 63726F73 6F667420 |(x86)\Microsoft | -; EMPTY-NEXT: 0030: 56697375 616C2053 74756469 6F203132 |Visual Studio 12| -; EMPTY-NEXT: 0040: 2E305C56 435C494E 434C5544 4522202D |.0\VC\INCLUDE" -| -; EMPTY-NEXT: 0050: 4922433A 5C50726F 6772616D 2046696C |I"C:\Program Fil| -; EMPTY-NEXT: 0060: 65732028 78383629 5C4D6963 726F736F |es (x86)\Microso| -; EMPTY-NEXT: 0070: 66742056 69737561 6C205374 7564696F |ft Visual Studio| -; EMPTY-NEXT: 0080: 2031322E 305C5643 5C41544C 4D46435C | 12.0\VC\ATLMFC\| -; EMPTY-NEXT: 0090: 494E434C 55444522 202D4922 433A5C50 |INCLUDE" -I"C:\P| -; EMPTY-NEXT: 00A0: 726F6772 616D2046 696C6573 20287838 |rogram Files (x8| -; EMPTY-NEXT: 00B0: 36295C57 696E646F 7773204B 6974735C |6)\Windows Kits\| -; EMPTY-NEXT: 00C0: 382E315C 696E636C 7564655C 73686172 |8.1\include\shar| -; EMPTY-NEXT: 00D0: 65642220 2D492243 3A5C5072 6F677261 |ed" -I"C:\Progra| -; EMPTY-NEXT: 00E0: 6D204669 6C657320 28783836 295C5769 |m Files (x86)\Wi| -; EMPTY-NEXT: 00F0: 6E646F77 7300F2F1 |ndows...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringList (0x100C) { -; EMPTY-NEXT: TypeLeafKind: LF_SUBSTR_LIST (0x1604) -; EMPTY-NEXT: NumStrings: 1 -; EMPTY-NEXT: Strings [ -; EMPTY-NEXT: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 01000000 0B100000 |........| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: StringId (0x100D) { -; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605) -; EMPTY-NEXT: Id: "-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows" (0x100C) -; EMPTY-NEXT: StringData: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 0C100000 204B6974 735C382E 315C696E |.... Kits\8.1\in| -; EMPTY-NEXT: 0010: 636C7564 655C756D 22202D49 22433A5C |clude\um" -I"C:\| -; EMPTY-NEXT: 0020: 50726F67 72616D20 46696C65 73202878 |Program Files (x| -; EMPTY-NEXT: 0030: 3836295C 57696E64 6F777320 4B697473 |86)\Windows Kits| -; EMPTY-NEXT: 0040: 5C382E31 5C696E63 6C756465 5C77696E |\8.1\include\win| -; EMPTY-NEXT: 0050: 72742220 2D545020 2D5800F1 |rt" -TP -X..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: BuildInfo (0x100E) { -; EMPTY-NEXT: TypeLeafKind: LF_BUILDINFO (0x1603) -; EMPTY-NEXT: NumArgs: 5 -; EMPTY-NEXT: Arguments [ -; EMPTY-NEXT: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs (0x1007) -; EMPTY-NEXT: ArgType: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe (0x1008) -; EMPTY-NEXT: ArgType: empty.cpp (0x1009) -; EMPTY-NEXT: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb (0x100A) -; EMPTY-NEXT: ArgType: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X (0x100D) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 05000710 00000810 00000910 00000A10 |................| -; EMPTY-NEXT: 0010: 00000D10 0000F2F1 |........| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: TypeIndexOffsets [ -; EMPTY-NEXT: Index: 0x1000, Offset: 0 -; EMPTY-NEXT: ] -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY: DBI Stream { -; EMPTY-NEXT: Dbi Version: 19990903 -; EMPTY-NEXT: Age: 1 -; EMPTY-NEXT: Incremental Linking: Yes -; EMPTY-NEXT: Has CTypes: No -; EMPTY-NEXT: Is Stripped: No -; EMPTY-NEXT: Machine Type: x86 -; EMPTY-NEXT: Symbol Record Stream Index: 8 -; EMPTY-NEXT: Public Symbol Stream Index: 7 -; EMPTY-NEXT: Global Symbol Stream Index: 6 -; EMPTY-NEXT: Toolchain Version: 12.0 -; EMPTY-NEXT: mspdb120.dll version: 12.0.31101 -; EMPTY-NEXT: Modules [ -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; EMPTY-NEXT: Debug Stream Index: 12 -; EMPTY-NEXT: Object File Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; EMPTY-NEXT: Num Files: 1 -; EMPTY-NEXT: Source File Name Idx: 0 -; EMPTY-NEXT: Pdb File Name Idx: 0 -; EMPTY-NEXT: Line Info Byte Size: 0 -; EMPTY-NEXT: C13 Line Info Byte Size: 88 -; EMPTY-NEXT: Symbol Byte Size: 208 -; EMPTY-NEXT: Type Server Index: 0 -; EMPTY-NEXT: Has EC Info: No -; EMPTY-NEXT: 1 Contributing Source Files [ -; EMPTY-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -; EMPTY-NEXT: ] -; EMPTY-NEXT: Symbols [ -; EMPTY-NEXT: { -; EMPTY-NEXT: ObjectName { -; EMPTY-NEXT: Signature: 0x0 -; EMPTY-NEXT: ObjectName: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\| -; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P| -; EMPTY-NEXT: 0020: 44425C49 6E707574 735C656D 7074792E |DB\Inputs\empty.| -; EMPTY-NEXT: 0030: 6F626A00 |obj.| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: CompilerFlags3 { -; EMPTY-NEXT: Language: Cpp (0x1) -; EMPTY-NEXT: Flags [ (0x2000) -; EMPTY-NEXT: SecurityChecks (0x2000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Machine: Pentium3 (0x7) -; EMPTY-NEXT: FrontendVersion: 18.0.31101.0 -; EMPTY-NEXT: BackendVersion: 18.0.31101.0 -; EMPTY-NEXT: VersionName: Microsoft (R) Optimizing Compiler -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 01200000 07001200 00007D79 00001200 |. ........}y....| -; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft | -; EMPTY-NEXT: 0020: 28522920 4F707469 6D697A69 6E672043 |(R) Optimizing C| -; EMPTY-NEXT: 0030: 6F6D7069 6C657200 |ompiler.| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: ProcStart { -; EMPTY-NEXT: Kind: S_GPROC32 (0x1110) -; EMPTY-NEXT: PtrParent: 0x0 -; EMPTY-NEXT: PtrEnd: 0xC4 -; EMPTY-NEXT: PtrNext: 0x0 -; EMPTY-NEXT: CodeSize: 0xA -; EMPTY-NEXT: DbgStart: 0x3 -; EMPTY-NEXT: DbgEnd: 0x8 -; EMPTY-NEXT: FunctionType: int () (0x1001) -; EMPTY-NEXT: Segment: 0x1 -; EMPTY-NEXT: Flags [ (0x1) -; EMPTY-NEXT: HasFP (0x1) -; EMPTY-NEXT: ] -; EMPTY-NEXT: DisplayName: main -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 C4000000 00000000 0A000000 |................| -; EMPTY-NEXT: 0010: 03000000 08000000 01100000 10000000 |................| -; EMPTY-NEXT: 0020: 0100016D 61696E00 |...main.| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: FrameProc { -; EMPTY-NEXT: TotalFrameBytes: 0x0 -; EMPTY-NEXT: PaddingFrameBytes: 0x0 -; EMPTY-NEXT: OffsetToPadding: 0x0 -; EMPTY-NEXT: BytesOfCalleeSavedRegisters: 0x0 -; EMPTY-NEXT: OffsetOfExceptionHandler: 0x0 -; EMPTY-NEXT: SectionIdOfExceptionHandler: 0x0 -; EMPTY-NEXT: Flags [ (0x128200) -; EMPTY-NEXT: AsynchronousExceptionHandling (0x200) -; EMPTY-NEXT: OptimizedForSpeed (0x100000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 00000000 00000000 00000000 |................| -; EMPTY-NEXT: 0010: 00000000 00000082 12000000 |............| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: BlockEnd { -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: BuildInfo { -; EMPTY-NEXT: BuildId: 4110 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 0E100000 |....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: Subsections [ -; EMPTY-NEXT: Lines { -; EMPTY-NEXT: RelocSegment: 1 -; EMPTY-NEXT: RelocOffset: 16 -; EMPTY-NEXT: CodeSize: 10 -; EMPTY-NEXT: HasColumns: No -; EMPTY-NEXT: FileEntry { -; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: LineNumberStart: 5 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 3 -; EMPTY-NEXT: LineNumberStart: 6 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 8 -; EMPTY-NEXT: LineNumberStart: 7 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: FileChecksums { -; EMPTY-NEXT: Checksum { -; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -; EMPTY-NEXT: Kind: MD5 (0x1) -; EMPTY-NEXT: Checksum ( -; EMPTY-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: * Linker * -; EMPTY-NEXT: Debug Stream Index: 14 -; EMPTY-NEXT: Object File Name: -; EMPTY-NEXT: Num Files: 0 -; EMPTY-NEXT: Source File Name Idx: 0 -; EMPTY-NEXT: Pdb File Name Idx: 1 -; EMPTY-NEXT: Line Info Byte Size: 0 -; EMPTY-NEXT: C13 Line Info Byte Size: 0 -; EMPTY-NEXT: Symbol Byte Size: 516 -; EMPTY-NEXT: Type Server Index: 0 -; EMPTY-NEXT: Has EC Info: No -; EMPTY-NEXT: 0 Contributing Source Files [ -; EMPTY-NEXT: ] -; EMPTY-NEXT: Symbols [ -; EMPTY-NEXT: { -; EMPTY-NEXT: ObjectName { -; EMPTY-NEXT: Signature: 0x0 -; EMPTY-NEXT: ObjectName: * Linker * -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 2A204C69 6E6B6572 202A0000 |....* Linker *..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: CompilerFlags3 { -; EMPTY-NEXT: Language: Link (0x7) -; EMPTY-NEXT: Flags [ (0x0) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Machine: Intel80386 (0x3) -; EMPTY-NEXT: FrontendVersion: 0.0.0.0 -; EMPTY-NEXT: BackendVersion: 12.0.31101.0 -; EMPTY-NEXT: VersionName: Microsoft (R) LINK -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 07000000 03000000 00000000 00000C00 |................| -; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft | -; EMPTY-NEXT: 0020: 28522920 4C494E4B 00000000 |(R) LINK....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: EnvBlock { -; EMPTY-NEXT: Entries [ -; EMPTY-NEXT: cwd -; EMPTY-NEXT: d:\src\llvm\test\DebugInfo\PDB\Inputs -; EMPTY-NEXT: exe -; EMPTY-NEXT: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe -; EMPTY-NEXT: pdb -; EMPTY-NEXT: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00637764 00643A5C 7372635C 6C6C766D |.cwd.d:\src\llvm| -; EMPTY-NEXT: 0010: 5C746573 745C4465 62756749 6E666F5C |\test\DebugInfo\| -; EMPTY-NEXT: 0020: 5044425C 496E7075 74730065 78650043 |PDB\Inputs.exe.C| -; EMPTY-NEXT: 0030: 3A5C5072 6F677261 6D204669 6C657320 |:\Program Files | -; EMPTY-NEXT: 0040: 28783836 295C4D69 63726F73 6F667420 |(x86)\Microsoft | -; EMPTY-NEXT: 0050: 56697375 616C2053 74756469 6F203132 |Visual Studio 12| -; EMPTY-NEXT: 0060: 2E305C56 435C4249 4E5C6C69 6E6B2E65 |.0\VC\BIN\link.e| -; EMPTY-NEXT: 0070: 78650070 64620064 3A5C7372 635C6C6C |xe.pdb.d:\src\ll| -; EMPTY-NEXT: 0080: 766D5C74 6573745C 44656275 67496E66 |vm\test\DebugInf| -; EMPTY-NEXT: 0090: 6F5C5044 425C496E 70757473 5C656D70 |o\PDB\Inputs\emp| -; EMPTY-NEXT: 00A0: 74792E70 64620000 |ty.pdb..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Trampoline { -; EMPTY-NEXT: Type: TrampIncremental (0x0) -; EMPTY-NEXT: Size: 5 -; EMPTY-NEXT: ThunkOff: 5 -; EMPTY-NEXT: TargetOff: 16 -; EMPTY-NEXT: ThunkSection: 1 -; EMPTY-NEXT: TargetSection: 1 -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000500 05000000 10000000 01000100 |................| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Section { -; EMPTY-NEXT: SectionNumber: 1 -; EMPTY-NEXT: Alignment: 12 -; EMPTY-NEXT: Rva: 4096 -; EMPTY-NEXT: Length: 4122 -; EMPTY-NEXT: Characteristics [ (0x60000020) -; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20) -; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Name: .text -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 01000C00 00100000 1A100000 20000060 |............ ..`| -; EMPTY-NEXT: 0010: 2E746578 74000000 |.text...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: COFF Group { -; EMPTY-NEXT: Size: 4122 -; EMPTY-NEXT: Characteristics [ (0x60000020) -; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20) -; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: Segment: 1 -; EMPTY-NEXT: Name: .text$mn -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 1A100000 20000060 00000000 01002E74 |.... ..`.......t| -; EMPTY-NEXT: 0010: 65787424 6D6E0000 |ext$mn..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Section { -; EMPTY-NEXT: SectionNumber: 2 -; EMPTY-NEXT: Alignment: 12 -; EMPTY-NEXT: Rva: 12288 -; EMPTY-NEXT: Length: 690 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Name: .rdata -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 02000C00 00300000 B2020000 40000040 |.....0......@..@| -; EMPTY-NEXT: 0010: 2E726461 74610000 |.rdata..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: COFF Group { -; EMPTY-NEXT: Size: 323 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: Segment: 2 -; EMPTY-NEXT: Name: .rdata -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 43010000 40000040 00000000 02002E72 |C...@..@.......r| -; EMPTY-NEXT: 0010: 64617461 00000000 |data....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: COFF Group { -; EMPTY-NEXT: Size: 0 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Offset: 323 -; EMPTY-NEXT: Segment: 2 -; EMPTY-NEXT: Name: .edata -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 40000040 43010000 02002E65 |....@..@C......e| -; EMPTY-NEXT: 0010: 64617461 00000000 |data....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: COFF Group { -; EMPTY-NEXT: Size: 366 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Offset: 324 -; EMPTY-NEXT: Segment: 2 -; EMPTY-NEXT: Name: .rdata$debug -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 6E010000 40000040 44010000 02002E72 |n...@..@D......r| -; EMPTY-NEXT: 0010: 64617461 24646562 75670000 |data$debug..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Section { -; EMPTY-NEXT: SectionNumber: 3 -; EMPTY-NEXT: Alignment: 12 -; EMPTY-NEXT: Rva: 16384 -; EMPTY-NEXT: Length: 4 -; EMPTY-NEXT: Characteristics [ (0xC0000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Name: .data -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 03000C00 00400000 04000000 400000C0 |.....@......@...| -; EMPTY-NEXT: 0010: 2E646174 61000000 |.data...| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: COFF Group { -; EMPTY-NEXT: Size: 4 -; EMPTY-NEXT: Characteristics [ (0xC0000080) -; EMPTY-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: Segment: 3 -; EMPTY-NEXT: Name: .bss -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 04000000 800000C0 00000000 03002E62 |...............b| -; EMPTY-NEXT: 0010: 73730000 |ss..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Section { -; EMPTY-NEXT: SectionNumber: 4 -; EMPTY-NEXT: Alignment: 12 -; EMPTY-NEXT: Rva: 20480 -; EMPTY-NEXT: Length: 8 -; EMPTY-NEXT: Characteristics [ (0x42000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Name: .reloc -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 04000C00 00500000 08000000 40000042 |.....P......@..B| -; EMPTY-NEXT: 0010: 2E72656C 6F630000 |.reloc..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: Subsections [ -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Section Contributions [ -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 1 -; EMPTY-NEXT: Off: 0 -; EMPTY-NEXT: Size: 10 -; EMPTY-NEXT: Characteristics [ (0x60000020) -; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20) -; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 1 -; EMPTY-NEXT: Name: * Linker * -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 0 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 1 -; EMPTY-NEXT: Off: 16 -; EMPTY-NEXT: Size: 10 -; EMPTY-NEXT: Characteristics [ (0x60500020) -; EMPTY-NEXT: IMAGE_SCN_ALIGN_16BYTES (0x500000) -; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20) -; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 0 -; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 3617027124 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 2 -; EMPTY-NEXT: Off: 0 -; EMPTY-NEXT: Size: 56 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 1 -; EMPTY-NEXT: Name: * Linker * -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 0 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 2 -; EMPTY-NEXT: Off: 324 -; EMPTY-NEXT: Size: 72 -; EMPTY-NEXT: Characteristics [ (0x40300040) -; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 1 -; EMPTY-NEXT: Name: * Linker * -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 0 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 2 -; EMPTY-NEXT: Off: 396 -; EMPTY-NEXT: Size: 20 -; EMPTY-NEXT: Characteristics [ (0x40300040) -; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 1 -; EMPTY-NEXT: Name: * Linker * -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 0 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: Contribution { -; EMPTY-NEXT: ISect: 3 -; EMPTY-NEXT: Off: 0 -; EMPTY-NEXT: Size: 4 -; EMPTY-NEXT: Characteristics [ (0xC0300080) -; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; EMPTY-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Module { -; EMPTY-NEXT: Index: 0 -; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; EMPTY-NEXT: } -; EMPTY-NEXT: Data CRC: 0 -; EMPTY-NEXT: Reloc CRC: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: Section Map [ -; EMPTY-NEXT: Entry { -; EMPTY-NEXT: Flags [ (0x10D) -; EMPTY-NEXT: AddressIs32Bit (0x8) -; EMPTY-NEXT: Execute (0x4) -; EMPTY-NEXT: IsSelector (0x100) -; EMPTY-NEXT: Read (0x1) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Ovl: 0 -; EMPTY-NEXT: Group: 0 -; EMPTY-NEXT: Frame: 1 -; EMPTY-NEXT: SecName: 65535 -; EMPTY-NEXT: ClassName: 65535 -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: SecByteLength: 4122 -; EMPTY-NEXT: } -; EMPTY-NEXT: Entry { -; EMPTY-NEXT: Flags [ (0x109) -; EMPTY-NEXT: AddressIs32Bit (0x8) -; EMPTY-NEXT: IsSelector (0x100) -; EMPTY-NEXT: Read (0x1) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Ovl: 0 -; EMPTY-NEXT: Group: 0 -; EMPTY-NEXT: Frame: 2 -; EMPTY-NEXT: SecName: 65535 -; EMPTY-NEXT: ClassName: 65535 -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: SecByteLength: 690 -; EMPTY-NEXT: } -; EMPTY-NEXT: Entry { -; EMPTY-NEXT: Flags [ (0x10B) -; EMPTY-NEXT: AddressIs32Bit (0x8) -; EMPTY-NEXT: IsSelector (0x100) -; EMPTY-NEXT: Read (0x1) -; EMPTY-NEXT: Write (0x2) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Ovl: 0 -; EMPTY-NEXT: Group: 0 -; EMPTY-NEXT: Frame: 3 -; EMPTY-NEXT: SecName: 65535 -; EMPTY-NEXT: ClassName: 65535 -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: SecByteLength: 4 -; EMPTY-NEXT: } -; EMPTY-NEXT: Entry { -; EMPTY-NEXT: Flags [ (0x109) -; EMPTY-NEXT: AddressIs32Bit (0x8) -; EMPTY-NEXT: IsSelector (0x100) -; EMPTY-NEXT: Read (0x1) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Ovl: 0 -; EMPTY-NEXT: Group: 0 -; EMPTY-NEXT: Frame: 4 -; EMPTY-NEXT: SecName: 65535 -; EMPTY-NEXT: ClassName: 65535 -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: SecByteLength: 8 -; EMPTY-NEXT: } -; EMPTY-NEXT: Entry { -; EMPTY-NEXT: Flags [ (0x208) -; EMPTY-NEXT: AddressIs32Bit (0x8) -; EMPTY-NEXT: IsAbsoluteAddress (0x200) -; EMPTY-NEXT: ] -; EMPTY-NEXT: Ovl: 0 -; EMPTY-NEXT: Group: 0 -; EMPTY-NEXT: Frame: 0 -; EMPTY-NEXT: SecName: 65535 -; EMPTY-NEXT: ClassName: 65535 -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: SecByteLength: 4294967295 -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: Globals Stream { -; EMPTY-NEXT: Stream number: 6 -; EMPTY-NEXT: Number of buckets: 2 -; EMPTY-NEXT: Hash Buckets: [0, 12] -; EMPTY-NEXT: } -; EMPTY-NEXT: Publics Stream { -; EMPTY-NEXT: Stream number: 7 -; EMPTY-NEXT: SymHash: 556 -; EMPTY-NEXT: AddrMap: 8 -; EMPTY-NEXT: Number of buckets: 2 -; EMPTY-NEXT: Hash Buckets: [0, 12] -; EMPTY-NEXT: Address Map: [36, 0] -; EMPTY-NEXT: Thunk Map: [4112] -; EMPTY-NEXT: Section Offsets: [4096, 1] -; EMPTY-NEXT: Symbols [ -; EMPTY-NEXT: { -; EMPTY-NEXT: PublicSym { -; EMPTY-NEXT: Type: 0 -; EMPTY-NEXT: Seg: 3 -; EMPTY-NEXT: Off: 0 -; EMPTY-NEXT: Name: ?__purecall@@3PAXA -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 00000000 03003F5F 5F707572 |..........?__pur| -; EMPTY-NEXT: 0010: 6563616C 6C404033 50415841 00000000 |ecall@@3PAXA....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: PublicSym { -; EMPTY-NEXT: Type: 2 -; EMPTY-NEXT: Seg: 1 -; EMPTY-NEXT: Off: 16 -; EMPTY-NEXT: Name: _main -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 02000000 10000000 01005F6D 61696E00 |.........._main.| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: ProcRef { -; EMPTY-NEXT: SumName: 0 -; EMPTY-NEXT: SymOffset: 120 -; EMPTY-NEXT: Mod: 1 -; EMPTY-NEXT: Name: main -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 00000000 78000000 01006D61 696E0000 |....x.....main..| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: DataSym { -; EMPTY-NEXT: Kind: S_GDATA32 (0x110D) -; EMPTY-NEXT: Type: void* (0x403) -; EMPTY-NEXT: DisplayName: __purecall -; EMPTY-NEXT: } -; EMPTY-NEXT: Bytes ( -; EMPTY-NEXT: 0000: 03040000 00000000 03005F5F 70757265 |..........__pure| -; EMPTY-NEXT: 0010: 63616C6C 00000000 |call....| -; EMPTY-NEXT: ) -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: Section Headers [ -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: .text -; EMPTY-NEXT: Virtual Size: 4122 -; EMPTY-NEXT: Virtual Address: 4096 -; EMPTY-NEXT: Size of Raw Data: 4608 -; EMPTY-NEXT: File Pointer to Raw Data: 1024 -; EMPTY-NEXT: File Pointer to Relocations: 0 -; EMPTY-NEXT: File Pointer to Linenumbers: 0 -; EMPTY-NEXT: Number of Relocations: 0 -; EMPTY-NEXT: Number of Linenumbers: 0 -; EMPTY-NEXT: Characteristics [ (0x60000020) -; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20) -; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: .rdata -; EMPTY-NEXT: Virtual Size: 690 -; EMPTY-NEXT: Virtual Address: 12288 -; EMPTY-NEXT: Size of Raw Data: 1024 -; EMPTY-NEXT: File Pointer to Raw Data: 5632 -; EMPTY-NEXT: File Pointer to Relocations: 0 -; EMPTY-NEXT: File Pointer to Linenumbers: 0 -; EMPTY-NEXT: Number of Relocations: 0 -; EMPTY-NEXT: Number of Linenumbers: 0 -; EMPTY-NEXT: Characteristics [ (0x40000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: .data -; EMPTY-NEXT: Virtual Size: 4 -; EMPTY-NEXT: Virtual Address: 16384 -; EMPTY-NEXT: Size of Raw Data: 0 -; EMPTY-NEXT: File Pointer to Raw Data: 0 -; EMPTY-NEXT: File Pointer to Relocations: 0 -; EMPTY-NEXT: File Pointer to Linenumbers: 0 -; EMPTY-NEXT: Number of Relocations: 0 -; EMPTY-NEXT: Number of Linenumbers: 0 -; EMPTY-NEXT: Characteristics [ (0xC0000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Name: .reloc -; EMPTY-NEXT: Virtual Size: 8 -; EMPTY-NEXT: Virtual Address: 20480 -; EMPTY-NEXT: Size of Raw Data: 512 -; EMPTY-NEXT: File Pointer to Raw Data: 6656 -; EMPTY-NEXT: File Pointer to Relocations: 0 -; EMPTY-NEXT: File Pointer to Linenumbers: 0 -; EMPTY-NEXT: Number of Relocations: 0 -; EMPTY-NEXT: Number of Linenumbers: 0 -; EMPTY-NEXT: Characteristics [ (0x42000040) -; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; EMPTY-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000) -; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000) -; EMPTY-NEXT: ] -; EMPTY-NEXT: } -; EMPTY-NEXT: ] -; EMPTY: New FPO [ -; EMPTY-NEXT: { -; EMPTY-NEXT: Offset: 4112 -; EMPTY-NEXT: Size: 10 -; EMPTY-NEXT: Number of locals: 0 -; EMPTY-NEXT: Number of params: 0 -; EMPTY-NEXT: Size of Prolog: 0 -; EMPTY-NEXT: Number of Saved Registers: 0 -; EMPTY-NEXT: Has SEH: No -; EMPTY-NEXT: Use BP: No -; EMPTY-NEXT: Frame Pointer: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: { -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: Size: 134 -; EMPTY-NEXT: Number of locals: 3 -; EMPTY-NEXT: Number of params: 4 -; EMPTY-NEXT: Size of Prolog: 0 -; EMPTY-NEXT: Number of Saved Registers: 0 -; EMPTY-NEXT: Has SEH: No -; EMPTY-NEXT: Use BP: No -; EMPTY-NEXT: Frame Pointer: 0 -; EMPTY-NEXT: } -; EMPTY-NEXT: ] +ALL: Summary +ALL-NEXT: ============================================================ +ALL-NEXT: Block Size: 4096 +ALL-NEXT: Number of blocks: 25 +ALL-NEXT: Number of streams: 17 +ALL-NEXT: Signature: 1424295906 +ALL-NEXT: Age: 1 +ALL-NEXT: GUID: {0B355641-86A0-A249-896F-9988FAE52FF0} +ALL-NEXT: Features: 0x1 +ALL-NEXT: Has Debug Info: true +ALL-NEXT: Has Types: true +ALL-NEXT: Has IDs: true +ALL-NEXT: Has Globals: true +ALL-NEXT: Has Publics: true +ALL-NEXT: Is incrementally linked: true +ALL-NEXT: Has conflicting types: false +ALL-NEXT: Is stripped: false +ALL: Streams +ALL-NEXT: ============================================================ +ALL-NEXT: Stream 0: [Old MSF Directory] (40 bytes) +ALL-NEXT: Stream 1: [PDB Stream] (118 bytes) +ALL-NEXT: Stream 2: [TPI Stream] (5392 bytes) +ALL-NEXT: Stream 3: [DBI Stream] (739 bytes) +ALL-NEXT: Stream 4: [IPI Stream] (784 bytes) +ALL-NEXT: Stream 5: [Named Stream "/LinkInfo"] (0 bytes) +ALL-NEXT: Stream 6: [Global Symbol Hash] (556 bytes) +ALL-NEXT: Stream 7: [Public Symbol Hash] (604 bytes) +ALL-NEXT: Stream 8: [Public Symbol Records] (104 bytes) +ALL-NEXT: Stream 9: [Named Stream "/src/headerblock"] (0 bytes) +ALL-NEXT: Stream 10: [Section Header Data] (160 bytes) +ALL-NEXT: Stream 11: [New FPO Data] (32 bytes) +ALL-NEXT: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes) +ALL-NEXT: Stream 13: [Named Stream "/names"] (239 bytes) +ALL-NEXT: Stream 14: [Module "* Linker *"] (520 bytes) +ALL-NEXT: Stream 15: [TPI Hash] (308 bytes) +ALL-NEXT: Stream 16: [IPI Hash] (68 bytes) +ALL: String Table +ALL-NEXT: ============================================================ +ALL-NEXT: ID | String +ALL-NEXT: 1 | 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)' +ALL-NEXT: 86 | 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' +ALL-NEXT: 134 | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = ' +ALL: Modules +ALL-NEXT: ============================================================ +ALL-NEXT: Mod 0000 | Name: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: Obj: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: debug stream: 12, # files: 1, has ec info: false +ALL-NEXT: Mod 0001 | Name: `* Linker *`: +ALL-NEXT: Obj: ``: +ALL-NEXT: debug stream: 14, # files: 0, has ec info: false +ALL: Files +ALL-NEXT: ============================================================ +ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: - (MD5: A0A5BD0D3ECD93FC29D19DE826FBF4BC) d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +ALL-NEXT: Mod 0001 | `* Linker *`: +ALL: Lines +ALL-NEXT: ============================================================ +ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp (MD5: A0A5BD0D3ECD93FC29D19DE826FBF4BC) +ALL-NEXT: 0001:00000010-0000001A, line/addr entries = 3 +ALL-NEXT: 5 00000010 6 00000013 7 00000018 +ALL: Mod 0001 | `* Linker *`: +ALL: Inlinee Lines +ALL-NEXT: ============================================================ +ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: Mod 0001 | `* Linker *`: +ALL: Types (TPI Stream) +ALL-NEXT: ============================================================ +ALL-NEXT: Showing 75 records +ALL-NEXT: 0x1000 | LF_ARGLIST [size = 8, hash = 205956] +ALL-NEXT: 0x1001 | LF_PROCEDURE [size = 16, hash = 163561] +ALL-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000 +ALL-NEXT: calling conv = cdecl, options = None +ALL-NEXT: 0x1002 | LF_FIELDLIST [size = 76, hash = 59811] +ALL-NEXT: - LF_ENUMERATE [apartment = 1] +ALL-NEXT: - LF_ENUMERATE [single = 2] +ALL-NEXT: - LF_ENUMERATE [free = 3] +ALL-NEXT: - LF_ENUMERATE [neutral = 4] +ALL-NEXT: - LF_ENUMERATE [both = 5] +ALL-NEXT: 0x1003 | LF_ENUM [size = 120, hash = 208239] +ALL-NEXT: name: `__vc_attributes::threadingAttribute::threading_e` +ALL-NEXT: unique name: `.?AW4threading_e@threadingAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x1002, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x1004 | LF_STRUCTURE [size = 100, hash = 16377] +ALL-NEXT: class name: `__vc_attributes::threadingAttribute` +ALL-NEXT: unique name: `.?AUthreadingAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x1005 | LF_POINTER [size = 12, hash = 247078] +ALL-NEXT: referent = 0x1004, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x1006 | LF_ARGLIST [size = 12, hash = 194342] +ALL-NEXT: 0x1003: `__vc_attributes::threadingAttribute::threading_e` +ALL-NEXT: 0x1007 | LF_MFUNCTION [size = 28, hash = 254156] +ALL-NEXT: return type = 1, # args = 0x1006, param list = 0x0003 (void) +ALL-NEXT: class type = 0x1004, this type = 0x1005, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1008 | LF_MFUNCTION [size = 28, hash = 194536] +ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void) +ALL-NEXT: class type = 0x1004, this type = 0x1005, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1009 | LF_METHODLIST [size = 20, hash = 167492] +ALL-NEXT: - Method [type = 0x1007, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1008, vftable offset = -1, attrs = public] +ALL-NEXT: 0x100A | LF_FIELDLIST [size = 68, hash = 185421] +ALL-NEXT: - LF_NESTTYPE [name = `threading_e`, parent = 0x1003] +ALL-NEXT: - LF_METHOD [name = `threadingAttribute`, # overloads = 2, overload list = 0x1009] +ALL-NEXT: - LF_MEMBER [name = `value`, Type = 0x1003, offset = 0, attrs = public] +ALL-NEXT: 0x100B | LF_STRUCTURE [size = 100, hash = 119540] +ALL-NEXT: class name: `__vc_attributes::threadingAttribute` +ALL-NEXT: unique name: `.?AUthreadingAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x100A +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x100C | LF_FIELDLIST [size = 48, hash = 261871] +ALL-NEXT: - LF_ENUMERATE [native = 0] +ALL-NEXT: - LF_ENUMERATE [com = 1] +ALL-NEXT: - LF_ENUMERATE [managed = 2] +ALL-NEXT: 0x100D | LF_ENUM [size = 120, hash = 198119] +ALL-NEXT: name: `__vc_attributes::event_receiverAttribute::type_e` +ALL-NEXT: unique name: `.?AW4type_e@event_receiverAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x100C, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x100E | LF_STRUCTURE [size = 112, hash = 48056] +ALL-NEXT: class name: `__vc_attributes::event_receiverAttribute` +ALL-NEXT: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x100F | LF_POINTER [size = 12, hash = 251486] +ALL-NEXT: referent = 0x100E, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x1010 | LF_ARGLIST [size = 16, hash = 134580] +ALL-NEXT: 0x100D: `__vc_attributes::event_receiverAttribute::type_e` +ALL-NEXT: 0x0030 (bool): `bool` +ALL-NEXT: 0x1011 | LF_MFUNCTION [size = 28, hash = 148190] +ALL-NEXT: return type = 2, # args = 0x1010, param list = 0x0003 (void) +ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1012 | LF_ARGLIST [size = 12, hash = 113636] +ALL-NEXT: 0x100D: `__vc_attributes::event_receiverAttribute::type_e` +ALL-NEXT: 0x1013 | LF_MFUNCTION [size = 28, hash = 53336] +ALL-NEXT: return type = 1, # args = 0x1012, param list = 0x0003 (void) +ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1014 | LF_MFUNCTION [size = 28, hash = 55779] +ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void) +ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1015 | LF_METHODLIST [size = 28, hash = 220695] +ALL-NEXT: - Method [type = 0x1011, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1013, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1014, vftable offset = -1, attrs = public] +ALL-NEXT: 0x1016 | LF_FIELDLIST [size = 96, hash = 198114] +ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x100D] +ALL-NEXT: - LF_METHOD [name = `event_receiverAttribute`, # overloads = 3, overload list = 0x1015] +ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x100D, offset = 0, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `layout_dependent`, Type = 0x0030 (bool), offset = 4, attrs = public] +ALL-NEXT: 0x1017 | LF_STRUCTURE [size = 112, hash = 148734] +ALL-NEXT: class name: `__vc_attributes::event_receiverAttribute` +ALL-NEXT: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x1016 +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x1018 | LF_FIELDLIST [size = 48, hash = 81128] +ALL-NEXT: - LF_ENUMERATE [never = 0] +ALL-NEXT: - LF_ENUMERATE [allowed = 1] +ALL-NEXT: - LF_ENUMERATE [always = 2] +ALL-NEXT: 0x1019 | LF_ENUM [size = 116, hash = 60158] +ALL-NEXT: name: `__vc_attributes::aggregatableAttribute::type_e` +ALL-NEXT: unique name: `.?AW4type_e@aggregatableAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x1018, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x101A | LF_STRUCTURE [size = 108, hash = 217249] +ALL-NEXT: class name: `__vc_attributes::aggregatableAttribute` +ALL-NEXT: unique name: `.?AUaggregatableAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x101B | LF_POINTER [size = 12, hash = 174209] +ALL-NEXT: referent = 0x101A, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x101C | LF_ARGLIST [size = 12, hash = 159978] +ALL-NEXT: 0x1019: `__vc_attributes::aggregatableAttribute::type_e` +ALL-NEXT: 0x101D | LF_MFUNCTION [size = 28, hash = 249504] +ALL-NEXT: return type = 1, # args = 0x101C, param list = 0x0003 (void) +ALL-NEXT: class type = 0x101A, this type = 0x101B, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x101E | LF_MFUNCTION [size = 28, hash = 141941] +ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void) +ALL-NEXT: class type = 0x101A, this type = 0x101B, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x101F | LF_METHODLIST [size = 20, hash = 238785] +ALL-NEXT: - Method [type = 0x101D, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x101E, vftable offset = -1, attrs = public] +ALL-NEXT: 0x1020 | LF_FIELDLIST [size = 68, hash = 6214] +ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1019] +ALL-NEXT: - LF_METHOD [name = `aggregatableAttribute`, # overloads = 2, overload list = 0x101F] +ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1019, offset = 0, attrs = public] +ALL-NEXT: 0x1021 | LF_STRUCTURE [size = 108, hash = 94935] +ALL-NEXT: class name: `__vc_attributes::aggregatableAttribute` +ALL-NEXT: unique name: `.?AUaggregatableAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x1020 +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x1022 | LF_ENUM [size = 116, hash = 151449] +ALL-NEXT: name: `__vc_attributes::event_sourceAttribute::type_e` +ALL-NEXT: unique name: `.?AW4type_e@event_sourceAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x100C, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x1023 | LF_FIELDLIST [size = 28, hash = 135589] +ALL-NEXT: - LF_ENUMERATE [speed = 0] +ALL-NEXT: - LF_ENUMERATE [size = 1] +ALL-NEXT: 0x1024 | LF_ENUM [size = 124, hash = 73373] +ALL-NEXT: name: `__vc_attributes::event_sourceAttribute::optimize_e` +ALL-NEXT: unique name: `.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x1023, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x1025 | LF_STRUCTURE [size = 108, hash = 96512] +ALL-NEXT: class name: `__vc_attributes::event_sourceAttribute` +ALL-NEXT: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x1026 | LF_POINTER [size = 12, hash = 254299] +ALL-NEXT: referent = 0x1025, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x1027 | LF_ARGLIST [size = 12, hash = 17744] +ALL-NEXT: 0x1022: `__vc_attributes::event_sourceAttribute::type_e` +ALL-NEXT: 0x1028 | LF_MFUNCTION [size = 28, hash = 239514] +ALL-NEXT: return type = 1, # args = 0x1027, param list = 0x0003 (void) +ALL-NEXT: class type = 0x1025, this type = 0x1026, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1029 | LF_MFUNCTION [size = 28, hash = 173189] +ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void) +ALL-NEXT: class type = 0x1025, this type = 0x1026, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x102A | LF_METHODLIST [size = 20, hash = 130544] +ALL-NEXT: - Method [type = 0x1028, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1029, vftable offset = -1, attrs = public] +ALL-NEXT: 0x102B | LF_FIELDLIST [size = 128, hash = 204437] +ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1022] +ALL-NEXT: - LF_NESTTYPE [name = `optimize_e`, parent = 0x1024] +ALL-NEXT: - LF_METHOD [name = `event_sourceAttribute`, # overloads = 2, overload list = 0x102A] +ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1022, offset = 0, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `optimize`, Type = 0x1024, offset = 4, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `decorate`, Type = 0x0030 (bool), offset = 8, attrs = public] +ALL-NEXT: 0x102C | LF_STRUCTURE [size = 108, hash = 238560] +ALL-NEXT: class name: `__vc_attributes::event_sourceAttribute` +ALL-NEXT: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x102B +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x102D | LF_FIELDLIST [size = 92, hash = 144673] +ALL-NEXT: - LF_ENUMERATE [dll = 1] +ALL-NEXT: - LF_ENUMERATE [exe = 2] +ALL-NEXT: - LF_ENUMERATE [service = 3] +ALL-NEXT: - LF_ENUMERATE [unspecified = 4] +ALL-NEXT: - LF_ENUMERATE [EXE = 2] +ALL-NEXT: - LF_ENUMERATE [SERVICE = 3] +ALL-NEXT: 0x102E | LF_ENUM [size = 104, hash = 115151] +ALL-NEXT: name: `__vc_attributes::moduleAttribute::type_e` +ALL-NEXT: unique name: `.?AW4type_e@moduleAttribute@__vc_attributes@@` +ALL-NEXT: field list: 0x102D, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x102F | LF_STRUCTURE [size = 96, hash = 197306] +ALL-NEXT: class name: `__vc_attributes::moduleAttribute` +ALL-NEXT: unique name: `.?AUmoduleAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x1030 | LF_POINTER [size = 12, hash = 256035] +ALL-NEXT: referent = 0x102F, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x1031 | LF_MODIFIER [size = 12, hash = 101096] +ALL-NEXT: referent = 0x0070 (char), modifiers = const +ALL-NEXT: 0x1032 | LF_POINTER [size = 12, hash = 231280] +ALL-NEXT: referent = 0x1031, mode = pointer, opts = None, kind = ptr32 +ALL-NEXT: 0x1033 | LF_ARGLIST [size = 68, hash = 52156] +ALL-NEXT: 0x102E: `__vc_attributes::moduleAttribute::type_e` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x0074 (int): `int` +ALL-NEXT: 0x0030 (bool): `bool` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x0074 (int): `int` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x0074 (int): `int` +ALL-NEXT: 0x0030 (bool): `bool` +ALL-NEXT: 0x0030 (bool): `bool` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x1032: `const char*` +ALL-NEXT: 0x1034 | LF_MFUNCTION [size = 28, hash = 48854] +ALL-NEXT: return type = 15, # args = 0x1033, param list = 0x0003 (void) +ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1035 | LF_ARGLIST [size = 12, hash = 170035] +ALL-NEXT: 0x102E: `__vc_attributes::moduleAttribute::type_e` +ALL-NEXT: 0x1036 | LF_MFUNCTION [size = 28, hash = 177041] +ALL-NEXT: return type = 1, # args = 0x1035, param list = 0x0003 (void) +ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1037 | LF_MFUNCTION [size = 28, hash = 102745] +ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void) +ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1038 | LF_METHODLIST [size = 28, hash = 16947] +ALL-NEXT: - Method [type = 0x1034, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1036, vftable offset = -1, attrs = public] +ALL-NEXT: - Method [type = 0x1037, vftable offset = -1, attrs = public] +ALL-NEXT: 0x1039 | LF_FIELDLIST [size = 356, hash = 183703] +ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x102E] +ALL-NEXT: - LF_METHOD [name = `moduleAttribute`, # overloads = 3, overload list = 0x1038] +ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x102E, offset = 0, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `name`, Type = 0x1032, offset = 4, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `version`, Type = 0x1032, offset = 8, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `uuid`, Type = 0x1032, offset = 12, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `lcid`, Type = 0x0074 (int), offset = 16, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `control`, Type = 0x0030 (bool), offset = 20, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `helpstring`, Type = 0x1032, offset = 24, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `helpstringcontext`, Type = 0x0074 (int), offset = 28, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `helpstringdll`, Type = 0x1032, offset = 32, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `helpfile`, Type = 0x1032, offset = 36, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `helpcontext`, Type = 0x0074 (int), offset = 40, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `hidden`, Type = 0x0030 (bool), offset = 44, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `restricted`, Type = 0x0030 (bool), offset = 45, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `custom`, Type = 0x1032, offset = 48, attrs = public] +ALL-NEXT: - LF_MEMBER [name = `resource_name`, Type = 0x1032, offset = 52, attrs = public] +ALL-NEXT: 0x103A | LF_STRUCTURE [size = 96, hash = 98548] +ALL-NEXT: class name: `__vc_attributes::moduleAttribute` +ALL-NEXT: unique name: `.?AUmoduleAttribute@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x1039 +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x103B | LF_FIELDLIST [size = 756, hash = 35693] +ALL-NEXT: - LF_ENUMERATE [eAnyUsage = 0] +ALL-NEXT: - LF_ENUMERATE [eCoClassUsage = 1] +ALL-NEXT: - LF_ENUMERATE [eCOMInterfaceUsage = 2] +ALL-NEXT: - LF_ENUMERATE [eInterfaceUsage = 6] +ALL-NEXT: - LF_ENUMERATE [eMemberUsage = 8] +ALL-NEXT: - LF_ENUMERATE [eMethodUsage = 16] +ALL-NEXT: - LF_ENUMERATE [eInterfaceMethodUsage = 32] +ALL-NEXT: - LF_ENUMERATE [eInterfaceMemberUsage = 64] +ALL-NEXT: - LF_ENUMERATE [eCoClassMemberUsage = 128] +ALL-NEXT: - LF_ENUMERATE [eCoClassMethodUsage = 256] +ALL-NEXT: - LF_ENUMERATE [eGlobalMethodUsage = 768] +ALL-NEXT: - LF_ENUMERATE [eGlobalDataUsage = 1024] +ALL-NEXT: - LF_ENUMERATE [eClassUsage = 2048] +ALL-NEXT: - LF_ENUMERATE [eInterfaceParameterUsage = 4096] +ALL-NEXT: - LF_ENUMERATE [eMethodParameterUsage = 12288] +ALL-NEXT: - LF_ENUMERATE [eIDLModuleUsage = 16384] +ALL-NEXT: - LF_ENUMERATE [eAnonymousUsage = 32768] +ALL-NEXT: - LF_ENUMERATE [eTypedefUsage = 65536] +ALL-NEXT: - LF_ENUMERATE [eUnionUsage = 131072] +ALL-NEXT: - LF_ENUMERATE [eEnumUsage = 262144] +ALL-NEXT: - LF_ENUMERATE [eDefineTagUsage = 524288] +ALL-NEXT: - LF_ENUMERATE [eStructUsage = 1048576] +ALL-NEXT: - LF_ENUMERATE [eLocalUsage = 2097152] +ALL-NEXT: - LF_ENUMERATE [ePropertyUsage = 4194304] +ALL-NEXT: - LF_ENUMERATE [eEventUsage = 8388608] +ALL-NEXT: - LF_ENUMERATE [eTemplateUsage = 16777216] +ALL-NEXT: - LF_ENUMERATE [eModuleUsage = 16777216] +ALL-NEXT: - LF_ENUMERATE [eIllegalUsage = 33554432] +ALL-NEXT: - LF_ENUMERATE [eAsynchronousUsage = 67108864] +ALL-NEXT: - LF_ENUMERATE [eAnyIDLUsage = 4161535] +ALL-NEXT: 0x103C | LF_ENUM [size = 140, hash = 171328] +ALL-NEXT: name: `__vc_attributes::helper_attributes::usageAttribute::usage_e` +ALL-NEXT: unique name: `.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: field list: 0x103B, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x103D | LF_STRUCTURE [size = 128, hash = 203640] +ALL-NEXT: class name: `__vc_attributes::helper_attributes::usageAttribute` +ALL-NEXT: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x103E | LF_POINTER [size = 12, hash = 139292] +ALL-NEXT: referent = 0x103D, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x103F | LF_ARGLIST [size = 12, hash = 49018] +ALL-NEXT: 0x0075 (unsigned): `unsigned` +ALL-NEXT: 0x1040 | LF_MFUNCTION [size = 28, hash = 43821] +ALL-NEXT: return type = 1, # args = 0x103F, param list = 0x0003 (void) +ALL-NEXT: class type = 0x103D, this type = 0x103E, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1041 | LF_FIELDLIST [size = 60, hash = 202555] +ALL-NEXT: - LF_NESTTYPE [name = `usage_e`, parent = 0x103C] +ALL-NEXT: - LF_ONEMETHOD [name = `usageAttribute`] +ALL-NEXT: type = 0x1040, vftable offset = -1, attrs = public +ALL-NEXT: - LF_MEMBER [name = `value`, Type = 0x0075 (unsigned), offset = 0, attrs = public] +ALL-NEXT: 0x1042 | LF_STRUCTURE [size = 128, hash = 165040] +ALL-NEXT: class name: `__vc_attributes::helper_attributes::usageAttribute` +ALL-NEXT: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x1041 +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL-NEXT: 0x1043 | LF_FIELDLIST [size = 68, hash = 215835] +ALL-NEXT: - LF_ENUMERATE [eBoolean = 0] +ALL-NEXT: - LF_ENUMERATE [eInteger = 1] +ALL-NEXT: - LF_ENUMERATE [eFloat = 2] +ALL-NEXT: - LF_ENUMERATE [eDouble = 3] +ALL-NEXT: 0x1044 | LF_ENUM [size = 148, hash = 142625] +ALL-NEXT: name: `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e` +ALL-NEXT: unique name: `.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: field list: 0x1043, underlying type: 0x0074 (int) +ALL-NEXT: options: has unique name | is nested +ALL-NEXT: 0x1045 | LF_STRUCTURE [size = 140, hash = 52534] +ALL-NEXT: class name: `__vc_attributes::helper_attributes::v1_alttypeAttribute` +ALL-NEXT: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: +ALL-NEXT: options: forward ref | has unique name +ALL-NEXT: 0x1046 | LF_POINTER [size = 12, hash = 44186] +ALL-NEXT: referent = 0x1045, mode = pointer, opts = const, kind = ptr32 +ALL-NEXT: 0x1047 | LF_ARGLIST [size = 12, hash = 103930] +ALL-NEXT: 0x1044: `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e` +ALL-NEXT: 0x1048 | LF_MFUNCTION [size = 28, hash = 110942] +ALL-NEXT: return type = 1, # args = 0x1047, param list = 0x0003 (void) +ALL-NEXT: class type = 0x1045, this type = 0x1046, this adjust = 0 +ALL-NEXT: calling conv = thiscall, options = constructor +ALL-NEXT: 0x1049 | LF_FIELDLIST [size = 64, hash = 17991] +ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1044] +ALL-NEXT: - LF_ONEMETHOD [name = `v1_alttypeAttribute`] +ALL-NEXT: type = 0x1048, vftable offset = -1, attrs = public +ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1044, offset = 0, attrs = public] +ALL-NEXT: 0x104A | LF_STRUCTURE [size = 140, hash = 213215] +ALL-NEXT: class name: `__vc_attributes::helper_attributes::v1_alttypeAttribute` +ALL-NEXT: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@` +ALL-NEXT: vtable: , base list: , field list: 0x1049 +ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name +ALL: Type Index Offsets: +ALL-NEXT: TI: 0x1000, Offset: 0 +ALL: Hash Adjusters: +ALL: Types (IPI Stream) +ALL-NEXT: ============================================================ +ALL-NEXT: Showing 15 records +ALL-NEXT: 0x1000 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7186] +ALL-NEXT: udt = 0x100B, mod = 1, file = 1, line = 481 +ALL-NEXT: 0x1001 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7198] +ALL-NEXT: udt = 0x1017, mod = 1, file = 1, line = 194 +ALL-NEXT: 0x1002 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7180] +ALL-NEXT: udt = 0x1021, mod = 1, file = 1, line = 603 +ALL-NEXT: 0x1003 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7191] +ALL-NEXT: udt = 0x102C, mod = 1, file = 1, line = 1200 +ALL-NEXT: 0x1004 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7201] +ALL-NEXT: udt = 0x103A, mod = 1, file = 1, line = 540 +ALL-NEXT: 0x1005 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7241] +ALL-NEXT: udt = 0x1042, mod = 1, file = 1, line = 108 +ALL-NEXT: 0x1006 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7249] +ALL-NEXT: udt = 0x104A, mod = 1, file = 1, line = 96 +ALL-NEXT: 0x1007 | LF_STRING_ID [size = 48, hash = 80727] ID: , String: d:\src\llvm\test\DebugInfo\PDB\Inputs +ALL-NEXT: 0x1008 | LF_STRING_ID [size = 76, hash = 154177] ID: , String: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe +ALL-NEXT: 0x1009 | LF_STRING_ID [size = 20, hash = 75189] ID: , String: empty.cpp +ALL-NEXT: 0x100A | LF_STRING_ID [size = 56, hash = 253662] ID: , String: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb +ALL-NEXT: 0x100B | LF_STRING_ID [size = 252, hash = 193467] ID: , String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows +ALL-NEXT: 0x100C | LF_SUBSTR_LIST [size = 12, hash = 222705] +ALL-NEXT: 0x100B: `-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows` +ALL-NEXT: 0x100D | LF_STRING_ID [size = 96, hash = 186099] ID: 0x100C, String: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X +ALL-NEXT: 0x100E | LF_BUILDINFO [size = 28, hash = 257108] +ALL-NEXT: 0x1007: `d:\src\llvm\test\DebugInfo\PDB\Inputs` +ALL-NEXT: 0x1008: `C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe` +ALL-NEXT: 0x1009: `empty.cpp` +ALL-NEXT: 0x100A: `d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb` +ALL-NEXT: 0x100D: ` Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X` +ALL: Type Index Offsets: +ALL-NEXT: TI: 0x1000, Offset: 0 +ALL: Hash Adjusters: +ALL: Public Symbols +ALL-NEXT: ============================================================ +ALL-NEXT: - S_PUB32 [size = 36] `?__purecall@@3PAXA` +ALL-NEXT: type = , addr = 0003:0000 +ALL-NEXT: - S_PUB32 [size = 20] `_main` +ALL-NEXT: type = 0x0002 (), addr = 0001:0016 +ALL-NEXT: - S_PROCREF [size = 20] `main` +ALL-NEXT: module = 1, sum name = 0, offset = 120 +ALL-NEXT: - S_GDATA32 [size = 28] `__purecall` +ALL-NEXT: type = 0x0403 (void*), addr = 0003:0000 +ALL: Symbols +ALL-NEXT: ============================================================ +ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`: +ALL-NEXT: - S_OBJNAME [size = 56] sig=0, `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj` +ALL-NEXT: - S_COMPILE3 [size = 60] +ALL-NEXT: machine = intel pentium 3, Ver = Microsoft (R) Optimizing Compiler, language = c++ +ALL-NEXT: frontend = 18.0.31101.0, backend = 18.0.31101.0 +ALL-NEXT: flags = security checks +ALL-NEXT: - S_GPROC32 [size = 44] `main` +ALL-NEXT: parent = 0, addr = 0001:0016, code size = 10, end = 196 +ALL-NEXT: debug start = 3, debug end = 8, flags = has fp +ALL-NEXT: - S_FRAMEPROC [size = 32] +ALL-NEXT: size = 0, padding size = 0, offset to padding = 0 +ALL-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 +ALL-NEXT: flags = has async eh | opt speed +ALL-NEXT: - S_END [size = 4] +ALL-NEXT: - S_BUILDINFO [size = 8] BuildId = `4110` +ALL-NEXT: Mod 0001 | `* Linker *`: +ALL-NEXT: - S_OBJNAME [size = 20] sig=0, `* Linker *` +ALL-NEXT: - S_COMPILE3 [size = 48] +ALL-NEXT: machine = intel 80386, Ver = Microsoft (R) LINK, language = link +ALL-NEXT: frontend = 0.0.0.0, backend = 12.0.31101.0 +ALL-NEXT: flags = none +ALL-NEXT: - S_ENVBLOCK [size = 172] +ALL-NEXT: - cwd +ALL-NEXT: - d:\src\llvm\test\DebugInfo\PDB\Inputs +ALL-NEXT: - exe +ALL-NEXT: - C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe +ALL-NEXT: - pdb +ALL-NEXT: - d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb +ALL-NEXT: - S_TRAMPOLINE [size = 20] +ALL-NEXT: type = tramp incremental, size = 5, source = 0001:0005, target = 0001:0005 +ALL-NEXT: - S_SECTION [size = 28] `.text` +ALL-NEXT: length = 4122, alignment = 12, rva = 4096, section # = 1, characteristics = 1610612768 +ALL-NEXT: - S_COFFGROUP [size = 28] `.text$mn` +ALL-NEXT: length = 4122, addr = 0001:0000, characteristics = 1610612768 +ALL-NEXT: - S_SECTION [size = 28] `.rdata` +ALL-NEXT: length = 690, alignment = 12, rva = 12288, section # = 2, characteristics = 1073741888 +ALL-NEXT: - S_COFFGROUP [size = 28] `.rdata` +ALL-NEXT: length = 323, addr = 0002:0000, characteristics = 1073741888 +ALL-NEXT: - S_COFFGROUP [size = 28] `.edata` +ALL-NEXT: length = 0, addr = 0002:0323, characteristics = 1073741888 +ALL-NEXT: - S_COFFGROUP [size = 32] `.rdata$debug` +ALL-NEXT: length = 366, addr = 0002:0324, characteristics = 1073741888 +ALL-NEXT: - S_SECTION [size = 28] `.data` +ALL-NEXT: length = 4, alignment = 12, rva = 16384, section # = 3, characteristics = 3221225536 +ALL-NEXT: - S_COFFGROUP [size = 24] `.bss` +ALL-NEXT: length = 4, addr = 0003:0000, characteristics = 3221225600 +ALL-NEXT: - S_SECTION [size = 28] `.reloc` +ALL-NEXT: length = 8, alignment = 12, rva = 20480, section # = 4, characteristics = 1107296320 +ALL: Section Contributions +ALL-NEXT: ============================================================ +ALL-NEXT: SC | mod = 1, 0001:0000, size = 10, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ +ALL-NEXT: SC | mod = 0, 0001:0016, size = 10, data crc = 3617027124, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE | +ALL-NEXT: IMAGE_SCN_MEM_READ +ALL-NEXT: SC | mod = 1, 0002:0000, size = 56, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ +ALL-NEXT: SC | mod = 1, 0002:0324, size = 72, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ +ALL-NEXT: SC | mod = 1, 0002:0396, size = 20, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ +ALL-NEXT: SC | mod = 0, 0003:0000, size = 4, data crc = 0, reloc crc = 0 +ALL-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ | +ALL-NEXT: IMAGE_SCN_MEM_WRITE +ALL: Section Map +ALL-NEXT: ============================================================ +ALL-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1 +ALL-NEXT: class = 65535, offset = 0, size = 4122 +ALL-NEXT: flags = read | execute | 32 bit addr | selector +ALL-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2 +ALL-NEXT: class = 65535, offset = 0, size = 690 +ALL-NEXT: flags = read | 32 bit addr | selector +ALL-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3 +ALL-NEXT: class = 65535, offset = 0, size = 4 +ALL-NEXT: flags = read | write | 32 bit addr | selector +ALL-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4 +ALL-NEXT: class = 65535, offset = 0, size = 8 +ALL-NEXT: flags = read | 32 bit addr | selector +ALL-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 0 +ALL-NEXT: class = 65535, offset = 0, size = 4294967295 +ALL-NEXT: flags = 32 bit addr | absolute addr -; ALL: FileHeaders { -; ALL: BlockSize: 4096 -; ALL: FreeBlockMap: 2 -; ALL: NumBlocks: 25 -; ALL: NumDirectoryBytes: 136 -; ALL: Unknown1: 0 -; ALL: BlockMapAddr: 24 -; ALL: NumDirectoryBlocks: 1 -; ALL: DirectoryBlocks: [23] -; ALL: NumStreams: 17 -; ALL: } -; ALL: Streams [ -; ALL: Stream 0: [Old MSF Directory] (40 bytes) -; ALL: Stream 1: [PDB Stream] (118 bytes) -; ALL: Stream 2: [TPI Stream] (5392 bytes) -; ALL: Stream 3: [DBI Stream] (739 bytes) -; ALL: Stream 4: [IPI Stream] (784 bytes) -; ALL: Stream 5: [Named Stream "/LinkInfo"] (0 bytes) -; ALL: Stream 6: [Global Symbol Hash] (556 bytes) -; ALL: Stream 7: [Public Symbol Hash] (604 bytes) -; ALL: Stream 8: [Public Symbol Records] (104 bytes) -; ALL: Stream 9: [Named Stream "/src/headerblock"] (0 bytes) -; ALL: Stream 10: [Section Header Data] (160 bytes) -; ALL: Stream 11: [New FPO Data] (32 bytes) -; ALL: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes) -; ALL: Stream 13: [Named Stream "/names"] (239 bytes) -; ALL: Stream 14: [Module "* Linker *"] (520 bytes) -; ALL: Stream 15: [TPI Hash] (308 bytes) -; ALL: Stream 16: [IPI Hash] (68 bytes) -; ALL: ] -; ALL: Msf Free Pages: [3, 4, 5, 8, 9] -; ALL: Orphaned Pages: [] -; ALL: Multiply Used Pages: [] -; ALL: Use After Free Pages: [] -; ALL: StreamBlocks [ -; ALL: Stream 0: [8] -; ALL: Stream 1: [19] -; ALL: Stream 2: [18, 17] -; ALL: Stream 3: [14] -; ALL: Stream 4: [20] -; ALL: Stream 5: [] -; ALL: Stream 6: [11] -; ALL: Stream 7: [13] -; ALL: Stream 8: [12] -; ALL: Stream 9: [] -; ALL: Stream 10: [10] -; ALL: Stream 11: [15] -; ALL: Stream 12: [6] -; ALL: Stream 13: [16] -; ALL: Stream 14: [7] -; ALL: Stream 15: [21] -; ALL: Stream 16: [22] -; ALL: ] -; ALL: PDB Stream { -; ALL: Version: 20000404 -; ALL: Signature: 0x54E507E2 -; ALL: Age: 1 -; ALL: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0} -; ALL: Features: 0x1 -; ALL: } -; ALL: Type Info Stream (IPI) { -; ALL: IPI Version: 20040203 -; ALL: Record count: 15 -; ALL: Records [ -; ALL: { -; ALL: UdtModSourceLine (0x1000) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::threadingAttribute (0x100B) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 481 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1001) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::event_receiverAttribute (0x1017) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 194 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1002) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::aggregatableAttribute (0x1021) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 603 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1003) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::event_sourceAttribute (0x102C) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 1200 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1004) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::moduleAttribute (0x103A) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 540 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1005) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::helper_attributes::usageAttribute (0x1042) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 108 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: UdtModSourceLine (0x1006) { -; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607) -; ALL: UDT: __vc_attributes::helper_attributes::v1_alttypeAttribute (0x104A) -; ALL: SourceFile: (0x1) -; ALL: LineNumber: 96 -; ALL: Module: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x1007) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: 0x0 -; ALL: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x1008) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: 0x0 -; ALL: StringData: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x1009) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: 0x0 -; ALL: StringData: empty.cpp -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x100A) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: 0x0 -; ALL: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x100B) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: 0x0 -; ALL: StringData: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows -; ALL: } -; ALL: } -; ALL: { -; ALL: StringList (0x100C) { -; ALL: TypeLeafKind: LF_SUBSTR_LIST (0x1604) -; ALL: NumStrings: 1 -; ALL: Strings [ -; ALL: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows (0x100B) -; ALL: ] -; ALL: } -; ALL: } -; ALL: { -; ALL: StringId (0x100D) { -; ALL: TypeLeafKind: LF_STRING_ID (0x1605) -; ALL: Id: "-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows" (0x100C) -; ALL: StringData: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X -; ALL: } -; ALL: } -; ALL: { -; ALL: BuildInfo (0x100E) { -; ALL: TypeLeafKind: LF_BUILDINFO (0x1603) -; ALL: NumArgs: 5 -; ALL: Arguments [ -; ALL: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs (0x1007) -; ALL: ArgType: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe (0x1008) -; ALL: ArgType: empty.cpp (0x1009) -; ALL: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb (0x100A) -; ALL: ArgType: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X (0x100D) -; ALL: ] -; ALL: } -; ALL: } -; ALL: ] -; ALL: } -; ALL: DBI Stream { -; ALL: Dbi Version: 19990903 -; ALL: Age: 1 -; ALL: Incremental Linking: Yes -; ALL: Has CTypes: No -; ALL: Is Stripped: No -; ALL: Machine Type: x86 -; ALL: Symbol Record Stream Index: 8 -; ALL: Public Symbol Stream Index: 7 -; ALL: Global Symbol Stream Index: 6 -; ALL: Toolchain Version: 12.0 -; ALL: mspdb120.dll version: 12.0.31101 -; ALL: Modules [ -; ALL: { -; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; ALL: Debug Stream Index: 12 -; ALL: Object File Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; ALL: Num Files: 1 -; ALL: Source File Name Idx: 0 -; ALL: Pdb File Name Idx: 0 -; ALL: Line Info Byte Size: 0 -; ALL: C13 Line Info Byte Size: 88 -; ALL: Symbol Byte Size: 208 -; ALL: Type Server Index: 0 -; ALL: Has EC Info: No -; ALL: 1 Contributing Source Files [ -; ALL: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -; ALL: ] -; ALL: Symbols [ -; ALL: { -; ALL: ObjectName { -; ALL: Signature: 0x0 -; ALL: ObjectName: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; ALL: } -; ALL: } -; ALL: { -; ALL: CompilerFlags3 { -; ALL: Language: Cpp (0x1) -; ALL: Flags [ (0x2000) -; ALL: SecurityChecks (0x2000) -; ALL: ] -; ALL: Machine: Pentium3 (0x7) -; ALL: FrontendVersion: 18.0.31101.0 -; ALL: BackendVersion: 18.0.31101.0 -; ALL: VersionName: Microsoft (R) Optimizing Compiler -; ALL: } -; ALL: } -; ALL: { -; ALL: ProcStart { -; ALL: PtrParent: 0x0 -; ALL: PtrEnd: 0xC4 -; ALL: PtrNext: 0x0 -; ALL: CodeSize: 0xA -; ALL: DbgStart: 0x3 -; ALL: DbgEnd: 0x8 -; ALL: FunctionType: int () (0x1001) -; ALL: Segment: 0x1 -; ALL: Flags [ (0x1) -; ALL: HasFP (0x1) -; ALL: ] -; ALL: DisplayName: main -; ALL: } -; ALL: } -; ALL: { -; ALL: FrameProc { -; ALL: TotalFrameBytes: 0x0 -; ALL: PaddingFrameBytes: 0x0 -; ALL: OffsetToPadding: 0x0 -; ALL: BytesOfCalleeSavedRegisters: 0x0 -; ALL: OffsetOfExceptionHandler: 0x0 -; ALL: SectionIdOfExceptionHandler: 0x0 -; ALL: Flags [ (0x128200) -; ALL: AsynchronousExceptionHandling (0x200) -; ALL: OptimizedForSpeed (0x100000) -; ALL: ] -; ALL: } -; ALL: } -; ALL: { -; ALL: BlockEnd { -; ALL: } -; ALL: } -; ALL: { -; ALL: BuildInfo { -; ALL: BuildId: 4110 -; ALL: } -; ALL: } -; ALL: ] -; ALL: } -; ALL: { -; ALL: Name: * Linker * -; ALL: Debug Stream Index: 14 -; ALL: Object File Name: -; ALL: Num Files: 0 -; ALL: Source File Name Idx: 0 -; ALL: Pdb File Name Idx: 1 -; ALL: Line Info Byte Size: 0 -; ALL: C13 Line Info Byte Size: 0 -; ALL: Symbol Byte Size: 516 -; ALL: Type Server Index: 0 -; ALL: Has EC Info: No -; ALL: 0 Contributing Source Files [ -; ALL: ] -; ALL: Symbols [ -; ALL: { -; ALL: ObjectName { -; ALL: Signature: 0x0 -; ALL: ObjectName: * Linker * -; ALL: } -; ALL: } -; ALL: { -; ALL: CompilerFlags3 { -; ALL: Language: Link (0x7) -; ALL: Flags [ (0x0) -; ALL: ] -; ALL: Machine: Intel80386 (0x3) -; ALL: FrontendVersion: 0.0.0.0 -; ALL: BackendVersion: 12.0.31101.0 -; ALL: VersionName: Microsoft (R) LINK -; ALL: } -; ALL: } -; ALL: { -; ALL: EnvBlock { -; ALL: Entries [ -; ALL: cwd -; ALL: d:\src\llvm\test\DebugInfo\PDB\Inputs -; ALL: exe -; ALL: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe -; ALL: pdb -; ALL: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb -; ALL: ] -; ALL: } -; ALL: } -; ALL: { -; ALL: Trampoline { -; ALL: Type: TrampIncremental (0x0) -; ALL: Size: 5 -; ALL: ThunkOff: 5 -; ALL: TargetOff: 16 -; ALL: ThunkSection: 1 -; ALL: TargetSection: 1 -; ALL: } -; ALL: } -; ALL: { -; ALL: Section { -; ALL: SectionNumber: 1 -; ALL: Alignment: 12 -; ALL: Rva: 4096 -; ALL: Length: 4122 -; ALL: Characteristics [ (0x60000020) -; ALL: IMAGE_SCN_CNT_CODE (0x20) -; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Name: .text -; ALL: } -; ALL: } -; ALL: { -; ALL: COFF Group { -; ALL: Size: 4122 -; ALL: Characteristics [ (0x60000020) -; ALL: IMAGE_SCN_CNT_CODE (0x20) -; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Offset: 0 -; ALL: Segment: 1 -; ALL: Name: .text$mn -; ALL: } -; ALL: } -; ALL: { -; ALL: Section { -; ALL: SectionNumber: 2 -; ALL: Alignment: 12 -; ALL: Rva: 12288 -; ALL: Length: 690 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Name: .rdata -; ALL: } -; ALL: } -; ALL: { -; ALL: COFF Group { -; ALL: Size: 323 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Offset: 0 -; ALL: Segment: 2 -; ALL: Name: .rdata -; ALL: } -; ALL: } -; ALL: { -; ALL: COFF Group { -; ALL: Size: 0 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Offset: 323 -; ALL: Segment: 2 -; ALL: Name: .edata -; ALL: } -; ALL: } -; ALL: { -; ALL: COFF Group { -; ALL: Size: 366 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Offset: 324 -; ALL: Segment: 2 -; ALL: Name: .rdata$debug -; ALL: } -; ALL: } -; ALL: { -; ALL: Section { -; ALL: SectionNumber: 3 -; ALL: Alignment: 12 -; ALL: Rva: 16384 -; ALL: Length: 4 -; ALL: Characteristics [ (0xC0000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: IMAGE_SCN_MEM_WRITE (0x80000000) -; ALL: ] -; ALL: Name: .data -; ALL: } -; ALL: } -; ALL: { -; ALL: COFF Group { -; ALL: Size: 4 -; ALL: Characteristics [ (0xC0000080) -; ALL: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: IMAGE_SCN_MEM_WRITE (0x80000000) -; ALL: ] -; ALL: Offset: 0 -; ALL: Segment: 3 -; ALL: Name: .bss -; ALL: } -; ALL: } -; ALL: { -; ALL: Section { -; ALL: SectionNumber: 4 -; ALL: Alignment: 12 -; ALL: Rva: 20480 -; ALL: Length: 8 -; ALL: Characteristics [ (0x42000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_DISCARDABLE (0x2000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Name: .reloc -; ALL: } -; ALL: } -; ALL: ] -; ALL: } -; ALL: ] -; ALL: } -; ALL: Section Contributions [ -; ALL: Contribution { -; ALL: ISect: 1 -; ALL: Off: 0 -; ALL: Size: 10 -; ALL: Characteristics [ (0x60000020) -; ALL: IMAGE_SCN_CNT_CODE (0x20) -; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 1 -; ALL: Name: * Linker * -; ALL: } -; ALL: Data CRC: 0 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: Contribution { -; ALL: ISect: 1 -; ALL: Off: 16 -; ALL: Size: 10 -; ALL: Characteristics [ (0x60500020) -; ALL: IMAGE_SCN_ALIGN_16BYTES (0x500000) -; ALL: IMAGE_SCN_CNT_CODE (0x20) -; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 0 -; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; ALL: } -; ALL: Data CRC: 3617027124 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: Contribution { -; ALL: ISect: 2 -; ALL: Off: 0 -; ALL: Size: 56 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 1 -; ALL: Name: * Linker * -; ALL: } -; ALL: Data CRC: 0 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: Contribution { -; ALL: ISect: 2 -; ALL: Off: 324 -; ALL: Size: 72 -; ALL: Characteristics [ (0x40300040) -; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 1 -; ALL: Name: * Linker * -; ALL: } -; ALL: Data CRC: 0 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: Contribution { -; ALL: ISect: 2 -; ALL: Off: 396 -; ALL: Size: 20 -; ALL: Characteristics [ (0x40300040) -; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 1 -; ALL: Name: * Linker * -; ALL: } -; ALL: Data CRC: 0 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: Contribution { -; ALL: ISect: 3 -; ALL: Off: 0 -; ALL: Size: 4 -; ALL: Characteristics [ (0xC0300080) -; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000) -; ALL: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: IMAGE_SCN_MEM_WRITE (0x80000000) -; ALL: ] -; ALL: Module { -; ALL: Index: 0 -; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -; ALL: } -; ALL: Data CRC: 0 -; ALL: Reloc CRC: 0 -; ALL: } -; ALL: ] -; ALL: Section Map [ -; ALL: Entry { -; ALL: Flags [ (0x10D) -; ALL: AddressIs32Bit (0x8) -; ALL: Execute (0x4) -; ALL: IsSelector (0x100) -; ALL: Read (0x1) -; ALL: ] -; ALL: Ovl: 0 -; ALL: Group: 0 -; ALL: Frame: 1 -; ALL: SecName: 65535 -; ALL: ClassName: 65535 -; ALL: Offset: 0 -; ALL: SecByteLength: 4122 -; ALL: } -; ALL: Entry { -; ALL: Flags [ (0x109) -; ALL: AddressIs32Bit (0x8) -; ALL: IsSelector (0x100) -; ALL: Read (0x1) -; ALL: ] -; ALL: Ovl: 0 -; ALL: Group: 0 -; ALL: Frame: 2 -; ALL: SecName: 65535 -; ALL: ClassName: 65535 -; ALL: Offset: 0 -; ALL: SecByteLength: 690 -; ALL: } -; ALL: Entry { -; ALL: Flags [ (0x10B) -; ALL: AddressIs32Bit (0x8) -; ALL: IsSelector (0x100) -; ALL: Read (0x1) -; ALL: Write (0x2) -; ALL: ] -; ALL: Ovl: 0 -; ALL: Group: 0 -; ALL: Frame: 3 -; ALL: SecName: 65535 -; ALL: ClassName: 65535 -; ALL: Offset: 0 -; ALL: SecByteLength: 4 -; ALL: } -; ALL: Entry { -; ALL: Flags [ (0x109) -; ALL: AddressIs32Bit (0x8) -; ALL: IsSelector (0x100) -; ALL: Read (0x1) -; ALL: ] -; ALL: Ovl: 0 -; ALL: Group: 0 -; ALL: Frame: 4 -; ALL: SecName: 65535 -; ALL: ClassName: 65535 -; ALL: Offset: 0 -; ALL: SecByteLength: 8 -; ALL: } -; ALL: Entry { -; ALL: Flags [ (0x208) -; ALL: AddressIs32Bit (0x8) -; ALL: IsAbsoluteAddress (0x200) -; ALL: ] -; ALL: Ovl: 0 -; ALL: Group: 0 -; ALL: Frame: 0 -; ALL: SecName: 65535 -; ALL: ClassName: 65535 -; ALL: Offset: 0 -; ALL: SecByteLength: 4294967295 -; ALL: } -; ALL: ] -; ALL: Globals Stream { -; ALL: Stream number: 6 -; ALL: Number of buckets: 2 -; ALL: Hash Buckets: [0, 12] -; ALL: } -; ALL: Publics Stream { -; ALL: Stream number: 7 -; ALL: SymHash: 556 -; ALL: AddrMap: 8 -; ALL: Number of buckets: 2 -; ALL: Hash Buckets: [0, 12] -; ALL: Address Map: [36, 0] -; ALL: Thunk Map: [4112] -; ALL: Section Offsets: [4096, 1] -; ALL: Symbols [ -; ALL: { -; ALL: PublicSym { -; ALL: Type: 0 -; ALL: Seg: 3 -; ALL: Off: 0 -; ALL: Name: ?__purecall@@3PAXA -; ALL: } -; ALL: } -; ALL: { -; ALL: PublicSym { -; ALL: Type: 2 -; ALL: Seg: 1 -; ALL: Off: 16 -; ALL: Name: _main -; ALL: } -; ALL: } -; ALL: { -; ALL: ProcRef { -; ALL: SumName: 0 -; ALL: SymOffset: 120 -; ALL: Mod: 1 -; ALL: Name: main -; ALL: } -; ALL: } -; ALL: { -; ALL: DataSym { -; ALL: Type: void* (0x403) -; ALL: DisplayName: __purecall -; ALL: } -; ALL: } -; ALL: ] -; ALL: } -; ALL: Section Headers [ -; ALL: { -; ALL: Name: .text -; ALL: Virtual Size: 4122 -; ALL: Virtual Address: 4096 -; ALL: Size of Raw Data: 4608 -; ALL: File Pointer to Raw Data: 1024 -; ALL: File Pointer to Relocations: 0 -; ALL: File Pointer to Linenumbers: 0 -; ALL: Number of Relocations: 0 -; ALL: Number of Linenumbers: 0 -; ALL: Characteristics [ (0x60000020) -; ALL: IMAGE_SCN_CNT_CODE (0x20) -; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: } -; ALL: { -; ALL: Name: .rdata -; ALL: Virtual Size: 690 -; ALL: Virtual Address: 12288 -; ALL: Size of Raw Data: 1024 -; ALL: File Pointer to Raw Data: 5632 -; ALL: File Pointer to Relocations: 0 -; ALL: File Pointer to Linenumbers: 0 -; ALL: Number of Relocations: 0 -; ALL: Number of Linenumbers: 0 -; ALL: Characteristics [ (0x40000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: } -; ALL: { -; ALL: Name: .data -; ALL: Virtual Size: 4 -; ALL: Virtual Address: 16384 -; ALL: Size of Raw Data: 0 -; ALL: File Pointer to Raw Data: 0 -; ALL: File Pointer to Relocations: 0 -; ALL: File Pointer to Linenumbers: 0 -; ALL: Number of Relocations: 0 -; ALL: Number of Linenumbers: 0 -; ALL: Characteristics [ (0xC0000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: IMAGE_SCN_MEM_WRITE (0x80000000) -; ALL: ] -; ALL: } -; ALL: { -; ALL: Name: .reloc -; ALL: Virtual Size: 8 -; ALL: Virtual Address: 20480 -; ALL: Size of Raw Data: 512 -; ALL: File Pointer to Raw Data: 6656 -; ALL: File Pointer to Relocations: 0 -; ALL: File Pointer to Linenumbers: 0 -; ALL: Number of Relocations: 0 -; ALL: Number of Linenumbers: 0 -; ALL: Characteristics [ (0x42000040) -; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40) -; ALL: IMAGE_SCN_MEM_DISCARDABLE (0x2000000) -; ALL: IMAGE_SCN_MEM_READ (0x40000000) -; ALL: ] -; ALL: } -; ALL: ] -; BIG: FileHeaders { -; BIG-NEXT: BlockSize: 4096 -; BIG-NEXT: FreeBlockMap: 2 -; BIG-NEXT: NumBlocks: 99 -; BIG-NEXT: NumDirectoryBytes: 616 -; BIG-NEXT: Unknown1: 0 -; BIG-NEXT: BlockMapAddr: 97 -; BIG-NEXT: NumDirectoryBlocks: 1 -; BIG-NEXT: DirectoryBlocks: [96] -; BIG-NEXT: NumStreams: 64 -; BIG-NEXT: } -; BIG-NEXT: PDB Stream { -; BIG-NEXT: Version: 20000404 -; BIG-NEXT: Signature: 0x571FFE67 -; BIG-NEXT: Age: 1 -; BIG-NEXT: Guid: {880ECC89-DF81-0B4F-839C-58CBD052E937} -; BIG-NEXT: Features: 0x1 -; BIG-NEXT: Named Streams { -; BIG-NEXT: /names: 13 -; BIG-NEXT: /LinkInfo: 5 -; BIG-NEXT: /src/headerblock: 61 -; BIG-NEXT: } -; BIG-NEXT: } -; BIG-NEXT: DBI Stream { -; BIG-NEXT: Dbi Version: 19990903 -; BIG-NEXT: Age: 1 -; BIG-NEXT: Incremental Linking: Yes -; BIG-NEXT: Has CTypes: No -; BIG-NEXT: Is Stripped: No -; BIG-NEXT: Machine Type: x86 -; BIG-NEXT: Symbol Record Stream Index: 9 -; BIG-NEXT: Public Symbol Stream Index: 8 -; BIG-NEXT: Global Symbol Stream Index: 7 -; BIG-NEXT: Toolchain Version: 14.0 -; BIG-NEXT: mspdb140.dll version: 14.0.23918 -; BIG-NEXT: Modules [ -; BIG-NEXT: { -; BIG-NEXT: Name: D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj -; BIG-NEXT: Debug Stream Index: 12 -; BIG-NEXT: Object File Name: D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 400 -; BIG-NEXT: Symbol Byte Size: 872 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\test.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj -; BIG-NEXT: Debug Stream Index: 14 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 14 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 344 -; BIG-NEXT: Symbol Byte Size: 720 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 14 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\i386\cpu_disp.c -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj -; BIG-NEXT: Debug Stream Index: 15 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 19 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 464 -; BIG-NEXT: Symbol Byte Size: 464 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 19 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\rtc\initsect.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj -; BIG-NEXT: Debug Stream Index: 16 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 1 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 32 -; BIG-NEXT: Symbol Byte Size: 444 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj -; BIG-NEXT: Debug Stream Index: 17 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 14 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 344 -; BIG-NEXT: Symbol Byte Size: 604 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 14 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\chandler4gs.c -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj -; BIG-NEXT: Debug Stream Index: 18 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 14 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 344 -; BIG-NEXT: Symbol Byte Size: 344 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 14 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\secchk.c -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj -; BIG-NEXT: Debug Stream Index: 19 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 9 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 224 -; BIG-NEXT: Symbol Byte Size: 160 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 9 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj -; BIG-NEXT: Debug Stream Index: 20 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 14 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 1392 -; BIG-NEXT: Symbol Byte Size: 1144 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 14 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\gs\gs_report.c -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj -; BIG-NEXT: Debug Stream Index: 21 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 10 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 432 -; BIG-NEXT: Symbol Byte Size: 552 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 10 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\gs\gs_support.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj -; BIG-NEXT: Debug Stream Index: 22 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 14 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 392 -; BIG-NEXT: Symbol Byte Size: 328 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 14 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\checkcfg.c -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj -; BIG-NEXT: Debug Stream Index: 23 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 10 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 352 -; BIG-NEXT: Symbol Byte Size: 424 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 10 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\guard_support.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj -; BIG-NEXT: Debug Stream Index: 24 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 9 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 224 -; BIG-NEXT: Symbol Byte Size: 156 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 9 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj -; BIG-NEXT: Debug Stream Index: 25 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 11 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 328 -; BIG-NEXT: Symbol Byte Size: 272 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 11 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_dtor.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj -; BIG-NEXT: Debug Stream Index: 26 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 10 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 304 -; BIG-NEXT: Symbol Byte Size: 272 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 10 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_init.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj -; BIG-NEXT: Debug Stream Index: 27 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 276 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\matherr_detection.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj -; BIG-NEXT: Debug Stream Index: 28 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 268 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_detection.c -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj -; BIG-NEXT: Debug Stream Index: 29 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 260 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\argv_mode.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj -; BIG-NEXT: Debug Stream Index: 30 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 260 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\commit_mode.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj -; BIG-NEXT: Debug Stream Index: 31 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 24 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 760 -; BIG-NEXT: Symbol Byte Size: 620 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 24 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\default_local_stdio_options.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdio.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vadefs.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj -; BIG-NEXT: Debug Stream Index: 32 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 80 -; BIG-NEXT: Symbol Byte Size: 272 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\denormal_control.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj -; BIG-NEXT: Debug Stream Index: 33 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 268 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\env_mode.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj -; BIG-NEXT: Debug Stream Index: 34 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 260 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\file_mode.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj -; BIG-NEXT: Debug Stream Index: 35 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 80 -; BIG-NEXT: Symbol Byte Size: 292 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\invalid_parameter_handler.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj -; BIG-NEXT: Debug Stream Index: 36 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 2 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 112 -; BIG-NEXT: Symbol Byte Size: 312 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 2 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\matherr.cpp -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj -; BIG-NEXT: Debug Stream Index: 37 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 260 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\new_mode.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj -; BIG-NEXT: Debug Stream Index: 38 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 88 -; BIG-NEXT: Symbol Byte Size: 272 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\thread_locale.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj -; BIG-NEXT: Debug Stream Index: 39 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 21 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 624 -; BIG-NEXT: Symbol Byte Size: 432 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 21 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\tncleanup.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_typeinfo.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_exception.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj -; BIG-NEXT: Debug Stream Index: 40 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 26 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 1668 -; BIG-NEXT: Symbol Byte Size: 2364 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 26 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdio.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vadefs.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj -; BIG-NEXT: Debug Stream Index: 41 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 20 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 488 -; BIG-NEXT: Symbol Byte Size: 196 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 20 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj -; BIG-NEXT: Debug Stream Index: 42 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 20 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 2500 -; BIG-NEXT: Symbol Byte Size: 6020 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 20 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\utility.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj -; BIG-NEXT: Debug Stream Index: 43 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 1 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 368 -; BIG-NEXT: Symbol Byte Size: 988 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 1 Contributing Source Files [ -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_stubs.cpp -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj -; BIG-NEXT: Debug Stream Index: 44 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 20 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 1240 -; BIG-NEXT: Symbol Byte Size: 1844 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 20 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\utility_desktop.cpp -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj -; BIG-NEXT: Debug Stream Index: 45 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib -; BIG-NEXT: Num Files: 20 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 552 -; BIG-NEXT: Symbol Byte Size: 356 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 20 Contributing Source Files [ -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\default_precision.cpp -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h -; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h -; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h -; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h -; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:KERNEL32.dll -; BIG-NEXT: Debug Stream Index: 47 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 1616 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: KERNEL32.dll -; BIG-NEXT: Debug Stream Index: 46 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 208 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:VCRUNTIME140.dll -; BIG-NEXT: Debug Stream Index: 49 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 664 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: VCRUNTIME140.dll -; BIG-NEXT: Debug Stream Index: 48 -; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 148 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:api-ms-win-crt-stdio-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 59 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 264 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: api-ms-win-crt-stdio-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 58 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 180 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:api-ms-win-crt-runtime-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 57 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 3068 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: api-ms-win-crt-runtime-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 56 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 188 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:api-ms-win-crt-math-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 55 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 140 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: api-ms-win-crt-math-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 54 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 180 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:api-ms-win-crt-locale-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 53 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 148 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: api-ms-win-crt-locale-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 52 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 188 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: Import:api-ms-win-crt-heap-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 51 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 136 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: api-ms-win-crt-heap-l1-1-0.dll -; BIG-NEXT: Debug Stream Index: 50 -; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 0 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 180 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: { -; BIG-NEXT: Name: * Linker * -; BIG-NEXT: Debug Stream Index: 60 -; BIG-NEXT: Object File Name: -; BIG-NEXT: Num Files: 0 -; BIG-NEXT: Source File Name Idx: 0 -; BIG-NEXT: Pdb File Name Idx: 55 -; BIG-NEXT: Line Info Byte Size: 0 -; BIG-NEXT: C13 Line Info Byte Size: 0 -; BIG-NEXT: Symbol Byte Size: 3080 -; BIG-NEXT: Type Server Index: 0 -; BIG-NEXT: Has EC Info: No -; BIG-NEXT: 0 Contributing Source Files [ -; BIG-NEXT: ] -; BIG-NEXT: } -; BIG-NEXT: ] -; BIG-NEXT: } -; BAD-BLOCK-SIZE: Native PDB Error: The PDB file is corrupt. Does not contain superblock +BIG: Summary +BIG-NEXT: ============================================================ +BIG-NEXT: Block Size: 4096 +BIG-NEXT: Number of blocks: 99 +BIG-NEXT: Number of streams: 64 +BIG-NEXT: Signature: 1461714535 +BIG-NEXT: Age: 1 +BIG-NEXT: GUID: {880ECC89-DF81-0B4F-839C-58CBD052E937} +BIG-NEXT: Features: 0x1 +BIG-NEXT: Has Debug Info: true +BIG-NEXT: Has Types: true +BIG-NEXT: Has IDs: true +BIG-NEXT: Has Globals: true +BIG-NEXT: Has Publics: true +BIG-NEXT: Is incrementally linked: true +BIG-NEXT: Has conflicting types: false +BIG-NEXT: Is stripped: false +BIG: Modules +BIG-NEXT: ============================================================ +BIG-NEXT: Mod 0000 | Name: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`: +BIG-NEXT: Obj: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`: +BIG-NEXT: debug stream: 12, # files: 1, has ec info: false +BIG-NEXT: Mod 0001 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 14, # files: 14, has ec info: false +BIG-NEXT: Mod 0002 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 15, # files: 19, has ec info: false +BIG-NEXT: Mod 0003 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 16, # files: 1, has ec info: false +BIG-NEXT: Mod 0004 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 17, # files: 14, has ec info: false +BIG-NEXT: Mod 0005 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 18, # files: 14, has ec info: false +BIG-NEXT: Mod 0006 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 19, # files: 9, has ec info: false +BIG-NEXT: Mod 0007 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 20, # files: 14, has ec info: false +BIG-NEXT: Mod 0008 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 21, # files: 10, has ec info: false +BIG-NEXT: Mod 0009 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 22, # files: 14, has ec info: false +BIG-NEXT: Mod 0010 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 23, # files: 10, has ec info: false +BIG-NEXT: Mod 0011 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 24, # files: 9, has ec info: false +BIG-NEXT: Mod 0012 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 25, # files: 11, has ec info: false +BIG-NEXT: Mod 0013 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 26, # files: 10, has ec info: false +BIG-NEXT: Mod 0014 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 27, # files: 1, has ec info: false +BIG-NEXT: Mod 0015 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 28, # files: 1, has ec info: false +BIG-NEXT: Mod 0016 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 29, # files: 1, has ec info: false +BIG-NEXT: Mod 0017 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 30, # files: 1, has ec info: false +BIG-NEXT: Mod 0018 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 31, # files: 24, has ec info: false +BIG-NEXT: Mod 0019 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 32, # files: 1, has ec info: false +BIG-NEXT: Mod 0020 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 33, # files: 1, has ec info: false +BIG-NEXT: Mod 0021 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 34, # files: 1, has ec info: false +BIG-NEXT: Mod 0022 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 35, # files: 1, has ec info: false +BIG-NEXT: Mod 0023 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 36, # files: 2, has ec info: false +BIG-NEXT: Mod 0024 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 37, # files: 1, has ec info: false +BIG-NEXT: Mod 0025 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 38, # files: 1, has ec info: false +BIG-NEXT: Mod 0026 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 39, # files: 21, has ec info: false +BIG-NEXT: Mod 0027 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 40, # files: 26, has ec info: false +BIG-NEXT: Mod 0028 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 41, # files: 20, has ec info: false +BIG-NEXT: Mod 0029 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 42, # files: 20, has ec info: false +BIG-NEXT: Mod 0030 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 43, # files: 1, has ec info: false +BIG-NEXT: Mod 0031 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 44, # files: 20, has ec info: false +BIG-NEXT: Mod 0032 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`: +BIG-NEXT: debug stream: 45, # files: 20, has ec info: false +BIG-NEXT: Mod 0033 | Name: `Import:KERNEL32.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`: +BIG-NEXT: debug stream: 47, # files: 0, has ec info: false +BIG-NEXT: Mod 0034 | Name: `KERNEL32.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`: +BIG-NEXT: debug stream: 46, # files: 0, has ec info: false +BIG-NEXT: Mod 0035 | Name: `Import:VCRUNTIME140.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`: +BIG-NEXT: debug stream: 49, # files: 0, has ec info: false +BIG-NEXT: Mod 0036 | Name: `VCRUNTIME140.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`: +BIG-NEXT: debug stream: 48, # files: 0, has ec info: false +BIG-NEXT: Mod 0037 | Name: `Import:api-ms-win-crt-stdio-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 59, # files: 0, has ec info: false +BIG-NEXT: Mod 0038 | Name: `api-ms-win-crt-stdio-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 58, # files: 0, has ec info: false +BIG-NEXT: Mod 0039 | Name: `Import:api-ms-win-crt-runtime-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 57, # files: 0, has ec info: false +BIG-NEXT: Mod 0040 | Name: `api-ms-win-crt-runtime-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 56, # files: 0, has ec info: false +BIG-NEXT: Mod 0041 | Name: `Import:api-ms-win-crt-math-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 55, # files: 0, has ec info: false +BIG-NEXT: Mod 0042 | Name: `api-ms-win-crt-math-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 54, # files: 0, has ec info: false +BIG-NEXT: Mod 0043 | Name: `Import:api-ms-win-crt-locale-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 53, # files: 0, has ec info: false +BIG-NEXT: Mod 0044 | Name: `api-ms-win-crt-locale-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 52, # files: 0, has ec info: false +BIG-NEXT: Mod 0045 | Name: `Import:api-ms-win-crt-heap-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 51, # files: 0, has ec info: false +BIG-NEXT: Mod 0046 | Name: `api-ms-win-crt-heap-l1-1-0.dll`: +BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`: +BIG-NEXT: debug stream: 50, # files: 0, has ec info: false +BIG-NEXT: Mod 0047 | Name: `* Linker *`: +BIG-NEXT: Obj: ``: +BIG-NEXT: debug stream: 60, # files: 0, has ec info: false +BIG: Files +BIG-NEXT: ============================================================ +BIG-NEXT: Mod 0000 | `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`: +BIG-NEXT: - (MD5: A20261917ADC01A12CBDBF778BC6CCC8) d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\test.cpp +BIG-NEXT: Mod 0001 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: 884E12AC852D3B4E1E625A0F01595A68) f:\dd\vctools\crt\vcstartup\src\misc\i386\cpu_disp.c +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0002 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`: +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: DD3FFC8C4284997F6762C449313244B2) f:\dd\vctools\crt\vcstartup\src\rtc\initsect.cpp +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: Mod 0003 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`: +BIG-NEXT: - (MD5: E562BB073C88A6A3791CE9FBDC64E7A7) f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm +BIG-NEXT: Mod 0004 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: D014BFD91FD6D4163AF92452CBC9EEA0) f:\dd\vctools\crt\vcstartup\src\eh\i386\chandler4gs.c +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0005 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: 6C34B4E5ACA82CB0D6BD6CB8C059C9C9) f:\dd\vctools\crt\vcstartup\src\eh\i386\secchk.c +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0006 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0007 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: 87566AA39C18DD3CEAC021002D34B63D) f:\dd\vctools\crt\vcstartup\src\gs\gs_report.c +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0008 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: 57AC84319EF78F67DAA9372FDA8CBFCC) f:\dd\vctools\crt\vcstartup\src\gs\gs_support.c +BIG-NEXT: Mod 0009 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: 9552C4FC4125F9D7D3A8B5FD18B7BCCF) f:\dd\vctools\crt\vcstartup\src\misc\checkcfg.c +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0010 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: 8BFBA3D0672A148A9FB0E9F0A6BC256D) f:\dd\vctools\crt\vcstartup\src\misc\guard_support.c +BIG-NEXT: Mod 0011 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: Mod 0012 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: EE3858E06B118BDBAAE53F5E55B0BB0C) f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_dtor.c +BIG-NEXT: Mod 0013 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`: +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: 9DA48F59075BBAAAB4F7FC4575F34405) f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_init.c +BIG-NEXT: Mod 0014 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`: +BIG-NEXT: - (MD5: 2DF28D8BA8B7AAAA67C94719B214B060) f:\dd\vctools\crt\vcstartup\src\utility\matherr_detection.c +BIG-NEXT: Mod 0015 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`: +BIG-NEXT: - (MD5: 737902C62D7458629D0DDD52E122C033) f:\dd\vctools\crt\vcstartup\src\utility\ucrt_detection.c +BIG-NEXT: Mod 0016 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`: +BIG-NEXT: - (MD5: 634D3D57BDE292817F77F8DBF366E2D2) f:\dd\vctools\crt\vcstartup\src\defaults\argv_mode.cpp +BIG-NEXT: Mod 0017 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`: +BIG-NEXT: - (MD5: CF5B0F6243121A3F5E206E07CA457128) f:\dd\vctools\crt\vcstartup\src\defaults\commit_mode.cpp +BIG-NEXT: Mod 0018 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: E6391682D136711F96E730F4D6162E0C) f:\dd\vctools\crt\vcstartup\src\defaults\default_local_stdio_options.cpp +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2D5E699DF1BED89FCCCCCF0DCFC49050) f:\dd\externalapis\unifiedcrt\inc\stdio.h +BIG-NEXT: - (MD5: 2443DB19DCC585E308F60DAFEF1D4C4C) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h +BIG-NEXT: - (MD5: 79921ECB03C5C56E28D771ADF8910FD8) f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: 303C50A7BC924CD426BAA20C7F16192C) f:\dd\vctools\crt\vcruntime\inc\vadefs.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: Mod 0019 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`: +BIG-NEXT: - (MD5: 0513001DBCB8CB8F8561DC117FD943BA) f:\dd\vctools\crt\vcstartup\src\defaults\denormal_control.cpp +BIG-NEXT: Mod 0020 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`: +BIG-NEXT: - (MD5: 5B7121FC3210A120D7B70CB668D8EF0C) f:\dd\vctools\crt\vcstartup\src\defaults\env_mode.cpp +BIG-NEXT: Mod 0021 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`: +BIG-NEXT: - (MD5: 749603C05EB2FB5024819A3107DA9A7D) f:\dd\vctools\crt\vcstartup\src\defaults\file_mode.cpp +BIG-NEXT: Mod 0022 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`: +BIG-NEXT: - (MD5: 0C385FD7C6DB91E0BA7C72C1AB680BE6) f:\dd\vctools\crt\vcstartup\src\defaults\invalid_parameter_handler.cpp +BIG-NEXT: Mod 0023 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`: +BIG-NEXT: - (MD5: F8B3DAD79F14E4169CCBA611203C89CD) f:\dd\vctools\crt\vcstartup\src\defaults\matherr.cpp +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: Mod 0024 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`: +BIG-NEXT: - (MD5: 4F22B6A5E4E0D01E8C000B17F2B2640D) f:\dd\vctools\crt\vcstartup\src\defaults\new_mode.cpp +BIG-NEXT: Mod 0025 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`: +BIG-NEXT: - (MD5: 435F5F51541F7D6565DF6BE20F8AC8A3) f:\dd\vctools\crt\vcstartup\src\defaults\thread_locale.cpp +BIG-NEXT: Mod 0026 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`: +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 984A18787250F7F6D0506E6BC1FD7991) f:\dd\vctools\crt\vcstartup\src\eh\tncleanup.cpp +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 2465A06B1F50CD26AD5EC7D20DA6DB3D) f:\dd\vctools\crt\vcruntime\inc\vcruntime_typeinfo.h +BIG-NEXT: - (MD5: 385CF08DA92F72075026067CE03F8402) f:\dd\vctools\crt\vcruntime\inc\vcruntime_exception.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: Mod 0027 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: B71A807A307A52C400179EF5D3FAA1A7) f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: 2D5E699DF1BED89FCCCCCF0DCFC49050) f:\dd\externalapis\unifiedcrt\inc\stdio.h +BIG-NEXT: - (MD5: 2443DB19DCC585E308F60DAFEF1D4C4C) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h +BIG-NEXT: - (MD5: 79921ECB03C5C56E28D771ADF8910FD8) f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 36A3069CD09EC9F92668000F200D5545) f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: 303C50A7BC924CD426BAA20C7F16192C) f:\dd\vctools\crt\vcruntime\inc\vadefs.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: Mod 0028 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: Mod 0029 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: 2D42DDF1AAE9B3491E4BB346255346D5) f:\dd\vctools\crt\vcstartup\src\utility\utility.cpp +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: Mod 0030 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`: +BIG-NEXT: - (MD5: 20976B3B6CD70F2DF77312D18D9C8D32) f:\dd\vctools\crt\vcstartup\src\utility\ucrt_stubs.cpp +BIG-NEXT: Mod 0031 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`: +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: CC9AAE4BAA114C08FFC7F1515EC09E4C) f:\dd\vctools\crt\vcstartup\src\utility\utility_desktop.cpp +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: Mod 0032 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`: +BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h +BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h +BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h +BIG-NEXT: - (MD5: 9621B7E7C6A138B5185711F98CCC568E) f:\dd\vctools\crt\vcstartup\src\defaults\default_precision.cpp +BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h +BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h +BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h +BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h +BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h +BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h +BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h +BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h +BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h +BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h +BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h +BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h +BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h +BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h +BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h +BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h +BIG-NEXT: Mod 0033 | `Import:KERNEL32.dll`: +BIG-NEXT: Mod 0034 | `KERNEL32.dll`: +BIG-NEXT: Mod 0035 | `Import:VCRUNTIME140.dll`: +BIG-NEXT: Mod 0036 | `VCRUNTIME140.dll`: +BIG-NEXT: Mod 0037 | `Import:api-ms-win-crt-stdio-l1-1-0.dll`: +BIG-NEXT: Mod 0038 | `api-ms-win-crt-stdio-l1-1-0.dll`: +BIG-NEXT: Mod 0039 | `Import:api-ms-win-crt-runtime-l1-1-0.dll`: +BIG-NEXT: Mod 0040 | `api-ms-win-crt-runtime-l1-1-0.dll`: +BIG-NEXT: Mod 0041 | `Import:api-ms-win-crt-math-l1-1-0.dll`: +BIG-NEXT: Mod 0042 | `api-ms-win-crt-math-l1-1-0.dll`: +BIG-NEXT: Mod 0043 | `Import:api-ms-win-crt-locale-l1-1-0.dll`: +BIG-NEXT: Mod 0044 | `api-ms-win-crt-locale-l1-1-0.dll`: +BIG-NEXT: Mod 0045 | `Import:api-ms-win-crt-heap-l1-1-0.dll`: +BIG-NEXT: Mod 0046 | `api-ms-win-crt-heap-l1-1-0.dll`: +BIG-NEXT: Mod 0047 | `* Linker *`: + +BAD-BLOCK-SIZE: Native PDB Error: The PDB file is corrupt. Does not contain superblock diff --git a/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test b/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test index 2639490..f25e902 100644 --- a/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test +++ b/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test @@ -1,65 +1,51 @@ ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml ; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s -; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s -; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s -; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s +; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s +; RUN: llvm-pdbutil raw -ids %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s -TPI-TYPES: Type Info Stream (TPI) -TPI-TYPES: Record count: 9 -TPI-TYPES-DAG: TypeLeafKind: LF_POINTER -TPI-TYPES-DAG: TypeLeafKind: LF_FIELDLIST -TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST -TPI-TYPES-DAG: TypeLeafKind: LF_STRUCTURE -TPI-TYPES-DAG: TypeLeafKind: LF_MEMBER -TPI-TYPES-DAG: TypeLeafKind: LF_POINTER -TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST -TPI-TYPES-DAG: TypeLeafKind: LF_MFUNCTION -TPI-TYPES-DAG: TypeLeafKind: LF_PROCEDURE -TPI-TYPES-DAG: TypeLeafKind: LF_PROCEDURE -TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST +TPI-TYPES: Types (TPI Stream) +TPI-TYPES-NEXT: ============================================================ +TPI-TYPES-NEXT: Showing 9 records +TPI-TYPES-NEXT: 0x1000 | LF_POINTER [size = 12] +TPI-TYPES-NEXT: referent = 0x0470 (char*), mode = pointer, opts = None, kind = ptr32 +TPI-TYPES-NEXT: 0x1001 | LF_FIELDLIST [size = 24] +TPI-TYPES-NEXT: - LF_MEMBER [name = `FooMember`, Type = 0x0403 (void*), offset = 0, attrs = public] +TPI-TYPES-NEXT: 0x1002 | LF_ARGLIST [size = 16] +TPI-TYPES-NEXT: 0x0074 (int): `int` +TPI-TYPES-NEXT: 0x1000: `char**` +TPI-TYPES-NEXT: 0x1003 | LF_STRUCTURE [size = 36] +TPI-TYPES-NEXT: class name: `FooBar` +TPI-TYPES-NEXT: unique name: `FooBar` +TPI-TYPES-NEXT: vtable: , base list: , field list: 0x1001 +TPI-TYPES-NEXT: options: has unique name +TPI-TYPES-NEXT: 0x1004 | LF_POINTER [size = 12] +TPI-TYPES-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32 +TPI-TYPES-NEXT: 0x1005 | LF_ARGLIST [size = 12] +TPI-TYPES-NEXT: 0x0074 (int): `int` +TPI-TYPES-NEXT: 0x1006 | LF_MFUNCTION [size = 28] +TPI-TYPES-NEXT: return type = 1, # args = 0x1005, param list = 0x0003 (void) +TPI-TYPES-NEXT: class type = 0x1003, this type = 0x1004, this adjust = 0 +TPI-TYPES-NEXT: calling conv = thiscall, options = constructor +TPI-TYPES-NEXT: 0x1007 | LF_PROCEDURE [size = 16] +TPI-TYPES-NEXT: return type = 0x0074 (int), # args = 2, param list = 0x1002 +TPI-TYPES-NEXT: calling conv = cdecl, options = None +TPI-TYPES-NEXT: 0x1008 | LF_PROCEDURE [size = 16] +TPI-TYPES-NEXT: return type = 0x0003 (void), # args = 2, param list = 0x1002 +TPI-TYPES-NEXT: calling conv = cdecl, options = None -; Both procedures should use the same arglist even though they have a different -; return type. -INTMAIN: ArgList ([[ID:.*]]) -INTMAIN-NEXT: TypeLeafKind: LF_ARGLIST -INTMAIN-NEXT: NumArgs: 2 -INTMAIN-NEXT: Arguments [ -INTMAIN-NEXT: ArgType: int -INTMAIN-NEXT: ArgType: char** -INTMAIN: TypeLeafKind: LF_PROCEDURE -INTMAIN: ReturnType: int -INTMAIN: NumParameters: 2 -INTMAIN-NEXT: ArgListType: (int, char**) ([[ID]]) - -VOIDMAIN: ArgList ([[ID:.*]]) -VOIDMAIN-NEXT: TypeLeafKind: LF_ARGLIST -VOIDMAIN-NEXT: NumArgs: 2 -VOIDMAIN-NEXT: Arguments [ -VOIDMAIN-NEXT: ArgType: int -VOIDMAIN-NEXT: ArgType: char** -VOIDMAIN: TypeLeafKind: LF_PROCEDURE -VOIDMAIN: ReturnType: void -VOIDMAIN: NumParameters: 2 -VOIDMAIN-NEXT: ArgListType: (int, char**) ([[ID]]) - -IPI-TYPES: Type Info Stream (IPI) -IPI-TYPES: Record count: 6 -IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID -IPI-TYPES-DAG: TypeLeafKind: LF_MFUNC_ID -IPI-TYPES-DAG: TypeLeafKind: LF_UDT_MOD_SRC_LINE -IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID -IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID -IPI-TYPES-DAG: TypeLeafKind: LF_MFUNC_ID - -IPI-NAMES-DAG: Name: main -IPI-NAMES-DAG: Name: FooMethod -IPI-NAMES-DAG: Name: main2 -IPI-NAMES-DAG: Name: foo -IPI-NAMES-DAG: Name: FooMethod2 - -IPI-UDT: TypeLeafKind: LF_UDT_MOD_SRC_LINE -IPI-UDT-NEXT: UDT: FooBar +IPI-TYPES: Types (IPI Stream) +IPI-TYPES-NEXT: ============================================================ +IPI-TYPES-NEXT: Showing 6 records +IPI-TYPES-NEXT: 0x1000 | LF_FUNC_ID [size = 20] +IPI-TYPES-NEXT: name = main, type = 0x1007, parent scope = +IPI-TYPES-NEXT: 0x1001 | LF_MFUNC_ID [size = 24] +IPI-TYPES-NEXT: name = FooMethod, type = 0x1006, class type = 0x1003 +IPI-TYPES-NEXT: 0x1002 | LF_UDT_MOD_SRC_LINE [size = 20] +IPI-TYPES-NEXT: udt = 0x1003, mod = 0, file = 0, line = 0 +IPI-TYPES-NEXT: 0x1003 | LF_FUNC_ID [size = 20] +IPI-TYPES-NEXT: name = main2, type = 0x1007, parent scope = +IPI-TYPES-NEXT: 0x1004 | LF_FUNC_ID [size = 16] +IPI-TYPES-NEXT: name = foo, type = 0x1008, parent scope = +IPI-TYPES-NEXT: 0x1005 | LF_MFUNC_ID [size = 24] +IPI-TYPES-NEXT: name = FooMethod2, type = 0x1006, class type = 0x1003 diff --git a/test/DebugInfo/PDB/pdbdump-mergeids.test b/test/DebugInfo/PDB/pdbdump-mergeids.test index 1c0a870..441ce4d 100644 --- a/test/DebugInfo/PDB/pdbdump-mergeids.test +++ b/test/DebugInfo/PDB/pdbdump-mergeids.test @@ -1,31 +1,24 @@ ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml ; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml ; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb -; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s -; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s +; RUN: llvm-pdbutil raw -ids %t.3.pdb | FileCheck -check-prefix=MERGED %s +; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s -MERGED: Type Info Stream (IPI) -MERGED: Record count: 8 -MERGED-DAG: StringData: One -MERGED-DAG: StringData: Two -MERGED-DAG: StringData: SubOne -MERGED-DAG: StringData: SubTwo -MERGED-DAG: StringData: Main -MERGED-DAG: TypeLeafKind: LF_SUBSTR_LIST -MERGED-DAG: StringData: OnlyInFirst -MERGED-DAG: StringData: OnlyInSecond +MERGED: Types (IPI Stream) +MERGED-NEXT: ============================================================ +MERGED-NEXT: Showing 8 records +MERGED-NEXT: 0x1000 | LF_STRING_ID [size = 12] ID: , String: One +MERGED-NEXT: 0x1001 | LF_STRING_ID [size = 12] ID: , String: Two +MERGED-NEXT: 0x1002 | LF_STRING_ID [size = 20] ID: , String: OnlyInFirst +MERGED-NEXT: 0x1003 | LF_STRING_ID [size = 16] ID: , String: SubOne +MERGED-NEXT: 0x1004 | LF_STRING_ID [size = 16] ID: , String: SubTwo +MERGED-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 16] +MERGED-NEXT: 0x1003: `SubOne` +MERGED-NEXT: 0x1004: `SubTwo` +MERGED-NEXT: 0x1006 | LF_STRING_ID [size = 16] ID: 0x1005, String: Main +MERGED-NEXT: 0x1007 | LF_STRING_ID [size = 24] ID: , String: OnlyInSecond -SUBSTRS: StringList -SUBSTRS: TypeLeafKind: LF_SUBSTR_LIST -SUBSTRS-NEXT: NumStrings: 2 -SUBSTRS-NEXT: Strings [ -SUBSTRS-NEXT: SubOne -SUBSTRS-NEXT: SubTwo -SUBSTRS: StringId -SUBSTRS-NEXT: TypeLeafKind: LF_STRING_ID -SUBSTRS-NEXT: Id: "SubOne" "SubTwo" -SUBSTRS-NEXT: StringData: Main - -TPI-EMPTY: Record count: 0 +TPI-EMPTY: Types (TPI Stream) +TPI-EMPTY-NEXT: ============================================================ +TPI-EMPTY-NEXT: Showing 0 records diff --git a/test/DebugInfo/PDB/pdbdump-mergetypes.test b/test/DebugInfo/PDB/pdbdump-mergetypes.test index 8d32b4d..9aae405 100644 --- a/test/DebugInfo/PDB/pdbdump-mergetypes.test +++ b/test/DebugInfo/PDB/pdbdump-mergetypes.test @@ -1,24 +1,36 @@ -; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml -; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml -; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s -; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s - - -MERGED: Type Info Stream (TPI) -MERGED: Record count: 9 -MERGED-DAG: PointeeType: unsigned -MERGED-DAG: PointeeType: unsigned* -MERGED-DAG: PointeeType: unsigned** -MERGED-DAG: PointeeType: __int64 -MERGED-DAG: PointeeType: __int64* -MERGED-DAG: Name: OnlyInMerge1 -MERGED-DAG: Name: OnlyInMerge2 -MERGED-DAG: TypeLeafKind: LF_ARGLIST - -ARGLIST: TypeLeafKind: LF_ARGLIST -ARGLIST-NEXT: NumArgs: 3 -ARGLIST-NEXT: Arguments [ -ARGLIST-NEXT: ArgType: unsigned -ARGLIST-NEXT: ArgType: unsigned* -ARGLIST-NEXT: ArgType: unsigned** ++; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml +; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml +; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb +; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=MERGED %s + + +MERGED: Types (TPI Stream) +MERGED-NEXT: ============================================================ +MERGED-NEXT: Showing 9 records +MERGED-NEXT: 0x1000 | LF_POINTER [size = 12] +MERGED-NEXT: referent = 0x0075 (unsigned), mode = pointer, opts = None, kind = ptr32 +MERGED-NEXT: 0x1001 | LF_POINTER [size = 12] +MERGED-NEXT: referent = 0x0076 (__int64), mode = pointer, opts = None, kind = ptr32 +MERGED-NEXT: 0x1002 | LF_STRUCTURE [size = 48] +MERGED-NEXT: class name: `OnlyInMerge1` +MERGED-NEXT: unique name: `OnlyInMerge1` +MERGED-NEXT: vtable: , base list: , field list: +MERGED-NEXT: options: forward ref | has unique name +MERGED-NEXT: 0x1003 | LF_POINTER [size = 12] +MERGED-NEXT: referent = 0x1000, mode = pointer, opts = None, kind = ptr32 +MERGED-NEXT: 0x1004 | LF_POINTER [size = 12] +MERGED-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32 +MERGED-NEXT: 0x1005 | LF_POINTER [size = 12] +MERGED-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr32 +MERGED-NEXT: 0x1006 | LF_ARGLIST [size = 20] +MERGED-NEXT: 0x0075 (unsigned): `unsigned` +MERGED-NEXT: 0x1000: `unsigned*` +MERGED-NEXT: 0x1003: `unsigned**` +MERGED-NEXT: 0x1007 | LF_PROCEDURE [size = 16] +MERGED-NEXT: return type = 0x0075 (unsigned), # args = 0, param list = 0x1006 +MERGED-NEXT: calling conv = cdecl, options = None +MERGED-NEXT: 0x1008 | LF_STRUCTURE [size = 48] +MERGED-NEXT: class name: `OnlyInMerge2` +MERGED-NEXT: unique name: `OnlyInMerge2` +MERGED-NEXT: vtable: , base list: , field list: +MERGED-NEXT: options: forward ref | has unique name diff --git a/test/DebugInfo/PDB/pdbdump-raw-blocks.test b/test/DebugInfo/PDB/pdbdump-raw-blocks.test index 14e1f86..b695d5a 100644 --- a/test/DebugInfo/PDB/pdbdump-raw-blocks.test +++ b/test/DebugInfo/PDB/pdbdump-raw-blocks.test @@ -1,35 +1,29 @@ -; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s -; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s -; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s -; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s -; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s - -BLOCK0: Block Data { -BLOCK0-NEXT: Block 0 ( -BLOCK0-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ | -BLOCK0-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...| -BLOCK0-NEXT: 0020: 00100000 02000000 19000000 88000000 |................| -BLOCK0-NEXT: 0030: 00000000 18000000 00000000 00000000 |................| -BLOCK0: 0FE0: 00000000 00000000 00000000 00000000 |................| -BLOCK0-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................| -BLOCK0-NEXT: ) -BLOCK0-NEXT: } - -BLOCK01: Block Data { -BLOCK01-NEXT: Block 0 ( -BLOCK01-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ | -BLOCK01-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...| -BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 |................| -BLOCK01-NEXT: 0030: 00000000 18000000 00000000 00000000 |................| -BLOCK01: 0FE0: 00000000 00000000 00000000 00000000 |................| -BLOCK01-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................| -BLOCK01-NEXT: ) -BLOCK01-NEXT: Block 1 ( -BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................| -BLOCK01-NEXT: 0010: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................| -BLOCK01: 0FE0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................| -BLOCK01-NEXT: 0FF0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................| -BLOCK01-NEXT: ) -BLOCK01-NEXT: } - -BADSYNTAX: Argument '{{.*}}' invalid format. +; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s +; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s +; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s +; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s +; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s + +BLOCK0: MSF Blocks +BLOCK0-NEXT: ============================================================ +BLOCK0-NEXT: Block 0 ( +BLOCK0-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 4D534620 372E3030 0D0A1A44 53000000 |Microsoft C/C++ MSF 7.00...DS...| +BLOCK0-NEXT: 0020: 00100000 02000000 19000000 88000000 00000000 18000000 00000000 00000000 |................................| +BLOCK0-NEXT: 0040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +BLOCK0-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +BLOCK0-NOT: Block 1 ( + +BLOCK01: MSF Blocks +BLOCK01-NEXT: ============================================================ +BLOCK01-NEXT: Block 0 ( +BLOCK01-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 4D534620 372E3030 0D0A1A44 53000000 |Microsoft C/C++ MSF 7.00...DS...| +BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 00000000 18000000 00000000 00000000 |................................| +BLOCK01-NEXT: 0040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +BLOCK01-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| +BLOCK01: Block 1 ( +BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NEXT: 0020: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NEXT: 0040: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................| +BLOCK01-NOT: Block 2 ( + +BADSYNTAX: Argument '{{.*}}' invalid format. diff --git a/test/DebugInfo/PDB/pdbdump-raw-stream.test b/test/DebugInfo/PDB/pdbdump-raw-stream.test index 846960a..2f8e05a 100644 --- a/test/DebugInfo/PDB/pdbdump-raw-stream.test +++ b/test/DebugInfo/PDB/pdbdump-raw-stream.test @@ -1,23 +1,28 @@ -; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s -; RUN: not llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s - -STREAM1: Stream Data { -STREAM1-NEXT: Stream { -STREAM1-NEXT: Index: 1 -STREAM1-NEXT: Type: PDB Stream -STREAM1-NEXT: Size: 118 -STREAM1-NEXT: Blocks: [19] -STREAM1-NEXT: Data ( -STREAM1-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 |..1....T.....5VA| -STREAM1-NEXT: 0010: 86A0A249 896F9988 FAE52FF0 22000000 |...I.o..../."...| -STREAM1-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 |/LinkInfo./names| -STREAM1-NEXT: 0030: 002F7372 632F6865 61646572 626C6F63 |./src/headerbloc| -STREAM1-NEXT: 0040: 6B000300 00000600 00000100 00001A00 |k...............| -STREAM1-NEXT: 0050: 00000000 00001100 00000900 00000A00 |................| -STREAM1-NEXT: 0060: 00000D00 00000000 00000500 00000000 |................| -STREAM1-NEXT: 0070: 00004191 3201 |..A.2.| -STREAM1-NEXT: ) -STREAM1-NEXT: } -STREAM1-NEXT: } - -INVALIDSTREAM: Native PDB Error: The specified stream could not be loaded. +; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM %s +; RUN: llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s +; RUN: llvm-pdbutil raw -stream-data=1,100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BOTH %s + +STREAM: Stream Data +STREAM-NEXT: ============================================================ +STREAM-NEXT: Stream 1 (118 bytes): PDB Stream +STREAM-NEXT: Data ( +STREAM-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| +STREAM-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| +STREAM-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| +STREAM-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| +STREAM-NEXT: ) + +INVALIDSTREAM: Stream Data +INVALIDSTREAM-NEXT: ============================================================ +INVALIDSTREAM-NEXT: Stream 100: Not present + +BOTH: Stream Data +BOTH-NEXT: ============================================================ +BOTH-NEXT: Stream 1 (118 bytes): PDB Stream +BOTH-NEXT: Data ( +BOTH-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...| +BOTH-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc| +BOTH-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................| +BOTH-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.| +BOTH-NEXT: ) +BOTH-NEXT: Stream 100: Not present diff --git a/test/DebugInfo/PDB/pdbdump-readwrite.test b/test/DebugInfo/PDB/pdbdump-readwrite.test index ee53f3b..51ebd75 100644 --- a/test/DebugInfo/PDB/pdbdump-readwrite.test +++ b/test/DebugInfo/PDB/pdbdump-readwrite.test @@ -3,48 +3,33 @@ RUN: -pdb-stream -string-table -tpi-stream -stream-directory \ RUN: -stream-metadata %p/Inputs/empty.pdb > %t.1 RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1 -RUN: llvm-pdbutil raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s -RUN: llvm-pdbutil raw -headers -string-table -tpi-records %t.2 | FileCheck %s +RUN: llvm-pdbutil raw -summary -string-table -types %p/Inputs/empty.pdb | FileCheck %s +RUN: llvm-pdbutil raw -summary -string-table -types %t.2 | FileCheck %s -CHECK: FileHeaders { -CHECK-NEXT: BlockSize: 4096 -CHECK-NEXT: FreeBlockMap: -CHECK-NEXT: NumBlocks: -CHECK-NEXT: NumDirectoryBytes: -CHECK-NEXT: Unknown1: 0 -CHECK-NEXT: BlockMapAddr: -CHECK-NEXT: NumDirectoryBlocks: 1 -CHECK-NEXT: DirectoryBlocks: -CHECK-NEXT: NumStreams: -CHECK-NEXT: } -CHECK: String Table { -CHECK-DAG: 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)' -CHECK-DAG: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' -CHECK-DAG: '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = ' -CHECK-NEXT: } -CHECK: PDB Stream { -CHECK-NEXT: Version: 20000404 -CHECK-NEXT: Signature: 0x54E507E2 -CHECK-NEXT: Age: 1 -CHECK-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0} -CHECK-NEXT: Features: 0x1 -CHECK-NEXT: Named Streams { -CHECK: /names: -CHECK: } -CHECK-NEXT: } -CHECK: Type Info Stream (TPI) { -CHECK-NEXT: TPI Version: 20040203 -CHECK-NEXT: Record count: 75 -CHECK: DBI Stream { -CHECK-NEXT: Dbi Version: 19990903 -CHECK-NEXT: Age: 1 -CHECK-NEXT: Incremental Linking: Yes -CHECK-NEXT: Has CTypes: No -CHECK-NEXT: Is Stripped: No -CHECK-NEXT: Machine Type: x86 -CHECK-NEXT: Symbol Record Stream Index: -CHECK-NEXT: Public Symbol Stream Index: -CHECK-NEXT: Global Symbol Stream Index: -CHECK-NEXT: Toolchain Version: 12.0 -CHECK-NEXT: mspdb120.dll version: 12.0.31101 -CHECK-NEXT: } + +CHECK: Summary +CHECK-NEXT: ============================================================ +CHECK-NEXT: Block Size: 4096 +CHECK-NEXT: Number of blocks: +CHECK-NEXT: Number of streams: +CHECK-NEXT: Signature: 1424295906 +CHECK-NEXT: Age: 1 +CHECK-NEXT: GUID: {0B355641-86A0-A249-896F-9988FAE52FF0} +CHECK-NEXT: Features: 0x1 +CHECK-NEXT: Has Debug Info: true +CHECK-NEXT: Has Types: true +CHECK-NEXT: Has IDs: true +CHECK-NEXT: Has Globals: +CHECK-NEXT: Has Publics: +CHECK-NEXT: Is incrementally linked: true +CHECK-NEXT: Has conflicting types: false +CHECK-NEXT: Is stripped: false +CHECK: String Table +CHECK-NEXT: ============================================================ +CHECK-NEXT: ID | String +CHECK-NEXT: {{.*}} | 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)' +CHECK-NEXT: {{.*}} | 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' +CHECK-NEXT: {{.*}} | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = ' +CHECK: Types (TPI Stream) +CHECK-NEXT: ============================================================ +CHECK-NEXT: Showing 75 records diff --git a/test/DebugInfo/X86/block-capture.ll b/test/DebugInfo/X86/block-capture.ll index 1680405..14927ee 100644 --- a/test/DebugInfo/X86/block-capture.ll +++ b/test/DebugInfo/X86/block-capture.ll @@ -123,7 +123,7 @@ attributes #3 = { nounwind } !66 = !DILocation(line: 2, column: 20, scope: !8) !67 = !DILocation(line: 2, column: 21, scope: !8) !68 = !DILocalVariable(name: "block", line: 2, scope: !8, file: !5, type: !25) -!69 = !DIExpression(DW_OP_deref, DW_OP_plus, 32) +!69 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32) !70 = !DILocation(line: 2, column: 9, scope: !8) !71 = !DILocation(line: 2, column: 23, scope: !72) !72 = distinct !DILexicalBlock(line: 2, column: 21, file: !1, scope: !8) diff --git a/test/DebugInfo/X86/debug-info-block-captured-self.ll b/test/DebugInfo/X86/debug-info-block-captured-self.ll index 1085eae..e1620af 100644 --- a/test/DebugInfo/X86/debug-info-block-captured-self.ll +++ b/test/DebugInfo/X86/debug-info-block-captured-self.ll @@ -107,5 +107,5 @@ define internal void @"__24-[Main initWithContext:]_block_invoke_2"(i8* %.block_ !106 = !DILocation(line: 40, scope: !42) !107 = !DIFile(filename: "llvm/tools/clang/test/CodeGenObjC/debug-info-block-captured-self.m", directory: "") !108 = !{i32 1, !"Debug Info Version", i32 3} -!109 = !DIExpression(DW_OP_plus, 32, DW_OP_deref) -!110 = !DIExpression(DW_OP_plus, 32, DW_OP_deref) +!109 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref) +!110 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref) diff --git a/test/DebugInfo/X86/debug-info-blocks.ll b/test/DebugInfo/X86/debug-info-blocks.ll index 859eef8..b79ad89 100644 --- a/test/DebugInfo/X86/debug-info-blocks.ll +++ b/test/DebugInfo/X86/debug-info-blocks.ll @@ -380,4 +380,4 @@ attributes #3 = { nounwind } !108 = !DILocation(line: 61, scope: !36) !109 = !DILocation(line: 62, scope: !36) !110 = !{i32 1, !"Debug Info Version", i32 3} -!111 = !DIExpression(DW_OP_deref, DW_OP_plus, 32) +!111 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32) diff --git a/test/DebugInfo/X86/double-declare.ll b/test/DebugInfo/X86/double-declare.ll new file mode 100644 index 0000000..8ed4319 --- /dev/null +++ b/test/DebugInfo/X86/double-declare.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple=x86_64-apple-darwin -O0 -filetype=obj -o - < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s +; PR33157. Don't crash on duplicate dbg.declare. +; CHECK: DW_TAG_formal_parameter +; CHECK: DW_AT_location [DW_FORM_exprloc] +; CHECK-NOT: DW_AT_location +@g = external global i32 +@h = external global i32 + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define void @f(i32* byval %p, i1 %c) !dbg !5 { + br i1 %c, label %x, label %y + +x: + call void @llvm.dbg.declare(metadata i32* %p, metadata !10, metadata !DIExpression()), !dbg !12 + store i32 42, i32* @g, !dbg !12 + br label %done + +y: + call void @llvm.dbg.declare(metadata i32* %p, metadata !10, metadata !DIExpression()), !dbg !12 + store i32 42, i32* @h, !dbg !12 + br label %done + +done: + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!22, !23} + +!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 2, emissionKind: FullDebug) +!1 = !DIFile(filename: "", directory: "C:\5Csrc\5Cllvm-project\5Cbuild") +!5 = distinct !DISubprogram(name: "f", isLocal: true, isDefinition: true, scopeLine: 37, flags: DIFlagPrototyped, isOptimized: true, unit: !0, type: !99, scope: !1) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DILocalVariable(name: "aRect", arg: 1, scope: !11, file: !1, line: 38, type: !6) +!11 = distinct !DILexicalBlock(scope: !98, file: !1, line: 38) +!12 = !DILocation(line: 43, scope: !11, inlinedAt: !13) +!13 = distinct !DILocation(line: 43, scope: !5) +!22 = !{i32 2, !"Dwarf Version", i32 4} +!23 = !{i32 2, !"Debug Info Version", i32 3} +!62 = !{!10} +!98 = distinct !DISubprogram(name: "NSMaxX", scope: !1, file: !1, line: 27, isLocal: true, isDefinition: true, scopeLine: 27, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !62, type: !99) +!99 = !DISubroutineType(types: !100) +!100 = !{null} diff --git a/test/DebugInfo/X86/dw_op_minus.ll b/test/DebugInfo/X86/dw_op_minus.ll index 8e65b48..30bf583 100644 --- a/test/DebugInfo/X86/dw_op_minus.ll +++ b/test/DebugInfo/X86/dw_op_minus.ll @@ -10,7 +10,7 @@ ; Capture(buf); ; } ; } -; The interesting part is !DIExpression(DW_OP_minus, 400) +; The interesting part is !DIExpression(DW_OP_constu, 400, DW_OP_minus) target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -56,7 +56,7 @@ declare void @Capture(i32*) !14 = !{i32 2, !"Debug Info Version", i32 3} !15 = !{!"clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)"} !16 = !DILocation(line: 5, column: 3, scope: !4) -!17 = !DIExpression(DW_OP_minus, 400) +!17 = !DIExpression(DW_OP_constu, 400, DW_OP_minus) !18 = !DILocation(line: 5, column: 7, scope: !4) !19 = !DILocation(line: 6, column: 11, scope: !4) !20 = !DILocation(line: 6, column: 3, scope: !4) diff --git a/test/DebugInfo/X86/dw_op_minus_direct.ll b/test/DebugInfo/X86/dw_op_minus_direct.ll index 8d346be..69f4b2c 100644 --- a/test/DebugInfo/X86/dw_op_minus_direct.ll +++ b/test/DebugInfo/X86/dw_op_minus_direct.ll @@ -51,7 +51,7 @@ attributes #1 = { nounwind readnone } !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !11 = !{!12} !12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10) -!13 = !DIExpression(DW_OP_minus, 1, DW_OP_stack_value) +!13 = !DIExpression(DW_OP_constu, 1, DW_OP_minus, DW_OP_stack_value) !14 = !DILocation(line: 1, column: 13, scope: !7) !15 = !DILocation(line: 2, column: 11, scope: !7) !16 = !DILocation(line: 2, column: 3, scope: !7) diff --git a/test/DebugInfo/X86/safestack-byval.ll b/test/DebugInfo/X86/safestack-byval.ll index 42e9469..8742c90 100644 --- a/test/DebugInfo/X86/safestack-byval.ll +++ b/test/DebugInfo/X86/safestack-byval.ll @@ -14,7 +14,7 @@ ; } ; CHECK: ![[ZZZ:.*]] = !DILocalVariable(name: "zzz", -; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_minus, 400) +; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus) ; CHECK: DBG_VALUE {{.*}} ![[ZZZ]], ![[ZZZ_EXPR]] %struct.S = type { [100 x i32] } @@ -79,7 +79,7 @@ attributes #2 = { argmemonly nounwind } !20 = !{i32 2, !"Debug Info Version", i32 3} !21 = !{!"clang version 3.8.0 (trunk 254107) (llvm/trunk 254109)"} !22 = !DILocation(line: 8, column: 9, scope: !12) -!23 = !DIExpression(DW_OP_deref, DW_OP_minus, 400) +!23 = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus) !24 = !DILocation(line: 8, column: 28, scope: !12) !25 = !DIExpression() !26 = !DILocation(line: 9, column: 10, scope: !12) diff --git a/test/DebugInfo/X86/stack-value-dwarf2.ll b/test/DebugInfo/X86/stack-value-dwarf2.ll index 61595f7..b653784 100644 --- a/test/DebugInfo/X86/stack-value-dwarf2.ll +++ b/test/DebugInfo/X86/stack-value-dwarf2.ll @@ -93,4 +93,4 @@ attributes #1 = { nounwind readnone } !15 = !DISubprogram(name: "<(lambda at test.ii:87:58)>", scope: !0, file: !1, line: 27, type: !6, isLocal: false, isDefinition: false, scopeLine: 27, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !2) !16 = distinct !DILocation(line: 99, column: 21, scope: !17) !17 = !DILexicalBlockFile(scope: !5, file: !1, discriminator: 2) -!18 = !DIExpression(DW_OP_plus, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32) +!18 = !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32) diff --git a/test/DebugInfo/X86/unattached-global.ll b/test/DebugInfo/X86/unattached-global.ll index 5d4be73..5e9af69 100644 --- a/test/DebugInfo/X86/unattached-global.ll +++ b/test/DebugInfo/X86/unattached-global.ll @@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu" !1 = !{!2} !2 = !DIGlobalVariableExpression(var: !3, expr: !4) !3 = distinct !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true, type: !6) -!4 = !DIExpression(DW_OP_plus, 4) +!4 = !DIExpression(DW_OP_plus_uconst, 4) !5 = !DIFile(filename: "", directory: "/") !6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) diff --git a/test/DebugInfo/dwarfdump-str-offsets-dwp.test b/test/DebugInfo/dwarfdump-str-offsets-dwp.test new file mode 100644 index 0000000..ceca322 --- /dev/null +++ b/test/DebugInfo/dwarfdump-str-offsets-dwp.test @@ -0,0 +1,56 @@ +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-dwp.x86_64.o | FileCheck %s + +; Verify that the correct strings from each unit are displayed and that the +; index for the .debug_str_offsets section has the right values. + +; CHECK: Compile Unit +; CHECK-NOT: NULL +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_1") +; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU1") +; CHECK-NOT: NULL + +; CHECK: Compile Unit +; CHECK-NOT: NULL +; CHECK: DW_TAG_compile_unit +; CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2") +; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2") +; +; CHECK: Type Unit +; CHECK-NOT: NULL +; CHECK: DW_TAG_type_unit +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_1") +; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c) +; CHECK-NOT: NULL +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_1") +; +; CHECK: Type Unit +; CHECK-NOT: NULL +; CHECK: DW_TAG_type_unit +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_2") +; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c) +; CHECK-NOT: NULL +; CHECK: DW_TAG_structure_type +; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_2") + +; Verify the correct offets of the compile and type units contributions in the +; index tables. + +; CHECK: .debug_cu_index contents: +; CHECK-NOT: contents: +; CHECK: 1 0xddeeaaddbbaabbee [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) +; CHECK-SAME: [0x00000000 +; CHECK-NEXT: 2 0xff00ffeeffaaff00 [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) +; CHECK-SAME: [0x00000024 + +; CHECK: .debug_tu_index contents: +; CHECK-NOT: contents: +; CHECK: 1 0xeeaaddbbaabbeedd [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) +; CHECK-SAME: [0x00000000 +; CHECK-NEXT: 2 0x00ffeeffaaff00ff [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) +; CHECK: [0x00000024 diff --git a/test/DebugInfo/dwarfdump-zlib.test b/test/DebugInfo/dwarfdump-zlib.test index d3ef806..82f29af 100644 --- a/test/DebugInfo/dwarfdump-zlib.test +++ b/test/DebugInfo/dwarfdump-zlib.test @@ -1,6 +1,7 @@ REQUIRES: zlib RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.elf-x86-64 | FileCheck %s +RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.o.elf-x86-64 | FileCheck %s RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 | FileCheck %s CHECK: .debug_abbrev contents @@ -10,3 +11,7 @@ CHECK: .debug_abbrev contents // that sections names are properly shown in zlib-gnu style (without additional 'z' prefix). CHECK: .debug_info contents CHECK: 0x00000000: Compile Unit: length = 0x00000144 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000148) + +// Also check that relocations in the .zdebug sections are handled correctly: +CHECK: DW_AT_ranges {{.*}} (0x00000000{{$}} +CHECK-NEXT: [0x diff --git a/test/Instrumentation/InstrProfiling/always_inline.ll b/test/Instrumentation/InstrProfiling/always_inline.ll new file mode 100644 index 0000000..4be7848 --- /dev/null +++ b/test/Instrumentation/InstrProfiling/always_inline.ll @@ -0,0 +1,28 @@ +; Check that '__attribute__((always_inline)) inline' functions are inlined. + +; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -inline -S | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.13.0" + +@__profn_foo = linkonce_odr hidden constant [3 x i8] c"foo" + +; CHECK-LABEL: @main +; CHECK-NOT: call +define i32 @main() { +entry: + %call = call i32 @foo() + ret i32 %call +} + +declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #0 + +; CHECK-NOT: define available_externally i32 @foo +define available_externally i32 @foo() #1 { +entry: + call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0) + ret i32 0 +} + +attributes #0 = { nounwind } +attributes #1 = { alwaysinline } diff --git a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll index 4df6ffe..5b5b751 100644 --- a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll +++ b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll @@ -10,4 +10,4 @@ entry: ; CHECK: store i8 %1, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @__sancov_gen_, i64 0, i64 0), !nosanitize ret void } -; CHECK: call void @__sanitizer_cov_8bit_counters_init(i8* bitcast (i8** @__start___sancov_counters to i8*), i8* bitcast (i8** @__stop___sancov_counters to i8*)) +; CHECK: call void @__sanitizer_cov_8bit_counters_init(i8* bitcast (i8** @__start___sancov_cntrs to i8*), i8* bitcast (i8** @__stop___sancov_cntrs to i8*)) diff --git a/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll b/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll new file mode 100644 index 0000000..6675488 --- /dev/null +++ b/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll @@ -0,0 +1,16 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @live1() { + call void @live2() + ret void +} + +declare void @live2() + +define void @dead1() { + call void @dead2() + ret void +} + +declare void @dead2() diff --git a/test/LTO/Resolution/X86/dead-strip-fulllto.ll b/test/LTO/Resolution/X86/dead-strip-fulllto.ll new file mode 100644 index 0000000..a9be275 --- /dev/null +++ b/test/LTO/Resolution/X86/dead-strip-fulllto.ll @@ -0,0 +1,37 @@ +; RUN: opt -module-summary -o %t %s +; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll +; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \ +; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, \ +; RUN: -save-temps -o %t3 +; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s +; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s + +; FULL-NOT: dead +; FULL: U live1 +; FULL: T live2 +; FULL: T main + +; THIN-NOT: dead +; THIN: T live1 +; THIN: U live2 + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @main() { + call void @live1() + ret void +} + +declare void @live1() + +define void @live2() { + ret void +} + +define void @dead2() { + ret void +} + +!0 = !{i32 1, !"ThinLTO", i32 0} +!llvm.module.flags = !{ !0 } diff --git a/test/LTO/Resolution/X86/symtab-elf.ll b/test/LTO/Resolution/X86/symtab-elf.ll index 1683b06..d5f0fbe 100644 --- a/test/LTO/Resolution/X86/symtab-elf.ll +++ b/test/LTO/Resolution/X86/symtab-elf.ll @@ -6,8 +6,8 @@ target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; CHECK-NOT: linker opts: -!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}} -!llvm.module.flags = !{ !0 } +!0 = !{!"/include:foo"} +!llvm.linker.options = !{ !0 } @g1 = global i32 0 diff --git a/test/LTO/Resolution/X86/symtab.ll b/test/LTO/Resolution/X86/symtab.ll index b7bc117..fecea0a 100644 --- a/test/LTO/Resolution/X86/symtab.ll +++ b/test/LTO/Resolution/X86/symtab.ll @@ -9,8 +9,8 @@ target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" source_filename = "src.c" ; CHECK: linker opts: /include:foo -!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}} -!llvm.module.flags = !{ !0 } +!0 = !{!"/include:foo"} +!llvm.linker.options = !{ !0 } ; CHECK: D------X _fun define i32 @fun() { diff --git a/test/LibDriver/use-paths.test b/test/LibDriver/use-paths.test new file mode 100644 index 0000000..971c216 --- /dev/null +++ b/test/LibDriver/use-paths.test @@ -0,0 +1,24 @@ +llvm-lib should behave like "link.exe /lib" and use relative paths to describe +archive members. + +First, get in a clean working directory. +RUN: rm -rf %t && mkdir -p %t && cd %t + +Make foo/a.obj and foo/b.obj. +RUN: mkdir foo +RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/a.obj %S/Inputs/a.s +RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/b.obj %S/Inputs/b.s + +RUN: llvm-lib -out:foo.lib foo/a.obj foo/b.obj +RUN: llvm-ar t foo.lib | FileCheck %s + +FIXME: We should probably use backslashes on Windows to better match MSVC tools. +CHECK: foo/a.obj +CHECK: foo/b.obj + +Do it again with absolute paths and see that we get something. +RUN: llvm-lib -out:foo.lib %t/foo/a.obj %t/foo/b.obj +RUN: llvm-ar t foo.lib | FileCheck %s --check-prefix=ABS + +ABS: {{.*}}/foo/a.obj +ABS: {{.*}}/foo/b.obj diff --git a/test/MC/AMDGPU/flat-gfx9.s b/test/MC/AMDGPU/flat-gfx9.s new file mode 100644 index 0000000..5f93a73 --- /dev/null +++ b/test/MC/AMDGPU/flat-gfx9.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx900 -show-encoding %s | FileCheck -check-prefix=GFX9 -check-prefix=GCN %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s | FileCheck -check-prefix=VI -check-prefix=GCN %s + +// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx900 -show-encoding 2>&1 %s | FileCheck -check-prefix=GFX9-ERR -check-prefix=GCNERR %s +// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding 2>&1 %s | FileCheck -check-prefix=VI-ERR -check-prefix=GCNERR %s + + +flat_load_dword v1, v[3:4] offset:0 +// GCN: flat_load_dword v1, v[3:4] ; encoding: [0x00,0x00,0x50,0xdc,0x03,0x00,0x00,0x01] + +flat_load_dword v1, v[3:4] offset:-1 +// GCN-ERR: :35: error: failed parsing operand. + +// FIXME: Error on VI in wrong column +flat_load_dword v1, v[3:4] offset:4095 +// GFX9: flat_load_dword v1, v[3:4] offset:4095 ; encoding: [0xff,0x0f,0x50,0xdc,0x03,0x00,0x00,0x01] +// VIERR: :1: error: invalid operand for instruction + +flat_load_dword v1, v[3:4] offset:4096 +// GCNERR: :28: error: invalid operand for instruction + +flat_load_dword v1, v[3:4] offset:4 glc +// GFX9: flat_load_dword v1, v[3:4] offset:4 glc ; encoding: [0x04,0x00,0x51,0xdc,0x03,0x00,0x00,0x01] +// VIERR: :1: error: invalid operand for instruction + +flat_load_dword v1, v[3:4] offset:4 glc slc +// GFX9: flat_load_dword v1, v[3:4] offset:4 glc slc ; encoding: [0x04,0x00,0x53,0xdc,0x03,0x00,0x00,0x01] +// VIERR: :1: error: invalid operand for instruction + +flat_atomic_add v[3:4], v5 offset:8 slc +// GFX9: flat_atomic_add v[3:4], v5 offset:8 slc ; encoding: [0x08,0x00,0x0a,0xdd,0x03,0x05,0x00,0x00] +// VIERR: :1: error: invalid operand for instruction + +flat_atomic_swap v[3:4], v5 offset:16 +// GFX9: flat_atomic_swap v[3:4], v5 offset:16 ; encoding: [0x10,0x00,0x00,0xdd,0x03,0x05,0x00,0x00] +// VIERR: :1: error: invalid operand for instruction + +flat_store_dword v[3:4], v1 offset:16 +// GFX9: flat_store_dword v[3:4], v1 offset:16 ; encoding: [0x10,0x00,0x70,0xdc,0x03,0x01,0x00,0x00] +// VIERR: :1: error: invalid operand for instruction diff --git a/test/MC/AMDGPU/flat.s b/test/MC/AMDGPU/flat.s index 4e81799..d8cad13 100644 --- a/test/MC/AMDGPU/flat.s +++ b/test/MC/AMDGPU/flat.s @@ -49,9 +49,10 @@ flat_store_dword v[3:4], v1 slc // FIXME: For atomic instructions, glc must be placed immediately following // the data regiser. These forms aren't currently supported: +// FIXME: offset:0 required // flat_atomic_add v1, v[3:4], v5 slc glc -flat_atomic_add v1 v[3:4], v5 glc slc +flat_atomic_add v1, v[3:4], v5 offset:0 glc slc // NOSI: error: // CI: flat_atomic_add v1, v[3:4], v5 glc slc ; encoding: [0x00,0x00,0xcb,0xdc,0x03,0x05,0x00,0x01] // VI: flat_atomic_add v1, v[3:4], v5 glc slc ; encoding: [0x00,0x00,0x0b,0xdd,0x03,0x05,0x00,0x01] diff --git a/test/MC/COFF/cv-compiler-info.ll b/test/MC/COFF/cv-compiler-info.ll index 6c33a25..f7cd173 100644 --- a/test/MC/COFF/cv-compiler-info.ll +++ b/test/MC/COFF/cv-compiler-info.ll @@ -13,7 +13,7 @@ entry: attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !7, !8} +!llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) @@ -35,10 +35,6 @@ attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="fa ; CHECK-NOT: .short 4412 # Record kind: S_COMPILE3 !1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang") !2 = !{} -!3 = !{i32 6, !"Linker Options", !4} -!4 = !{!5, !6} -!5 = !{!"/DEFAULTLIB:libcmtd.lib"} -!6 = !{!"/DEFAULTLIB:oldnames.lib"} !7 = !{i32 2, !"CodeView", i32 1} !8 = !{i32 2, !"Debug Info Version", i32 3} !9 = !{!"clang version 4.0.0 "} diff --git a/test/MC/COFF/linker-options.ll b/test/MC/COFF/linker-options.ll index afc55af..24ac84d 100755 --- a/test/MC/COFF/linker-options.ll +++ b/test/MC/COFF/linker-options.ll @@ -1,8 +1,10 @@ ; RUN: llc -O0 -mtriple=i386-pc-win32 -filetype=asm -o - %s | FileCheck %s -!0 = !{i32 6, !"Linker Options", !{!{!"/DEFAULTLIB:msvcrt.lib"}, !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"}, !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"}, !{!"\22/with spaces\22"}}} - -!llvm.module.flags = !{ !0 } +!0 = !{!"/DEFAULTLIB:msvcrt.lib"} +!1 = !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"} +!2 = !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"} +!3 = !{!"\22/with spaces\22"} +!llvm.linker.options = !{!0, !1, !2, !3} define dllexport void @foo() { ret void diff --git a/test/MC/Disassembler/PowerPC/ppc64-encoding.txt b/test/MC/Disassembler/PowerPC/ppc64-encoding.txt index a6d0792..25ed35f 100644 --- a/test/MC/Disassembler/PowerPC/ppc64-encoding.txt +++ b/test/MC/Disassembler/PowerPC/ppc64-encoding.txt @@ -352,6 +352,18 @@ # CHECK: divweu. 2, 3, 4 0x7c 0x43 0x23 0x17 +# CHECK: modsw 2, 3, 4 +0x7c 0x43 0x26 0x16 + +# CHECK: moduw 2, 3, 4 +0x7c 0x43 0x22 0x16 + +# CHECK: modsd 2, 3, 4 +0x7c 0x43 0x26 0x12 + +# CHECK: modud 2, 3, 4 +0x7c 0x43 0x22 0x12 + # CHECK: mulld 2, 3, 4 0x7c 0x43 0x21 0xd2 diff --git a/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt b/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt index 9ddc286..9dc9940 100644 --- a/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt +++ b/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt @@ -349,6 +349,18 @@ # CHECK: divweu. 2, 3, 4 0x17 0x23 0x43 0x7c +# CHECK: modsw 2, 3, 4 +0x16 0x26 0x43 0x7c + +# CHECK: moduw 2, 3, 4 +0x16 0x22 0x43 0x7c + +# CHECK: modsd 2, 3, 4 +0x12 0x26 0x43 0x7c + +# CHECK: modud 2, 3, 4 +0x12 0x22 0x43 0x7c + # CHECK: mulld 2, 3, 4 0xd2 0x21 0x43 0x7c diff --git a/test/MC/ELF/section.s b/test/MC/ELF/section.s index 03a0f22..c3f7d42 100644 --- a/test/MC/ELF/section.s +++ b/test/MC/ELF/section.s @@ -267,3 +267,15 @@ bar: // CHECK-NEXT: SHF_TLS // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] + +// Test SHT_LLVM_ODRTAB + +.section .odrtab,"e",@llvm_odrtab +// ASM: .section .odrtab,"e",@llvm_odrtab + +// CHECK: Section { +// CHECK: Name: .odrtab +// CHECK-NEXT: Type: SHT_LLVM_ODRTAB +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_EXCLUDE +// CHECK-NEXT: ] diff --git a/test/MC/MachO/linker-options.ll b/test/MC/MachO/linker-options.ll index 09ebd0f..d9d7a4a 100644 --- a/test/MC/MachO/linker-options.ll +++ b/test/MC/MachO/linker-options.ll @@ -27,6 +27,7 @@ ; CHECK-OBJ: ] ; CHECK-OBJ: } -!0 = !{i32 6, !"Linker Options", !{!{!"-lz"}, !{!"-framework", !"Cocoa"}, !{!"-lmath"}}} - -!llvm.module.flags = !{ !0 } +!0 = !{!"-lz"} +!1 = !{!"-framework", !"Cocoa"} +!2 = !{!"-lmath"} +!llvm.linker.options = !{!0, !1, !2} diff --git a/test/MC/PowerPC/ppc64-encoding.s b/test/MC/PowerPC/ppc64-encoding.s index a772ca4..237dd5c 100644 --- a/test/MC/PowerPC/ppc64-encoding.s +++ b/test/MC/PowerPC/ppc64-encoding.s @@ -493,6 +493,19 @@ # FIXME: divweuo 2, 3, 4 # FIXME: divweuo. 2, 3, 4 +# CHECK-BE: modsw 2, 3, 4 # encoding: [0x7c,0x43,0x26,0x16] +# CHECK-LE: modsw 2, 3, 4 # encoding: [0x16,0x26,0x43,0x7c] + modsw 2, 3, 4 +# CHECK-BE: moduw 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x16] +# CHECK-LE: moduw 2, 3, 4 # encoding: [0x16,0x22,0x43,0x7c] + moduw 2, 3, 4 +# CHECK-BE: modsd 2, 3, 4 # encoding: [0x7c,0x43,0x26,0x12] +# CHECK-LE: modsd 2, 3, 4 # encoding: [0x12,0x26,0x43,0x7c] + modsd 2, 3, 4 +# CHECK-BE: modud 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x12] +# CHECK-LE: modud 2, 3, 4 # encoding: [0x12,0x22,0x43,0x7c] + modud 2, 3, 4 + # CHECK-BE: mulld 2, 3, 4 # encoding: [0x7c,0x43,0x21,0xd2] # CHECK-LE: mulld 2, 3, 4 # encoding: [0xd2,0x21,0x43,0x7c] mulld 2, 3, 4 diff --git a/test/MC/WebAssembly/external-data.ll b/test/MC/WebAssembly/external-data.ll index 91e05b3..6914736 100644 --- a/test/MC/WebAssembly/external-data.ll +++ b/test/MC/WebAssembly/external-data.ll @@ -2,10 +2,10 @@ ; Verify relocations are correctly generated for addresses of externals ; in the data section. -declare i32 @f1(...) +@myimport = external global i32, align 4 @foo = global i64 7, align 4 -@far = local_unnamed_addr global i32 (...)* @f1, align 4 +@bar = hidden global i32* @myimport, align 4 ; CHECK: - Type: DATA ; CHECK: Relocations: diff --git a/test/MC/WebAssembly/external-func-address.ll b/test/MC/WebAssembly/external-func-address.ll new file mode 100644 index 0000000..4022b2c --- /dev/null +++ b/test/MC/WebAssembly/external-func-address.ll @@ -0,0 +1,25 @@ +; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s +; Verify that addresses of external functions generate correctly typed +; imports and relocations or type R_TABLE_INDEX_I32. + +declare void @f1() #1 +@ptr_to_f1 = hidden global void ()* @f1, align 4 + + +; CHECK: - Type: IMPORT +; CHECK: Imports: +; CHECK: - Module: env +; CHECK: Field: f1 +; CHECK: Kind: FUNCTION +; CHECK: SigIndex: 0 +; CHECK: - Type: ELEM +; CHECK: Segments: +; CHECK: - Offset: +; CHECK: Opcode: I32_CONST +; CHECK: Value: 0 +; CHECK: Functions: [ 0 ] +; CHECK: - Type: DATA +; CHECK: Relocations: +; CHECK: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 +; CHECK: Index: 0 +; CHECK: Offset: 0x00000006 diff --git a/test/MC/WebAssembly/func-address.ll b/test/MC/WebAssembly/func-address.ll new file mode 100644 index 0000000..c0a9d9a --- /dev/null +++ b/test/MC/WebAssembly/func-address.ll @@ -0,0 +1,48 @@ +; RUN: llc -mtriple wasm32-unknown-unknown-wasm -O2 -filetype=obj %s -o - | llvm-readobj -r -s -expand-relocs | FileCheck %s + +declare i32 @import1() +declare i32 @import2() +declare i32 @import3() + +; call the imports to make sure they are included in the imports section +define hidden void @call_imports() #0 { +entry: + %call = call i32 @import1() + %call1 = call i32 @import2() + ret void +} + +; take the address of the third import. This should generate a TABLE_INDEX +; relocation with index of 0 since its the first and only address taken +; function. +define hidden void @call_indirect() #0 { +entry: + %adr = alloca i32 ()*, align 4 + store i32 ()* @import3, i32 ()** %adr, align 4 + ret void +} + +; CHECK: Section { +; CHECK: Type: ELEM (0x9) +; CHECK: Size: 7 +; CHECK: Offset: 165 +; CHECK: } + +; CHECK: Relocations [ +; CHECK: Section (9) CODE { +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0x4 +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0xB +; CHECK: Index: 0x1 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1) +; CHECK: Offset: 0x1A +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: } diff --git a/test/ThinLTO/X86/cfi-icall.ll b/test/ThinLTO/X86/cfi-icall.ll new file mode 100644 index 0000000..ef5d33c --- /dev/null +++ b/test/ThinLTO/X86/cfi-icall.ll @@ -0,0 +1,29 @@ +; RUN: opt -thinlto-bc %s -o %t1.bc +; RUN: llvm-lto2 run -thinlto-distributed-indexes %t1.bc -o %t.out -save-temps \ +; RUN: -r %t1.bc,foo,plx \ +; RUN: -r %t1.bc,bar,x +; RUN: llvm-bcanalyzer -dump %t.out.index.bc | FileCheck %s --check-prefix=COMBINED + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i1 @foo(i8* %p) !type !0 { +entry: + %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1") + ret i1 %x +} + +declare !type !0 void @bar() + +declare i1 @llvm.type.test(i8* %ptr, metadata %type) nounwind readnone + +!0 = !{i64 0, !"typeid1"} + +; COMBINED: +; COMBINED: +; COMBINED: + +; COMBINED: blob data = 'foobar' +; COMBINED-NEXT: diff --git a/test/Transforms/CodeExtractor/live_shrink.ll b/test/Transforms/CodeExtractor/live_shrink.ll new file mode 100644 index 0000000..c25ed2b --- /dev/null +++ b/test/Transforms/CodeExtractor/live_shrink.ll @@ -0,0 +1,67 @@ +; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s +; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s + +%class.A = type { i32 } +@cond = local_unnamed_addr global i32 0, align 4 + +; Function Attrs: uwtable +define void @_Z3foov() local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 4 + %tmp1 = bitcast %class.A* %tmp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) + %tmp2 = load i32, i32* @cond, align 4, !tbaa !2 + %tmp3 = icmp eq i32 %tmp2, 0 + br i1 %tmp3, label %bb4, label %bb5 + +bb4: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb5 + +bb5: ; preds = %bb4, %bb + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) + +; Function Attrs: uwtable +define void @_Z3goov() local_unnamed_addr { +; CHECK-LABEL: @_Z3goov() +bb: +; CHECK: bb: +; CHECK-NOT: alloca +; CHECK-NOT: bitcast +; CHECK-NOT: llvm.lifetime +; CHECK: br i1 +; CHECK: codeRepl.i: +; CHECK: call void @_Z3foov.1_ + + tail call void @_Z3foov() + ret void +} + +; CHECK-LABEL: define internal void @_Z3foov.1_ +; CHECK: newFuncRoot: +; CHECK-NEXT: %tmp = alloca %class.A +; CHECK-NEXT: %tmp1 = bitcast %class.A* %tmp to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) +; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) +; CHECK-NEXT: br label %bb5.exitStub + + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 5.0.0 (trunk 304489)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C++ TBAA"} diff --git a/test/Transforms/CodeExtractor/live_shrink_gep.ll b/test/Transforms/CodeExtractor/live_shrink_gep.ll new file mode 100644 index 0000000..ac6aa4f --- /dev/null +++ b/test/Transforms/CodeExtractor/live_shrink_gep.ll @@ -0,0 +1,66 @@ +; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s +; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s + +%class.A = type { i8 } + +@cond = local_unnamed_addr global i32 0, align 4 + +; Function Attrs: uwtable +define void @_Z3foov() local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 1 + %tmp1 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0 + call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %tmp1) + %tmp2 = load i32, i32* @cond, align 4, !tbaa !2 + %tmp3 = icmp eq i32 %tmp2, 0 + br i1 %tmp3, label %bb4, label %bb5 + +bb4: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb5 + +bb5: ; preds = %bb4, %bb + call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %tmp1) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) + +; Function Attrs: uwtable +define void @_Z3goov() local_unnamed_addr { +; CHECK-LABEL: @_Z3goov() +bb: +; CHECK: bb: +; CHECK-NOT: alloca +; CHECK-NOT: getelementptr +; CHECK-NOT: llvm.lifetime +; CHECK: br i1 +; CHECK: codeRepl.i: +; CHECK: call void @_Z3foov.1_ + tail call void @_Z3foov() + ret void +} + +; CHECK-LABEL: define internal void @_Z3foov.1_ +; CHECK: newFuncRoot: +; CHECK-NEXT: %tmp = alloca %class.A +; CHECK-NEXT: %tmp1 = getelementptr +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8 +; CHECK: call void @llvm.lifetime.end.p0i8 +; CHECK-NEXT: br label %bb5.exitStub + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 5.0.0 (trunk 304489)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C++ TBAA"} diff --git a/test/Transforms/CodeExtractor/live_shrink_hoist.ll b/test/Transforms/CodeExtractor/live_shrink_hoist.ll new file mode 100644 index 0000000..d1b310f --- /dev/null +++ b/test/Transforms/CodeExtractor/live_shrink_hoist.ll @@ -0,0 +1,66 @@ +; RUN: opt -S -partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s +; RUN: opt -S -passes=partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s + +%class.A = type { i32 } + +@cond = local_unnamed_addr global i32 0, align 4 + +; Function Attrs: uwtable +define void @_Z3foov() local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 4 + %tmp1 = bitcast %class.A* %tmp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) + %tmp2 = load i32, i32* @cond, align 4, !tbaa !2 + %tmp3 = icmp eq i32 %tmp2, 0 + br i1 %tmp3, label %bb4, label %bb9 + +bb4: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + %tmp5 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0 + %tmp6 = load i32, i32* %tmp5, align 4, !tbaa !6 + %tmp7 = icmp sgt i32 %tmp6, 0 + br i1 %tmp7, label %bb9, label %bb8 + +bb8: ; preds = %bb4 + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb9 + +bb9: ; preds = %bb8, %bb4, %bb + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) + +; Function Attrs: uwtable +define void @_Z3goov() local_unnamed_addr { +bb: + tail call void @_Z3foov() + ret void +} + +; CHECK-LABEL: define internal void @_Z3foov.1_ +; CHECK: bb9: +; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) +; CHECK: br label %.exitStub + + + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 5.0.0 (trunk 304489)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C++ TBAA"} +!6 = !{!7, !3, i64 0} +!7 = !{!"_ZTS1A", !3, i64 0} diff --git a/test/Transforms/CodeExtractor/live_shrink_multiple.ll b/test/Transforms/CodeExtractor/live_shrink_multiple.ll new file mode 100644 index 0000000..8d9045c --- /dev/null +++ b/test/Transforms/CodeExtractor/live_shrink_multiple.ll @@ -0,0 +1,66 @@ +; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s +; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s + +%class.A = type { i32 } +@cond = local_unnamed_addr global i32 0, align 4 + +; Function Attrs: uwtable +define void @_Z3foov() local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 4 + %tmp1 = alloca %class.A, align 4 + %tmp2 = bitcast %class.A* %tmp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2) + %tmp3 = bitcast %class.A* %tmp1 to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3) + %tmp4 = load i32, i32* @cond, align 4, !tbaa !2 + %tmp5 = icmp eq i32 %tmp4, 0 + br i1 %tmp5, label %bb6, label %bb7 + +bb6: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb7 + +bb7: ; preds = %bb6, %bb + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2) + ret void +} + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) + +; Function Attrs: uwtable +define void @_Z3goov() local_unnamed_addr { +bb: + tail call void @_Z3foov() + ret void +} + +; CHECK-LABEL: define internal void @_Z3foov.1_ +; CHECK: newFuncRoot: +; CHECK-NEXT: alloca +; CHECK-NEXT: bitcast +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8 +; CHECK-NEXT: alloca +; CHECK-NEXT: bitcast +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8 +; CHECK: call void @llvm.lifetime.end.p0i8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8 +; CHECK-NEXT: br label {{.*}}exitStub + + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 5.0.0 (trunk 304489)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"int", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C++ TBAA"} diff --git a/test/Transforms/CodeExtractor/live_shrink_unsafe.ll b/test/Transforms/CodeExtractor/live_shrink_unsafe.ll new file mode 100644 index 0000000..ea6458c --- /dev/null +++ b/test/Transforms/CodeExtractor/live_shrink_unsafe.ll @@ -0,0 +1,94 @@ +; The expected behavior of this file is expected to change when partial +; inlining legality check is enhanced. + +; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s +; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s + +%class.A = type { i32 } + +@cond = local_unnamed_addr global i32 0, align 4 +@condptr = external local_unnamed_addr global i32*, align 8 + +; Function Attrs: uwtable +define void @_Z3foo_unknown_mem_accessv() local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 4 + %tmp1 = alloca %class.A, align 4 + %tmp2 = bitcast %class.A* %tmp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2) + %tmp3 = bitcast %class.A* %tmp1 to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3) + %tmp4 = load i32*, i32** @condptr, align 8, !tbaa !2 + %tmp5 = load i32, i32* %tmp4, align 4, !tbaa !6 + %tmp6 = icmp eq i32 %tmp5, 0 + br i1 %tmp6, label %bb7, label %bb8 + +bb7: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb8 + +bb8: ; preds = %bb7, %bb + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2) + ret void +} + +declare void @_Z3barv() local_unnamed_addr +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) +declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr +declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) + +define void @_Z3foo_unknown_calli(i32 %arg) local_unnamed_addr { +bb: + %tmp = alloca %class.A, align 4 + %tmp1 = bitcast %class.A* %tmp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1) + tail call void @_Z3barv() + %tmp2 = icmp eq i32 %arg, 0 + br i1 %tmp2, label %bb3, label %bb4 + +bb3: ; preds = %bb + call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp) + br label %bb4 + +bb4: ; preds = %bb3, %bb + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1) + ret void +} + +define void @_Z3goov() local_unnamed_addr { +; CHECK-LABEL: @_Z3goov +; CHECK-NEXT: bb: +; CHECK: alloca +; CHECK: lifetime +bb: + call void @_Z3foo_unknown_mem_accessv() + %tmp = load i32, i32* @cond, align 4, !tbaa !2 + tail call void @_Z3foo_unknown_calli(i32 %tmp) + ret void +} + +; CHECK-LABEL define internal void @_Z3foo_unknown_calli.1_bb3 +; CHECK: newFuncRoot: +; CHECK-NEXT: br label %bb3 + +; CHECK: bb4.exitStub: +; CHECK-NEXT: ret void + +; CHECK: bb3: +; CHECK-NOT: lifetime.ed +; CHECK: br label %bb4.exitStub + + + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 5.0.0 (trunk 304489)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"any pointer", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C++ TBAA"} +!6 = !{!7, !7, i64 0} +!7 = !{!"int", !4, i64 0} diff --git a/test/Transforms/CrossDSOCFI/cfi_functions.ll b/test/Transforms/CrossDSOCFI/cfi_functions.ll new file mode 100644 index 0000000..ccbde51 --- /dev/null +++ b/test/Transforms/CrossDSOCFI/cfi_functions.ll @@ -0,0 +1,23 @@ +; Test that types referenced in ThinLTO-style !cfi.functions are known to __cfi_check. +; RUN: opt -S -cross-dso-cfi < %s | FileCheck %s +; RUN: opt -S -passes=cross-dso-cfi < %s | FileCheck %s + +; CHECK: define void @__cfi_check( +; CHECK: switch i64 +; CHECK-NEXT: i64 1234, label +; CHECK-NEXT: i64 5678, label +; CHECK-NEXT: ] + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +!cfi.functions = !{!0, !1} +!llvm.module.flags = !{!6} + +!0 = !{!"f", i8 0, !2, !4} +!1 = !{!"g", i8 1, !3, !5} +!2 = !{i64 0, !"typeid1"} +!3 = !{i64 0, !"typeid2"} +!4 = !{i64 0, i64 1234} +!5 = !{i64 0, i64 5678} +!6 = !{i32 4, !"Cross-DSO CFI", i32 1} diff --git a/test/Transforms/EarlyCSE/pr33406.ll b/test/Transforms/EarlyCSE/pr33406.ll new file mode 100644 index 0000000..4d3312e --- /dev/null +++ b/test/Transforms/EarlyCSE/pr33406.ll @@ -0,0 +1,26 @@ +; RUN: opt -early-cse-memssa -S %s | FileCheck %s + +; CHECK: define void @patatino() { +; CHECK: for.cond: +; CHECK-NEXT: br i1 true, label %if.end, label %for.inc +; CHECK: if.end: +; CHECK-NEXT: %tinkywinky = load i32, i32* @b +; CHECK-NEXT: br i1 true, label %for.inc, label %for.inc +; CHECK: for.inc: +; CHECK-NEXT: ret void + + +@b = external global i32 + +define void @patatino() { +for.cond: + br i1 true, label %if.end, label %for.inc + +if.end: + %tinkywinky = load i32, i32* @b + store i32 %tinkywinky, i32* @b + br i1 true, label %for.inc, label %for.inc + +for.inc: + ret void +} diff --git a/test/Transforms/GVN/pr32314.ll b/test/Transforms/GVN/pr32314.ll new file mode 100644 index 0000000..90d14f6 --- /dev/null +++ b/test/Transforms/GVN/pr32314.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -gvn < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; The load in the loop can not bypass the data from the previous loop. The store above it in the loop aliases. +define void @foo() { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca [3 x i32], align 4 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[P_017:%.*]] = phi i32* [ undef, [[ENTRY]] ], [ [[ARRAYIDX3:%.*]], [[FOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[INDVARS_IV]], -1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[TMP0]] +; CHECK-NEXT: store i32 50, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[P_017]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP1]] to i32 +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[TMP2]], [[TMP3]] +; CHECK-NEXT: [[ARRAYIDX3]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[INDVARS_IV]] +; CHECK-NEXT: store i32 60, i32* [[ARRAYIDX3]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 3 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +entry: + %a = alloca [3 x i32], align 4 + br label %for.body + +for.cond.cleanup: ; preds = %for.body + ret void + +for.body: ; preds = %for.body, %entry + %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.body ] + %p.017 = phi i32* [ undef, %entry ], [ %arrayidx3, %for.body ] + %0 = add nsw i64 %indvars.iv, -1 + %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %0 + store i32 50, i32* %arrayidx, align 4 + %1 = shl i64 %indvars.iv, 1 + %2 = load i32, i32* %p.017, align 4 + %3 = trunc i64 %1 to i32 + %add1 = add nsw i32 %2, %3 + %arrayidx3 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %indvars.iv + store i32 60, i32* %arrayidx3, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, 3 + br i1 %exitcond, label %for.body, label %for.cond.cleanup +} diff --git a/test/Transforms/GlobalMerge/debug-info.ll b/test/Transforms/GlobalMerge/debug-info.ll index 97e0bb2..8d60f36 100644 --- a/test/Transforms/GlobalMerge/debug-info.ll +++ b/test/Transforms/GlobalMerge/debug-info.ll @@ -17,7 +17,7 @@ define void @use1() { ; CHECK: [[AVAR]] = !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true) ; CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BVAR:![0-9]+]], expr: [[EXPR:![0-9]+]]) ; CHECK: [[BVAR]] = !DIGlobalVariable(name: "b", scope: null, isLocal: false, isDefinition: true) -; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus, 4) +; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus_uconst, 4) !llvm.module.flags = !{!4, !5} diff --git a/test/Transforms/Inline/always-inline.ll b/test/Transforms/Inline/always-inline.ll index 5366b5a..791eb94 100644 --- a/test/Transforms/Inline/always-inline.ll +++ b/test/Transforms/Inline/always-inline.ll @@ -305,3 +305,14 @@ entry: ret void ; CHECK: ret void } + +define void @inner14() readnone nounwind { +; CHECK: define void @inner14 + ret void +} + +define void @outer14() { +; CHECK: call void @inner14 + call void @inner14() + ret void +} diff --git a/test/Transforms/InstCombine/debuginfo-dce.ll b/test/Transforms/InstCombine/debuginfo-dce.ll index 086743e..50b8f1c 100644 --- a/test/Transforms/InstCombine/debuginfo-dce.ll +++ b/test/Transforms/InstCombine/debuginfo-dce.ll @@ -93,12 +93,12 @@ entry: ret void, !dbg !32 } -; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus, 0) -; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus, 0) -; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_plus, 0, DW_OP_stack_value) -; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value, +; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 0) +; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus_uconst, 0) +; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 0, DW_OP_stack_value) +; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value, ; CHECK-SAME: DW_OP_LLVM_fragment, 0, 32) -; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value) +; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value) ; Function Attrs: nounwind readnone declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 @@ -130,7 +130,7 @@ attributes #1 = { nounwind readnone } !17 = !{!18} !18 = !DILocalVariable(name: "entry", scope: !14, file: !1, line: 6, type: !4) !19 = !DILocation(line: 6, column: 17, scope: !14) -!20 = !DIExpression(DW_OP_plus, 0) +!20 = !DIExpression(DW_OP_plus_uconst, 0) !21 = !DILocation(line: 11, column: 1, scope: !14) !22 = distinct !DISubprogram(name: "scan", scope: !1, file: !1, line: 4, type: !15, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !17) !23 = !DILocation(line: 6, column: 17, scope: !22) diff --git a/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll b/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll index 107440f..230ac17 100644 --- a/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll +++ b/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll @@ -1,10 +1,11 @@ ; RUN: opt -instcombine -unfold-element-atomic-memcpy-max-elements=8 -S < %s | FileCheck %s +; Temporarily an expected failure until inst combine is updated in the next patch target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -; Test basic unfolding -define void @test1(i8* %Src, i8* %Dst) { -; CHECK-LABEL: test1 -; CHECK-NOT: llvm.memcpy.element.atomic +; Test basic unfolding -- unordered load & store +define void @test1a(i8* %Src, i8* %Dst) { +; CHECK-LABEL: test1a +; CHECK-NOT: llvm.memcpy.element.unordered.atomic ; CHECK-DAG: %memcpy_unfold.src_casted = bitcast i8* %Src to i32* ; CHECK-DAG: %memcpy_unfold.dst_casted = bitcast i8* %Dst to i32* @@ -21,7 +22,7 @@ define void @test1(i8* %Src, i8* %Dst) { ; CHECK-DAG: [[VAL4:%[^\s]+]] = load atomic i32, i32* %{{[^\s]+}} unordered, align 4 ; CHECK-DAG: store atomic i32 [[VAL4]], i32* %{{[^\s]+}} unordered, align 4 entry: - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 8 %Src, i64 4, i32 4) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %Dst, i8* align 4 %Src, i32 16, i32 4) ret void } @@ -31,9 +32,9 @@ define void @test2(i8* %Src, i8* %Dst) { ; CHECK-NOT: load ; CHECK-NOT: store -; CHECK: llvm.memcpy.element.atomic +; CHECK: llvm.memcpy.element.unordered.atomic entry: - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 4 %Src, i64 1000, i32 4) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %Dst, i8* align 4 %Src, i32 256, i32 4) ret void } @@ -43,16 +44,16 @@ define void @test3(i8* %Src, i8* %Dst) { ; CHECK-NOT: load ; CHECK-NOT: store -; CHECK: llvm.memcpy.element.atomic +; CHECK: llvm.memcpy.element.unordered.atomic entry: - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 4, i32 64) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 64, i32 64) ret void } ; Test that we will eliminate redundant bitcasts define void @test4(i64* %Src, i64* %Dst) { ; CHECK-LABEL: test4 -; CHECK-NOT: llvm.memcpy.element.atomic +; CHECK-NOT: llvm.memcpy.element.unordered.atomic ; CHECK-NOT: bitcast @@ -76,17 +77,18 @@ define void @test4(i64* %Src, i64* %Dst) { entry: %Src.casted = bitcast i64* %Src to i8* %Dst.casted = bitcast i64* %Dst to i8* - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %Dst.casted, i8* align 16 %Src.casted, i64 4, i32 8) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 16 %Dst.casted, i8* align 16 %Src.casted, i32 32, i32 8) ret void } +; Test that 0-length unordered atomic memcpy gets removed. define void @test5(i8* %Src, i8* %Dst) { ; CHECK-LABEL: test5 -; CHECK-NOT: llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 0, i32 64) +; CHECK-NOT: llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 0, i32 8) entry: - call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 0, i32 64) + call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 0, i32 8) ret void } -declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* nocapture, i8* nocapture, i64, i32) +declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind diff --git a/test/Transforms/InstCombine/ffs-1.ll b/test/Transforms/InstCombine/ffs-1.ll index d27fb5d..af4ee85 100644 --- a/test/Transforms/InstCombine/ffs-1.ll +++ b/test/Transforms/InstCombine/ffs-1.ll @@ -1,12 +1,12 @@ ; Test that the ffs* library call simplifier works correctly. ; -; RUN: opt < %s -instcombine -S | FileCheck %s -; RUN: opt < %s -mtriple i386-pc-linux -instcombine -S | FileCheck %s -check-prefix=CHECK-FFS -; RUN: opt -instcombine -mtriple=arm64-apple-ios9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s -; RUN: opt -instcombine -mtriple=arm64-apple-tvos9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s -; RUN: opt -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s -; RUN: opt -instcombine -mtriple=x86_64-apple-macosx10.11 -S %s | FileCheck --check-prefix=CHECK-FFS %s -; RUN: opt -instcombine -mtriple=x86_64-freebsd-gnu -S %s | FileCheck --check-prefix=CHECK-FFS %s +; RUN: opt < %s -instcombine -S | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC +; RUN: opt < %s -instcombine -mtriple i386-pc-linux -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET +; RUN: opt < %s -instcombine -mtriple=arm64-apple-ios9.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET +; RUN: opt < %s -instcombine -mtriple=arm64-apple-tvos9.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET +; RUN: opt < %s -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET +; RUN: opt < %s -instcombine -mtriple=x86_64-apple-macosx10.11 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET +; RUN: opt < %s -instcombine -mtriple=x86_64-freebsd-gnu -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET declare i32 @ffs(i32) declare i32 @ffsl(i32) @@ -15,123 +15,179 @@ declare i32 @ffsll(i64) ; Check ffs(0) -> 0. define i32 @test_simplify1() { -; CHECK-LABEL: @test_simplify1( +; ALL-LABEL: @test_simplify1( +; ALL-NEXT: ret i32 0 +; %ret = call i32 @ffs(i32 0) ret i32 %ret -; CHECK-NEXT: ret i32 0 } define i32 @test_simplify2() { -; CHECK-FFS-LABEL: @test_simplify2( +; GENERIC-LABEL: @test_simplify2( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 0) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify2( +; TARGET-NEXT: ret i32 0 +; %ret = call i32 @ffsl(i32 0) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 0 } define i32 @test_simplify3() { -; CHECK-FFS-LABEL: @test_simplify3( +; GENERIC-LABEL: @test_simplify3( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 0) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify3( +; TARGET-NEXT: ret i32 0 +; %ret = call i32 @ffsll(i64 0) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 0 } ; Check ffs(c) -> cttz(c) + 1, where 'c' is a constant. define i32 @test_simplify4() { -; CHECK-LABEL: @test_simplify4( +; ALL-LABEL: @test_simplify4( +; ALL-NEXT: ret i32 1 +; %ret = call i32 @ffs(i32 1) ret i32 %ret -; CHECK-NEXT: ret i32 1 } define i32 @test_simplify5() { -; CHECK-LABEL: @test_simplify5( +; ALL-LABEL: @test_simplify5( +; ALL-NEXT: ret i32 12 +; %ret = call i32 @ffs(i32 2048) ret i32 %ret -; CHECK-NEXT: ret i32 12 } define i32 @test_simplify6() { -; CHECK-LABEL: @test_simplify6( +; ALL-LABEL: @test_simplify6( +; ALL-NEXT: ret i32 17 +; %ret = call i32 @ffs(i32 65536) ret i32 %ret -; CHECK-NEXT: ret i32 17 } define i32 @test_simplify7() { -; CHECK-FFS-LABEL: @test_simplify7( +; GENERIC-LABEL: @test_simplify7( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 65536) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify7( +; TARGET-NEXT: ret i32 17 +; %ret = call i32 @ffsl(i32 65536) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 17 } define i32 @test_simplify8() { -; CHECK-FFS-LABEL: @test_simplify8( +; GENERIC-LABEL: @test_simplify8( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 1024) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify8( +; TARGET-NEXT: ret i32 11 +; %ret = call i32 @ffsll(i64 1024) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 11 } define i32 @test_simplify9() { -; CHECK-FFS-LABEL: @test_simplify9( +; GENERIC-LABEL: @test_simplify9( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 65536) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify9( +; TARGET-NEXT: ret i32 17 +; %ret = call i32 @ffsll(i64 65536) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 17 } define i32 @test_simplify10() { -; CHECK-FFS-LABEL: @test_simplify10( +; GENERIC-LABEL: @test_simplify10( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 17179869184) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify10( +; TARGET-NEXT: ret i32 35 +; %ret = call i32 @ffsll(i64 17179869184) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 35 } define i32 @test_simplify11() { -; CHECK-FFS-LABEL: @test_simplify11( +; GENERIC-LABEL: @test_simplify11( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 281474976710656) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify11( +; TARGET-NEXT: ret i32 49 +; %ret = call i32 @ffsll(i64 281474976710656) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 49 } define i32 @test_simplify12() { -; CHECK-FFS-LABEL: @test_simplify12( +; GENERIC-LABEL: @test_simplify12( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 1152921504606846976) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify12( +; TARGET-NEXT: ret i32 61 +; %ret = call i32 @ffsll(i64 1152921504606846976) ret i32 %ret -; CHECK-FFS-NEXT: ret i32 61 } ; Check ffs(x) -> x != 0 ? (i32)llvm.cttz(x) + 1 : 0. define i32 @test_simplify13(i32 %x) { -; CHECK-LABEL: @test_simplify13( +; ALL-LABEL: @test_simplify13( +; ALL-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) +; ALL-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[CTTZ]], 1 +; ALL-NEXT: [[TMP2:%.*]] = icmp ne i32 %x, 0 +; ALL-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0 +; ALL-NEXT: ret i32 [[TMP3]] +; %ret = call i32 @ffs(i32 %x) -; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) -; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1 -; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0 -; CHECK-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0 ret i32 %ret -; CHECK-NEXT: ret i32 [[RET]] } define i32 @test_simplify14(i32 %x) { -; CHECK-FFS-LABEL: @test_simplify14( +; GENERIC-LABEL: @test_simplify14( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 %x) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify14( +; TARGET-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) +; TARGET-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[CTTZ]], 1 +; TARGET-NEXT: [[TMP2:%.*]] = icmp ne i32 %x, 0 +; TARGET-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0 +; TARGET-NEXT: ret i32 [[TMP3]] +; %ret = call i32 @ffsl(i32 %x) -; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true) -; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1 -; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0 -; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0 ret i32 %ret -; CHECK-FFS-NEXT: ret i32 [[RET]] } define i32 @test_simplify15(i64 %x) { -; CHECK-FFS-LABEL: @test_simplify15( +; GENERIC-LABEL: @test_simplify15( +; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 %x) +; GENERIC-NEXT: ret i32 [[RET]] +; +; TARGET-LABEL: @test_simplify15( +; TARGET-NEXT: [[CTTZ:%.*]] = call i64 @llvm.cttz.i64(i64 %x, i1 true) +; TARGET-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[CTTZ]], 1 +; TARGET-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32 +; TARGET-NEXT: [[TMP3:%.*]] = icmp ne i64 %x, 0 +; TARGET-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 0 +; TARGET-NEXT: ret i32 [[TMP4]] +; %ret = call i32 @ffsll(i64 %x) -; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 true) -; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1 -; CHECK-FFS-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32 -; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0 -; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0 ret i32 %ret -; CHECK-FFS-NEXT: ret i32 [[RET]] } + diff --git a/test/Transforms/InstCombine/lshr.ll b/test/Transforms/InstCombine/lshr.ll index 71b2517..4cdcb98 100644 --- a/test/Transforms/InstCombine/lshr.ll +++ b/test/Transforms/InstCombine/lshr.ll @@ -122,10 +122,19 @@ define <2 x i8> @bool_zext_splat(<2 x i1> %x) { ret <2 x i8> %hibit } -; FIXME: The replicated sign bits are all that's left. This could be ashr+zext. - -define i16 @smear_sign_and_widen(i4 %x) { +define i32 @smear_sign_and_widen(i8 %x) { ; CHECK-LABEL: @smear_sign_and_widen( +; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 %x, 7 +; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[HIBIT]] +; + %sext = sext i8 %x to i32 + %hibit = lshr i32 %sext, 24 + ret i32 %hibit +} + +define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) { +; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type( ; CHECK-NEXT: [[SEXT:%.*]] = sext i4 %x to i16 ; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12 ; CHECK-NEXT: ret i16 [[HIBIT]] @@ -137,8 +146,8 @@ define i16 @smear_sign_and_widen(i4 %x) { define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) { ; CHECK-LABEL: @smear_sign_and_widen_splat( -; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i6> %x to <2 x i8> -; CHECK-NEXT: [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], +; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> %x, +; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8> ; CHECK-NEXT: ret <2 x i8> [[HIBIT]] ; %sext = sext <2 x i6> %x to <2 x i8> diff --git a/test/Transforms/InstCombine/onehot_merge.ll b/test/Transforms/InstCombine/onehot_merge.ll index 496d847..47a4ca4 100644 --- a/test/Transforms/InstCombine/onehot_merge.ll +++ b/test/Transforms/InstCombine/onehot_merge.ll @@ -33,3 +33,79 @@ bb: ret i1 %or } +; Same as above but with operands commuted one of the ands, but not the other. +define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) { +; CHECK-LABEL: @foo1_and_commuted( +; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]] +; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[TMP]], [[TMP4]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K2]], [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], [[TMP0]] +; CHECK-NEXT: ret i1 [[TMP2]] +; + %k2 = mul i32 %k, %k ; to trick the complexity sorting + %tmp = shl i32 1, %c1 + %tmp4 = lshr i32 -2147483648, %c2 + %tmp1 = and i32 %k2, %tmp + %tmp2 = icmp eq i32 %tmp1, 0 + %tmp5 = and i32 %tmp4, %k2 + %tmp6 = icmp eq i32 %tmp5, 0 + %or = or i1 %tmp2, %tmp6 + ret i1 %or +} + +define i1 @or_consts(i32 %k, i32 %c1, i32 %c2) { +; CHECK-LABEL: @or_consts( +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K:%.*]], 12 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 12 +; CHECK-NEXT: ret i1 [[TMP2]] +; + %tmp1 = and i32 4, %k + %tmp2 = icmp ne i32 %tmp1, 0 + %tmp5 = and i32 8, %k + %tmp6 = icmp ne i32 %tmp5, 0 + %or = and i1 %tmp2, %tmp6 + ret i1 %or +} + +define i1 @foo1_or(i32 %k, i32 %c1, i32 %c2) { +; CHECK-LABEL: @foo1_or( +; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP]], [[TMP4]] +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP3]] +; + %tmp = shl i32 1, %c1 + %tmp4 = lshr i32 -2147483648, %c2 + %tmp1 = and i32 %tmp, %k + %tmp2 = icmp ne i32 %tmp1, 0 + %tmp5 = and i32 %tmp4, %k + %tmp6 = icmp ne i32 %tmp5, 0 + %or = and i1 %tmp2, %tmp6 + ret i1 %or +} + +; Same as above but with operands commuted one of the ors, but not the other. +define i1 @foo1_or_commuted(i32 %k, i32 %c1, i32 %c2) { +; CHECK-LABEL: @foo1_or_commuted( +; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]] +; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]] +; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP]], [[TMP4]] +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[K2]], [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP3]] +; + %k2 = mul i32 %k, %k ; to trick the complexity sorting + %tmp = shl i32 1, %c1 + %tmp4 = lshr i32 -2147483648, %c2 + %tmp1 = and i32 %k2, %tmp + %tmp2 = icmp ne i32 %tmp1, 0 + %tmp5 = and i32 %tmp4, %k2 + %tmp6 = icmp ne i32 %tmp5, 0 + %or = and i1 %tmp2, %tmp6 + ret i1 %or +} diff --git a/test/Transforms/InstCombine/or-xor.ll b/test/Transforms/InstCombine/or-xor.ll index f2bc290..485f961 100644 --- a/test/Transforms/InstCombine/or-xor.ll +++ b/test/Transforms/InstCombine/or-xor.ll @@ -114,6 +114,17 @@ define i32 @test10(i32 %A, i32 %B) { ret i32 %or } +define i32 @test10_commuted(i32 %A, i32 %B) { +; CHECK-LABEL: @test10_commuted( +; CHECK-NEXT: ret i32 -1 +; + %xor1 = xor i32 %B, %A + %not = xor i32 %A, -1 + %xor2 = xor i32 %not, %B + %or = or i32 %xor2, %xor1 + ret i32 %or +} + ; (x | y) & ((~x) ^ y) -> (x & y) define i32 @test11(i32 %x, i32 %y) { ; CHECK-LABEL: @test11( @@ -300,3 +311,36 @@ define i8 @or_xor_or(i8 %x) { ret i8 %or2 } +define i8 @test17(i8 %A, i8 %B) { +; CHECK-LABEL: @test17( +; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 +; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] +; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], [[XOR2]] +; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]] +; CHECK-NEXT: ret i8 [[RES]] +; + %xor1 = xor i8 %B, %A + %not = xor i8 %A, 33 + %xor2 = xor i8 %not, %B + %or = or i8 %xor1, %xor2 + %res = mul i8 %or, %xor2 ; to increase the use count for the xor + ret i8 %res +} + +define i8 @test18(i8 %A, i8 %B) { +; CHECK-LABEL: @test18( +; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 +; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] +; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR2]], [[XOR1]] +; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]] +; CHECK-NEXT: ret i8 [[RES]] +; + %xor1 = xor i8 %B, %A + %not = xor i8 %A, 33 + %xor2 = xor i8 %not, %B + %or = or i8 %xor2, %xor1 + %res = mul i8 %or, %xor2 ; to increase the use count for the xor + ret i8 %res +} diff --git a/test/Transforms/InstCombine/select-with-bitwise-ops.ll b/test/Transforms/InstCombine/select-with-bitwise-ops.ll index 68b73af..faeb4e0 100644 --- a/test/Transforms/InstCombine/select-with-bitwise-ops.ll +++ b/test/Transforms/InstCombine/select-with-bitwise-ops.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = "n8:16:32:64" + define i32 @select_icmp_eq_and_1_0_or_2(i32 %x, i32 %y) { ; CHECK-LABEL: @select_icmp_eq_and_1_0_or_2( ; CHECK-NEXT: [[AND:%.*]] = shl i32 %x, 1 @@ -295,3 +297,269 @@ define i32 @test67(i16 %x) { ret i32 %3 } +define i32 @test68(i32 %x, i32 %y) { +; CHECK-LABEL: @test68( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[TMP1]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]] +; CHECK-NEXT: ret i32 [[SELECT]] +; + %and = and i32 %x, 128 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 2 + %select = select i1 %cmp, i32 %y, i32 %or + ret i32 %select +} + +define i32 @test69(i32 %x, i32 %y) { +; CHECK-LABEL: @test69( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2 +; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]] +; CHECK-NEXT: ret i32 [[SELECT]] +; + %and = and i32 %x, 128 + %cmp = icmp ne i32 %and, 0 + %or = or i32 %y, 2 + %select = select i1 %cmp, i32 %y, i32 %or + ret i32 %select +} + +define i32 @shift_no_xor_multiuse_or(i32 %x, i32 %y) { +; CHECK-LABEL: @shift_no_xor_multiuse_or( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2 +; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[OR]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 1 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 2 + %select = select i1 %cmp, i32 %y, i32 %or + %res = mul i32 %select, %or ; to bump up use count of the Or + ret i32 %res +} + +define i32 @no_shift_no_xor_multiuse_or(i32 %x, i32 %y) { +; CHECK-LABEL: @no_shift_no_xor_multiuse_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096 +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[OR]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %res = mul i32 %select, %or ; to bump up use count of the Or + ret i32 %res +} + +define i32 @no_shift_xor_multiuse_or(i32 %x, i32 %y) { +; CHECK-LABEL: @no_shift_xor_multiuse_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[OR]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %res = mul i32 %select, %or ; to bump up use count of the Or + ret i32 %res +} + +; TODO this increased the number of instructions +define i32 @shift_xor_multiuse_or(i32 %x, i32 %y) { +; CHECK-LABEL: @shift_xor_multiuse_or( +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2048 +; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 1 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2048 +; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048 +; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[OR]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 2048 + %select = select i1 %cmp, i32 %y, i32 %or + %res = mul i32 %select, %or ; to bump up use count of the Or + ret i32 %res +} + +define i32 @shift_no_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @shift_no_xor_multiuse_cmp( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i32 [[AND]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 1 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 2 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + ret i32 %res +} + +define i32 @no_shift_no_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @no_shift_no_xor_multiuse_cmp( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y:%.*]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[SELECT2]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + ret i32 %res +} + +define i32 @no_shift_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @no_shift_xor_multiuse_cmp( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y:%.*]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + ret i32 %res +} + +; TODO this increased the number of instructions +define i32 @shift_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @shift_xor_multiuse_cmp( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[AND]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048 +; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y:%.*]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[SELECT2]] +; CHECK-NEXT: ret i32 [[RES]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 2048 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + ret i32 %res +} + +; TODO this increased the number of instructions +define i32 @shift_no_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @shift_no_xor_multiuse_cmp_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2 +; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i32 [[AND]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]] +; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]] +; CHECK-NEXT: ret i32 [[RES2]] +; + %and = and i32 %x, 1 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 2 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + %res2 = mul i32 %res, %or ; to bump up the use count of the or + ret i32 %res2 +} + +define i32 @no_shift_no_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @no_shift_no_xor_multiuse_cmp_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096 +; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[SELECT2]] +; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]] +; CHECK-NEXT: ret i32 [[RES2]] +; + %and = and i32 %x, 4096 + %cmp = icmp eq i32 %and, 0 + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + %res2 = mul i32 %res, %or ; to bump up the use count of the or + ret i32 %res2 +} + +; TODO this increased the number of instructions +define i32 @no_shift_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @no_shift_xor_multiuse_cmp_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]] +; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]] +; CHECK-NEXT: ret i32 [[RES2]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 4096 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + %res2 = mul i32 %res, %or ; to bump up the use count of the or + ret i32 %res2 +} + +; TODO this increased the number of instructions +define i32 @shift_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) { +; CHECK-LABEL: @shift_xor_multiuse_cmp_or( +; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2048 +; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[AND]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048 +; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y]] +; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]] +; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[SELECT2]] +; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]] +; CHECK-NEXT: ret i32 [[RES2]] +; + %and = and i32 %x, 4096 + %cmp = icmp ne i32 0, %and + %or = or i32 %y, 2048 + %select = select i1 %cmp, i32 %y, i32 %or + %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp + %res = mul i32 %select, %select2 + %res2 = mul i32 %res, %or ; to bump up the use count of the or + ret i32 %res2 +} diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll index ce8e2fc..68bbf35 100644 --- a/test/Transforms/InstCombine/shift.ll +++ b/test/Transforms/InstCombine/shift.ll @@ -1306,3 +1306,13 @@ define <2 x i8> @lshr_demanded_bits_splat(<2 x i8> %x) { ret <2 x i8> %shr } +; Make sure known bits works correctly with non power of 2 bit widths. +define i7 @test65(i7 %a, i7 %b) { +; CHECK-LABEL: @test65( +; CHECK-NEXT: ret i7 0 +; + %shiftamt = and i7 %b, 6 ; this ensures the shift amount is even and less than the bit width. + %x = lshr i7 42, %shiftamt ; 42 has a zero in every even numbered bit and a one in every odd bit. + %y = and i7 %x, 1 ; this extracts the lsb which should be 0 because we shifted an even number of bits and all even bits of the shift input are 0. + ret i7 %y +} diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index 3afbf63..49e6b99 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -325,3 +325,36 @@ define i32 @test14(i32 %a, i32 %b, i32 %c) { ret i32 %xor } +define i8 @test15(i8 %A, i8 %B) { +; CHECK-LABEL: @test15( +; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 +; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR1]], [[XOR2]] +; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]] +; CHECK-NEXT: ret i8 [[RES]] +; + %xor1 = xor i8 %B, %A + %not = xor i8 %A, 33 + %xor2 = xor i8 %not, %B + %and = and i8 %xor1, %xor2 + %res = mul i8 %and, %xor2 ; to increase the use count for the xor + ret i8 %res +} + +define i8 @test16(i8 %A, i8 %B) { +; CHECK-LABEL: @test16( +; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33 +; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR2]], [[XOR1]] +; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]] +; CHECK-NEXT: ret i8 [[RES]] +; + %xor1 = xor i8 %B, %A + %not = xor i8 %A, 33 + %xor2 = xor i8 %not, %B + %and = and i8 %xor2, %xor1 + %res = mul i8 %and, %xor2 ; to increase the use count for the xor + ret i8 %res +} diff --git a/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll b/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll index ec93847..d52378b 100644 --- a/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll +++ b/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll @@ -5,7 +5,7 @@ target triple = "x86_64-unknown-linux-gnu" ;; memcpy.atomic formation (atomic load & store) define void @test1(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test1( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -30,7 +30,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation (atomic store, normal load) define void @test2(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test2( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -55,7 +55,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic store, normal load w/ no align) define void @test2b(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test2b( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -80,7 +80,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic store, normal load w/ bad align) define void @test2c(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test2c( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -105,7 +105,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic store w/ bad align, normal load) define void @test2d(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test2d( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -131,7 +131,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation (normal store, atomic load) define void @test3(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test3( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -156,7 +156,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (normal store w/ no align, atomic load) define void @test3b(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test3b( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -181,7 +181,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (normal store, atomic load w/ bad align) define void @test3c(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test3c( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -206,7 +206,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (normal store w/ bad align, atomic load) define void @test3d(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test3d( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -232,7 +232,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic load, ordered-atomic store) define void @test4(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test4( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -257,7 +257,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (ordered-atomic load, unordered-atomic store) define void @test5(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test5( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: @@ -282,7 +282,8 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation (atomic load & store) -- element size 2 define void @test6(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test6( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 2 %Dest{{[0-9]*}}, i8* align 2 %Base{{[0-9]*}}, i64 %Size, i32 2) +; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 1 +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 2 %Dest{{[0-9]*}}, i8* align 2 %Base{{[0-9]*}}, i64 [[Sz]], i32 2) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -307,7 +308,8 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation (atomic load & store) -- element size 4 define void @test7(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test7( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dest{{[0-9]*}}, i8* align 4 %Base{{[0-9]*}}, i64 %Size, i32 4) +; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 2 +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 4 %Dest{{[0-9]*}}, i8* align 4 %Base{{[0-9]*}}, i64 [[Sz]], i32 4) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -332,7 +334,8 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation (atomic load & store) -- element size 8 define void @test8(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test8( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 8 %Dest{{[0-9]*}}, i8* align 8 %Base{{[0-9]*}}, i64 %Size, i32 8) +; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 3 +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 8 %Dest{{[0-9]*}}, i8* align 8 %Base{{[0-9]*}}, i64 [[Sz]], i32 8) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -357,7 +360,8 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic load & store) -- element size 16 define void @test9(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test9( -; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %Dest{{[0-9]*}}, i8* align 16 %Base{{[0-9]*}}, i64 %Size, i32 16) +; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 4 +; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 16 %Dest{{[0-9]*}}, i8* align 16 %Base{{[0-9]*}}, i64 [[Sz]], i32 16) ; CHECK-NOT: store ; CHECK: ret void bb.nph: @@ -382,7 +386,7 @@ for.end: ; preds = %for.body, %entry ;; memcpy.atomic formation rejection (atomic load & store) -- element size 32 define void @test10(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test10( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: diff --git a/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll b/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll index b2528f1..341a7a0 100644 --- a/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll +++ b/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll @@ -5,7 +5,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ;; Will not create call due to a max element size of 0 define void @test1(i64 %Size) nounwind ssp { ; CHECK-LABEL: @test1( -; CHECK-NOT: call void @llvm.memcpy.element.atomic +; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic ; CHECK: store ; CHECK: ret void bb.nph: diff --git a/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml b/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml new file mode 100644 index 0000000..17b634a --- /dev/null +++ b/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml @@ -0,0 +1,19 @@ +--- +TypeIdMap: + typeid1: + TTRes: + Kind: AllOnes + SizeM1BitWidth: 7 + typeid2: + TTRes: + Kind: Single + SizeM1BitWidth: 0 +WithGlobalValueDeadStripping: false +CfiFunctionDefs: + - local_a + - local_b + - does_not_exist +CfiFunctionDecls: + - external + - external_weak +... diff --git a/test/Transforms/LowerTypeTests/export-icall.ll b/test/Transforms/LowerTypeTests/export-icall.ll new file mode 100644 index 0000000..ad36048 --- /dev/null +++ b/test/Transforms/LowerTypeTests/export-icall.ll @@ -0,0 +1,70 @@ +; RUN: opt -S -lowertypetests -lowertypetests-summary-action=export -lowertypetests-read-summary=%S/Inputs/use-typeid1-typeid2.yaml -lowertypetests-write-summary=%t < %s | FileCheck %s +; RUN: FileCheck --check-prefix=SUMMARY %s < %t + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @h(i8 %x) !type !2 { + ret void +} + +declare !type !8 void @f(i32 %x) + +!cfi.functions = !{!0, !1, !3, !4, !5, !6} + +; declaration of @h with a different type is ignored +!0 = !{!"h", i8 1, !7} + +; extern_weak declaration of @h with a different type is ignored as well +!1 = !{!"h", i8 2, !8} +!2 = !{i64 0, !"typeid1"} + +; definition of @f replaces types on the IR declaration above +!3 = !{!"f", i8 0, !2} +!4 = !{!"external", i8 1, !2} +!5 = !{!"external_weak", i8 2, !2} +!6 = !{!"g", i8 0, !7} +!7 = !{i64 0, !"typeid2"} +!8 = !{i64 0, !"typeid3"} + + +; CHECK-DAG: @__typeid_typeid1_global_addr = hidden alias i8, bitcast (void ()* [[JT1:.*]] to i8*) +; CHECK-DAG: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 3 to i8*) +; CHECK-DAG: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 3 to i8*) + +; CHECK-DAG: @h = alias void (i8), bitcast (void ()* [[JT1]] to void (i8)*) +; CHECK-DAG: @f = alias void (i32), {{.*}}getelementptr {{.*}}void ()* [[JT1]] +; CHECK-DAG: @external.cfi_jt = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]] +; CHECK-DAG: @external_weak.cfi_jt = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]] + +; CHECK-DAG: @__typeid_typeid2_global_addr = hidden alias i8, bitcast (void ()* [[JT2:.*]] to i8*) + +; CHECK-DAG: @g = alias void (), void ()* [[JT2]] + +; CHECK-DAG: define internal void @h.cfi(i8 {{.*}}) !type !{{.*}} +; CHECK-DAG: declare !type !{{.*}} void @external() +; CHECK-DAG: declare !type !{{.*}} void @external_weak() +; CHECK-DAG: declare !type !{{.*}} void @f.cfi(i32) +; CHECK-DAG: declare !type !{{.*}} void @g.cfi() + + +; SUMMARY: TypeIdMap: +; SUMMARY-NEXT: typeid1: +; SUMMARY-NEXT: TTRes: +; SUMMARY-NEXT: Kind: AllOnes +; SUMMARY-NEXT: SizeM1BitWidth: 7 +; SUMMARY-NEXT: WPDRes: +; SUMMARY-NEXT: typeid2: +; SUMMARY-NEXT: TTRes: +; SUMMARY-NEXT: Kind: Single +; SUMMARY-NEXT: SizeM1BitWidth: 0 +; SUMMARY-NEXT: WPDRes: + +; SUMMARY: CfiFunctionDefs: +; SUMMARY-NEXT: - f +; SUMMARY-NEXT: - g +; SUMMARY-NEXT: - h +; SUMMARY-NEXT: CfiFunctionDecls: +; SUMMARY-NEXT: - external +; SUMMARY-NEXT: - external_weak +; SUMMARY-NEXT: ... diff --git a/test/Transforms/LowerTypeTests/import-icall.ll b/test/Transforms/LowerTypeTests/import-icall.ll new file mode 100644 index 0000000..ddeb7fb --- /dev/null +++ b/test/Transforms/LowerTypeTests/import-icall.ll @@ -0,0 +1,40 @@ +; RUN: opt -S -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%S/Inputs/import-icall.yaml < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i8 @local_a() { + call void @external() + call void @external_weak() + ret i8 1 +} + +define internal i8 @local_b() { + %x = call i8 @local_a() + ret i8 %x +} + +define i8 @use_b() { + %x = call i8 @local_b() + ret i8 %x +} + + +declare void @external() +declare extern_weak void @external_weak() + +; CHECK: define hidden i8 @local_a.cfi() { +; CHECK-NEXT: call void @external.cfi_jt() +; CHECK-NEXT: call void select (i1 icmp ne (void ()* @external_weak, void ()* null), void ()* @external_weak.cfi_jt, void ()* null)() +; CHECK-NEXT: ret i8 1 +; CHECK-NEXT: } + +; internal @local_b is not the same function as "local_b" in the summary. +; CHECK: define internal i8 @local_b() { +; CHECK-NEXT: call i8 @local_a() + +; CHECK: declare void @external() +; CHECK: declare extern_weak void @external_weak() +; CHECK: declare i8 @local_a() +; CHECK: declare hidden void @external.cfi_jt() +; CHECK: declare hidden void @external_weak.cfi_jt() diff --git a/test/Transforms/PGOProfile/memop_size_opt.ll b/test/Transforms/PGOProfile/memop_size_opt.ll index 19a2b7e..e11f235 100644 --- a/test/Transforms/PGOProfile/memop_size_opt.ll +++ b/test/Transforms/PGOProfile/memop_size_opt.ll @@ -38,7 +38,7 @@ for.body3: ; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i32 1, i1 false) ; MEMOP_OPT: br label %[[MERGE_LABEL:.*]] ; MEMOP_OPT: [[DEFAULT_LABEL]]: -; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i32 1, i1 false){{[[:space:]]}} +; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i32 1, i1 false), !prof [[NEWVP:![0-9]+]] ; MEMOP_OPT: br label %[[MERGE_LABEL]] ; MEMOP_OPT: [[MERGE_LABEL]]: ; MEMOP_OPT: switch i64 %conv, label %[[DEFAULT_LABEL2:.*]] [ @@ -48,11 +48,16 @@ for.body3: ; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 1, i32 1, i1 false) ; MEMOP_OPT: br label %[[MERGE_LABEL2:.*]] ; MEMOP_OPT: [[DEFAULT_LABEL2]]: -; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i32 1, i1 false){{[[:space:]]}} +; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i32 1, i1 false), !prof [[NEWVP]] ; MEMOP_OPT: br label %[[MERGE_LABEL2]] ; MEMOP_OPT: [[MERGE_LABEL2]]: ; MEMOP_OPT: br label %for.inc ; MEMOP_OPT: [[SWITCH_BW]] = !{!"branch_weights", i32 457, i32 99} +; Should be 457 total left (original total count 556, minus 99 from specialized +; value 1, which is removed from VP array. Also, we only end up with 5 total +; values, since the default max number of promotions is 5 and therefore +; the rest of the values are ignored when extracting the VP metadata. +; MEMOP_OPT: [[NEWVP]] = !{!"VP", i32 1, i64 457, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66} for.inc: %inc = add nsw i32 %j.0, 1 diff --git a/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll b/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll new file mode 100644 index 0000000..105afa9 --- /dev/null +++ b/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll @@ -0,0 +1,92 @@ +; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s + +; This test checks that metadata that's invalid after RS4GC is dropped. +; We can miscompile if optimizations scheduled after RS4GC uses the +; metadata that's infact invalid. + +declare void @bar() + +declare void @baz(i32) +; Confirm that loadedval instruction does not contain invariant.load metadata. +; but contains the range metadata. +; Since loadedval is not marked invariant, it will prevent incorrectly sinking +; %loadedval in LICM and avoid creation of an unrelocated use of %baseaddr. +define void @test_invariant_load() gc "statepoint-example" { +; CHECK-LABEL: @test_invariant_load +; CHECK: %loadedval = load i32, i32 addrspace(1)* %baseaddr, align 8, !range !0 +bb: + br label %outerloopHdr + +outerloopHdr: ; preds = %bb6, %bb + %baseaddr = phi i32 addrspace(1)* [ undef, %bb ], [ %tmp4, %bb6 ] +; LICM may sink this load to exit block after RS4GC because it's tagged invariant. + %loadedval = load i32, i32 addrspace(1)* %baseaddr, align 8, !range !0, !invariant.load !1 + br label %innerloopHdr + +innerloopHdr: ; preds = %innerlooplatch, %outerloopHdr + %tmp4 = phi i32 addrspace(1)* [ %baseaddr, %outerloopHdr ], [ %gep, %innerlooplatch ] + br label %innermostloophdr + +innermostloophdr: ; preds = %bb6, %innerloopHdr + br i1 undef, label %exitblock, label %bb6 + +bb6: ; preds = %innermostloophdr + switch i32 undef, label %innermostloophdr [ + i32 0, label %outerloopHdr + i32 1, label %innerlooplatch + ] + +innerlooplatch: ; preds = %bb6 + call void @bar() + %gep = getelementptr inbounds i32, i32 addrspace(1)* %tmp4, i64 8 + br label %innerloopHdr + +exitblock: ; preds = %innermostloophdr + %tmp13 = add i32 42, %loadedval + call void @baz(i32 %tmp13) + unreachable +} + +; drop the noalias metadata. +define void @test_noalias(i32 %x, i32 addrspace(1)* %p, i32 addrspace(1)* %q) gc "statepoint-example" { +; CHECK-LABEL: test_noalias +; CHECK: %y = load i32, i32 addrspace(1)* %q, align 16 +; CHECK: gc.statepoint +; CHECK: %p.relocated +; CHECK-NEXT: %p.relocated.casted = bitcast i8 addrspace(1)* %p.relocated to i32 addrspace(1)* +; CHECK-NEXT: store i32 %x, i32 addrspace(1)* %p.relocated.casted, align 16 +entry: + %y = load i32, i32 addrspace(1)* %q, align 16, !noalias !3 + call void @baz(i32 %x) + store i32 %x, i32 addrspace(1)* %p, align 16, !noalias !4 + ret void +} + +; drop the dereferenceable metadata +define void @test_dereferenceable(i32 addrspace(1)* addrspace(1)* %p, i32 %x, i32 addrspace(1)* %q) gc "statepoint-example" { +; CHECK-LABEL: test_dereferenceable +; CHECK: %v1 = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p +; CHECK-NEXT: %v2 = load i32, i32 addrspace(1)* %v1 +; CHECK: gc.statepoint + %v1 = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p, !dereferenceable !5 + %v2 = load i32, i32 addrspace(1)* %v1 + call void @baz(i32 %x) + store i32 %v2, i32 addrspace(1)* %q, align 16 + ret void +} + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidi32f(i64, i32, void (i32)*, i32, i32, ...) + +; Function Attrs: nounwind readonly +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) #0 + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) + +attributes #0 = { nounwind readonly } + +!0 = !{i32 0, i32 2147483647} +!1 = !{} +!2 = !{i32 10, i32 1} +!3 = !{!3} +!4 = !{!4} +!5 = !{i64 8} diff --git a/test/Transforms/SLPVectorizer/X86/arith-add.ll b/test/Transforms/SLPVectorizer/X86/arith-add.ll index 0266758..22b2c74 100644 --- a/test/Transforms/SLPVectorizer/X86/arith-add.ll +++ b/test/Transforms/SLPVectorizer/X86/arith-add.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F @@ -38,6 +39,25 @@ define void @add_v8i64() { ; SSE-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8 ; SSE-NEXT: ret void ; +; SLM-LABEL: @add_v8i64( +; SLM-NEXT: [[TMP1:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @a64 to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP4:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @b64 to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP6:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP8:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP9:%.*]] = add <2 x i64> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = add <2 x i64> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = add <2 x i64> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = add <2 x i64> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <2 x i64> [[TMP9]], <2 x i64>* bitcast ([8 x i64]* @c64 to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP10]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP11]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: ret void +; ; AVX-LABEL: @add_v8i64( ; AVX-NEXT: [[TMP1:%.*]] = load <4 x i64>, <4 x i64>* bitcast ([8 x i64]* @a64 to <4 x i64>*), align 8 ; AVX-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <4 x i64>*), align 8 @@ -111,6 +131,25 @@ define void @add_v16i32() { ; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 ; SSE-NEXT: ret void ; +; SLM-LABEL: @add_v16i32( +; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP9:%.*]] = add <4 x i32> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = add <4 x i32> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = add <4 x i32> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = add <4 x i32> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: ret void +; ; AVX-LABEL: @add_v16i32( ; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4 ; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4 @@ -216,6 +255,25 @@ define void @add_v32i16() { ; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 ; SSE-NEXT: ret void ; +; SLM-LABEL: @add_v32i16( +; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP9:%.*]] = add <8 x i16> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = add <8 x i16> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = add <8 x i16> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = add <8 x i16> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: ret void +; ; AVX-LABEL: @add_v32i16( ; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2 ; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2 diff --git a/test/Transforms/SLPVectorizer/X86/arith-fp.ll b/test/Transforms/SLPVectorizer/X86/arith-fp.ll index e00ed84..119cf59 100644 --- a/test/Transforms/SLPVectorizer/X86/arith-fp.ll +++ b/test/Transforms/SLPVectorizer/X86/arith-fp.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=skx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX @@ -69,13 +70,32 @@ define <2 x double> @buildvector_mul_2f64(<2 x double> %a, <2 x double> %b) { } define <2 x double> @buildvector_div_2f64(<2 x double> %a, <2 x double> %b) { -; CHECK-LABEL: @buildvector_div_2f64( -; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0 -; CHECK-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1 -; CHECK-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1 -; CHECK-NEXT: ret <2 x double> [[R1]] +; SSE-LABEL: @buildvector_div_2f64( +; SSE-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]] +; SSE-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0 +; SSE-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0 +; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1 +; SSE-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1 +; SSE-NEXT: ret <2 x double> [[R1]] +; +; SLM-LABEL: @buildvector_div_2f64( +; SLM-NEXT: [[A0:%.*]] = extractelement <2 x double> [[A:%.*]], i32 0 +; SLM-NEXT: [[A1:%.*]] = extractelement <2 x double> [[A]], i32 1 +; SLM-NEXT: [[B0:%.*]] = extractelement <2 x double> [[B:%.*]], i32 0 +; SLM-NEXT: [[B1:%.*]] = extractelement <2 x double> [[B]], i32 1 +; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]] +; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]] +; SLM-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[C0]], i32 0 +; SLM-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[C1]], i32 1 +; SLM-NEXT: ret <2 x double> [[R1]] +; +; AVX-LABEL: @buildvector_div_2f64( +; AVX-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]] +; AVX-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0 +; AVX-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0 +; AVX-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1 +; AVX-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1 +; AVX-NEXT: ret <2 x double> [[R1]] ; %a0 = extractelement <2 x double> %a, i32 0 %a1 = extractelement <2 x double> %a, i32 1 @@ -317,17 +337,48 @@ define <4 x double> @buildvector_mul_4f64(<4 x double> %a, <4 x double> %b) { } define <4 x double> @buildvector_div_4f64(<4 x double> %a, <4 x double> %b) { -; CHECK-LABEL: @buildvector_div_4f64( -; CHECK-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 -; CHECK-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 -; CHECK-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 -; CHECK-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 -; CHECK-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3 -; CHECK-NEXT: ret <4 x double> [[R3]] +; SSE-LABEL: @buildvector_div_4f64( +; SSE-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]] +; SSE-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +; SSE-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0 +; SSE-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +; SSE-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1 +; SSE-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +; SSE-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2 +; SSE-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +; SSE-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3 +; SSE-NEXT: ret <4 x double> [[R3]] +; +; SLM-LABEL: @buildvector_div_4f64( +; SLM-NEXT: [[A0:%.*]] = extractelement <4 x double> [[A:%.*]], i32 0 +; SLM-NEXT: [[A1:%.*]] = extractelement <4 x double> [[A]], i32 1 +; SLM-NEXT: [[A2:%.*]] = extractelement <4 x double> [[A]], i32 2 +; SLM-NEXT: [[A3:%.*]] = extractelement <4 x double> [[A]], i32 3 +; SLM-NEXT: [[B0:%.*]] = extractelement <4 x double> [[B:%.*]], i32 0 +; SLM-NEXT: [[B1:%.*]] = extractelement <4 x double> [[B]], i32 1 +; SLM-NEXT: [[B2:%.*]] = extractelement <4 x double> [[B]], i32 2 +; SLM-NEXT: [[B3:%.*]] = extractelement <4 x double> [[B]], i32 3 +; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]] +; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]] +; SLM-NEXT: [[C2:%.*]] = fdiv double [[A2]], [[B2]] +; SLM-NEXT: [[C3:%.*]] = fdiv double [[A3]], [[B3]] +; SLM-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[C0]], i32 0 +; SLM-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[C1]], i32 1 +; SLM-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[C2]], i32 2 +; SLM-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[C3]], i32 3 +; SLM-NEXT: ret <4 x double> [[R3]] +; +; AVX-LABEL: @buildvector_div_4f64( +; AVX-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]] +; AVX-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +; AVX-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0 +; AVX-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +; AVX-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1 +; AVX-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +; AVX-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2 +; AVX-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +; AVX-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3 +; AVX-NEXT: ret <4 x double> [[R3]] ; %a0 = extractelement <4 x double> %a, i32 0 %a1 = extractelement <4 x double> %a, i32 1 @@ -745,25 +796,80 @@ define <8 x double> @buildvector_mul_8f64(<8 x double> %a, <8 x double> %b) { } define <8 x double> @buildvector_div_8f64(<8 x double> %a, <8 x double> %b) { -; CHECK-LABEL: @buildvector_div_8f64( -; CHECK-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0 -; CHECK-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1 -; CHECK-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2 -; CHECK-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2 -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3 -; CHECK-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4 -; CHECK-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4 -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5 -; CHECK-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5 -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6 -; CHECK-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6 -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7 -; CHECK-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7 -; CHECK-NEXT: ret <8 x double> [[R7]] +; SSE-LABEL: @buildvector_div_8f64( +; SSE-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]] +; SSE-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0 +; SSE-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +; SSE-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1 +; SSE-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1 +; SSE-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2 +; SSE-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2 +; SSE-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3 +; SSE-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3 +; SSE-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4 +; SSE-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4 +; SSE-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5 +; SSE-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5 +; SSE-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6 +; SSE-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6 +; SSE-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7 +; SSE-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7 +; SSE-NEXT: ret <8 x double> [[R7]] +; +; SLM-LABEL: @buildvector_div_8f64( +; SLM-NEXT: [[A0:%.*]] = extractelement <8 x double> [[A:%.*]], i32 0 +; SLM-NEXT: [[A1:%.*]] = extractelement <8 x double> [[A]], i32 1 +; SLM-NEXT: [[A2:%.*]] = extractelement <8 x double> [[A]], i32 2 +; SLM-NEXT: [[A3:%.*]] = extractelement <8 x double> [[A]], i32 3 +; SLM-NEXT: [[A4:%.*]] = extractelement <8 x double> [[A]], i32 4 +; SLM-NEXT: [[A5:%.*]] = extractelement <8 x double> [[A]], i32 5 +; SLM-NEXT: [[A6:%.*]] = extractelement <8 x double> [[A]], i32 6 +; SLM-NEXT: [[A7:%.*]] = extractelement <8 x double> [[A]], i32 7 +; SLM-NEXT: [[B0:%.*]] = extractelement <8 x double> [[B:%.*]], i32 0 +; SLM-NEXT: [[B1:%.*]] = extractelement <8 x double> [[B]], i32 1 +; SLM-NEXT: [[B2:%.*]] = extractelement <8 x double> [[B]], i32 2 +; SLM-NEXT: [[B3:%.*]] = extractelement <8 x double> [[B]], i32 3 +; SLM-NEXT: [[B4:%.*]] = extractelement <8 x double> [[B]], i32 4 +; SLM-NEXT: [[B5:%.*]] = extractelement <8 x double> [[B]], i32 5 +; SLM-NEXT: [[B6:%.*]] = extractelement <8 x double> [[B]], i32 6 +; SLM-NEXT: [[B7:%.*]] = extractelement <8 x double> [[B]], i32 7 +; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]] +; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]] +; SLM-NEXT: [[C2:%.*]] = fdiv double [[A2]], [[B2]] +; SLM-NEXT: [[C3:%.*]] = fdiv double [[A3]], [[B3]] +; SLM-NEXT: [[C4:%.*]] = fdiv double [[A4]], [[B4]] +; SLM-NEXT: [[C5:%.*]] = fdiv double [[A5]], [[B5]] +; SLM-NEXT: [[C6:%.*]] = fdiv double [[A6]], [[B6]] +; SLM-NEXT: [[C7:%.*]] = fdiv double [[A7]], [[B7]] +; SLM-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[C0]], i32 0 +; SLM-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[C1]], i32 1 +; SLM-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[C2]], i32 2 +; SLM-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[C3]], i32 3 +; SLM-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[C4]], i32 4 +; SLM-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[C5]], i32 5 +; SLM-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[C6]], i32 6 +; SLM-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[C7]], i32 7 +; SLM-NEXT: ret <8 x double> [[R7]] +; +; AVX-LABEL: @buildvector_div_8f64( +; AVX-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]] +; AVX-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0 +; AVX-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0 +; AVX-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1 +; AVX-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1 +; AVX-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2 +; AVX-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2 +; AVX-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3 +; AVX-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3 +; AVX-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4 +; AVX-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4 +; AVX-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5 +; AVX-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5 +; AVX-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6 +; AVX-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6 +; AVX-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7 +; AVX-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7 +; AVX-NEXT: ret <8 x double> [[R7]] ; %a0 = extractelement <8 x double> %a, i32 0 %a1 = extractelement <8 x double> %a, i32 1 diff --git a/test/Transforms/SLPVectorizer/X86/arith-mul.ll b/test/Transforms/SLPVectorizer/X86/arith-mul.ll index 95875d7..4763a9a 100644 --- a/test/Transforms/SLPVectorizer/X86/arith-mul.ll +++ b/test/Transforms/SLPVectorizer/X86/arith-mul.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F @@ -54,6 +55,41 @@ define void @mul_v8i64() { ; SSE-NEXT: store i64 [[R7]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 7), align 8 ; SSE-NEXT: ret void ; +; SLM-LABEL: @mul_v8i64( +; SLM-NEXT: [[A0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 0), align 8 +; SLM-NEXT: [[A1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 1), align 8 +; SLM-NEXT: [[A2:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2), align 8 +; SLM-NEXT: [[A3:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 3), align 8 +; SLM-NEXT: [[A4:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4), align 8 +; SLM-NEXT: [[A5:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 5), align 8 +; SLM-NEXT: [[A6:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6), align 8 +; SLM-NEXT: [[A7:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 7), align 8 +; SLM-NEXT: [[B0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 0), align 8 +; SLM-NEXT: [[B1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 1), align 8 +; SLM-NEXT: [[B2:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2), align 8 +; SLM-NEXT: [[B3:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 3), align 8 +; SLM-NEXT: [[B4:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4), align 8 +; SLM-NEXT: [[B5:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 5), align 8 +; SLM-NEXT: [[B6:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6), align 8 +; SLM-NEXT: [[B7:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 7), align 8 +; SLM-NEXT: [[R0:%.*]] = mul i64 [[A0]], [[B0]] +; SLM-NEXT: [[R1:%.*]] = mul i64 [[A1]], [[B1]] +; SLM-NEXT: [[R2:%.*]] = mul i64 [[A2]], [[B2]] +; SLM-NEXT: [[R3:%.*]] = mul i64 [[A3]], [[B3]] +; SLM-NEXT: [[R4:%.*]] = mul i64 [[A4]], [[B4]] +; SLM-NEXT: [[R5:%.*]] = mul i64 [[A5]], [[B5]] +; SLM-NEXT: [[R6:%.*]] = mul i64 [[A6]], [[B6]] +; SLM-NEXT: [[R7:%.*]] = mul i64 [[A7]], [[B7]] +; SLM-NEXT: store i64 [[R0]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 0), align 8 +; SLM-NEXT: store i64 [[R1]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 1), align 8 +; SLM-NEXT: store i64 [[R2]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2), align 8 +; SLM-NEXT: store i64 [[R3]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 3), align 8 +; SLM-NEXT: store i64 [[R4]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4), align 8 +; SLM-NEXT: store i64 [[R5]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 5), align 8 +; SLM-NEXT: store i64 [[R6]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6), align 8 +; SLM-NEXT: store i64 [[R7]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 7), align 8 +; SLM-NEXT: ret void +; ; AVX1-LABEL: @mul_v8i64( ; AVX1-NEXT: [[A0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 0), align 8 ; AVX1-NEXT: [[A1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 1), align 8 @@ -162,6 +198,25 @@ define void @mul_v16i32() { ; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 ; SSE-NEXT: ret void ; +; SLM-LABEL: @mul_v16i32( +; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP9:%.*]] = mul <4 x i32> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = mul <4 x i32> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = mul <4 x i32> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = mul <4 x i32> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: ret void +; ; AVX-LABEL: @mul_v16i32( ; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4 ; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4 @@ -267,6 +322,25 @@ define void @mul_v32i16() { ; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 ; SSE-NEXT: ret void ; +; SLM-LABEL: @mul_v32i16( +; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP9:%.*]] = mul <8 x i16> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = mul <8 x i16> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = mul <8 x i16> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = mul <8 x i16> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: ret void +; ; AVX-LABEL: @mul_v32i16( ; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2 ; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2 diff --git a/test/Transforms/SLPVectorizer/X86/arith-sub.ll b/test/Transforms/SLPVectorizer/X86/arith-sub.ll index 8583836..2bbaaca 100644 --- a/test/Transforms/SLPVectorizer/X86/arith-sub.ll +++ b/test/Transforms/SLPVectorizer/X86/arith-sub.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2 ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F @@ -38,6 +39,25 @@ define void @sub_v8i64() { ; SSE-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8 ; SSE-NEXT: ret void ; +; SLM-LABEL: @sub_v8i64( +; SLM-NEXT: [[TMP1:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @a64 to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP4:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @b64 to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP6:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP8:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: [[TMP9:%.*]] = sub <2 x i64> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = sub <2 x i64> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = sub <2 x i64> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = sub <2 x i64> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <2 x i64> [[TMP9]], <2 x i64>* bitcast ([8 x i64]* @c64 to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP10]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2) to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP11]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4) to <2 x i64>*), align 8 +; SLM-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8 +; SLM-NEXT: ret void +; ; AVX-LABEL: @sub_v8i64( ; AVX-NEXT: [[TMP1:%.*]] = load <4 x i64>, <4 x i64>* bitcast ([8 x i64]* @a64 to <4 x i64>*), align 8 ; AVX-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <4 x i64>*), align 8 @@ -111,6 +131,25 @@ define void @sub_v16i32() { ; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 ; SSE-NEXT: ret void ; +; SLM-LABEL: @sub_v16i32( +; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = sub <4 x i32> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = sub <4 x i32> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = sub <4 x i32> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4 +; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4 +; SLM-NEXT: ret void +; ; AVX-LABEL: @sub_v16i32( ; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4 ; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4 @@ -216,6 +255,25 @@ define void @sub_v32i16() { ; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 ; SSE-NEXT: ret void ; +; SLM-LABEL: @sub_v32i16( +; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: [[TMP9:%.*]] = sub <8 x i16> [[TMP1]], [[TMP5]] +; SLM-NEXT: [[TMP10:%.*]] = sub <8 x i16> [[TMP2]], [[TMP6]] +; SLM-NEXT: [[TMP11:%.*]] = sub <8 x i16> [[TMP3]], [[TMP7]] +; SLM-NEXT: [[TMP12:%.*]] = sub <8 x i16> [[TMP4]], [[TMP8]] +; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2 +; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2 +; SLM-NEXT: ret void +; ; AVX-LABEL: @sub_v32i16( ; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2 ; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2 diff --git a/test/Transforms/SafeStack/X86/debug-loc.ll b/test/Transforms/SafeStack/X86/debug-loc.ll index 88cda69..d6b2171 100644 --- a/test/Transforms/SafeStack/X86/debug-loc.ll +++ b/test/Transforms/SafeStack/X86/debug-loc.ll @@ -37,10 +37,10 @@ entry: ; CHECK-DAG: ![[VAR_ARG]] = !DILocalVariable(name: "zzz" ; 100 aligned up to 8 -; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_minus, 104) +; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_constu, 104, DW_OP_minus ; CHECK-DAG: ![[VAR_LOCAL]] = !DILocalVariable(name: "xxx" -; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_minus, 208) +; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_constu, 208, DW_OP_minus ; Function Attrs: nounwind readnone declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 diff --git a/test/Transforms/SafeStack/X86/debug-loc2.ll b/test/Transforms/SafeStack/X86/debug-loc2.ll index 8059a72..731516c 100644 --- a/test/Transforms/SafeStack/X86/debug-loc2.ll +++ b/test/Transforms/SafeStack/X86/debug-loc2.ll @@ -84,8 +84,8 @@ attributes #4 = { nounwind } !13 = !DILocation(line: 5, column: 3, scope: !6) !14 = !DILocation(line: 6, column: 3, scope: !6) -; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 4) -; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 8) +; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 4, DW_OP_minus) +; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 8, DW_OP_minus) !15 = !DIExpression(DW_OP_deref) !16 = !DILocation(line: 5, column: 7, scope: !6) !17 = !DILocation(line: 8, column: 3, scope: !6) @@ -95,4 +95,4 @@ attributes #4 = { nounwind } !21 = !DILocation(line: 10, column: 1, scope: !22) !22 = !DILexicalBlockFile(scope: !6, file: !1, discriminator: 1) !23 = !DIExpression() -!24 = !DIExpression(DW_OP_minus, 42) +!24 = !DIExpression(DW_OP_constu, 42, DW_OP_minus) diff --git a/test/Transforms/Util/PredicateInfo/pr33456.ll b/test/Transforms/Util/PredicateInfo/pr33456.ll new file mode 100644 index 0000000..f1cc83a --- /dev/null +++ b/test/Transforms/Util/PredicateInfo/pr33456.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s +; Don't insert predicate info for conditions with a single target. +@a = global i32 1, align 4 +@d = common global i32 0, align 4 +@c = common global i32 0, align 4 +@b = common global i32 0, align 4 +@e = common global i32 0, align 4 + +define i32 @main() { +; CHECK-LABEL: @main( +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @d, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP13:%.*]] +; CHECK: [[TMP4:%.*]] = load i32, i32* @a, align 4 +; CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @c, align 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 1 +; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP9:%.*]] +; CHECK: [[TMP8:%.*]] = icmp eq i32 [[TMP4]], 0 +; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9]], label [[TMP9]] +; CHECK: [[DOT0:%.*]] = phi i32 [ [[TMP4]], [[TMP7]] ], [ [[TMP4]], [[TMP7]] ], [ [[DOT1:%.*]], [[TMP13]] ], [ [[TMP4]], [[TMP3]] ] +; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* @b, align 4 +; CHECK-NEXT: [[TMP11:%.*]] = sdiv i32 [[TMP10]], [[DOT0]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 0 +; CHECK-NEXT: br i1 [[TMP12]], label [[TMP13]], label [[TMP13]] +; CHECK: [[DOT1]] = phi i32 [ [[DOT0]], [[TMP9]] ], [ [[DOT0]], [[TMP9]] ], [ undef, [[TMP0:%.*]] ] +; CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* @e, align 4 +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i32 [[TMP14]], 0 +; CHECK-NEXT: br i1 [[TMP15]], label [[TMP16:%.*]], label [[TMP9]] +; CHECK: ret i32 0 +; + %1 = load i32, i32* @d, align 4 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %3, label %13 + +;