diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-08-07 23:01:33 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-08-07 23:01:33 +0000 |
commit | ee8648bdac07986a0f1ec897b02ec82a2f144d46 (patch) | |
tree | 52d1861acda1205241ee35a94aa63129c604d469 | |
parent | 1a82d4c088707c791c792f6822f611b47a12bdfe (diff) | |
download | src-ee8648bdac07986a0f1ec897b02ec82a2f144d46.tar.gz src-ee8648bdac07986a0f1ec897b02ec82a2f144d46.zip |
Vendor import of llvm trunk r242221:vendor/llvm/llvm-trunk-r242221
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=286425
svn path=/vendor/llvm/llvm-trunk-r242221/; revision=286426; tag=vendor/llvm/llvm-trunk-r242221
860 files changed, 32133 insertions, 11025 deletions
diff --git a/.gitignore b/.gitignore index f3424d231e2d..e3d191dcbcce 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,9 @@ autoconf/autom4te.cache # Directories to ignore (do not add trailing '/'s, they skip symlinks). #==============================================================================# # External projects that are tracked independently. -projects/*/ +projects/* +!projects/*.* +!projects/Makefile # Clang, which is tracked independently. tools/clang # LLDB, which is tracked independently. diff --git a/autoconf/config.guess b/autoconf/config.guess index 73d671bc2c6b..b209a1a06c6f 100755 --- a/autoconf/config.guess +++ b/autoconf/config.guess @@ -810,6 +810,9 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 diff --git a/bindings/python/llvm/object.py b/bindings/python/llvm/object.py index 4e912ed5da9d..b427113e9cea 100644 --- a/bindings/python/llvm/object.py +++ b/bindings/python/llvm/object.py @@ -372,14 +372,6 @@ class Relocation(LLVMObject): self.expired = False @CachedProperty - def address(self): - """The address of this relocation, in long bytes.""" - if self.expired: - raise Exception('Relocation instance has expired.') - - return lib.LLVMGetRelocationAddress(self) - - @CachedProperty def offset(self): """The offset of this relocation, in long bytes.""" if self.expired: @@ -498,9 +490,6 @@ def register_library(library): library.LLVMGetSymbolSize.argtypes = [Symbol] library.LLVMGetSymbolSize.restype = c_uint64 - library.LLVMGetRelocationAddress.argtypes = [c_object_p] - library.LLVMGetRelocationAddress.restype = c_uint64 - library.LLVMGetRelocationOffset.argtypes = [c_object_p] library.LLVMGetRelocationOffset.restype = c_uint64 diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index 4f60d9e6e7d6..45f6746948d2 100755 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -93,20 +93,9 @@ function(add_llvm_symbol_exports target_name export_file) else() set(native_export_file "${target_name}.def") - set(CAT "cat") - set(export_file_nativeslashes ${export_file}) - if(WIN32 AND NOT CYGWIN AND NOT MSYS) - set(CAT "type") - # Convert ${export_file} to native format (backslashes) for "type" - # Does not use file(TO_NATIVE_PATH) as it doesn't create a native - # path but a build-system specific format (see CMake bug - # http://public.kitware.com/Bug/print_bug_page.php?bug_id=5939 ) - string(REPLACE / \\ export_file_nativeslashes ${export_file}) - endif() - add_custom_command(OUTPUT ${native_export_file} - COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file} - COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file} + COMMAND ${PYTHON_EXECUTABLE} -c "import sys;print(''.join(['EXPORTS\\n']+sys.stdin.readlines(),))" + < ${export_file} > ${native_export_file} DEPENDS ${export_file} VERBATIM COMMENT "Creating export file for ${target_name}") @@ -700,10 +689,18 @@ macro(add_llvm_external_project name) list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") string(REPLACE "-" "_" nameUNDERSCORE ${name}) string(TOUPPER ${nameUNDERSCORE} nameUPPER) - set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}" - CACHE PATH "Path to ${name} source directory") - if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL "" - AND EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt) + #TODO: Remove this check in a few days once it has circulated through + # buildbots and people's checkouts (cbieneman - July 14, 2015) + if("${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") + unset(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR CACHE) + endif() + if(NOT LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR) + set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") + else() + set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR + CACHE PATH "Path to ${name} source directory") + endif() + if (EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt) option(LLVM_EXTERNAL_${nameUPPER}_BUILD "Whether to build ${name} as part of LLVM" ON) if (LLVM_EXTERNAL_${nameUPPER}_BUILD) diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst index 72ed78a3c99a..55ffdb45efe9 100644 --- a/docs/ExceptionHandling.rst +++ b/docs/ExceptionHandling.rst @@ -339,11 +339,11 @@ original context before code generation. Catch handlers are called with a pointer to the handler itself as the first argument and a pointer to the parent function's stack frame as the second -argument. The catch handler uses the `llvm.recoverframe -<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ to get a +argument. The catch handler uses the `llvm.localrecover +<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ to get a pointer to a frame allocation block that is created in the parent frame using -the `llvm.allocateframe -<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ intrinsic. +the `llvm.localescape +<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ intrinsic. The ``WinEHPrepare`` pass will have created a structure definition for the contents of this block. The first two members of the structure will always be (1) a 32-bit integer that the runtime uses to track the exception state of the @@ -520,12 +520,12 @@ action. A code of ``i32 1`` indicates a catch action, which expects three additional arguments. Different EH schemes give different meanings to the three arguments, but the first argument indicates whether the catch should fire, the second is -the frameescape index of the exception object, and the third is the code to run +the localescape index of the exception object, and the third is the code to run to catch the exception. For Windows C++ exception handling, the first argument for a catch handler is a pointer to the RTTI type descriptor for the object to catch. The second -argument is an index into the argument list of the ``llvm.frameescape`` call in +argument is an index into the argument list of the ``llvm.localescape`` call in the main function. The exception object will be copied into the provided stack object. If the exception object is not required, this argument should be -1. The third argument is a pointer to a function implementing the catch. This diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 167280f75f7f..e7d6f67c9399 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -1326,6 +1326,14 @@ example: On an argument, this attribute indicates that the function does not write through this pointer argument, even though it may write to the memory that the pointer points to. +``argmemonly`` + This attribute indicates that the only memory accesses inside function are + loads and stores from objects pointed to by its pointer-typed arguments, + with arbitrary offsets. Or in other words, all memory operations in the + function can refer to memory only using pointers based on its function + arguments. + Note that ``argmemonly`` can be used together with ``readonly`` attribute + in order to specify that function reads only from its arguments. ``returns_twice`` This attribute indicates that this function can return twice. The C ``setjmp`` is an example of such a function. The compiler disables @@ -1446,8 +1454,8 @@ The strings can contain any character by escaping non-printable characters. The escape sequence used is simply "\\xx" where "xx" is the two digit hex code for the number. -The inline asm code is simply printed to the machine code .s file when -assembly code is generated. +Note that the assembly string *must* be parseable by LLVM's integrated assembler +(unless it is disabled), even when emitting a ``.s`` file. .. _langref_datalayout: @@ -1837,8 +1845,8 @@ Fast-Math Flags LLVM IR floating-point binary ops (:ref:`fadd <i_fadd>`, :ref:`fsub <i_fsub>`, :ref:`fmul <i_fmul>`, :ref:`fdiv <i_fdiv>`, -:ref:`frem <i_frem>`) have the following flags that can be set to enable -otherwise unsafe floating point operations +:ref:`frem <i_frem>`, :ref:`fcmp <i_fcmp>`) have the following flags that can +be set to enable otherwise unsafe floating point operations ``nnan`` No NaNs - Allow optimizations to assume the arguments and result are not @@ -2800,13 +2808,36 @@ Inline Assembler Expressions ---------------------------- LLVM supports inline assembler expressions (as opposed to :ref:`Module-Level -Inline Assembly <moduleasm>`) through the use of a special value. This -value represents the inline assembler as a string (containing the -instructions to emit), a list of operand constraints (stored as a -string), a flag that indicates whether or not the inline asm expression -has side effects, and a flag indicating whether the function containing -the asm needs to align its stack conservatively. An example inline -assembler expression is: +Inline Assembly <moduleasm>`) through the use of a special value. This value +represents the inline assembler as a template string (containing the +instructions to emit), a list of operand constraints (stored as a string), a +flag that indicates whether or not the inline asm expression has side effects, +and a flag indicating whether the function containing the asm needs to align its +stack conservatively. + +The template string supports argument substitution of the operands using "``$``" +followed by a number, to indicate substitution of the given register/memory +location, as specified by the constraint string. "``${NUM:MODIFIER}``" may also +be used, where ``MODIFIER`` is a target-specific annotation for how to print the +operand (See :ref:`inline-asm-modifiers`). + +A literal "``$``" may be included by using "``$$``" in the template. To include +other special characters into the output, the usual "``\XX``" escapes may be +used, just as in other strings. Note that after template substitution, the +resulting assembly string is parsed by LLVM's integrated assembler unless it is +disabled -- even when emitting a ``.s`` file -- and thus must contain assembly +syntax known to LLVM. + +LLVM's support for inline asm is modeled closely on the requirements of Clang's +GCC-compatible inline-asm support. Thus, the feature-set and the constraint and +modifier codes listed here are similar or identical to those in GCC's inline asm +support. However, to be clear, the syntax of the template and constraint strings +described here is *not* the same as the syntax accepted by GCC and Clang, and, +while most constraint letters are passed through as-is by Clang, some get +translated to other codes when converting from the C source to the LLVM +assembly. + +An example inline assembler expression is: .. code-block:: llvm @@ -2852,6 +2883,596 @@ If multiple keywords appear the '``sideeffect``' keyword must come first, the '``alignstack``' keyword second and the '``inteldialect``' keyword last. +Inline Asm Constraint String +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The constraint list is a comma-separated string, each element containing one or +more constraint codes. + +For each element in the constraint list an appropriate register or memory +operand will be chosen, and it will be made available to assembly template +string expansion as ``$0`` for the first constraint in the list, ``$1`` for the +second, etc. + +There are three different types of constraints, which are distinguished by a +prefix symbol in front of the constraint code: Output, Input, and Clobber. The +constraints must always be given in that order: outputs first, then inputs, then +clobbers. They cannot be intermingled. + +There are also three different categories of constraint codes: + +- Register constraint. This is either a register class, or a fixed physical + register. This kind of constraint will allocate a register, and if necessary, + bitcast the argument or result to the appropriate type. +- Memory constraint. This kind of constraint is for use with an instruction + taking a memory operand. Different constraints allow for different addressing + modes used by the target. +- Immediate value constraint. This kind of constraint is for an integer or other + immediate value which can be rendered directly into an instruction. The + various target-specific constraints allow the selection of a value in the + proper range for the instruction you wish to use it with. + +Output constraints +"""""""""""""""""" + +Output constraints are specified by an "``=``" prefix (e.g. "``=r``"). This +indicates that the assembly will write to this operand, and the operand will +then be made available as a return value of the ``asm`` expression. Output +constraints do not consume an argument from the call instruction. (Except, see +below about indirect outputs). + +Normally, it is expected that no output locations are written to by the assembly +expression until *all* of the inputs have been read. As such, LLVM may assign +the same register to an output and an input. If this is not safe (e.g. if the +assembly contains two instructions, where the first writes to one output, and +the second reads an input and writes to a second output), then the "``&``" +modifier must be used (e.g. "``=&r``") to specify that the output is an +"early-clobber" output. Marking an ouput as "early-clobber" ensures that LLVM +will not use the same register for any inputs (other than an input tied to this +output). + +Input constraints +""""""""""""""""" + +Input constraints do not have a prefix -- just the constraint codes. Each input +constraint will consume one argument from the call instruction. It is not +permitted for the asm to write to any input register or memory location (unless +that input is tied to an output). Note also that multiple inputs may all be +assigned to the same register, if LLVM can determine that they necessarily all +contain the same value. + +Instead of providing a Constraint Code, input constraints may also "tie" +themselves to an output constraint, by providing an integer as the constraint +string. Tied inputs still consume an argument from the call instruction, and +take up a position in the asm template numbering as is usual -- they will simply +be constrained to always use the same register as the output they've been tied +to. For example, a constraint string of "``=r,0``" says to assign a register for +output, and use that register as an input as well (it being the 0'th +constraint). + +It is permitted to tie an input to an "early-clobber" output. In that case, no +*other* input may share the same register as the input tied to the early-clobber +(even when the other input has the same value). + +You may only tie an input to an output which has a register constraint, not a +memory constraint. Only a single input may be tied to an output. + +There is also an "interesting" feature which deserves a bit of explanation: if a +register class constraint allocates a register which is too small for the value +type operand provided as input, the input value will be split into multiple +registers, and all of them passed to the inline asm. + +However, this feature is often not as useful as you might think. + +Firstly, the registers are *not* guaranteed to be consecutive. So, on those +architectures that have instructions which operate on multiple consecutive +instructions, this is not an appropriate way to support them. (e.g. the 32-bit +SparcV8 has a 64-bit load, which instruction takes a single 32-bit register. The +hardware then loads into both the named register, and the next register. This +feature of inline asm would not be useful to support that.) + +A few of the targets provide a template string modifier allowing explicit access +to the second register of a two-register operand (e.g. MIPS ``L``, ``M``, and +``D``). On such an architecture, you can actually access the second allocated +register (yet, still, not any subsequent ones). But, in that case, you're still +probably better off simply splitting the value into two separate operands, for +clarity. (e.g. see the description of the ``A`` constraint on X86, which, +despite existing only for use with this feature, is not really a good idea to +use) + +Indirect inputs and outputs +""""""""""""""""""""""""""" + +Indirect output or input constraints can be specified by the "``*``" modifier +(which goes after the "``=``" in case of an output). This indicates that the asm +will write to or read from the contents of an *address* provided as an input +argument. (Note that in this way, indirect outputs act more like an *input* than +an output: just like an input, they consume an argument of the call expression, +rather than producing a return value. An indirect output constraint is an +"output" only in that the asm is expected to write to the contents of the input +memory location, instead of just read from it). + +This is most typically used for memory constraint, e.g. "``=*m``", to pass the +address of a variable as a value. + +It is also possible to use an indirect *register* constraint, but only on output +(e.g. "``=*r``"). This will cause LLVM to allocate a register for an output +value normally, and then, separately emit a store to the address provided as +input, after the provided inline asm. (It's not clear what value this +functionality provides, compared to writing the store explicitly after the asm +statement, and it can only produce worse code, since it bypasses many +optimization passes. I would recommend not using it.) + + +Clobber constraints +""""""""""""""""""" + +A clobber constraint is indicated by a "``~``" prefix. A clobber does not +consume an input operand, nor generate an output. Clobbers cannot use any of the +general constraint code letters -- they may use only explicit register +constraints, e.g. "``~{eax}``". The one exception is that a clobber string of +"``~{memory}``" indicates that the assembly writes to arbitrary undeclared +memory locations -- not only the memory pointed to by a declared indirect +output. + + +Constraint Codes +"""""""""""""""" +After a potential prefix comes constraint code, or codes. + +A Constraint Code is either a single letter (e.g. "``r``"), a "``^``" character +followed by two letters (e.g. "``^wc``"), or "``{``" register-name "``}``" +(e.g. "``{eax}``"). + +The one and two letter constraint codes are typically chosen to be the same as +GCC's constraint codes. + +A single constraint may include one or more than constraint code in it, leaving +it up to LLVM to choose which one to use. This is included mainly for +compatibility with the translation of GCC inline asm coming from clang. + +There are two ways to specify alternatives, and either or both may be used in an +inline asm constraint list: + +1) Append the codes to each other, making a constraint code set. E.g. "``im``" + or "``{eax}m``". This means "choose any of the options in the set". The + choice of constraint is made independently for each constraint in the + constraint list. + +2) Use "``|``" between constraint code sets, creating alternatives. Every + constraint in the constraint list must have the same number of alternative + sets. With this syntax, the same alternative in *all* of the items in the + constraint list will be chosen together. + +Putting those together, you might have a two operand constraint string like +``"rm|r,ri|rm"``. This indicates that if operand 0 is ``r`` or ``m``, then +operand 1 may be one of ``r`` or ``i``. If operand 0 is ``r``, then operand 1 +may be one of ``r`` or ``m``. But, operand 0 and 1 cannot both be of type m. + +However, the use of either of the alternatives features is *NOT* recommended, as +LLVM is not able to make an intelligent choice about which one to use. (At the +point it currently needs to choose, not enough information is available to do so +in a smart way.) Thus, it simply tries to make a choice that's most likely to +compile, not one that will be optimal performance. (e.g., given "``rm``", it'll +always choose to use memory, not registers). And, if given multiple registers, +or multiple register classes, it will simply choose the first one. (In fact, it +doesn't currently even ensure explicitly specified physical registers are +unique, so specifying multiple physical registers as alternatives, like +``{r11}{r12},{r11}{r12}``, will assign r11 to both operands, not at all what was +intended.) + +Supported Constraint Code List +"""""""""""""""""""""""""""""" + +The constraint codes are, in general, expected to behave the same way they do in +GCC. LLVM's support is often implemented on an 'as-needed' basis, to support C +inline asm code which was supported by GCC. A mismatch in behavior between LLVM +and GCC likely indicates a bug in LLVM. + +Some constraint codes are typically supported by all targets: + +- ``r``: A register in the target's general purpose register class. +- ``m``: A memory address operand. It is target-specific what addressing modes + are supported, typical examples are register, or register + register offset, + or register + immediate offset (of some target-specific size). +- ``i``: An integer constant (of target-specific width). Allows either a simple + immediate, or a relocatable value. +- ``n``: An integer constant -- *not* including relocatable values. +- ``s``: An integer constant, but allowing *only* relocatable values. +- ``X``: Allows an operand of any kind, no constraint whatsoever. Typically + useful to pass a label for an asm branch or call. + + .. FIXME: but that surely isn't actually okay to jump out of an asm + block without telling llvm about the control transfer???) + +- ``{register-name}``: Requires exactly the named physical register. + +Other constraints are target-specific: + +AArch64: + +- ``z``: An immediate integer 0. Outputs ``WZR`` or ``XZR``, as appropriate. +- ``I``: An immediate integer valid for an ``ADD`` or ``SUB`` instruction, + i.e. 0 to 4095 with optional shift by 12. +- ``J``: An immediate integer that, when negated, is valid for an ``ADD`` or + ``SUB`` instruction, i.e. -1 to -4095 with optional left shift by 12. +- ``K``: An immediate integer that is valid for the 'bitmask immediate 32' of a + logical instruction like ``AND``, ``EOR``, or ``ORR`` with a 32-bit register. +- ``L``: An immediate integer that is valid for the 'bitmask immediate 64' of a + logical instruction like ``AND``, ``EOR``, or ``ORR`` with a 64-bit register. +- ``M``: An immediate integer for use with the ``MOV`` assembly alias on a + 32-bit register. This is a superset of ``K``: in addition to the bitmask + immediate, also allows immediate integers which can be loaded with a single + ``MOVZ`` or ``MOVL`` instruction. +- ``N``: An immediate integer for use with the ``MOV`` assembly alias on a + 64-bit register. This is a superset of ``L``. +- ``Q``: Memory address operand must be in a single register (no + offsets). (However, LLVM currently does this for the ``m`` constraint as + well.) +- ``r``: A 32 or 64-bit integer register (W* or X*). +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register. +- ``x``: A lower 128-bit floating-point/SIMD register (``V0`` to ``V15``). + +AMDGPU: + +- ``r``: A 32 or 64-bit integer register. +- ``[0-9]v``: The 32-bit VGPR register, number 0-9. +- ``[0-9]s``: The 32-bit SGPR register, number 0-9. + + +All ARM modes: + +- ``Q``, ``Um``, ``Un``, ``Uq``, ``Us``, ``Ut``, ``Uv``, ``Uy``: Memory address + operand. Treated the same as operand ``m``, at the moment. + +ARM and ARM's Thumb2 mode: + +- ``j``: An immediate integer between 0 and 65535 (valid for ``MOVW``) +- ``I``: An immediate integer valid for a data-processing instruction. +- ``J``: An immediate integer between -4095 and 4095. +- ``K``: An immediate integer whose bitwise inverse is valid for a + data-processing instruction. (Can be used with template modifier "``B``" to + print the inverted value). +- ``L``: An immediate integer whose negation is valid for a data-processing + instruction. (Can be used with template modifier "``n``" to print the negated + value). +- ``M``: A power of two or a integer between 0 and 32. +- ``N``: Invalid immediate constraint. +- ``O``: Invalid immediate constraint. +- ``r``: A general-purpose 32-bit integer register (``r0-r15``). +- ``l``: In Thumb2 mode, low 32-bit GPR registers (``r0-r7``). In ARM mode, same + as ``r``. +- ``h``: In Thumb2 mode, a high 32-bit GPR register (``r8-r15``). In ARM mode, + invalid. +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s31``, + ``d0-d31``, or ``q0-q15``. +- ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``, + ``d0-d7``, or ``q0-q3``. +- ``t``: A floating-point/SIMD register, only supports 32-bit values: + ``s0-s31``. + +ARM's Thumb1 mode: + +- ``I``: An immediate integer between 0 and 255. +- ``J``: An immediate integer between -255 and -1. +- ``K``: An immediate integer between 0 and 255, with optional left-shift by + some amount. +- ``L``: An immediate integer between -7 and 7. +- ``M``: An immediate integer which is a multiple of 4 between 0 and 1020. +- ``N``: An immediate integer between 0 and 31. +- ``O``: An immediate integer which is a multiple of 4 between -508 and 508. +- ``r``: A low 32-bit GPR register (``r0-r7``). +- ``l``: A low 32-bit GPR register (``r0-r7``). +- ``h``: A high GPR register (``r0-r7``). +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s31``, + ``d0-d31``, or ``q0-q15``. +- ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``, + ``d0-d7``, or ``q0-q3``. +- ``t``: A floating-point/SIMD register, only supports 32-bit values: + ``s0-s31``. + + +Hexagon: + +- ``o``, ``v``: A memory address operand, treated the same as constraint ``m``, + at the moment. +- ``r``: A 32 or 64-bit register. + +MSP430: + +- ``r``: An 8 or 16-bit register. + +MIPS: + +- ``I``: An immediate signed 16-bit integer. +- ``J``: An immediate integer zero. +- ``K``: An immediate unsigned 16-bit integer. +- ``L``: An immediate 32-bit integer, where the lower 16 bits are 0. +- ``N``: An immediate integer between -65535 and -1. +- ``O``: An immediate signed 15-bit integer. +- ``P``: An immediate integer between 1 and 65535. +- ``m``: A memory address operand. In MIPS-SE mode, allows a base address + register plus 16-bit immediate offset. In MIPS mode, just a base register. +- ``R``: A memory address operand. In MIPS-SE mode, allows a base address + register plus a 9-bit signed offset. In MIPS mode, the same as constraint + ``m``. +- ``ZC``: A memory address operand, suitable for use in a ``pref``, ``ll``, or + ``sc`` instruction on the given subtarget (details vary). +- ``r``, ``d``, ``y``: A 32 or 64-bit GPR register. +- ``f``: A 32 or 64-bit FPU register (``F0-F31``), or a 128-bit MSA register + (``W0-W31``). In the case of MSA registers, it is recommended to use the ``w`` + argument modifier for compatibility with GCC. +- ``c``: A 32-bit or 64-bit GPR register suitable for indirect jump (always + ``25``). +- ``l``: The ``lo`` register, 32 or 64-bit. +- ``x``: Invalid. + +NVPTX: + +- ``b``: A 1-bit integer register. +- ``c`` or ``h``: A 16-bit integer register. +- ``r``: A 32-bit integer register. +- ``l`` or ``N``: A 64-bit integer register. +- ``f``: A 32-bit float register. +- ``d``: A 64-bit float register. + + +PowerPC: + +- ``I``: An immediate signed 16-bit integer. +- ``J``: An immediate unsigned 16-bit integer, shifted left 16 bits. +- ``K``: An immediate unsigned 16-bit integer. +- ``L``: An immediate signed 16-bit integer, shifted left 16 bits. +- ``M``: An immediate integer greater than 31. +- ``N``: An immediate integer that is an exact power of 2. +- ``O``: The immediate integer constant 0. +- ``P``: An immediate integer constant whose negation is a signed 16-bit + constant. +- ``es``, ``o``, ``Q``, ``Z``, ``Zy``: A memory address operand, currently + treated the same as ``m``. +- ``r``: A 32 or 64-bit integer register. +- ``b``: A 32 or 64-bit integer register, excluding ``R0`` (that is: + ``R1-R31``). +- ``f``: A 32 or 64-bit float register (``F0-F31``), or when QPX is enabled, a + 128 or 256-bit QPX register (``Q0-Q31``; aliases the ``F`` registers). +- ``v``: For ``4 x f32`` or ``4 x f64`` types, when QPX is enabled, a + 128 or 256-bit QPX register (``Q0-Q31``), otherwise a 128-bit + altivec vector register (``V0-V31``). + + .. FIXME: is this a bug that v accepts QPX registers? I think this + is supposed to only use the altivec vector registers? + +- ``y``: Condition register (``CR0-CR7``). +- ``wc``: An individual CR bit in a CR register. +- ``wa``, ``wd``, ``wf``: Any 128-bit VSX vector register, from the full VSX + register set (overlapping both the floating-point and vector register files). +- ``ws``: A 32 or 64-bit floating point register, from the full VSX register + set. + +Sparc: + +- ``I``: An immediate 13-bit signed integer. +- ``r``: A 32-bit integer register. + +SystemZ: + +- ``I``: An immediate unsigned 8-bit integer. +- ``J``: An immediate unsigned 12-bit integer. +- ``K``: An immediate signed 16-bit integer. +- ``L``: An immediate signed 20-bit integer. +- ``M``: An immediate integer 0x7fffffff. +- ``Q``, ``R``, ``S``, ``T``: A memory address operand, treated the same as + ``m``, at the moment. +- ``r`` or ``d``: A 32, 64, or 128-bit integer register. +- ``a``: A 32, 64, or 128-bit integer address register (excludes R0, which in an + address context evaluates as zero). +- ``h``: A 32-bit value in the high part of a 64bit data register + (LLVM-specific) +- ``f``: A 32, 64, or 128-bit floating point register. + +X86: + +- ``I``: An immediate integer between 0 and 31. +- ``J``: An immediate integer between 0 and 64. +- ``K``: An immediate signed 8-bit integer. +- ``L``: An immediate integer, 0xff or 0xffff or (in 64-bit mode only) + 0xffffffff. +- ``M``: An immediate integer between 0 and 3. +- ``N``: An immediate unsigned 8-bit integer. +- ``O``: An immediate integer between 0 and 127. +- ``e``: An immediate 32-bit signed integer. +- ``Z``: An immediate 32-bit unsigned integer. +- ``o``, ``v``: Treated the same as ``m``, at the moment. +- ``q``: An 8, 16, 32, or 64-bit register which can be accessed as an 8-bit + ``l`` integer register. On X86-32, this is the ``a``, ``b``, ``c``, and ``d`` + registers, and on X86-64, it is all of the integer registers. +- ``Q``: An 8, 16, 32, or 64-bit register which can be accessed as an 8-bit + ``h`` integer register. This is the ``a``, ``b``, ``c``, and ``d`` registers. +- ``r`` or ``l``: An 8, 16, 32, or 64-bit integer register. +- ``R``: An 8, 16, 32, or 64-bit "legacy" integer register -- one which has + existed since i386, and can be accessed without the REX prefix. +- ``f``: A 32, 64, or 80-bit '387 FPU stack pseudo-register. +- ``y``: A 64-bit MMX register, if MMX is enabled. +- ``x``: If SSE is enabled: a 32 or 64-bit scalar operand, or 128-bit vector + operand in a SSE register. If AVX is also enabled, can also be a 256-bit + vector operand in an AVX register. If AVX-512 is also enabled, can also be a + 512-bit vector operand in an AVX512 register, Otherwise, an error. +- ``Y``: The same as ``x``, if *SSE2* is enabled, otherwise an error. +- ``A``: Special case: allocates EAX first, then EDX, for a single operand (in + 32-bit mode, a 64-bit integer operand will get split into two registers). It + is not recommended to use this constraint, as in 64-bit mode, the 64-bit + operand will get allocated only to RAX -- if two 32-bit operands are needed, + you're better off splitting it yourself, before passing it to the asm + statement. + +XCore: + +- ``r``: A 32-bit integer register. + + +.. _inline-asm-modifiers: + +Asm template argument modifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the asm template string, modifiers can be used on the operand reference, like +"``${0:n}``". + +The modifiers are, in general, expected to behave the same way they do in +GCC. LLVM's support is often implemented on an 'as-needed' basis, to support C +inline asm code which was supported by GCC. A mismatch in behavior between LLVM +and GCC likely indicates a bug in LLVM. + +Target-independent: + +- ``c``: Print an immediate integer constant unadorned, without + the target-specific immediate punctuation (e.g. no ``$`` prefix). +- ``n``: Negate and print immediate integer constant unadorned, without the + target-specific immediate punctuation (e.g. no ``$`` prefix). +- ``l``: Print as an unadorned label, without the target-specific label + punctuation (e.g. no ``$`` prefix). + +AArch64: + +- ``w``: Print a GPR register with a ``w*`` name instead of ``x*`` name. E.g., + instead of ``x30``, print ``w30``. +- ``x``: Print a GPR register with a ``x*`` name. (this is the default, anyhow). +- ``b``, ``h``, ``s``, ``d``, ``q``: Print a floating-point/SIMD register with a + ``b*``, ``h*``, ``s*``, ``d*``, or ``q*`` name, rather than the default of + ``v*``. + +AMDGPU: + +- ``r``: No effect. + +ARM: + +- ``a``: Print an operand as an address (with ``[`` and ``]`` surrounding a + register). +- ``P``: No effect. +- ``q``: No effect. +- ``y``: Print a VFP single-precision register as an indexed double (e.g. print + as ``d4[1]`` instead of ``s9``) +- ``B``: Bitwise invert and print an immediate integer constant without ``#`` + prefix. +- ``L``: Print the low 16-bits of an immediate integer constant. +- ``M``: Print as a register set suitable for ldm/stm. Also prints *all* + register operands subsequent to the specified one (!), so use carefully. +- ``Q``: Print the low-order register of a register-pair, or the low-order + register of a two-register operand. +- ``R``: Print the high-order register of a register-pair, or the high-order + register of a two-register operand. +- ``H``: Print the second register of a register-pair. (On a big-endian system, + ``H`` is equivalent to ``Q``, and on little-endian system, ``H`` is equivalent + to ``R``.) + + .. FIXME: H doesn't currently support printing the second register + of a two-register operand. + +- ``e``: Print the low doubleword register of a NEON quad register. +- ``f``: Print the high doubleword register of a NEON quad register. +- ``m``: Print the base register of a memory operand without the ``[`` and ``]`` + adornment. + +Hexagon: + +- ``L``: Print the second register of a two-register operand. Requires that it + has been allocated consecutively to the first. + + .. FIXME: why is it restricted to consecutive ones? And there's + nothing that ensures that happens, is there? + +- ``I``: Print the letter 'i' if the operand is an integer constant, otherwise + nothing. Used to print 'addi' vs 'add' instructions. + +MSP430: + +No additional modifiers. + +MIPS: + +- ``X``: Print an immediate integer as hexadecimal +- ``x``: Print the low 16 bits of an immediate integer as hexadecimal. +- ``d``: Print an immediate integer as decimal. +- ``m``: Subtract one and print an immediate integer as decimal. +- ``z``: Print $0 if an immediate zero, otherwise print normally. +- ``L``: Print the low-order register of a two-register operand, or prints the + address of the low-order word of a double-word memory operand. + + .. FIXME: L seems to be missing memory operand support. + +- ``M``: Print the high-order register of a two-register operand, or prints the + address of the high-order word of a double-word memory operand. + + .. FIXME: M seems to be missing memory operand support. + +- ``D``: Print the second register of a two-register operand, or prints the + second word of a double-word memory operand. (On a big-endian system, ``D`` is + equivalent to ``L``, and on little-endian system, ``D`` is equivalent to + ``M``.) +- ``w``: No effect. Provided for compatibility with GCC which requires this + modifier in order to print MSA registers (``W0-W31``) with the ``f`` + constraint. + +NVPTX: + +- ``r``: No effect. + +PowerPC: + +- ``L``: Print the second register of a two-register operand. Requires that it + has been allocated consecutively to the first. + + .. FIXME: why is it restricted to consecutive ones? And there's + nothing that ensures that happens, is there? + +- ``I``: Print the letter 'i' if the operand is an integer constant, otherwise + nothing. Used to print 'addi' vs 'add' instructions. +- ``y``: For a memory operand, prints formatter for a two-register X-form + instruction. (Currently always prints ``r0,OPERAND``). +- ``U``: Prints 'u' if the memory operand is an update form, and nothing + otherwise. (NOTE: LLVM does not support update form, so this will currently + always print nothing) +- ``X``: Prints 'x' if the memory operand is an indexed form. (NOTE: LLVM does + not support indexed form, so this will currently always print nothing) + +Sparc: + +- ``r``: No effect. + +SystemZ: + +SystemZ implements only ``n``, and does *not* support any of the other +target-independent modifiers. + +X86: + +- ``c``: Print an unadorned integer or symbol name. (The latter is + target-specific behavior for this typically target-independent modifier). +- ``A``: Print a register name with a '``*``' before it. +- ``b``: Print an 8-bit register name (e.g. ``al``); do nothing on a memory + operand. +- ``h``: Print the upper 8-bit register name (e.g. ``ah``); do nothing on a + memory operand. +- ``w``: Print the 16-bit register name (e.g. ``ax``); do nothing on a memory + operand. +- ``k``: Print the 32-bit register name (e.g. ``eax``); do nothing on a memory + operand. +- ``q``: Print the 64-bit register name (e.g. ``rax``), if 64-bit registers are + available, otherwise the 32-bit register name; do nothing on a memory operand. +- ``n``: Negate and print an unadorned integer, or, for operands other than an + immediate integer (e.g. a relocatable symbol expression), print a '-' before + the operand. (The behavior for relocatable symbol expressions is a + target-specific behavior for this typically target-independent modifier) +- ``H``: Print a memory reference with additional offset +8. +- ``P``: Print a memory reference or operand for use as the argument of a call + instruction. (E.g. omit ``(rip)``, even though it's PC-relative.) + +XCore: + +No additional modifiers. + + Inline Asm Metadata ^^^^^^^^^^^^^^^^^^^ @@ -6108,7 +6729,8 @@ Overview: The '``getelementptr``' instruction is used to get the address of a subelement of an :ref:`aggregate <t_aggregate>` data structure. It performs -address calculation only and does not access memory. +address calculation only and does not access memory. The instruction can also +be used to calculate a vector of such addresses. Arguments: """""""""" @@ -6234,12 +6856,61 @@ Example: ; yields i32*:iptr %iptr = getelementptr [10 x i32], [10 x i32]* @arr, i16 0, i16 0 -In cases where the pointer argument is a vector of pointers, each index -must be a vector with the same number of elements. For example: +Vector of pointers: +""""""""""""""""""" + +The ``getelementptr`` returns a vector of pointers, instead of a single address, +when one or more of its arguments is a vector. In such cases, all vector +arguments should have the same number of elements, and every scalar argument +will be effectively broadcast into a vector during address calculation. + +.. code-block:: llvm + + ; All arguments are vectors: + ; A[i] = ptrs[i] + offsets[i]*sizeof(i8) + %A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets + + ; Add the same scalar offset to each pointer of a vector: + ; A[i] = ptrs[i] + offset*sizeof(i8) + %A = getelementptr i8, <4 x i8*> %ptrs, i64 %offset + + ; Add distinct offsets to the same pointer: + ; A[i] = ptr + offsets[i]*sizeof(i8) + %A = getelementptr i8, i8* %ptr, <4 x i64> %offsets + + ; In all cases described above the type of the result is <4 x i8*> + +The two following instructions are equivalent: .. code-block:: llvm - %A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets, + getelementptr %struct.ST, <4 x %struct.ST*> %s, <4 x i64> %ind1, + <4 x i32> <i32 2, i32 2, i32 2, i32 2>, + <4 x i32> <i32 1, i32 1, i32 1, i32 1>, + <4 x i32> %ind4, + <4 x i64> <i64 13, i64 13, i64 13, i64 13> + + getelementptr %struct.ST, <4 x %struct.ST*> %s, <4 x i64> %ind1, + i32 2, i32 1, <4 x i32> %ind4, i64 13 + +Let's look at the C code, where the vector version of ``getelementptr`` +makes sense: + +.. code-block:: c + + // Let's assume that we vectorize the following loop: + double *A, B; int *C; + for (int i = 0; i < size; ++i) { + A[i] = B[C[i]]; + } + +.. code-block:: llvm + + ; get pointers for 8 elements from array B + %ptrs = getelementptr double, double* %B, <8 x i32> %C + ; load 8 elements from array B into A + %A = call <8 x double> @llvm.masked.gather.v8f64(<8 x double*> %ptrs, + i32 8, <8 x i1> %mask, <8 x double> %passthru) Conversion Operations --------------------- @@ -6913,7 +7584,7 @@ Syntax: :: - <result> = fcmp <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result + <result> = fcmp [fast-math flags]* <cond> <ty> <op1>, <op2> ; yields i1 or <N x i1>:result Overview: """"""""" @@ -6996,6 +7667,15 @@ always yields an :ref:`i1 <t_integer>` result, as follows: #. ``uno``: yields ``true`` if either operand is a QNAN. #. ``true``: always yields ``true``, regardless of operands. +The ``fcmp`` instruction can also optionally take any number of +:ref:`fast-math flags <fastmath>`, which are optimization hints to enable +otherwise unsafe floating point optimizations. + +Any set of fast-math flags are legal on an ``fcmp`` instruction, but the +only flags that have any effect on its semantics are those that allow +assumptions to be made about the values of input arguments; namely +``nnan``, ``ninf``, and ``nsz``. See :ref:`fastmath` for more information. + Example: """""""" @@ -7780,7 +8460,7 @@ Note that calling this intrinsic does not prevent function inlining or other aggressive transformations, so the value returned may not be that of the obvious source-language caller. -'``llvm.frameescape``' and '``llvm.framerecover``' Intrinsics +'``llvm.localescape``' and '``llvm.localrecover``' Intrinsics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: @@ -7788,49 +8468,47 @@ Syntax: :: - declare void @llvm.frameescape(...) - declare i8* @llvm.framerecover(i8* %func, i8* %fp, i32 %idx) + declare void @llvm.localescape(...) + declare i8* @llvm.localrecover(i8* %func, i8* %fp, i32 %idx) Overview: """"""""" -The '``llvm.frameescape``' intrinsic escapes offsets of a collection of static -allocas, and the '``llvm.framerecover``' intrinsic applies those offsets to a +The '``llvm.localescape``' intrinsic escapes offsets of a collection of static +allocas, and the '``llvm.localrecover``' intrinsic applies those offsets to a live frame pointer to recover the address of the allocation. The offset is -computed during frame layout of the caller of ``llvm.frameescape``. +computed during frame layout of the caller of ``llvm.localescape``. Arguments: """""""""" -All arguments to '``llvm.frameescape``' must be pointers to static allocas or -casts of static allocas. Each function can only call '``llvm.frameescape``' +All arguments to '``llvm.localescape``' must be pointers to static allocas or +casts of static allocas. Each function can only call '``llvm.localescape``' once, and it can only do so from the entry block. -The ``func`` argument to '``llvm.framerecover``' must be a constant +The ``func`` argument to '``llvm.localrecover``' must be a constant bitcasted pointer to a function defined in the current module. The code generator cannot determine the frame allocation offset of functions defined in other modules. -The ``fp`` argument to '``llvm.framerecover``' must be a frame -pointer of a call frame that is currently live. The return value of -'``llvm.frameaddress``' is one way to produce such a value, but most platforms -also expose the frame pointer through stack unwinding mechanisms. +The ``fp`` argument to '``llvm.localrecover``' must be a frame pointer of a +call frame that is currently live. The return value of '``llvm.localaddress``' +is one way to produce such a value, but various runtimes also expose a suitable +pointer in platform-specific ways. -The ``idx`` argument to '``llvm.framerecover``' indicates which alloca passed to -'``llvm.frameescape``' to recover. It is zero-indexed. +The ``idx`` argument to '``llvm.localrecover``' indicates which alloca passed to +'``llvm.localescape``' to recover. It is zero-indexed. Semantics: """""""""" -These intrinsics allow a group of functions to access one stack memory -allocation in an ancestor stack frame. The memory returned from -'``llvm.frameallocate``' may be allocated prior to stack realignment, so the -memory is only aligned to the ABI-required stack alignment. Each function may -only call '``llvm.frameallocate``' one or zero times from the function entry -block. The frame allocation intrinsic inhibits inlining, as any frame -allocations in the inlined function frame are likely to be at a different -offset from the one used by '``llvm.framerecover``' called with the -uninlined function. +These intrinsics allow a group of functions to share access to a set of local +stack allocations of a one parent function. The parent function may call the +'``llvm.localescape``' intrinsic once from the function entry block, and the +child functions can use '``llvm.localrecover``' to access the escaped allocas. +The '``llvm.localescape``' intrinsic blocks inlining, as inlining changes where +the escaped allocas are allocated, which would break attempts to use +'``llvm.localrecover``'. .. _int_read_register: .. _int_write_register: @@ -9532,6 +10210,75 @@ Examples: Specialised Arithmetic Intrinsics --------------------------------- +'``llvm.canonicalize.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare float @llvm.canonicalize.f32(float %a) + declare double @llvm.canonicalize.f64(double %b) + +Overview: +""""""""" + +The '``llvm.canonicalize.*``' intrinsic returns the platform specific canonical +encoding of a floating point number. This canonicalization is useful for +implementing certain numeric primitives such as frexp. The canonical encoding is +defined by IEEE-754-2008 to be: + +:: + + 2.1.8 canonical encoding: The preferred encoding of a floating-point + representation in a format. Applied to declets, significands of finite + numbers, infinities, and NaNs, especially in decimal formats. + +This operation can also be considered equivalent to the IEEE-754-2008 +conversion of a floating-point value to the same format. NaNs are handled +according to section 6.2. + +Examples of non-canonical encodings: + +- x87 pseudo denormals, pseudo NaNs, pseudo Infinity, Unnormals. These are + converted to a canonical representation per hardware-specific protocol. +- Many normal decimal floating point numbers have non-canonical alternative + encodings. +- Some machines, like GPUs or ARMv7 NEON, do not support subnormal values. + These are treated as non-canonical encodings of zero and with be flushed to + a zero of the same sign by this operation. + +Note that per IEEE-754-2008 6.2, systems that support signaling NaNs with +default exception handling must signal an invalid exception, and produce a +quiet NaN result. + +This function should always be implementable as multiplication by 1.0, provided +that the compiler does not constant fold the operation. Likewise, division by +1.0 and ``llvm.minnum(x, x)`` are possible implementations. Addition with +-0.0 is also sufficient provided that the rounding mode is not -Infinity. + +``@llvm.canonicalize`` must preserve the equality relation. That is: + +- ``(@llvm.canonicalize(x) == x)`` is equivalent to ``(x == x)`` +- ``(@llvm.canonicalize(x) == @llvm.canonicalize(y))`` is equivalent to + to ``(x == y)`` + +Additionally, the sign of zero must be conserved: +``@llvm.canonicalize(-0.0) = -0.0`` and ``@llvm.canonicalize(+0.0) = +0.0`` + +The payload bits of a NaN must be conserved, with two exceptions. +First, environments which use only a single canonical representation of NaN +must perform said canonicalization. Second, SNaNs must be quieted per the +usual methods. + +The canonicalization operation may be optimized away if: + +- The input is known to be canonical. For example, it was produced by a + floating-point operation that is required by the standard to be canonical. +- The result is consumed only by (or fused with) other floating-point + operations. That is, the bits of the floating point value are not examined. + '``llvm.fmuladd.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index ceb39e18efdf..08cc61a187b5 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -1868,7 +1868,7 @@ Iterating over predecessors & successors of blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Iterating over the predecessors and successors of a block is quite easy with the -routines defined in ``"llvm/Support/CFG.h"``. Just use code like this to +routines defined in ``"llvm/IR/CFG.h"``. Just use code like this to iterate over all predecessors of BB: .. code-block:: c++ diff --git a/docs/StackMaps.rst b/docs/StackMaps.rst index 43c60c9e7850..dbdf78f992ca 100644 --- a/docs/StackMaps.rst +++ b/docs/StackMaps.rst @@ -221,12 +221,10 @@ lowered according to the calling convention specified at the intrinsic's callsite. Variants of the intrinsic with non-void return type also return a value according to calling convention. -On PowerPC, note that ``<target>`` must be the actual intended target of -the indirect call. Specifically, even when compiling for the ELF V1 ABI, -``<target>`` is not the function-descriptor address normally used as the C/C++ -function-pointer representation. As a result, the call target must be local -because no adjustment or restoration of the TOC pointer (in register r2) will -be performed. +On PowerPC, note that ``<target>`` must be the ABI function pointer for the +intended target of the indirect call. Specifically, when compiling for the +ELF V1 ABI, ``<target>`` is the function-descriptor address normally used as +the C/C++ function-pointer representation. Requesting zero patch point arguments is valid. In this case, all variable operands are handled just like diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 713894f57639..15290072abe8 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -1888,6 +1888,20 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, void LLVMDeleteFunction(LLVMValueRef Fn); /** + * Obtain the personality function attached to the function. + * + * @see llvm::Function::getPersonalityFn() + */ +LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn); + +/** + * Set the personality function attached to the function. + * + * @see llvm::Function::setPersonalityFn() + */ +void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn); + +/** * Obtain the ID number from a function instance. * * @see llvm::Function::getIntrinsicID() diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index 447fcea7bc24..9cab5c426c45 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -81,7 +81,6 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI); uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI); // RelocationRef accessors -uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI); uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI); LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI); uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 42c05a2fc59e..cb3a69160454 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 16 +#define LTO_API_VERSION 17 /** * \since prior to LTO_API_VERSION=3 @@ -63,7 +63,8 @@ typedef enum { LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800, LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800, - LTO_SYMBOL_COMDAT = 0x00004000 + LTO_SYMBOL_COMDAT = 0x00004000, + LTO_SYMBOL_ALIAS = 0x00008000 } lto_symbol_attributes; /** diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 958e3fdaea14..76615affb253 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -276,6 +276,10 @@ public: /// \param isIEEE - If 128 bit number, select between PPC and IEEE static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + /// Returns the size of the floating point number (in bits) in the given + /// semantics. + static unsigned getSizeInBits(const fltSemantics &Sem); + /// @} /// Used to insert APFloat objects, or objects that contain APFloat objects, diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 06f5870119c8..947812d94ecb 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -569,6 +569,22 @@ public: /// architecture if no such variant can be found. llvm::Triple get64BitArchVariant() const; + /// Form a triple with a big endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a big endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getBigEndianArchVariant() const; + + /// Form a triple with a little endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a little endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getLittleEndianArchVariant() const; + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. /// /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h index c2b2041242aa..06a01b18a9fb 100644 --- a/include/llvm/ADT/edit_distance.h +++ b/include/llvm/ADT/edit_distance.h @@ -50,50 +50,51 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray, // http://en.wikipedia.org/wiki/Levenshtein_distance // // Although the algorithm is typically described using an m x n - // array, only two rows are used at a time, so this implementation - // just keeps two separate vectors for those two rows. + // array, only one row plus one element are used at a time, so this + // implementation just keeps one vector for the row. To update one entry, + // only the entries to the left, top, and top-left are needed. The left + // entry is in Row[x-1], the top entry is what's in Row[x] from the last + // iteration, and the top-left entry is stored in Previous. typename ArrayRef<T>::size_type m = FromArray.size(); typename ArrayRef<T>::size_type n = ToArray.size(); const unsigned SmallBufferSize = 64; unsigned SmallBuffer[SmallBufferSize]; std::unique_ptr<unsigned[]> Allocated; - unsigned *Previous = SmallBuffer; - if (2*(n + 1) > SmallBufferSize) { - Previous = new unsigned [2*(n+1)]; - Allocated.reset(Previous); + unsigned *Row = SmallBuffer; + if (n + 1 > SmallBufferSize) { + Row = new unsigned[n + 1]; + Allocated.reset(Row); } - unsigned *Current = Previous + (n + 1); - for (unsigned i = 0; i <= n; ++i) - Previous[i] = i; + for (unsigned i = 1; i <= n; ++i) + Row[i] = i; for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) { - Current[0] = y; - unsigned BestThisRow = Current[0]; + Row[0] = y; + unsigned BestThisRow = Row[0]; + unsigned Previous = y - 1; for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) { + int OldRow = Row[x]; if (AllowReplacements) { - Current[x] = std::min( - Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), - std::min(Current[x-1], Previous[x])+1); + Row[x] = std::min( + Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), + std::min(Row[x-1], Row[x])+1); } else { - if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1]; - else Current[x] = std::min(Current[x-1], Previous[x]) + 1; + if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous; + else Row[x] = std::min(Row[x-1], Row[x]) + 1; } - BestThisRow = std::min(BestThisRow, Current[x]); + Previous = OldRow; + BestThisRow = std::min(BestThisRow, Row[x]); } if (MaxEditDistance && BestThisRow > MaxEditDistance) return MaxEditDistance + 1; - - unsigned *tmp = Current; - Current = Previous; - Previous = tmp; } - unsigned Result = Previous[n]; + unsigned Result = Row[n]; return Result; } diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index f4c1167314a1..36f8199a0322 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -211,6 +211,8 @@ public: /// (if it has any) are non-volatile loads from objects pointed to by its /// pointer-typed arguments, with arbitrary offsets. /// + /// This property corresponds to the LLVM IR 'argmemonly' attribute combined + /// with 'readonly' attribute. /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. OnlyReadsArgumentPointees = ArgumentPointees | Ref, @@ -218,6 +220,7 @@ public: /// function (if it has any) are non-volatile loads and stores from objects /// pointed to by its pointer-typed arguments, with arbitrary offsets. /// + /// This property corresponds to the LLVM IR 'argmemonly' attribute. /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag. OnlyAccessesArgumentPointees = ArgumentPointees | ModRef, @@ -518,14 +521,6 @@ public: /// virtual void deleteValue(Value *V); - /// copyValue - This method should be used whenever a preexisting value in the - /// program is copied or cloned, introducing a new value. Note that analysis - /// implementations should tolerate clients that use this method to introduce - /// the same value multiple times: if the analysis already knows about a - /// value, it should ignore the request. - /// - virtual void copyValue(Value *From, Value *To); - /// addEscapingUse - This method should be used whenever an escaping use is /// added to a pointer value. Analysis implementations may either return /// conservative responses for that value in the future, or may recompute @@ -541,7 +536,6 @@ public: /// above, and it provided as a helper to simplify client code. /// void replaceWithNewValue(Value *Old, Value *New) { - copyValue(Old, New); deleteValue(Old); } }; diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 541a2109af6c..e8185b3b6307 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -72,6 +72,17 @@ namespace llvm { Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef<unsigned> Idxs); +/// \brief Attempt to constant fold an extractvalue instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractValueInstruction(Constant *Agg, + ArrayRef<unsigned> Idxs); + +/// \brief Attempt to constant fold an extractelement instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); + /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index 996700efdb60..fb730054a8e5 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -202,8 +202,8 @@ public: void dump() const; }; -EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase<BasicBlock>); -EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase<BasicBlock>); +extern template class DominanceFrontierBase<BasicBlock>; +extern template class ForwardDominanceFrontierBase<BasicBlock>; } // End llvm namespace diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index ae9c1f5bd9ac..00dbcbdd7806 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -21,6 +21,7 @@ namespace llvm { +class AssumptionCache; class DominatorTree; class Instruction; class Value; @@ -119,15 +120,19 @@ private: class IVUsers : public LoopPass { friend class IVStrideUse; Loop *L; + AssumptionCache *AC; LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - SmallPtrSet<Instruction*,16> Processed; + SmallPtrSet<Instruction*, 16> Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions /// we are interested in. ilist<IVStrideUse> IVUses; + // Ephemeral values used by @llvm.assume in this function. + SmallPtrSet<const Value *, 32> EphValues; + void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnLoop(Loop *L, LPPassManager &LPM) override; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 706bd8000d3a..d44c5ff4078d 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -212,7 +212,7 @@ namespace llvm { /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout &DL, + FastMathFlags FMF, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -244,6 +244,24 @@ namespace llvm { AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// \brief Given operands for an ExtractValueInst, see if we can fold the + /// result. If not, this returns null. + Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + + /// \brief Given operands for an ExtractElementInst, see if we can fold the + /// result. If not, this returns null. + Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h deleted file mode 100644 index b6dad478cdf2..000000000000 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ /dev/null @@ -1,71 +0,0 @@ -//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Information about jump-instruction tables that have been created by -/// JumpInstrTables pass. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H -#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Pass.h" -#include <vector> - -namespace llvm { -class Function; -class FunctionType; - -/// This class stores information about jump-instruction tables created by the -/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a -/// map from a function type to a vector of pairs. The first element of each -/// pair is the function that has the jumptable annotation. The second element -/// is a function that was declared by JumpInstrTables and used to replace all -/// address-taking sites for the original function. -/// -/// The information in this pass is used in AsmPrinter -/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly -/// for the jump-instruction tables. -class JumpInstrTableInfo : public ImmutablePass { -public: - static char ID; - - /// The default byte alignment for jump tables is 16, which is large but - /// usually safe. - JumpInstrTableInfo(uint64_t ByteAlign = 16); - ~JumpInstrTableInfo() override; - const char *getPassName() const override { - return "Jump-Instruction Table Info"; - } - - typedef std::pair<Function *, Function *> JumpPair; - typedef DenseMap<FunctionType *, std::vector<JumpPair> > JumpTables; - - /// Inserts an entry in a table, adding the table if it doesn't exist. - void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump); - - /// Gets the tables. - const JumpTables &getTables() const { return Tables; } - - /// Gets the alignment in bytes of a jumptable entry. - uint64_t entryByteAlignment() const { return ByteAlignment; } -private: - JumpTables Tables; - - /// A power-of-two alignment of a jumptable entry. - uint64_t ByteAlignment; -}; - -/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This -/// bound specifies the maximum number of bytes needed to represent an -/// unconditional jump or a trap instruction in the back end currently in use. -ModulePass *createJumpInstrTableInfoPass(unsigned Bound); -} - -#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 170e2a49a8ea..b4bef310e590 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -206,6 +206,18 @@ class InvokeInst; llvm_unreachable("invalid enum"); } + /// \brief Return true if this personality may be safely removed if there + /// are no invoke instructions remaining in the current function. + inline bool isNoOpWithoutInvoke(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::Unknown: + return false; + // All known personalities currently have this behavior + default: return true; + } + llvm_unreachable("invalid enum"); + } + bool canSimplifyInvokeNoUnwind(const Function *F); } // end namespace llvm diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 7b635a8b4960..476e4b6686bb 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -292,6 +292,133 @@ private: bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize); }; +/// \brief Holds information about the memory runtime legality checks to verify +/// that a group of pointers do not overlap. +class RuntimePointerChecking { +public: + struct PointerInfo { + /// Holds the pointer value that we need to check. + TrackingVH<Value> PointerValue; + /// Holds the pointer value at the beginning of the loop. + const SCEV *Start; + /// Holds the pointer value at the end of the loop. + const SCEV *End; + /// Holds the information if this pointer is used for writing to memory. + bool IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + unsigned DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + unsigned AliasSetId; + /// SCEV for the access. + const SCEV *Expr; + + PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, + bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, + const SCEV *Expr) + : PointerValue(PointerValue), Start(Start), End(End), + IsWritePtr(IsWritePtr), DependencySetId(DependencySetId), + AliasSetId(AliasSetId), Expr(Expr) {} + }; + + RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, + unsigned ASId, const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// A grouping of pointers. A single memcheck is required between + /// two groups. + struct CheckingPtrGroup { + /// \brief Create a new pointer checking group containing a single + /// pointer, with index \p Index in RtCheck. + CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck) + : RtCheck(RtCheck), High(RtCheck.Pointers[Index].End), + Low(RtCheck.Pointers[Index].Start) { + Members.push_back(Index); + } + + /// \brief Tries to add the pointer recorded in RtCheck at index + /// \p Index to this pointer checking group. We can only add a pointer + /// to a checking group if we will still be able to get + /// the upper and lower bounds of the check. Returns true in case + /// of success, false otherwise. + bool addPointer(unsigned Index); + + /// Constitutes the context of this pointer checking group. For each + /// pointer that is a member of this group we will retain the index + /// at which it appears in RtCheck. + RuntimePointerChecking &RtCheck; + /// The SCEV expression which represents the upper bound of all the + /// pointers in this group. + const SCEV *High; + /// The SCEV expression which represents the lower bound of all the + /// pointers in this group. + const SCEV *Low; + /// Indices of all the pointers that constitute this grouping. + SmallVector<unsigned, 2> Members; + }; + + /// \brief Groups pointers such that a single memcheck is required + /// between two different groups. This will clear the CheckingGroups vector + /// and re-compute it. We will only group dependecies if \p UseDependencies + /// is true, otherwise we will create a separate group for each pointer. + void groupChecks(MemoryDepChecker::DepCandidates &DepCands, + bool UseDependencies); + + /// \brief Decide if we need to add a check between two groups of pointers, + /// according to needsChecking. + bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N, + const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Return true if any pointer requires run-time checking according + /// to needsChecking. + bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Returns the number of run-time checks required according to + /// needsChecking. + unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Print the list run-time memory checks necessary. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + void print(raw_ostream &OS, unsigned Depth = 0, + const SmallVectorImpl<int> *PtrPartition = nullptr) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + + /// Information about the pointers that may require checking. + SmallVector<PointerInfo, 2> Pointers; + + /// Holds a partitioning of pointers into "check groups". + SmallVector<CheckingPtrGroup, 2> CheckingGroups; + +private: + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + bool needsChecking(unsigned I, unsigned J, + const SmallVectorImpl<int> *PtrPartition) const; + + /// Holds a pointer to the ScalarEvolution analysis. + ScalarEvolution *SE; +}; + /// \brief Drive the analysis of memory accesses in the loop /// /// This class is responsible for analyzing the memory accesses of a loop. It @@ -308,72 +435,6 @@ private: /// RuntimePointerCheck class. class LoopAccessInfo { public: - /// This struct holds information about the memory runtime legality check that - /// a group of pointers do not overlap. - struct RuntimePointerCheck { - RuntimePointerCheck() : Need(false) {} - - /// Reset the state of the pointer runtime information. - void reset() { - Need = false; - Pointers.clear(); - Starts.clear(); - Ends.clear(); - IsWritePtr.clear(); - DependencySetId.clear(); - AliasSetId.clear(); - } - - /// Insert a pointer and calculate the start and end SCEVs. - void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, - unsigned DepSetId, unsigned ASId, - const ValueToValueMap &Strides); - - /// \brief No run-time memory checking is necessary. - bool empty() const { return Pointers.empty(); } - - /// \brief Decide whether we need to issue a run-time check for pointer at - /// index \p I and \p J to prove their independence. - /// - /// If \p PtrPartition is set, it contains the partition number for - /// pointers (-1 if the pointer belongs to multiple partitions). In this - /// case omit checks between pointers belonging to the same partition. - bool needsChecking(unsigned I, unsigned J, - const SmallVectorImpl<int> *PtrPartition) const; - - /// \brief Return true if any pointer requires run-time checking according - /// to needsChecking. - bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; - - /// \brief Returns the number of run-time checks required according to - /// needsChecking. - unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const; - - /// \brief Print the list run-time memory checks necessary. - /// - /// If \p PtrPartition is set, it contains the partition number for - /// pointers (-1 if the pointer belongs to multiple partitions). In this - /// case omit checks between pointers belonging to the same partition. - void print(raw_ostream &OS, unsigned Depth = 0, - const SmallVectorImpl<int> *PtrPartition = nullptr) const; - - /// This flag indicates if we need to add the runtime check. - bool Need; - /// Holds the pointers that we need to check. - SmallVector<TrackingVH<Value>, 2> Pointers; - /// Holds the pointer value at the beginning of the loop. - SmallVector<const SCEV*, 2> Starts; - /// Holds the pointer value at the end of the loop. - SmallVector<const SCEV*, 2> Ends; - /// Holds the information if this pointer is used for writing to memory. - SmallVector<bool, 2> IsWritePtr; - /// Holds the id of the set of pointers that could be dependent because of a - /// shared underlying object. - SmallVector<unsigned, 2> DependencySetId; - /// Holds the id of the disjoint alias set to which this pointer belongs. - SmallVector<unsigned, 2> AliasSetId; - }; - LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI, @@ -383,15 +444,15 @@ public: /// no memory dependence cycles. bool canVectorizeMemory() const { return CanVecMem; } - const RuntimePointerCheck *getRuntimePointerCheck() const { - return &PtrRtCheck; + const RuntimePointerChecking *getRuntimePointerChecking() const { + return &PtrRtChecking; } /// \brief Number of memchecks required to prove independence of otherwise /// may-alias pointers. unsigned getNumRuntimePointerChecks( const SmallVectorImpl<int> *PtrPartition = nullptr) const { - return PtrRtCheck.getNumberOfChecks(PtrPartition); + return PtrRtChecking.getNumberOfChecks(PtrPartition); } /// Return true if the block BB needs to be predicated in order for the loop @@ -461,7 +522,7 @@ private: /// We need to check that all of the pointers in this list are disjoint /// at runtime. - RuntimePointerCheck PtrRtCheck; + RuntimePointerChecking PtrRtChecking; /// \brief the Memory Dependence Checker which can determine the /// loop-independent and loop-carried dependences between memory accesses. diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index bbcde8d9721a..3ec83f2c21fd 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -347,9 +347,7 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) { } // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template class LoopBase<BasicBlock, Loop>; -#endif +extern template class LoopBase<BasicBlock, Loop>; class Loop : public LoopBase<BasicBlock, Loop> { public: @@ -633,9 +631,7 @@ public: }; // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template class LoopInfoBase<BasicBlock, Loop>; -#endif +extern template class LoopInfoBase<BasicBlock, Loop>; class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { typedef LoopInfoBase<BasicBlock, Loop> BaseT; diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 7ceb086ee0a1..8560f1f67160 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -902,9 +902,9 @@ inline raw_ostream &operator<<(raw_ostream &OS, return OS << Node.template getNodeAs<BlockT>()->getName(); } -EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<Function>>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<Function>>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<Function>>); +extern template class RegionBase<RegionTraits<Function>>; +extern template class RegionNodeBase<RegionTraits<Function>>; +extern template class RegionInfoBase<RegionTraits<Function>>; } // End llvm namespace #endif diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index bb6e266b1f5b..01f00896410e 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -69,7 +69,7 @@ public: /// /// The TTI implementation will reflect the information in the DataLayout /// provided if non-null. - explicit TargetTransformInfo(const DataLayout *DL); + explicit TargetTransformInfo(const DataLayout &DL); // Provide move semantics. TargetTransformInfo(TargetTransformInfo &&Arg); @@ -541,7 +541,7 @@ private: class TargetTransformInfo::Concept { public: virtual ~Concept() = 0; - + virtual const DataLayout &getDataLayout() const = 0; virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; virtual unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) = 0; @@ -636,6 +636,10 @@ public: Model(T Impl) : Impl(std::move(Impl)) {} ~Model() override {} + const DataLayout &getDataLayout() const override { + return Impl.getDataLayout(); + } + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { return Impl.getOperationCost(Opcode, Ty, OpTy); } diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 403175acae02..035cb04870a1 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -30,26 +30,17 @@ class TargetTransformInfoImplBase { protected: typedef TargetTransformInfo TTI; - const DataLayout *DL; + const DataLayout &DL; - explicit TargetTransformInfoImplBase(const DataLayout *DL) - : DL(DL) {} + explicit TargetTransformInfoImplBase(const DataLayout &DL) : DL(DL) {} public: // Provide value semantics. MSVC requires that we spell all of these out. TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) : DL(Arg.DL) {} - TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) - : DL(std::move(Arg.DL)) {} - TargetTransformInfoImplBase & - operator=(const TargetTransformInfoImplBase &RHS) { - DL = RHS.DL; - return *this; - } - TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { - DL = std::move(RHS.DL); - return *this; - } + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) : DL(Arg.DL) {} + + const DataLayout &getDataLayout() const { return DL; } unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { switch (Opcode) { @@ -70,28 +61,22 @@ public: return TTI::TCC_Basic; case Instruction::IntToPtr: { - if (!DL) - return TTI::TCC_Basic; - // An inttoptr cast is free so long as the input is a legal integer type // which doesn't contain values outside the range of a pointer. unsigned OpSize = OpTy->getScalarSizeInBits(); - if (DL->isLegalInteger(OpSize) && - OpSize <= DL->getPointerTypeSizeInBits(Ty)) + if (DL.isLegalInteger(OpSize) && + OpSize <= DL.getPointerTypeSizeInBits(Ty)) return TTI::TCC_Free; // Otherwise it's not a no-op. return TTI::TCC_Basic; } case Instruction::PtrToInt: { - if (!DL) - return TTI::TCC_Basic; - // A ptrtoint cast is free so long as the result is large enough to store // the pointer, and a legal integer type. unsigned DestSize = Ty->getScalarSizeInBits(); - if (DL->isLegalInteger(DestSize) && - DestSize >= DL->getPointerTypeSizeInBits(OpTy)) + if (DL.isLegalInteger(DestSize) && + DestSize >= DL.getPointerTypeSizeInBits(OpTy)) return TTI::TCC_Free; // Otherwise it's not a no-op. @@ -100,7 +85,7 @@ public: case Instruction::Trunc: // trunc to a native type is free (assuming the target has compare and // shift-right of the same width). - if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty))) + if (DL.isLegalInteger(DL.getTypeSizeInBits(Ty))) return TTI::TCC_Free; return TTI::TCC_Basic; @@ -353,8 +338,7 @@ private: typedef TargetTransformInfoImplBase BaseT; protected: - explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) - : BaseT(DL) {} + explicit TargetTransformInfoImplCRTPBase(const DataLayout &DL) : BaseT(DL) {} public: // Provide value semantics. MSVC requires that we spell all of these out. @@ -362,16 +346,6 @@ public: : BaseT(static_cast<const BaseT &>(Arg)) {} TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} - TargetTransformInfoImplCRTPBase & - operator=(const TargetTransformInfoImplCRTPBase &RHS) { - BaseT::operator=(static_cast<const BaseT &>(RHS)); - return *this; - } - TargetTransformInfoImplCRTPBase & - operator=(TargetTransformInfoImplCRTPBase &&RHS) { - BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - return *this; - } using BaseT::getCallCost; diff --git a/include/llvm/Analysis/VectorUtils.h b/include/llvm/Analysis/VectorUtils.h index aa538ecc0137..d8e9ca42e623 100644 --- a/include/llvm/Analysis/VectorUtils.h +++ b/include/llvm/Analysis/VectorUtils.h @@ -20,6 +20,12 @@ namespace llvm { +class GetElementPtrInst; +class Loop; +class ScalarEvolution; +class Type; +class Value; + /// \brief Identify if the intrinsic is trivially vectorizable. /// This method returns true if the intrinsic's argument types are all /// scalars for the scalar form of the intrinsic and all vectors for @@ -51,6 +57,28 @@ Intrinsic::ID checkBinaryFloatSignature(const CallInst &I, /// its intrinsic ID, in case it does not found it return not_intrinsic. Intrinsic::ID getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI); +/// \brief Find the operand of the GEP that should be checked for consecutive +/// stores. This ignores trailing indices that have no effect on the final +/// pointer. +unsigned getGEPInductionOperand(const GetElementPtrInst *Gep); + +/// \brief If the argument is a GEP, then returns the operand identified by +/// getGEPInductionOperand. However, if there is some other non-loop-invariant +/// operand, it returns that instead. +Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp); + +/// \brief If a value has only one user that is a CastInst, return it. +Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty); + +/// \brief Get the stride of a pointer access in a loop. Looks for symbolic +/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise. +Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp); + +/// \brief Given a vector and an element number, see if the scalar value is +/// already around as a register, for example if it were inserted then extracted +/// from the vector. +Value *findScalarElement(Value *V, unsigned EltNo); + } // llvm namespace #endif diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 605c4172dd87..7130ee755237 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -407,6 +407,7 @@ namespace bitc { ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42, ATTR_KIND_CONVERGENT = 43, ATTR_KIND_SAFESTACK = 44, + ATTR_KIND_ARGMEMONLY = 45 }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 6797aa133c42..452ec3bd0187 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -146,7 +146,7 @@ namespace llvm { } const std::error_category &BitcodeErrorCategory(); - enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; + enum class BitcodeError { InvalidBitcodeSignature = 1, CorruptedBitcode }; inline std::error_code make_error_code(BitcodeError E) { return std::error_code(static_cast<int>(E), BitcodeErrorCategory()); } diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index c4b94ede4f55..82d1e8ada17d 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -64,7 +64,7 @@ inline unsigned ComputeLinearIndex(Type *Ty, /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// -void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, +void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl<EVT> &ValueVTs, SmallVectorImpl<uint64_t> *Offsets = nullptr, uint64_t StartingOffset = 0); diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index 3e464f4f1e5a..9ba25169fda6 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -91,8 +91,10 @@ private: } protected: - explicit BasicTTIImplBase(const TargetMachine *TM) - : BaseT(TM->getDataLayout()) {} + explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL) + : BaseT(DL) {} + + using TargetTransformInfoImplBase::DL; public: // Provide value semantics. MSVC requires that we spell all of these out. @@ -100,14 +102,6 @@ public: : BaseT(static_cast<const BaseT &>(Arg)) {} BasicTTIImplBase(BasicTTIImplBase &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} - BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { - BaseT::operator=(static_cast<const BaseT &>(RHS)); - return *this; - } - BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { - BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - return *this; - } /// \name Scalar TTI Implementations /// @{ @@ -132,7 +126,7 @@ public: AM.BaseOffs = BaseOffset; AM.HasBaseReg = HasBaseReg; AM.Scale = Scale; - return getTLI()->isLegalAddressingMode(AM, Ty, AddrSpace); + return getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace); } int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, @@ -142,7 +136,7 @@ public: AM.BaseOffs = BaseOffset; AM.HasBaseReg = HasBaseReg; AM.Scale = Scale; - return getTLI()->getScalingFactorCost(AM, Ty, AddrSpace); + return getTLI()->getScalingFactorCost(DL, AM, Ty, AddrSpace); } bool isTruncateFree(Type *Ty1, Type *Ty2) { @@ -154,7 +148,7 @@ public: } bool isTypeLegal(Type *Ty) { - EVT VT = getTLI()->getValueType(Ty); + EVT VT = getTLI()->getValueType(DL, Ty); return getTLI()->isTypeLegal(VT); } @@ -192,7 +186,7 @@ public: bool haveFastSqrt(Type *Ty) { const TargetLoweringBase *TLI = getTLI(); - EVT VT = TLI->getValueType(Ty); + EVT VT = TLI->getValueType(DL, Ty); return TLI->isTypeLegal(VT) && TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); } @@ -282,7 +276,7 @@ public: /// \name Vector TTI Implementations /// @{ - unsigned getNumberOfRegisters(bool Vector) { return 1; } + unsigned getNumberOfRegisters(bool Vector) { return Vector ? 0 : 1; } unsigned getRegisterBitWidth(bool Vector) { return 32; } @@ -299,7 +293,7 @@ public: int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(Ty); + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty); bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); // Assume that floating point arithmetic operations cost twice as much as @@ -349,9 +343,8 @@ public: const TargetLoweringBase *TLI = getTLI(); int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - - std::pair<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(Src); - std::pair<unsigned, MVT> DstLT = TLI->getTypeLegalizationCost(Dst); + std::pair<unsigned, MVT> SrcLT = TLI->getTypeLegalizationCost(DL, Src); + std::pair<unsigned, MVT> DstLT = TLI->getTypeLegalizationCost(DL, Dst); // Check for NOOP conversions. if (SrcLT.first == DstLT.first && @@ -455,8 +448,7 @@ public: if (CondTy->isVectorTy()) ISD = ISD::VSELECT; } - - std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(ValTy); + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, ValTy); if (!(ValTy->isVectorTy() && !LT.second.isVector()) && !TLI->isOperationExpand(ISD, LT.second)) { @@ -485,7 +477,7 @@ public: unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { std::pair<unsigned, MVT> LT = - getTLI()->getTypeLegalizationCost(Val->getScalarType()); + getTLI()->getTypeLegalizationCost(DL, Val->getScalarType()); return LT.first; } @@ -493,7 +485,7 @@ public: unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned AddressSpace) { assert(!Src->isVoidTy() && "Invalid type"); - std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Src); + std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(DL, Src); // Assuming that all loads of legal types cost 1. unsigned Cost = LT.first; @@ -504,7 +496,7 @@ public: // itself. Unless the corresponding extending load or truncating store is // legal, then this will scalarize. TargetLowering::LegalizeAction LA = TargetLowering::Expand; - EVT MemVT = getTLI()->getValueType(Src, true); + EVT MemVT = getTLI()->getValueType(DL, Src, true); if (MemVT.isSimple() && MemVT != MVT::Other) { if (Opcode == Instruction::Store) LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); @@ -700,7 +692,7 @@ public: } const TargetLoweringBase *TLI = getTLI(); - std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(RetTy); + std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, RetTy); if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { // The operation is legal. Assume it costs 1. @@ -771,7 +763,7 @@ public: } unsigned getNumberOfParts(Type *Tp) { - std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(Tp); + std::pair<unsigned, MVT> LT = getTLI()->getTypeLegalizationCost(DL, Tp); return LT.first; } @@ -816,18 +808,6 @@ public: BasicTTIImpl(BasicTTIImpl &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)), TLI(std::move(Arg.TLI)) {} - BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { - BaseT::operator=(static_cast<const BaseT &>(RHS)); - ST = RHS.ST; - TLI = RHS.TLI; - return *this; - } - BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { - BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); - ST = std::move(RHS.ST); - TLI = std::move(RHS.TLI); - return *this; - } }; } diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 554511d6f4ab..4b2e0b06584c 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -206,6 +206,10 @@ cl::opt<std::string> StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); +cl::opt<std::string> + RunPass("run-pass", cl::desc("Run compiler only for one specific pass"), + cl::value_desc("pass-name"), cl::init("")); + cl::opt<bool> DataSections("data-sections", cl::desc("Emit data into separate sections"), cl::init(false)); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index c7237fd55b27..fa44301a2d4a 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,10 +72,13 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, - /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover - /// intrinsic. Materializes the offset from the frame pointer of another - /// function to the result of llvm.frameallocate. - FRAME_ALLOC_RECOVER, + /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. + /// Materializes the offset from the local object pointer of another + /// function to a particular local object passed to llvm.localescape. The + /// operand is the MCSymbol label used to represent this offset, since + /// typically the offset is not known until after code generation of the + /// parent. + LOCAL_RECOVER, /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. @@ -725,7 +728,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+300; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 967f0cbac719..f0f1637dc92d 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -203,6 +203,11 @@ public: assert(idx < Size && "idx out of bounds"); return LIUs[idx]; } + + const LiveIntervalUnion& operator[](unsigned Idx) const { + assert(Idx < Size && "Idx out of bounds"); + return LIUs[Idx]; + } }; }; diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index 878b4d9836f2..e169058ca563 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -32,13 +32,11 @@ namespace llvm { class LiveInterval; class LiveIntervalAnalysis; -class MachineRegisterInfo; class TargetRegisterInfo; class VirtRegMap; class LiveRegMatrix : public MachineFunctionPass { const TargetRegisterInfo *TRI; - MachineRegisterInfo *MRI; LiveIntervals *LIS; VirtRegMap *VRM; @@ -114,6 +112,9 @@ public: /// the assignment and updates VirtRegMap accordingly. void unassign(LiveInterval &VirtReg); + /// Returns true if the given \p PhysReg has any live intervals assigned. + bool isPhysRegUsed(unsigned PhysReg) const; + //===--------------------------------------------------------------------===// // Low-level interface. //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h index a6ffeb382978..9798e5cef645 100644 --- a/include/llvm/CodeGen/MIRYamlMapping.h +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -81,15 +81,30 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) namespace llvm { namespace yaml { +struct VirtualRegisterDefinition { + unsigned ID; + StringValue Class; + // TODO: Serialize the virtual register hints. +}; + +template <> struct MappingTraits<VirtualRegisterDefinition> { + static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { + YamlIO.mapRequired("id", Reg.ID); + YamlIO.mapRequired("class", Reg.Class); + } + + static const bool flow = true; +}; + struct MachineBasicBlock { unsigned ID; - std::string Name; + StringValue Name; unsigned Alignment = 0; bool IsLandingPad = false; bool AddressTaken = false; - // TODO: Serialize the successor weights and liveins. + // TODO: Serialize the successor weights. std::vector<FlowStringValue> Successors; - + std::vector<FlowStringValue> LiveIns; std::vector<StringValue> Instructions; }; @@ -97,23 +112,153 @@ template <> struct MappingTraits<MachineBasicBlock> { static void mapping(IO &YamlIO, MachineBasicBlock &MBB) { YamlIO.mapRequired("id", MBB.ID); YamlIO.mapOptional("name", MBB.Name, - std::string()); // Don't print out an empty name. + StringValue()); // Don't print out an empty name. YamlIO.mapOptional("alignment", MBB.Alignment); YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad); YamlIO.mapOptional("addressTaken", MBB.AddressTaken); YamlIO.mapOptional("successors", MBB.Successors); + YamlIO.mapOptional("liveins", MBB.LiveIns); YamlIO.mapOptional("instructions", MBB.Instructions); } }; +/// Serializable representation of stack object from the MachineFrameInfo class. +/// +/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are +/// determined by the object's type and frame information flags. +/// Dead stack objects aren't serialized. +/// +/// TODO: Determine isPreallocated flag by mapping between objects and local +/// objects (Serialize local objects). +struct MachineStackObject { + enum ObjectType { DefaultType, SpillSlot, VariableSized }; + // TODO: Serialize LLVM alloca reference. + unsigned ID; + ObjectType Type = DefaultType; + int64_t Offset = 0; + uint64_t Size = 0; + unsigned Alignment = 0; +}; + +template <> struct ScalarEnumerationTraits<MachineStackObject::ObjectType> { + static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { + IO.enumCase(Type, "default", MachineStackObject::DefaultType); + IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); + IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); + } +}; + +template <> struct MappingTraits<MachineStackObject> { + static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { + YamlIO.mapRequired("id", Object.ID); + YamlIO.mapOptional( + "type", Object.Type, + MachineStackObject::DefaultType); // Don't print the default type. + YamlIO.mapOptional("offset", Object.Offset); + if (Object.Type != MachineStackObject::VariableSized) + YamlIO.mapRequired("size", Object.Size); + YamlIO.mapOptional("alignment", Object.Alignment); + } + + static const bool flow = true; +}; + +/// Serializable representation of the fixed stack object from the +/// MachineFrameInfo class. +struct FixedMachineStackObject { + enum ObjectType { DefaultType, SpillSlot }; + unsigned ID; + ObjectType Type = DefaultType; + int64_t Offset = 0; + uint64_t Size = 0; + unsigned Alignment = 0; + bool IsImmutable = false; + bool IsAliased = false; +}; + +template <> +struct ScalarEnumerationTraits<FixedMachineStackObject::ObjectType> { + static void enumeration(yaml::IO &IO, + FixedMachineStackObject::ObjectType &Type) { + IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); + IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); + } +}; + +template <> struct MappingTraits<FixedMachineStackObject> { + static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { + YamlIO.mapRequired("id", Object.ID); + YamlIO.mapOptional( + "type", Object.Type, + FixedMachineStackObject::DefaultType); // Don't print the default type. + YamlIO.mapOptional("offset", Object.Offset); + YamlIO.mapOptional("size", Object.Size); + YamlIO.mapOptional("alignment", Object.Alignment); + if (Object.Type != FixedMachineStackObject::SpillSlot) { + YamlIO.mapOptional("isImmutable", Object.IsImmutable); + YamlIO.mapOptional("isAliased", Object.IsAliased); + } + } + + static const bool flow = true; +}; + } // end namespace yaml } // end namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) namespace llvm { namespace yaml { +/// Serializable representation of MachineFrameInfo. +/// +/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and +/// 'RealignOption' as they are determined by the target and LLVM function +/// attributes. +/// It also doesn't serialize attributes like 'NumFixedObject' and +/// 'HasVarSizedObjects' as they are determined by the frame objects themselves. +struct MachineFrameInfo { + bool IsFrameAddressTaken = false; + bool IsReturnAddressTaken = false; + bool HasStackMap = false; + bool HasPatchPoint = false; + uint64_t StackSize = 0; + int OffsetAdjustment = 0; + unsigned MaxAlignment = 0; + bool AdjustsStack = false; + bool HasCalls = false; + // TODO: Serialize StackProtectorIdx and FunctionContextIdx + unsigned MaxCallFrameSize = 0; + // TODO: Serialize callee saved info. + // TODO: Serialize local frame objects. + bool HasOpaqueSPAdjustment = false; + bool HasVAStart = false; + bool HasMustTailInVarArgFunc = false; + // TODO: Serialize save and restore MBB references. +}; + +template <> struct MappingTraits<MachineFrameInfo> { + static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { + YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken); + YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken); + YamlIO.mapOptional("hasStackMap", MFI.HasStackMap); + YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint); + YamlIO.mapOptional("stackSize", MFI.StackSize); + YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment); + YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment); + YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack); + YamlIO.mapOptional("hasCalls", MFI.HasCalls); + YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize); + YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment); + YamlIO.mapOptional("hasVAStart", MFI.HasVAStart); + YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc); + } +}; + struct MachineFunction { StringRef Name; unsigned Alignment = 0; @@ -123,9 +268,13 @@ struct MachineFunction { bool IsSSA = false; bool TracksRegLiveness = false; bool TracksSubRegLiveness = false; - // TODO: Serialize virtual register definitions. + std::vector<VirtualRegisterDefinition> VirtualRegisters; // TODO: Serialize the various register masks. // TODO: Serialize live in registers. + // Frame information + MachineFrameInfo FrameInfo; + std::vector<FixedMachineStackObject> FixedStackObjects; + std::vector<MachineStackObject> StackObjects; std::vector<MachineBasicBlock> BasicBlocks; }; @@ -139,6 +288,10 @@ template <> struct MappingTraits<MachineFunction> { YamlIO.mapOptional("isSSA", MF.IsSSA); YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness); YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness); + YamlIO.mapOptional("registers", MF.VirtualRegisters); + YamlIO.mapOptional("frameInfo", MF.FrameInfo); + YamlIO.mapOptional("fixedStack", MF.FixedStackObjects); + YamlIO.mapOptional("stack", MF.StackObjects); YamlIO.mapOptional("body", MF.BasicBlocks); } }; diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index c619afb83333..628400322f60 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -135,17 +135,18 @@ public: /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const TargetMachine &TM; ///< The target machine. unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries; + const DataLayout &DL; + + const DataLayout &getDataLayout() const { return DL; } - const DataLayout *getDataLayout() const; public: /// @brief The only constructor. - explicit MachineConstantPool(const TargetMachine &TM) - : TM(TM), PoolAlignment(1) {} + explicit MachineConstantPool(const DataLayout &DL) + : PoolAlignment(1), DL(DL) {} ~MachineConstantPool(); /// getConstantPoolAlignment - Return the alignment required by diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 4428fa618fb0..735dd069cf7f 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -29,8 +29,8 @@ inline void DominatorTreeBase<MachineBasicBlock>::addRoot(MachineBasicBlock* MBB this->Roots.push_back(MBB); } -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<MachineBasicBlock>); -EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<MachineBasicBlock>); +extern template class DomTreeNodeBase<MachineBasicBlock>; +extern template class DominatorTreeBase<MachineBasicBlock>; typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode; diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 0f5a4b1b09ec..cbc4e66ccc46 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -229,9 +229,9 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; - /// True if the function includes inline assembly that adjusts the stack - /// pointer. - bool HasInlineAsmWithSPAdjust; + /// True if the function dynamically adjusts the stack pointer through some + /// opaque mechanism like inline assembly or Win32 EH. + bool HasOpaqueSPAdjustment; /// True if the function contains a call to the llvm.vastart intrinsic. bool HasVAStart; @@ -269,7 +269,7 @@ public: LocalFrameSize = 0; LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; - HasInlineAsmWithSPAdjust = false; + HasOpaqueSPAdjustment = false; HasVAStart = false; HasMustTailInVarArgFunc = false; Save = nullptr; @@ -468,9 +468,9 @@ public: bool hasCalls() const { return HasCalls; } void setHasCalls(bool V) { HasCalls = V; } - /// Returns true if the function contains any stack-adjusting inline assembly. - bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } - void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } + /// Returns true if the function contains opaque dynamic stack adjustments. + bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; } + void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; } /// Returns true if the function calls the llvm.va_start intrinsic. bool hasVAStart() const { return HasVAStart; } @@ -541,6 +541,14 @@ public: return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; } + /// Returns true if the specified index corresponds to a variable sized + /// object. + bool isVariableSizedObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx + NumFixedObjects].Size == 0; + } + /// Create a new statically sized stack object, returning /// a nonnegative identifier to represent it. int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 94610cabf566..c15ee1c006cd 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -155,6 +155,9 @@ public: MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } + /// Return the DataLayout attached to the Module associated to this MF. + const DataLayout &getDataLayout() const; + /// getFunction - Return the LLVM function that this machine code represents /// const Function *getFunction() const { return Fn; } diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 438ef2e37255..4868b7363f82 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -37,10 +37,8 @@ namespace llvm { // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ class MachineLoop; -__extension__ extern template class LoopBase<MachineBasicBlock, MachineLoop>; -#endif +extern template class LoopBase<MachineBasicBlock, MachineLoop>; class MachineLoop : public LoopBase<MachineBasicBlock, MachineLoop> { public: @@ -65,10 +63,7 @@ private: }; // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template -class LoopInfoBase<MachineBasicBlock, MachineLoop>; -#endif +extern template class LoopInfoBase<MachineBasicBlock, MachineLoop>; class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase<MachineBasicBlock, MachineLoop> LI; diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index ccaa83a238a6..4cdfe2463c99 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -320,6 +320,7 @@ public: /// information. void addPersonality(MachineBasicBlock *LandingPad, const Function *Personality); + void addPersonality(const Function *Personality); void addWinEHState(MachineBasicBlock *LandingPad, int State); diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index cf49c297c288..df9823f741dc 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -172,10 +172,9 @@ template <> struct GraphTraits<MachineRegionInfoPass*> } }; -EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<MachineFunction>>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<MachineFunction>>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<MachineFunction>>); - +extern template class RegionBase<RegionTraits<MachineFunction>>; +extern template class RegionNodeBase<RegionTraits<MachineFunction>>; +extern template class RegionInfoBase<RegionTraits<MachineFunction>>; } #endif diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index e5b837aeea28..67583be616c3 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -95,20 +95,8 @@ private: return MO->Contents.Reg.Next; } - /// UsedRegUnits - This is a bit vector that is computed and set by the - /// register allocator, and must be kept up to date by passes that run after - /// register allocation (though most don't modify this). This is used - /// so that the code generator knows which callee save registers to save and - /// for other target specific uses. - /// This vector has bits set for register units that are modified in the - /// current function. It doesn't include registers clobbered by function - /// calls with register mask operands. - BitVector UsedRegUnits; - /// UsedPhysRegMask - Additional used physregs including aliases. /// This bit vector represents all the registers clobbered by function calls. - /// It can model things that UsedRegUnits can't, such as function calls that - /// clobber ymm7 but preserve the low half in xmm7. BitVector UsedPhysRegMask; /// ReservedRegs - This is a bit vector of reserved registers. The target @@ -647,40 +635,11 @@ public: /// deleted during LiveDebugVariables analysis. void markUsesInDebugValueAsUndef(unsigned Reg) const; - //===--------------------------------------------------------------------===// - // Physical Register Use Info - //===--------------------------------------------------------------------===// - - /// isPhysRegUsed - Return true if the specified register is used in this - /// function. Also check for clobbered aliases and registers clobbered by - /// function calls with register mask operands. - /// - /// This only works after register allocation. It is primarily used by - /// PrologEpilogInserter to determine which callee-saved registers need - /// spilling. - bool isPhysRegUsed(unsigned Reg) const { - if (UsedPhysRegMask.test(Reg)) - return true; - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - if (UsedRegUnits.test(*Units)) - return true; - return false; - } - - /// Mark the specified register unit as used in this function. - /// This should only be called during and after register allocation. - void setRegUnitUsed(unsigned RegUnit) { - UsedRegUnits.set(RegUnit); - } - - /// setPhysRegUsed - Mark the specified register used in this function. - /// This should only be called during and after register allocation. - void setPhysRegUsed(unsigned Reg) { - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - UsedRegUnits.set(*Units); - } + /// Return true if the specified register is modified in this function. + /// This checks that no defining machine operands exist for the register or + /// any of its aliases. Definitions found on functions marked noreturn are + /// ignored. + bool isPhysRegModified(unsigned PhysReg) const; /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. /// This corresponds to the bit mask attached to register mask operands. @@ -688,16 +647,6 @@ public: UsedPhysRegMask.setBitsNotInMask(RegMask); } - /// setPhysRegUnused - Mark the specified register unused in this function. - /// This should only be called during and after register allocation. - void setPhysRegUnused(unsigned Reg) { - UsedPhysRegMask.reset(Reg); - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - UsedRegUnits.reset(*Units); - } - - //===--------------------------------------------------------------------===// // Reserved Register Info //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 538c995a7b44..5d8292174476 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -101,7 +101,7 @@ public: private: PassManagerBase *PM; - AnalysisID StartAfter; + AnalysisID StartBefore, StartAfter; AnalysisID StopAfter; bool Started; bool Stopped; @@ -142,16 +142,24 @@ public: CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); } - /// setStartStopPasses - Set the StartAfter and StopAfter passes to allow - /// running only a portion of the normal code-gen pass sequence. If the - /// Start pass ID is zero, then compilation will begin at the normal point; - /// otherwise, clear the Started flag to indicate that passes should not be - /// added until the starting pass is seen. If the Stop pass ID is zero, - /// then compilation will continue to the end. - void setStartStopPasses(AnalysisID Start, AnalysisID Stop) { - StartAfter = Start; - StopAfter = Stop; - Started = (StartAfter == nullptr); + /// Set the StartAfter, StartBefore and StopAfter passes to allow running only + /// a portion of the normal code-gen pass sequence. + /// + /// If the StartAfter and StartBefore pass ID is zero, then compilation will + /// begin at the normal point; otherwise, clear the Started flag to indicate + /// that passes should not be added until the starting pass is seen. If the + /// Stop pass ID is zero, then compilation will continue to the end. + /// + /// This function expects that at least one of the StartAfter or the + /// StartBefore pass IDs is null. + void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter) { + if (StartAfter) + assert(!StartBefore && "Start after and start before passes are given"); + this->StartBefore = StartBefore; + this->StartAfter = StartAfter; + this->StopAfter = StopAfter; + Started = (StartAfter == nullptr) && (StartBefore == nullptr); } void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } @@ -597,7 +605,7 @@ namespace llvm { /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); + FunctionPass *createSjLjEHPreparePass(); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index fcb6feed68ca..9d8843d1d74a 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -135,6 +135,8 @@ public: void addPressureChange(unsigned RegUnit, bool IsDec, const MachineRegisterInfo *MRI); + + LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const; }; /// Array of PressureDiffs. diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index c2b1243ee26e..1ee92380e690 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -281,6 +281,7 @@ public: void clear(); MachineFunction &getMachineFunction() const { return *MF; } + const DataLayout &getDataLayout() const { return MF->getDataLayout(); } const TargetMachine &getTarget() const { return TM; } const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } @@ -322,6 +323,14 @@ public: return AllNodes.size(); } + iterator_range<allnodes_iterator> allnodes() { + return iterator_range<allnodes_iterator>(allnodes_begin(), allnodes_end()); + } + iterator_range<allnodes_const_iterator> allnodes() const { + return iterator_range<allnodes_const_iterator>(allnodes_begin(), + allnodes_end()); + } + /// Return the root tag of the SelectionDAG. const SDValue &getRoot() const { return Root; } diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 619119096d20..4821d1aae9e5 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -140,7 +140,7 @@ public: } // Return true if this node is an operand of N. - bool isOperandOf(SDNode *N) const; + bool isOperandOf(const SDNode *N) const; /// Return the ValueType of the referenced return value. inline EVT getValueType() const; @@ -357,9 +357,6 @@ private: /// The number of entries in the Operand/Value list. unsigned short NumOperands, NumValues; - /// Source line information. - DebugLoc debugLoc; - // The ordering of the SDNodes. It roughly corresponds to the ordering of the // original LLVM instructions. // This is used for turning off scheduling, because we'll forgo @@ -367,6 +364,9 @@ private: // this ordering. unsigned IROrder; + /// Source line information. + DebugLoc debugLoc; + /// Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); @@ -532,10 +532,10 @@ public: bool hasAnyUseOfValue(unsigned Value) const; /// Return true if this node is the only use of N. - bool isOnlyUserOf(SDNode *N) const; + bool isOnlyUserOf(const SDNode *N) const; /// Return true if this node is an operand of N. - bool isOperandOf(SDNode *N) const; + bool isOperandOf(const SDNode *N) const; /// Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as @@ -732,7 +732,7 @@ protected: SubclassData(0), NodeId(-1), OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), - NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { + NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); @@ -752,7 +752,7 @@ protected: : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), - debugLoc(std::move(dl)), IROrder(Order) { + IROrder(Order), debugLoc(std::move(dl)) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 46a773f74aac..fdc1a9143ed2 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,5 +1,4 @@ //===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// - // // The LLVM Compiler Infrastructure // @@ -42,10 +41,12 @@ class PatchPointOpers { public: /// Enumerate the meta operands. enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; + private: const MachineInstr *MI; bool HasDef; bool IsAnyReg; + public: explicit PatchPointOpers(const MachineInstr *MI); @@ -66,8 +67,8 @@ public: /// Get the operand index of the variable list of non-argument operands. /// These hold the "live state". unsigned getVarIdx() const { - return getMetaIdx() + MetaEnd - + MI->getOperand(getMetaIdx(NArgPos)).getImm(); + return getMetaIdx() + MetaEnd + + MI->getOperand(getMetaIdx(NArgPos)).getImm(); } /// Get the index at which stack map locations will be recorded. @@ -98,15 +99,10 @@ private: // These values are relative offests from the start of the statepoint meta // arguments (i.e. the end of the call arguments). - enum { - CCOffset = 1, - FlagsOffset = 3, - NumVMSArgsOffset = 5 - }; + enum { CCOffset = 1, FlagsOffset = 3, NumVMSArgsOffset = 5 }; public: - explicit StatepointOpers(const MachineInstr *MI): - MI(MI) { } + explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {} /// Get starting index of non call related arguments /// (calling convention, statepoint flags, vm state and gc state). @@ -134,31 +130,32 @@ private: class StackMaps { public: struct Location { - enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, - ConstantIndex }; - LocationType LocType; + enum LocationType { + Unprocessed, + Register, + Direct, + Indirect, + Constant, + ConstantIndex + }; + LocationType Type; unsigned Size; unsigned Reg; int64_t Offset; - Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} - Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) - : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} + Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {} + Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset) + : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {} }; struct LiveOutReg { unsigned short Reg; - unsigned short RegNo; + unsigned short DwarfRegNum; unsigned short Size; - LiveOutReg() : Reg(0), RegNo(0), Size(0) {} - LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size) - : Reg(Reg), RegNo(RegNo), Size(Size) {} - - void MarkInvalid() { Reg = 0; } - - // Only sort by the dwarf register number. - bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; } - static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; } + LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {} + LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum, + unsigned short Size) + : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {} }; // OpTypes are used to encode information about the following logical @@ -205,8 +202,8 @@ private: CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, LocationVec &&Locations, LiveOutVec &&LiveOuts) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), - LiveOuts(std::move(LiveOuts)) {} + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), + LiveOuts(std::move(LiveOuts)) {} }; typedef std::vector<CallsiteInfo> CallsiteInfoList; @@ -218,8 +215,8 @@ private: MachineInstr::const_mop_iterator parseOperand(MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE, - LocationVec &Locs, LiveOutVec &LiveOuts) const; + MachineInstr::const_mop_iterator MOE, LocationVec &Locs, + LiveOutVec &LiveOuts) const; /// \brief Create a live-out register record for the given register @p Reg. LiveOutReg createLiveOutReg(unsigned Reg, @@ -254,7 +251,6 @@ private: void print(raw_ostream &OS); void debug() { print(dbgs()); } }; - } #endif diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 291f3905512c..75638a058a30 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -91,7 +91,7 @@ private: // When the parseEHActions function is called to populate a vector of // instances of this class, the ExceptionObjectVar field will be nullptr // and the ExceptionObjectIndex will be the index of the exception object in - // the parent function's frameescape block. + // the parent function's localescape block. const Value *ExceptionObjectVar; int ExceptionObjectIndex; TinyPtrVector<BasicBlock *> ReturnTargets; @@ -148,7 +148,7 @@ struct WinEHFuncInfo { int UnwindHelpFrameOffset = -1; unsigned NumIPToStateFuncsVisited = 0; - /// frameescape index of the 32-bit EH registration node. Set by + /// localescape index of the 32-bit EH registration node. Set by /// WinEHStatePass and used indirectly by SEH filter functions of the parent. int EHRegNodeEscapeIndex = INT_MAX; diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index e8af601d83b6..821c0181ce83 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -31,6 +31,7 @@ #include <map> #include <string> #include <vector> +#include <functional> namespace llvm { @@ -89,6 +90,8 @@ public: uint64_t RemoveMapping(StringRef Name); }; +using FunctionCreator = std::function<void *(const std::string &)>; + /// \brief Abstract interface for implementation execution of LLVM modules, /// designed to support both interpreter and just-in-time (JIT) compiler /// implementations. @@ -147,7 +150,7 @@ protected: /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will /// abort. - void *(*LazyFunctionCreator)(const std::string &); + FunctionCreator LazyFunctionCreator; /// getMangledName - Get mangled name. std::string getMangledName(const GlobalValue *GV); @@ -470,8 +473,8 @@ public: /// InstallLazyFunctionCreator - If an unknown function is needed, the /// specified function pointer is invoked to create it. If it returns null, /// the JIT will abort. - void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { - LazyFunctionCreator = P; + void InstallLazyFunctionCreator(FunctionCreator C) { + LazyFunctionCreator = C; } protected: diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 94c4038e8183..a808d9231167 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -153,6 +153,10 @@ public: /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. + /// + /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will + /// skip all relocations for that symbol, and the client will be responsible + /// for handling them manually. virtual SymbolInfo findSymbol(const std::string &Name) = 0; /// This method returns the address of the specified symbol if it exists diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 366bf709ab16..4d6d7da1fa5b 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -98,6 +98,8 @@ public: OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory + ArgMemOnly, ///< Funciton can access memory only using pointers + ///< based on its arguments. Returned, ///< Return value is always equal to this argument ReturnsTwice, ///< Function can return twice SExt, ///< Sign extended before/after call diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index dd2903e807e1..2841781e8a9e 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -290,6 +290,15 @@ public: CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory()); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + CALLSITE_DELEGATE_GETTER(onlyAccessesArgMemory()); + } + void setOnlyAccessesArgMemory() { + CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory()); + } + /// @brief Determine if the call cannot return. bool doesNotReturn() const { CALLSITE_DELEGATE_GETTER(doesNotReturn()); diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index d6296b622aab..aa43c02d5cd8 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -47,7 +47,7 @@ namespace llvm { SmallVector<Metadata *, 4> AllGVs; SmallVector<TrackingMDNodeRef, 4> AllImportedModules; - /// \brief Track nodes that may be unresolved. + /// Track nodes that may be unresolved. SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes; bool AllowUnresolvedNodes; @@ -57,49 +57,52 @@ namespace llvm { DIBuilder(const DIBuilder &) = delete; void operator=(const DIBuilder &) = delete; - /// \brief Create a temporary. + /// Create a temporary. /// /// Create an \a temporary node and track it in \a UnresolvedNodes. void trackIfUnresolved(MDNode *N); public: - /// \brief Construct a builder for a module. + /// Construct a builder for a module. /// /// If \c AllowUnresolved, collect unresolved nodes attached to the module /// in order to resolve cycles during \a finalize(). explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; - /// finalize - Construct any deferred debug info descriptors. + /// Construct any deferred debug info descriptors. void finalize(); - /// createCompileUnit - A CompileUnit provides an anchor for all debugging + /// A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. - /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 - /// @param File File name - /// @param Dir Directory - /// @param Producer Identify the producer of debugging information and code. - /// Usually this is a compiler version string. - /// @param isOptimized A boolean flag which indicates whether optimization - /// is ON or not. - /// @param Flags This string lists command line options. This string is - /// directly embedded in debug info output which may be used - /// by a tool analyzing generated debugging information. - /// @param RV This indicates runtime version for languages like - /// Objective-C. - /// @param SplitName The name of the file that we'll split debug info out - /// into. - /// @param Kind The kind of debug information to generate. - /// @param DWOId The DWOId if this is a split skeleton compile unit. - /// @param EmitDebugInfo A boolean flag which indicates whether debug - /// information should be written to the final - /// output or not. When this is false, debug - /// information annotations will be present in - /// the IL but they are not written to the final - /// assembly or object file. This supports tracking - /// source location information in the back end - /// without actually changing the output (e.g., - /// when using optimization remarks). + /// \param Lang Source programming language, eg. dwarf::DW_LANG_C99 + /// \param File File name + /// \param Dir Directory + /// \param Producer Identify the producer of debugging information + /// and code. Usually this is a compiler + /// version string. + /// \param isOptimized A boolean flag which indicates whether optimization + /// is enabled or not. + /// \param Flags This string lists command line options. This + /// string is directly embedded in debug info + /// output which may be used by a tool + /// analyzing generated debugging information. + /// \param RV This indicates runtime version for languages like + /// Objective-C. + /// \param SplitName The name of the file that we'll split debug info + /// out into. + /// \param Kind The kind of debug information to generate. + /// \param DWOId The DWOId if this is a split skeleton compile unit. + /// \param EmitDebugInfo A boolean flag which indicates whether + /// debug information should be written to + /// the final output or not. When this is + /// false, debug information annotations will + /// be present in the IL but they are not + /// written to the final assembly or object + /// file. This supports tracking source + /// location information in the back end + /// without actually changing the output + /// (e.g., when using optimization remarks). DICompileUnit * createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, @@ -107,155 +110,155 @@ namespace llvm { DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0, bool EmitDebugInfo = true); - /// createFile - Create a file descriptor to hold debugging information + /// Create a file descriptor to hold debugging information /// for a file. DIFile *createFile(StringRef Filename, StringRef Directory); - /// createEnumerator - Create a single enumerator value. + /// Create a single enumerator value. DIEnumerator *createEnumerator(StringRef Name, int64_t Val); - /// \brief Create a DWARF unspecified type. + /// Create a DWARF unspecified type. DIBasicType *createUnspecifiedType(StringRef Name); - /// \brief Create C++11 nullptr type. + /// Create C++11 nullptr type. DIBasicType *createNullPtrType(); - /// createBasicType - Create debugging information entry for a basic + /// Create debugging information entry for a basic /// type. - /// @param Name Type name. - /// @param SizeInBits Size of the type. - /// @param AlignInBits Type alignment. - /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. + /// \param Name Type name. + /// \param SizeInBits Size of the type. + /// \param AlignInBits Type alignment. + /// \param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding); - /// createQualifiedType - Create debugging information entry for a qualified + /// Create debugging information entry for a qualified /// type, e.g. 'const int'. - /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type - /// @param FromTy Base Type. + /// \param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type + /// \param FromTy Base Type. DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); - /// createPointerType - Create debugging information entry for a pointer. - /// @param PointeeTy Type pointed by this pointer. - /// @param SizeInBits Size. - /// @param AlignInBits Alignment. (optional) - /// @param Name Pointer type name. (optional) + /// Create debugging information entry for a pointer. + /// \param PointeeTy Type pointed by this pointer. + /// \param SizeInBits Size. + /// \param AlignInBits Alignment. (optional) + /// \param Name Pointer type name. (optional) DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits = 0, StringRef Name = ""); - /// \brief Create debugging information entry for a pointer to member. - /// @param PointeeTy Type pointed to by this pointer. - /// @param SizeInBits Size. - /// @param AlignInBits Alignment. (optional) - /// @param Class Type for which this pointer points to members of. + /// Create debugging information entry for a pointer to member. + /// \param PointeeTy Type pointed to by this pointer. + /// \param SizeInBits Size. + /// \param AlignInBits Alignment. (optional) + /// \param Class Type for which this pointer points to members of. DIDerivedType *createMemberPointerType(DIType *PointeeTy, DIType *Class, uint64_t SizeInBits, uint64_t AlignInBits = 0); - /// createReferenceType - Create debugging information entry for a c++ + /// Create debugging information entry for a c++ /// style reference or rvalue reference type. DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy); - /// createTypedef - Create debugging information entry for a typedef. - /// @param Ty Original type. - /// @param Name Typedef name. - /// @param File File where this type is defined. - /// @param LineNo Line number. - /// @param Context The surrounding context for the typedef. + /// Create debugging information entry for a typedef. + /// \param Ty Original type. + /// \param Name Typedef name. + /// \param File File where this type is defined. + /// \param LineNo Line number. + /// \param Context The surrounding context for the typedef. DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File, unsigned LineNo, DIScope *Context); - /// createFriend - Create debugging information entry for a 'friend'. + /// Create debugging information entry for a 'friend'. DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); - /// createInheritance - Create debugging information entry to establish + /// Create debugging information entry to establish /// inheritance relationship between two types. - /// @param Ty Original type. - /// @param BaseTy Base type. Ty is inherits from base. - /// @param BaseOffset Base offset. - /// @param Flags Flags to describe inheritance attribute, + /// \param Ty Original type. + /// \param BaseTy Base type. Ty is inherits from base. + /// \param BaseOffset Base offset. + /// \param Flags Flags to describe inheritance attribute, /// e.g. private DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, uint64_t BaseOffset, unsigned Flags); - /// createMemberType - Create debugging information entry for a member. - /// @param Scope Member scope. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. + /// Create debugging information entry for a member. + /// \param Scope Member scope. + /// \param Name Member name. + /// \param File File where this member is defined. + /// \param LineNo Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Ty Parent type. DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType *Ty); - /// createStaticMemberType - Create debugging information entry for a + /// Create debugging information entry for a /// C++ static data member. - /// @param Scope Member scope. - /// @param Name Member name. - /// @param File File where this member is declared. - /// @param LineNo Line number. - /// @param Ty Type of the static member. - /// @param Flags Flags to encode member attribute, e.g. private. - /// @param Val Const initializer of the member. + /// \param Scope Member scope. + /// \param Name Member name. + /// \param File File where this member is declared. + /// \param LineNo Line number. + /// \param Ty Type of the static member. + /// \param Flags Flags to encode member attribute, e.g. private. + /// \param Val Const initializer of the member. DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, unsigned Flags, llvm::Constant *Val); - /// createObjCIVar - Create debugging information entry for Objective-C + /// Create debugging information entry for Objective-C /// instance variable. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. - /// @param PropertyNode Property associated with this ivar. + /// \param Name Member name. + /// \param File File where this member is defined. + /// \param LineNo Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Ty Parent type. + /// \param PropertyNode Property associated with this ivar. DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType *Ty, MDNode *PropertyNode); - /// createObjCProperty - Create debugging information entry for Objective-C + /// Create debugging information entry for Objective-C /// property. - /// @param Name Property name. - /// @param File File where this property is defined. - /// @param LineNumber Line number. - /// @param GetterName Name of the Objective C property getter selector. - /// @param SetterName Name of the Objective C property setter selector. - /// @param PropertyAttributes Objective C property attributes. - /// @param Ty Type. + /// \param Name Property name. + /// \param File File where this property is defined. + /// \param LineNumber Line number. + /// \param GetterName Name of the Objective C property getter selector. + /// \param SetterName Name of the Objective C property setter selector. + /// \param PropertyAttributes Objective C property attributes. + /// \param Ty Type. DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, unsigned PropertyAttributes, DIType *Ty); - /// createClassType - Create debugging information entry for a class. - /// @param Scope Scope in which this class is defined. - /// @param Name class name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements class members. - /// @param VTableHolder Debug info of the base class that contains vtable + /// Create debugging information entry for a class. + /// \param Scope Scope in which this class is defined. + /// \param Name class name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements class members. + /// \param VTableHolder Debug info of the base class that contains vtable /// for this type. This is used in /// DW_AT_containing_type. See DWARF documentation /// for more info. - /// @param TemplateParms Template type parameters. - /// @param UniqueIdentifier A unique identifier for the class. + /// \param TemplateParms Template type parameters. + /// \param UniqueIdentifier A unique identifier for the class. DICompositeType *createClassType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -265,34 +268,34 @@ namespace llvm { MDNode *TemplateParms = nullptr, StringRef UniqueIdentifier = ""); - /// createStructType - Create debugging information entry for a struct. - /// @param Scope Scope in which this struct is defined. - /// @param Name Struct name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements Struct elements. - /// @param RunTimeLang Optional parameter, Objective-C runtime version. - /// @param UniqueIdentifier A unique identifier for the struct. + /// Create debugging information entry for a struct. + /// \param Scope Scope in which this struct is defined. + /// \param Name Struct name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements Struct elements. + /// \param RunTimeLang Optional parameter, Objective-C runtime version. + /// \param UniqueIdentifier A unique identifier for the struct. DICompositeType *createStructType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); - /// createUnionType - Create debugging information entry for an union. - /// @param Scope Scope in which this union is defined. - /// @param Name Union name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements Union elements. - /// @param RunTimeLang Optional parameter, Objective-C runtime version. - /// @param UniqueIdentifier A unique identifier for the union. + /// Create debugging information entry for an union. + /// \param Scope Scope in which this union is defined. + /// \param Name Union name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements Union elements. + /// \param RunTimeLang Optional parameter, Objective-C runtime version. + /// \param UniqueIdentifier A unique identifier for the union. DICompositeType *createUnionType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, @@ -300,95 +303,95 @@ namespace llvm { unsigned RunTimeLang = 0, StringRef UniqueIdentifier = ""); - /// createTemplateTypeParameter - Create debugging information for template + /// Create debugging information for template /// type parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Type parameter name. - /// @param Ty Parameter type. + /// \param Scope Scope in which this type is defined. + /// \param Name Type parameter name. + /// \param Ty Parameter type. DITemplateTypeParameter * createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty); - /// createTemplateValueParameter - Create debugging information for template + /// Create debugging information for template /// value parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val Constant parameter value. + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val Constant parameter value. DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope, StringRef Name, DIType *Ty, Constant *Val); - /// \brief Create debugging information for a template template parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val The fully qualified name of the template. + /// Create debugging information for a template template parameter. + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val The fully qualified name of the template. DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope, StringRef Name, DIType *Ty, StringRef Val); - /// \brief Create debugging information for a template parameter pack. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val An array of types in the pack. + /// Create debugging information for a template parameter pack. + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val An array of types in the pack. DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope, StringRef Name, DIType *Ty, DINodeArray Val); - /// createArrayType - Create debugging information entry for an array. - /// @param Size Array size. - /// @param AlignInBits Alignment. - /// @param Ty Element type. - /// @param Subscripts Subscripts. + /// Create debugging information entry for an array. + /// \param Size Array size. + /// \param AlignInBits Alignment. + /// \param Ty Element type. + /// \param Subscripts Subscripts. DICompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, DIType *Ty, DINodeArray Subscripts); - /// createVectorType - Create debugging information entry for a vector type. - /// @param Size Array size. - /// @param AlignInBits Alignment. - /// @param Ty Element type. - /// @param Subscripts Subscripts. + /// Create debugging information entry for a vector type. + /// \param Size Array size. + /// \param AlignInBits Alignment. + /// \param Ty Element type. + /// \param Subscripts Subscripts. DICompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, DIType *Ty, DINodeArray Subscripts); - /// createEnumerationType - Create debugging information entry for an + /// Create debugging information entry for an /// enumeration. - /// @param Scope Scope in which this enumeration is defined. - /// @param Name Union name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Elements Enumeration elements. - /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. - /// @param UniqueIdentifier A unique identifier for the enum. + /// \param Scope Scope in which this enumeration is defined. + /// \param Name Union name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Elements Enumeration elements. + /// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + /// \param UniqueIdentifier A unique identifier for the enum. DICompositeType *createEnumerationType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, DIType *UnderlyingType, StringRef UniqueIdentifier = ""); - /// createSubroutineType - Create subroutine type. - /// @param File File in which this subroutine is defined. - /// @param ParameterTypes An array of subroutine parameter types. This + /// Create subroutine type. + /// \param File File in which this subroutine is defined. + /// \param ParameterTypes An array of subroutine parameter types. This /// includes return type at 0th index. - /// @param Flags E.g.: LValueReference. + /// \param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. DISubroutineType *createSubroutineType(DIFile *File, DITypeRefArray ParameterTypes, unsigned Flags = 0); - /// createArtificialType - Create a new DIType* with "artificial" flag set. + /// Create a new DIType* with "artificial" flag set. DIType *createArtificialType(DIType *Ty); - /// createObjectPointerType - Create a new DIType* with the "object pointer" + /// Create a new DIType* with the "object pointer" /// flag set. DIType *createObjectPointerType(DIType *Ty); - /// \brief Create a permanent forward-declared type. + /// Create a permanent forward-declared type. DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang = 0, @@ -396,43 +399,43 @@ namespace llvm { uint64_t AlignInBits = 0, StringRef UniqueIdentifier = ""); - /// \brief Create a temporary forward-declared type. + /// Create a temporary forward-declared type. DICompositeType *createReplaceableCompositeType( unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl, StringRef UniqueIdentifier = ""); - /// retainType - Retain DIType* in a module even if it is not referenced + /// Retain DIType* in a module even if it is not referenced /// through debug info anchors. void retainType(DIType *T); - /// createUnspecifiedParameter - Create unspecified parameter type + /// Create unspecified parameter type /// for a subroutine type. DIBasicType *createUnspecifiedParameter(); - /// getOrCreateArray - Get a DINodeArray, create one if required. + /// Get a DINodeArray, create one if required. DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements); - /// getOrCreateTypeArray - Get a DITypeRefArray, create one if required. + /// Get a DITypeRefArray, create one if required. DITypeRefArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); - /// getOrCreateSubrange - Create a descriptor for a value range. This + /// Create a descriptor for a value range. This /// implicitly uniques the values returned. DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); - /// createGlobalVariable - Create a new descriptor for the specified + /// Create a new descriptor for the specified /// variable. - /// @param Context Variable scope. - /// @param Name Name of the variable. - /// @param LinkageName Mangled name of the variable. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// \param Context Variable scope. + /// \param Name Name of the variable. + /// \param LinkageName Mangled name of the variable. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Variable Type. + /// \param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. - /// @param Val llvm::Value of the variable. - /// @param Decl Reference to the corresponding declaration. + /// \param Val llvm::Value of the variable. + /// \param Decl Reference to the corresponding declaration. DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, @@ -440,26 +443,26 @@ namespace llvm { llvm::Constant *Val, MDNode *Decl = nullptr); - /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable + /// Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. DIGlobalVariable *createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val, MDNode *Decl = nullptr); - /// createLocalVariable - Create a new descriptor for the specified + /// Create a new descriptor for the specified /// local variable. - /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// \param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. - /// @param Scope Variable scope. - /// @param Name Variable name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type - /// @param AlwaysPreserve Boolean. Set to true if debug info for this + /// \param Scope Variable scope. + /// \param Name Variable name. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Variable Type + /// \param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. - /// @param Flags Flags, e.g. artificial variable. - /// @param ArgNo If this variable is an argument then this argument's + /// \param Flags Flags, e.g. artificial variable. + /// \param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope, StringRef Name, DIFile *File, @@ -468,36 +471,36 @@ namespace llvm { unsigned Flags = 0, unsigned ArgNo = 0); - /// createExpression - Create a new descriptor for the specified + /// Create a new descriptor for the specified /// variable which has a complex address expression for its address. - /// @param Addr An array of complex address operations. + /// \param Addr An array of complex address operations. DIExpression *createExpression(ArrayRef<uint64_t> Addr = None); DIExpression *createExpression(ArrayRef<int64_t> Addr); - /// createBitPieceExpression - Create a descriptor to describe one part + /// Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBits Offset of the piece in bits. - /// @param SizeInBits Size of the piece in bits. + /// \param OffsetInBits Offset of the piece in bits. + /// \param SizeInBits Size of the piece in bits. DIExpression *createBitPieceExpression(unsigned OffsetInBits, unsigned SizeInBits); - /// createFunction - Create a new descriptor for the specified subprogram. + /// Create a new descriptor for the specified subprogram. /// See comments in DISubprogram* for descriptions of these fields. - /// @param Scope Function scope. - /// @param Name Function name. - /// @param LinkageName Mangled function name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Function type. - /// @param isLocalToUnit True if this function is not externally visible. - /// @param isDefinition True if this is a function definition. - /// @param ScopeLine Set to the beginning of the scope this starts - /// @param Flags e.g. is this function prototyped or not. + /// \param Scope Function scope. + /// \param Name Function name. + /// \param LinkageName Mangled function name. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Function type. + /// \param isLocalToUnit True if this function is not externally visible. + /// \param isDefinition True if this is a function definition. + /// \param ScopeLine Set to the beginning of the scope this starts + /// \param Flags e.g. is this function prototyped or not. /// These flags are used to emit dwarf attributes. - /// @param isOptimized True if optimization is ON. - /// @param Fn llvm::Function pointer. - /// @param TParam Function template parameters. + /// \param isOptimized True if optimization is ON. + /// \param Fn llvm::Function pointer. + /// \param TParam Function template parameters. DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, @@ -506,7 +509,7 @@ namespace llvm { Function *Fn = nullptr, MDNode *TParam = nullptr, MDNode *Decl = nullptr); - /// createTempFunctionFwdDecl - Identical to createFunction, + /// Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. DISubprogram *createTempFunctionFwdDecl( DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, @@ -525,25 +528,25 @@ namespace llvm { Function *Fn = nullptr, MDNode *TParam = nullptr, MDNode *Decl = nullptr); - /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in DISubprogram* for descriptions of these fields. - /// @param Scope Function scope. - /// @param Name Function name. - /// @param LinkageName Mangled function name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Function type. - /// @param isLocalToUnit True if this function is not externally visible.. - /// @param isDefinition True if this is a function definition. - /// @param Virtuality Attributes describing virtualness. e.g. pure + /// Create a new descriptor for the specified C++ method. + /// See comments in \a DISubprogram* for descriptions of these fields. + /// \param Scope Function scope. + /// \param Name Function name. + /// \param LinkageName Mangled function name. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Function type. + /// \param isLocalToUnit True if this function is not externally visible.. + /// \param isDefinition True if this is a function definition. + /// \param Virtuality Attributes describing virtualness. e.g. pure /// virtual function. - /// @param VTableIndex Index no of this method in virtual table. - /// @param VTableHolder Type that holds vtable. - /// @param Flags e.g. is this function prototyped or not. + /// \param VTableIndex Index no of this method in virtual table. + /// \param VTableHolder Type that holds vtable. + /// \param Flags e.g. is this function prototyped or not. /// This flags are used to emit dwarf attributes. - /// @param isOptimized True if optimization is ON. - /// @param Fn llvm::Function pointer. - /// @param TParam Function template parameters. + /// \param isOptimized True if optimization is ON. + /// \param Fn llvm::Function pointer. + /// \param TParam Function template parameters. DISubprogram * createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, @@ -552,131 +555,131 @@ namespace llvm { unsigned Flags = 0, bool isOptimized = false, Function *Fn = nullptr, MDNode *TParam = nullptr); - /// createNameSpace - This creates new descriptor for a namespace - /// with the specified parent scope. - /// @param Scope Namespace scope - /// @param Name Name of this namespace - /// @param File Source file - /// @param LineNo Line number + /// This creates new descriptor for a namespace with the specified + /// parent scope. + /// \param Scope Namespace scope + /// \param Name Name of this namespace + /// \param File Source file + /// \param LineNo Line number DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo); - /// createModule - This creates new descriptor for a module - /// with the specified parent scope. - /// @param Scope Parent scope - /// @param Name Name of this module - /// @param ConfigurationMacros + /// This creates new descriptor for a module with the specified + /// parent scope. + /// \param Scope Parent scope + /// \param Name Name of this module + /// \param ConfigurationMacros /// A space-separated shell-quoted list of -D macro /// definitions as they would appear on a command line. - /// @param IncludePath The path to the module map file. - /// @param ISysRoot The clang system root (value of -isysroot). + /// \param IncludePath The path to the module map file. + /// \param ISysRoot The clang system root (value of -isysroot). DIModule *createModule(DIScope *Scope, StringRef Name, StringRef ConfigurationMacros, StringRef IncludePath, StringRef ISysRoot); - /// createLexicalBlockFile - This creates a descriptor for a lexical - /// block with a new file attached. This merely extends the existing + /// This creates a descriptor for a lexical block with a new file + /// attached. This merely extends the existing /// lexical block as it crosses a file. - /// @param Scope Lexical block. - /// @param File Source file. - /// @param Discriminator DWARF path discriminator value. + /// \param Scope Lexical block. + /// \param File Source file. + /// \param Discriminator DWARF path discriminator value. DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File, unsigned Discriminator = 0); - /// createLexicalBlock - This creates a descriptor for a lexical block - /// with the specified parent context. - /// @param Scope Parent lexical scope. - /// @param File Source file. - /// @param Line Line number. - /// @param Col Column number. + /// This creates a descriptor for a lexical block with the + /// specified parent context. + /// \param Scope Parent lexical scope. + /// \param File Source file. + /// \param Line Line number. + /// \param Col Column number. DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File, unsigned Line, unsigned Col); - /// \brief Create a descriptor for an imported module. - /// @param Context The scope this module is imported into - /// @param NS The namespace being imported here - /// @param Line Line number + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param NS The namespace being imported here + /// \param Line Line number DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, unsigned Line); - /// \brief Create a descriptor for an imported module. - /// @param Context The scope this module is imported into - /// @param NS An aliased namespace - /// @param Line Line number + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param NS An aliased namespace + /// \param Line Line number DIImportedEntity *createImportedModule(DIScope *Context, DIImportedEntity *NS, unsigned Line); - /// \brief Create a descriptor for an imported module. - /// @param Context The scope this module is imported into - /// @param M The module being imported here - /// @param Line Line number + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param M The module being imported here + /// \param Line Line number DIImportedEntity *createImportedModule(DIScope *Context, DIModule *M, unsigned Line); - /// \brief Create a descriptor for an imported function. - /// @param Context The scope this module is imported into - /// @param Decl The declaration (or definition) of a function, type, or + /// Create a descriptor for an imported function. + /// \param Context The scope this module is imported into + /// \param Decl The declaration (or definition) of a function, type, or /// variable - /// @param Line Line number + /// \param Line Line number DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, unsigned Line, StringRef Name = ""); - /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. - /// @param Storage llvm::Value of the variable - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertAtEnd Location for the new intrinsic. + /// Insert a new llvm.dbg.declare intrinsic call. + /// \param Storage llvm::Value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, BasicBlock *InsertAtEnd); - /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. - /// @param Storage llvm::Value of the variable - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertBefore Location for the new intrinsic. + /// Insert a new llvm.dbg.declare intrinsic call. + /// \param Storage llvm::Value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore); - /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - /// @param Val llvm::Value of the variable - /// @param Offset Offset - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertAtEnd Location for the new intrinsic. + /// Insert a new llvm.dbg.value intrinsic call. + /// \param Val llvm::Value of the variable + /// \param Offset Offset + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, BasicBlock *InsertAtEnd); - /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - /// @param Val llvm::Value of the variable - /// @param Offset Offset - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertBefore Location for the new intrinsic. + /// Insert a new llvm.dbg.value intrinsic call. + /// \param Val llvm::Value of the variable + /// \param Offset Offset + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore); - /// \brief Replace the vtable holder in the given composite type. + /// Replace the vtable holder in the given composite type. /// /// If this creates a self reference, it may orphan some unresolved cycles /// in the operands of \c T, so \a DIBuilder needs to track that. void replaceVTableHolder(DICompositeType *&T, DICompositeType *VTableHolder); - /// \brief Replace arrays on a composite type. + /// Replace arrays on a composite type. /// /// If \c T is resolved, but the arrays aren't -- which can happen if \c T /// has a self-reference -- \a DIBuilder needs to track the array to @@ -684,7 +687,7 @@ namespace llvm { void replaceArrays(DICompositeType *&T, DINodeArray Elements, DINodeArray TParems = DINodeArray()); - /// \brief Replace a temporary node. + /// Replace a temporary node. /// /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c /// Replacement. diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 5c99300c35c7..9c5a95721d79 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1085,10 +1085,10 @@ public: /// deleted on a uniquing collision. In practice, uniquing collisions on \a /// DICompileUnit should be fairly rare. /// @{ - void replaceEnumTypes(DISubprogramArray N) { + void replaceEnumTypes(DICompositeTypeArray N) { replaceOperandWith(4, N.get()); } - void replaceRetainedTypes(DISubprogramArray N) { + void replaceRetainedTypes(DITypeArray N) { replaceOperandWith(5, N.get()); } void replaceSubprograms(DISubprogramArray N) { @@ -1097,7 +1097,7 @@ public: void replaceGlobalVariables(DIGlobalVariableArray N) { replaceOperandWith(7, N.get()); } - void replaceImportedEntities(DIGlobalVariableArray N) { + void replaceImportedEntities(DIImportedEntityArray N) { replaceOperandWith(8, N.get()); } /// @} @@ -1650,14 +1650,14 @@ class DIModule : public DIScope { StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, ConfigurationMacros), - getCanonicalMDString(Context, IncludePath), - getCanonicalMDString(Context, ISysRoot), + getCanonicalMDString(Context, IncludePath), + getCanonicalMDString(Context, ISysRoot), Storage, ShouldCreate); } static DIModule *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, - MDString *IncludePath, MDString *ISysRoot, - StorageType Storage, bool ShouldCreate = true); + MDString *IncludePath, MDString *ISysRoot, + StorageType Storage, bool ShouldCreate = true); TempDIModule cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), @@ -1667,12 +1667,12 @@ class DIModule : public DIScope { public: DEFINE_MDNODE_GET(DIModule, (DIScope *Scope, StringRef Name, - StringRef ConfigurationMacros, StringRef IncludePath, - StringRef ISysRoot), + StringRef ConfigurationMacros, StringRef IncludePath, + StringRef ISysRoot), (Scope, Name, ConfigurationMacros, IncludePath, ISysRoot)) DEFINE_MDNODE_GET(DIModule, (Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, - MDString *IncludePath, MDString *ISysRoot), + MDString *IncludePath, MDString *ISysRoot), (Scope, Name, ConfigurationMacros, IncludePath, ISysRoot)) TempDIModule clone() const { return cloneImpl(); } diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index c1f208e3d72f..27d989b0344c 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -36,18 +36,14 @@ namespace llvm { template <typename IRUnitT> class AnalysisManager; class PreservedAnalyses; -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>); -EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); - -#define LLVM_COMMA , -EXTERN_TEMPLATE_INSTANTIATION(void Calculate<Function LLVM_COMMA BasicBlock *>( - DominatorTreeBase<GraphTraits<BasicBlock *>::NodeType> &DT LLVM_COMMA - Function &F)); -EXTERN_TEMPLATE_INSTANTIATION( - void Calculate<Function LLVM_COMMA Inverse<BasicBlock *> >( - DominatorTreeBase<GraphTraits<Inverse<BasicBlock *> >::NodeType> &DT - LLVM_COMMA Function &F)); -#undef LLVM_COMMA +extern template class DomTreeNodeBase<BasicBlock>; +extern template class DominatorTreeBase<BasicBlock>; + +extern template void Calculate<Function, BasicBlock *>( + DominatorTreeBase<GraphTraits<BasicBlock *>::NodeType> &DT, Function &F); +extern template void Calculate<Function, Inverse<BasicBlock *>>( + DominatorTreeBase<GraphTraits<Inverse<BasicBlock *>>::NodeType> &DT, + Function &F); typedef DomTreeNodeBase<BasicBlock> DomTreeNode; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 02ea056de39b..ec9f4cad094a 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -293,6 +293,16 @@ public: addFnAttr(Attribute::ReadOnly); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addFnAttr(Attribute::ArgMemOnly); + } + /// @brief Determine if the function cannot return. bool doesNotReturn() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index f2379705d460..2961369a7327 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -252,10 +252,9 @@ public: /// mistake: when working at the IR level use mayBeOverridden instead as it /// knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { - return Linkage == AvailableExternallyLinkage || Linkage == WeakAnyLinkage || - Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || Linkage == CommonLinkage || - Linkage == ExternalWeakLinkage; + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; } bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } @@ -349,6 +348,12 @@ public: return isDeclaration(); } + /// Returns true if this global's definition will be the one chosen by the + /// linker. + bool isStrongDefinitionForLinker() const { + return !(isDeclarationForLinker() || isWeakForLinker()); + } + /// This method unlinks 'this' from the containing module, but does not delete /// it. virtual void removeFromParent() = 0; diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index e6b5393c3397..6c67c79b6c0e 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -1382,47 +1382,61 @@ public: return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); } - Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag); } Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, @@ -1433,11 +1447,12 @@ public: return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { + const Twine &Name = "", MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(new FCmpInst(P, LHS, RHS), Name); + return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS), + FPMathTag, FMF), Name); } //===--------------------------------------------------------------------===// @@ -1449,7 +1464,7 @@ public: return Insert(PHINode::Create(Ty, NumReservedValues), Name); } - CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, + CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None, const Twine &Name = "") { return Insert(CallInst::Create(Callee, Args), Name); } diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 6e3de1f13545..31f363f70a5b 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -382,7 +382,7 @@ public: /// /// Note that this does not consider malloc and alloca to have side /// effects because the newly allocated memory is completely invisible to - /// instructions which don't used the returned value. For cases where this + /// instructions which don't use the returned value. For cases where this /// matters, isSafeToSpeculativelyExecute may be more appropriate. bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow() || !mayReturn(); diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index c5890f01ea70..07d5f111b9e1 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -990,10 +990,14 @@ public: Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { - unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements(); + unsigned NumElem = Ptr->getType()->getVectorNumElements(); return VectorType::get(PtrTy, NumElem); } - + for (Value *Index : IdxList) + if (Index->getType()->isVectorTy()) { + unsigned NumElem = Index->getType()->getVectorNumElements(); + return VectorType::get(PtrTy, NumElem); + } // Scalar GEP return PtrTy; } @@ -1591,6 +1595,15 @@ public: addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return hasFnAttr(Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly); + } + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { @@ -3360,6 +3373,15 @@ public: addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } + /// @brief Determine if the call access memmory only using it's pointer + /// arguments. + bool onlyAccessesArgMemory() const { + return hasFnAttr(Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly); + } + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e6f6d0ffe8b6..bbae720b4e12 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -268,15 +268,23 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>; -def int_framerecover : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrReadMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [], "llvm.write_register">; +// Gets the address of the local variable area. This is typically a copy of the +// stack, frame, or base pointer depending on the type of prologue. +def int_localaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +// Escapes local variables to allow access from other functions. +def int_localescape : Intrinsic<[], [llvm_vararg_ty]>; + +// Given a function and the localaddress of a parent frame, returns a pointer +// to an escaped allocation indicated by the index. +def int_localrecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; // Note: we treat stacksave/stackrestore as writemem because we don't otherwise // model their dependencies on allocas. def int_stacksave : Intrinsic<[llvm_ptr_ty]>, @@ -362,6 +370,8 @@ let Properties = [IntrNoMem] in { def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_canonicalize : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], + [IntrNoMem]>; } // NOTE: these are internal interfaces. @@ -638,3 +648,4 @@ include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsAMDGPU.td" include "llvm/IR/IntrinsicsBPF.td" include "llvm/IR/IntrinsicsSystemZ.td" +include "llvm/IR/IntrinsicsWebAssembly.td" diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 05adc5a757be..eb8f1e6cd079 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -694,6 +694,18 @@ def int_ppc_vsx_xvrspip : def int_ppc_vsx_xvrdpip : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; +// Vector reciprocal estimate +def int_ppc_vsx_xvresp : GCCBuiltin<"__builtin_vsx_xvresp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvredp : GCCBuiltin<"__builtin_vsx_xvredp">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Vector rsqrte +def int_ppc_vsx_xvrsqrtesp : GCCBuiltin<"__builtin_vsx_xvrsqrtesp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvrsqrtedp : GCCBuiltin<"__builtin_vsx_xvrsqrtedp">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + // Vector compare def int_ppc_vsx_xvcmpeqdp : PowerPC_VSX_Intrinsic<"xvcmpeqdp", [llvm_v2i64_ty], @@ -713,6 +725,9 @@ def int_ppc_vsx_xvcmpgtdp : def int_ppc_vsx_xvcmpgtsp : PowerPC_VSX_Intrinsic<"xvcmpgtsp", [llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xxleqv : + PowerPC_VSX_Intrinsic<"xxleqv", [llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td new file mode 100644 index 000000000000..3ccde4742384 --- /dev/null +++ b/include/llvm/IR/IntrinsicsWebAssembly.td @@ -0,0 +1,16 @@ +//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines all of the WebAssembly-specific intrinsics. +/// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.". +} diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index b90825db93cd..a3bc4af84308 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -28,7 +28,7 @@ let TargetPrefix = "x86" in { def int_x86_seh_restoreframe : Intrinsic<[], [], []>; // Given a pointer to the end of an EH registration object, returns the true - // parent frame address that can be used with llvm.framerecover. + // parent frame address that can be used with llvm.localrecover. def int_x86_seh_recoverfp : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], [IntrNoMem]>; @@ -2107,6 +2107,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_mask_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_hr_sw_256 : GCCBuiltin<"__builtin_ia32_pmulhrsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; } // Vector sign and zero extend @@ -4466,6 +4475,24 @@ let TargetPrefix = "x86" in { def int_x86_avx512_mask_pmull_q_512 : GCCBuiltin<"__builtin_ia32_pmullq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_128 : GCCBuiltin<"__builtin_ia32_pmulhuw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_256 : GCCBuiltin<"__builtin_ia32_pmulhuw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_128 : GCCBuiltin<"__builtin_ia32_pmulhw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_256 : GCCBuiltin<"__builtin_ia32_pmulhw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_pavg_b_512 : GCCBuiltin<"__builtin_ia32_pavgb512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 1b9102ecc7e4..372b254ab183 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -305,7 +305,8 @@ public: float getFPAccuracy() const; static inline bool classof(const Instruction *I) { - return I->getType()->isFPOrFPVectorTy(); + return I->getType()->isFPOrFPVectorTy() || + I->getOpcode() == Instruction::FCmp; } static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 484afc6d232c..17a80c82d1bc 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -104,8 +104,8 @@ protected: /// /// Note, this should *NOT* be used directly by any class other than User. /// User uses this value to find the Use list. - static const unsigned NumUserOperandsBits = 29; - unsigned NumUserOperands : 29; + enum : unsigned { NumUserOperandsBits = 29 }; + unsigned NumUserOperands : NumUserOperandsBits; bool IsUsedByMD : 1; bool HasName : 1; diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 74fbc0f94b03..e3b9a95f0a3d 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -130,6 +130,7 @@ void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSELegacyPassPass(PassRegistry &); +void initializeEliminateAvailableExternallyPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); @@ -302,6 +303,7 @@ void initializePlaceSafepointsPass(PassRegistry&); void initializeDwarfEHPreparePass(PassRegistry&); void initializeFloat2IntPass(PassRegistry&); void initializeLoopDistributePass(PassRegistry&); +void initializeSjLjEHPreparePass(PassRegistry&); } #endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 8ac1b212ae5f..cea5530db3b8 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -176,6 +176,7 @@ namespace { (void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createMemDerefPrinter(); (void) llvm::createFloat2IntPass(); + (void) llvm::createEliminateAvailableExternallyPass(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 52017fda189b..41169e9a12a0 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -273,7 +273,7 @@ namespace llvm { /// Gets a symbol that will be defined to the final stack offset of a local /// variable after codegen. /// - /// \param Idx - The index of a local variable passed to @llvm.frameescape. + /// \param Idx - The index of a local variable passed to @llvm.localescape. MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index c7bed8eccda9..1e72dfee4ad1 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -54,13 +54,13 @@ struct MCDwarfFile { /// \brief Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { - unsigned FileNum; - unsigned Line; - unsigned Column; + uint32_t FileNum; + uint32_t Line; + uint16_t Column; // Flags (see #define's below) - unsigned Flags; - unsigned Isa; - unsigned Discriminator; + uint8_t Flags; + uint8_t Isa; + uint32_t Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. #define DWARF2_LINE_DEFAULT_IS_STMT 1 @@ -107,13 +107,22 @@ public: void setLine(unsigned line) { Line = line; } /// \brief Set the Column of this MCDwarfLoc. - void setColumn(unsigned column) { Column = column; } + void setColumn(unsigned column) { + assert(column <= UINT16_MAX); + Column = column; + } /// \brief Set the Flags of this MCDwarfLoc. - void setFlags(unsigned flags) { Flags = flags; } + void setFlags(unsigned flags) { + assert(flags <= UINT8_MAX); + Flags = flags; + } /// \brief Set the Isa of this MCDwarfLoc. - void setIsa(unsigned isa) { Isa = isa; } + void setIsa(unsigned isa) { + assert(isa <= UINT8_MAX); + Isa = isa; + } /// \brief Set the Discriminator of this MCDwarfLoc. void setDiscriminator(unsigned discriminator) { diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 3209a2ce0408..6a582e82d00e 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -154,7 +154,8 @@ public: // A complex method to determine is a certain is deprecated or not, and return // the reason for deprecation. - bool (*ComplexDeprecationInfo)(MCInst &, MCSubtargetInfo &, std::string &); + bool (*ComplexDeprecationInfo)(MCInst &, const MCSubtargetInfo &, + std::string &); /// \brief Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. @@ -170,7 +171,7 @@ public: /// \brief Returns true if a certain instruction is deprecated and if so /// returns the reason in \p Info. - bool getDeprecatedInfo(MCInst &MI, MCSubtargetInfo &STI, + bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info) const; /// \brief Return the opcode number for this descriptor. diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 1adfedd2638a..c09791631056 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -224,25 +224,9 @@ struct MCSchedModel { return &SchedClassTable[SchedClassIdx]; } - // /\brief Returns a default initialized model. Used for unknown processors. - static MCSchedModel GetDefaultSchedModel() { - MCSchedModel Ret = { DefaultIssueWidth, - DefaultMicroOpBufferSize, - DefaultLoopMicroOpBufferSize, - DefaultLoadLatency, - DefaultHighLatency, - DefaultMispredictPenalty, - false, - true, - 0, - nullptr, - nullptr, - 0, - 0, - nullptr - }; - return Ret; - } + /// Returns the default initialized model. + static const MCSchedModel &GetDefaultSchedModel() { return Default; } + static const MCSchedModel Default; }; } // End llvm namespace diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index b8ad02fbe696..d5ad4eebf9ef 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -37,22 +37,26 @@ class MCSubtargetInfo { const MCWriteProcResEntry *WriteProcResTable; const MCWriteLatencyEntry *WriteLatencyTable; const MCReadAdvanceEntry *ReadAdvanceTable; - MCSchedModel CPUSchedModel; + const MCSchedModel *CPUSchedModel; const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths FeatureBitset FeatureBits; // Feature bits for current CPU + FS + MCSubtargetInfo() = delete; + MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; + MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete; + public: - void InitMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, - ArrayRef<SubtargetFeatureKV> PF, - ArrayRef<SubtargetFeatureKV> PD, - const SubtargetInfoKV *ProcSched, - const MCWriteProcResEntry *WPR, - const MCWriteLatencyEntry *WL, - const MCReadAdvanceEntry *RA, const InstrStage *IS, - const unsigned *OC, const unsigned *FP); + MCSubtargetInfo(const MCSubtargetInfo &) = default; + MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, + ArrayRef<SubtargetFeatureKV> PF, + ArrayRef<SubtargetFeatureKV> PD, + const SubtargetInfoKV *ProcSched, + const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, + const MCReadAdvanceEntry *RA, const InstrStage *IS, + const unsigned *OC, const unsigned *FP); /// getTargetTriple - Return the target triple string. const Triple &getTargetTriple() const { return TargetTriple; } @@ -74,12 +78,16 @@ public: FeatureBits = FeatureBits_; } - /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with - /// feature string). Recompute feature bits and scheduling model. +protected: + /// Initialize the scheduling model and feature bits. + /// + /// FIXME: Find a way to stick this in the constructor, since it should only + /// be called during initialization. void InitMCProcessorInfo(StringRef CPU, StringRef FS); - /// InitCPUSchedModel - Recompute scheduling model based on CPU. - void InitCPUSchedModel(StringRef CPU); +public: + /// Set the features to the default for the given CPU. + void setDefaultFeatures(StringRef CPU); /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. @@ -99,11 +107,10 @@ public: /// getSchedModelForCPU - Get the machine model of a CPU. /// - MCSchedModel getSchedModelForCPU(StringRef CPU) const; + const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; - /// getSchedModel - Get the machine model for this subtarget's CPU. - /// - const MCSchedModel &getSchedModel() const { return CPUSchedModel; } + /// Get the machine model for this subtarget's CPU. + const MCSchedModel &getSchedModel() const { return *CPUSchedModel; } /// Return an iterator at the first process resource consumed by the given /// scheduling class. @@ -151,7 +158,7 @@ public: void initInstrItins(InstrItineraryData &InstrItins) const; /// Check whether the CPU string is valid. - bool isCPUStringValid(StringRef CPU) { + bool isCPUStringValid(StringRef CPU) const { auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), [=](const SubtargetFeatureKV &KV) { return CPU == KV.Key; diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 17e6b857cf20..b2910dfccd63 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -114,12 +114,12 @@ protected: /// The alignment is stored as log2(align) + 1. This allows all values from /// 0 to 2^31 to be stored which is every power of 2 representable by an /// unsigned. - static const unsigned NumCommonAlignmentBits = 5; + enum : unsigned { NumCommonAlignmentBits = 5 }; unsigned CommonAlignLog2 : NumCommonAlignmentBits; /// The Flags field is used by object file implementations to store /// additional per symbol information which is not easily classified. - static const unsigned NumFlagsBits = 16; + enum : unsigned { NumFlagsBits = 16 }; mutable uint32_t Flags : NumFlagsBits; /// Index field, for use by the object file implementation. diff --git a/include/llvm/MC/MCSymbolMachO.h b/include/llvm/MC/MCSymbolMachO.h index 166ae9e755a1..5b0321fe9f73 100644 --- a/include/llvm/MC/MCSymbolMachO.h +++ b/include/llvm/MC/MCSymbolMachO.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// #ifndef LLVM_MC_MCSYMBOLMACHO_H -#define setIsWeakExternal +#define LLVM_MC_MCSYMBOLMACHO_H #include "llvm/MC/MCSymbol.h" diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index ce28a196e974..7f4f23eda27f 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -55,7 +55,7 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && ARE_EQUAL(DwarfVersion) && - ARE_EQUAL(ABIName)); + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 8da6919a4655..597f0d48c118 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -94,9 +94,7 @@ public: /// \return the size in the archive header for this member. uint64_t getRawSize() const; - StringRef getBuffer() const { - return StringRef(Data.data() + StartOfFile, getSize()); - } + ErrorOr<StringRef> getBuffer() const; uint64_t getChildOffset() const; ErrorOr<MemoryBufferRef> getMemoryBufferRef() const; @@ -183,6 +181,7 @@ public: }; Kind kind() const { return (Kind)Format; } + bool isThin() const { return IsThin; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; @@ -207,6 +206,11 @@ public: bool hasSymbolTable() const; child_iterator getSymbolTableChild() const { return SymbolTable; } + StringRef getSymbolTable() const { + // We know that the symbol table is not an external file, + // so we just assert there is no error. + return *SymbolTable->getBuffer(); + } uint32_t getNumberOfSymbols() const; private: @@ -215,6 +219,7 @@ private: child_iterator FirstRegular; unsigned Format : 2; unsigned IsThin : 1; + mutable std::vector<std::unique_ptr<MemoryBuffer>> ThinBuffers; }; } diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h index 1616e46d3e6f..3648d0c77fb5 100644 --- a/include/llvm/Object/ArchiveWriter.h +++ b/include/llvm/Object/ArchiveWriter.h @@ -31,7 +31,6 @@ class NewArchiveIterator { public: NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); NewArchiveIterator(StringRef I, StringRef Name); - NewArchiveIterator(); bool isNewMember() const; StringRef getName() const; @@ -44,8 +43,7 @@ public: std::pair<StringRef, std::error_code> writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers, - bool WriteSymtab); - + bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic); } #endif diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index fc605826a8b0..025a9dbc6bc0 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -474,7 +474,7 @@ struct coff_import_header { support::ulittle16_t OrdinalHint; support::ulittle16_t TypeInfo; int getType() const { return TypeInfo & 0x3; } - int getNameType() const { return (TypeInfo & 0x7) >> 2; } + int getNameType() const { return (TypeInfo >> 2) & 0x7; } }; struct coff_import_directory_table_entry { @@ -648,9 +648,8 @@ public: protected: void moveSymbolNext(DataRefImpl &Symb) const override; ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - uint64_t getSymbolValue(DataRefImpl Symb) const override; + ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; @@ -672,7 +671,6 @@ protected: relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; uint64_t getRelocationType(DataRefImpl Rel) const override; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 3b0c548ffe15..cc271851e6b0 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" @@ -139,6 +140,7 @@ public: typedef Elf_Verneed_Impl<ELFT> Elf_Verneed; typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; typedef Elf_Versym_Impl<ELFT> Elf_Versym; + typedef Elf_Hash_Impl<ELFT> Elf_Hash; typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter; typedef iterator_range<Elf_Dyn_Iter> Elf_Dyn_Range; typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; @@ -174,8 +176,8 @@ private: StringRef DotShstrtab; // Section header string table. StringRef DotStrtab; // Symbol header string table. const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section. - StringRef DynSymStrTab; // Dynnamic symbol string table. const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. + const Elf_Hash *HashTable = nullptr; const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr; DenseMap<const Elf_Sym *, ELF::Elf64_Word> ExtendedSymbolTable; @@ -197,6 +199,7 @@ private: DynRegionInfo DynamicRegion; DynRegionInfo DynHashRegion; + DynRegionInfo DynStrRegion; DynRegionInfo DynRelaRegion; // Pointer to SONAME entry in dynamic string table @@ -229,6 +232,8 @@ private: void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionMap() const; + void scanDynamicTable(); + public: template<typename T> const T *getEntry(uint32_t Section, uint32_t Entry) const; @@ -237,6 +242,7 @@ public: const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; } const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } + const Elf_Hash *getHashTable() const { return HashTable; } ErrorOr<StringRef> getStringTable(const Elf_Shdr *Section) const; const char *getDynamicString(uintX_t Offset) const; @@ -578,8 +584,10 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) Header = reinterpret_cast<const Elf_Ehdr *>(base()); - if (Header->e_shoff == 0) + if (Header->e_shoff == 0) { + scanDynamicTable(); return; + } const uint64_t SectionTableOffset = Header->e_shoff; @@ -604,6 +612,13 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) for (const Elf_Shdr &Sec : sections()) { switch (Sec.sh_type) { + case ELF::SHT_HASH: + if (HashTable) { + EC = object_error::parse_failed; + return; + } + HashTable = reinterpret_cast<const Elf_Hash *>(base() + Sec.sh_offset); + break; case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) { // More than one .symtab_shndx! @@ -640,7 +655,9 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) ErrorOr<StringRef> SymtabOrErr = getStringTable(*SectionOrErr); if ((EC = SymtabOrErr.getError())) return; - DynSymStrTab = *SymtabOrErr; + DynStrRegion.Addr = SymtabOrErr->data(); + DynStrRegion.Size = SymtabOrErr->size(); + DynStrRegion.EntSize = 1; break; } case ELF::SHT_DYNAMIC: @@ -701,7 +718,23 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) } } - // Scan program headers. + scanDynamicTable(); + + EC = std::error_code(); +} + +template <class ELFT> +void ELFFile<ELFT>::scanDynamicTable() { + // Build load-address to file-offset map. + typedef IntervalMap< + uintX_t, uintptr_t, + IntervalMapImpl::NodeSizer<uintX_t, uintptr_t>::LeafSize, + IntervalMapHalfOpenInfo<uintX_t>> LoadMapT; + typename LoadMapT::Allocator Alloc; + // Allocate the IntervalMap on the heap to work around MSVC bug where the + // stack doesn't get realigned despite LoadMap having alignment 8 (PR24113). + std::unique_ptr<LoadMapT> LoadMap(new LoadMapT(Alloc)); + for (Elf_Phdr_Iter PhdrI = program_header_begin(), PhdrE = program_header_end(); PhdrI != PhdrE; ++PhdrI) { @@ -709,34 +742,44 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) DynamicRegion.Addr = base() + PhdrI->p_offset; DynamicRegion.Size = PhdrI->p_filesz; DynamicRegion.EntSize = sizeof(Elf_Dyn); - break; + continue; } + if (PhdrI->p_type != ELF::PT_LOAD) + continue; + if (PhdrI->p_filesz == 0) + continue; + LoadMap->insert(PhdrI->p_vaddr, PhdrI->p_vaddr + PhdrI->p_filesz, + PhdrI->p_offset); } - // Scan dynamic table. + auto toMappedAddr = [&](uint64_t VAddr) -> const uint8_t * { + auto I = LoadMap->find(VAddr); + if (I == LoadMap->end()) + return nullptr; + return this->base() + I.value() + (VAddr - I.start()); + }; + for (Elf_Dyn_Iter DynI = dynamic_table_begin(), DynE = dynamic_table_end(); DynI != DynE; ++DynI) { switch (DynI->d_tag) { - case ELF::DT_RELA: { - uint64_t VBase = 0; - const uint8_t *FBase = nullptr; - for (Elf_Phdr_Iter PhdrI = program_header_begin(), - PhdrE = program_header_end(); - PhdrI != PhdrE; ++PhdrI) { - if (PhdrI->p_type != ELF::PT_LOAD) - continue; - if (DynI->getPtr() >= PhdrI->p_vaddr && - DynI->getPtr() < PhdrI->p_vaddr + PhdrI->p_memsz) { - VBase = PhdrI->p_vaddr; - FBase = base() + PhdrI->p_offset; - break; - } - } - if (!VBase) - return; - DynRelaRegion.Addr = FBase + DynI->getPtr() - VBase; + case ELF::DT_HASH: + if (HashTable) + continue; + HashTable = + reinterpret_cast<const Elf_Hash *>(toMappedAddr(DynI->getPtr())); + break; + case ELF::DT_STRTAB: + if (!DynStrRegion.Addr) + DynStrRegion.Addr = toMappedAddr(DynI->getPtr()); + break; + case ELF::DT_STRSZ: + if (!DynStrRegion.Size) + DynStrRegion.Size = DynI->getVal(); + break; + case ELF::DT_RELA: + if (!DynRelaRegion.Addr) + DynRelaRegion.Addr = toMappedAddr(DynI->getPtr()); break; - } case ELF::DT_RELASZ: DynRelaRegion.Size = DynI->getVal(); break; @@ -744,8 +787,6 @@ ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &EC) DynRelaRegion.EntSize = DynI->getVal(); } } - - EC = std::error_code(); } template <class ELFT> @@ -868,9 +909,9 @@ ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { template <class ELFT> const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const { - if (!DotDynSymSec || Offset >= DynSymStrTab.size()) + if (Offset >= DynStrRegion.Size) return nullptr; - return (const char *)DynSymStrTab.begin() + Offset; + return (const char *)DynStrRegion.Addr + Offset; } template <class ELFT> @@ -983,7 +1024,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - if (name_offset >= DynSymStrTab.size()) + if (name_offset >= DynStrRegion.Size) return object_error::parse_failed; return StringRef(getDynamicString(name_offset)); } diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 5b9b113a2f0b..6e8ace427a20 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -196,9 +196,8 @@ protected: void moveSymbolNext(DataRefImpl &Symb) const override; ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const override; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - uint64_t getSymbolValue(DataRefImpl Symb) const override; + ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; @@ -226,7 +225,6 @@ protected: section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; uint64_t getRelocationType(DataRefImpl Rel) const override; @@ -235,7 +233,6 @@ protected: uint32_t getSectionType(DataRefImpl Sec) const override; uint64_t getSectionFlags(DataRefImpl Sec) const override; - uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; /// \brief Get the relocation section that contains \a Rel. @@ -276,11 +273,6 @@ protected: return DRI; } - Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { - return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), - reinterpret_cast<const char *>(Dyn.p)); - } - DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { DataRefImpl DRI; DRI.p = reinterpret_cast<uintptr_t>(Dyn.get()); @@ -378,19 +370,13 @@ uint32_t ELFObjectFile<ELFT>::getSectionType(DataRefImpl Sec) const { } template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb) const { +uint64_t ELFObjectFile<ELFT>::getSymbolValueImpl(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); - switch (ESym->st_shndx) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - return UnknownAddress; - case ELF::SHN_ABS: - return ESym->st_value; - } - - const Elf_Ehdr *Header = EF.getHeader(); uint64_t Ret = ESym->st_value; + if (ESym->st_shndx == ELF::SHN_ABS) + return Ret; + const Elf_Ehdr *Header = EF.getHeader(); // Clear the ARM/Thumb or microMIPS indicator flag. if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && ESym->getType() == ELF::STT_FUNC) @@ -400,15 +386,15 @@ uint64_t ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb) const { } template <class ELFT> -std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - Result = getSymbolValue(Symb); +ErrorOr<uint64_t> +ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb) const { + uint64_t Result = getSymbolValue(Symb); const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->st_shndx) { case ELF::SHN_COMMON: case ELF::SHN_UNDEF: case ELF::SHN_ABS: - return std::error_code(); + return Result; } const Elf_Ehdr *Header = EF.getHeader(); @@ -422,7 +408,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, Result += Section->sh_addr; } - return std::error_code(); + return Result; } template <class ELFT> @@ -689,31 +675,9 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { } template <class ELFT> -ErrorOr<uint64_t> -ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel) const { - uint64_t ROffset = getROffset(Rel); - const Elf_Ehdr *Header = EF.getHeader(); - - if (Header->e_type == ELF::ET_REL) { - const Elf_Shdr *RelocationSec = getRelSection(Rel); - ErrorOr<const Elf_Shdr *> RelocatedSec = - EF.getSection(RelocationSec->sh_info); - if (std::error_code EC = RelocatedSec.getError()) - return EC; - return ROffset + (*RelocatedSec)->sh_addr; - } - return ROffset; -} - -template <class ELFT> uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); - return getROffset(Rel); -} - -template <class ELFT> -uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { const Elf_Shdr *sec = getRelSection(Rel); if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->r_offset; diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 63e13909ae5c..27e987ba2852 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -10,6 +10,7 @@ #ifndef LLVM_OBJECT_ELFTYPES_H #define LLVM_OBJECT_ELFTYPES_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/Object/Error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ELF.h" @@ -463,6 +464,23 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { Elf_Xword p_align; // Segment alignment constraint }; +// ELFT needed for endianess. +template <class ELFT> +struct Elf_Hash_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word nbucket; + Elf_Word nchain; + + ArrayRef<Elf_Word> buckets() const { + return ArrayRef<Elf_Word>(&nbucket + 2, &nbucket + 2 + nbucket); + } + + ArrayRef<Elf_Word> chains() const { + return ArrayRef<Elf_Word>(&nbucket + 2 + nbucket, + &nbucket + 2 + nbucket + nchain); + } +}; + // MIPS .reginfo section template <class ELFT> struct Elf_Mips_RegInfo; diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index b45507920a9c..df0aa500c8a2 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -85,7 +85,13 @@ struct SectionOrType { }; struct Section { - enum class SectionKind { Group, RawContent, Relocation, MipsABIFlags }; + enum class SectionKind { + Group, + RawContent, + Relocation, + NoBits, + MipsABIFlags + }; SectionKind Kind; StringRef Name; ELF_SHT Type; @@ -106,6 +112,14 @@ struct RawContentSection : Section { } }; +struct NoBitsSection : Section { + llvm::yaml::Hex64 Size; + NoBitsSection() : Section(SectionKind::NoBits) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::NoBits; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index f4edfd057303..489ecef5c996 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -205,9 +205,7 @@ public: std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; unsigned getSectionType(SectionRef Sec) const; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - uint64_t getSymbolValue(DataRefImpl Symb) const override; + ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; @@ -233,7 +231,6 @@ public: relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const override; uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; section_iterator getRelocationSection(DataRefImpl Rel) const; @@ -245,6 +242,8 @@ public: // MachO specific. std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; + section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; + // TODO: Would be useful to have an iterator based version // of the load command interface too. @@ -425,6 +424,8 @@ public: } private: + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + union { MachO::mach_header_64 Header64; MachO::mach_header Header; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 62eab1066be5..8dd525626218 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -50,7 +50,6 @@ public: void moveNext(); - ErrorOr<uint64_t> getAddress() const; uint64_t getOffset() const; symbol_iterator getSymbol() const; uint64_t getType() const; @@ -135,7 +134,7 @@ public: ErrorOr<StringRef> getName() const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). - std::error_code getAddress(uint64_t &Result) const; + ErrorOr<uint64_t> getAddress() const; /// Return the value of the symbol depending on the object this can be an /// offset or a virtual address. @@ -198,9 +197,8 @@ protected: virtual ErrorOr<StringRef> getSymbolName(DataRefImpl Symb) const = 0; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - virtual std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const = 0; - virtual uint64_t getSymbolValue(DataRefImpl Symb) const = 0; + virtual ErrorOr<uint64_t> getSymbolAddress(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; virtual SymbolRef::Type getSymbolType(DataRefImpl Symb) const = 0; @@ -229,13 +227,14 @@ protected: // Same as above for RelocationRef. friend class RelocationRef; virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; - virtual ErrorOr<uint64_t> getRelocationAddress(DataRefImpl Rel) const = 0; virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; virtual void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const = 0; + uint64_t getSymbolValue(DataRefImpl Symb) const; + public: uint64_t getCommonSymbolSize(DataRefImpl Symb) const { assert(getSymbolFlags(Symb) & SymbolRef::SF_Common); @@ -308,8 +307,8 @@ inline ErrorOr<StringRef> SymbolRef::getName() const { return getObject()->getSymbolName(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getAddress(uint64_t &Result) const { - return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); +inline ErrorOr<uint64_t> SymbolRef::getAddress() const { + return getObject()->getSymbolAddress(getRawDataRefImpl()); } inline uint64_t SymbolRef::getValue() const { @@ -430,10 +429,6 @@ inline void RelocationRef::moveNext() { return OwningObject->moveRelocationNext(RelocationPimpl); } -inline ErrorOr<uint64_t> RelocationRef::getAddress() const { - return OwningObject->getRelocationAddress(RelocationPimpl); -} - inline uint64_t RelocationRef::getOffset() const { return OwningObject->getRelocationOffset(RelocationPimpl); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 950e2ed0e338..d5e4258cb0a7 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -100,9 +100,9 @@ private: case Triple::mips64: switch (RelocType) { case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); + return visitELF_MIPS64_32(R, Value); case llvm::ELF::R_MIPS_64: - return visitELF_MIPS_64(R, Value); + return visitELF_MIPS64_64(R, Value); default: HasError = true; return RelocToApply(); @@ -313,11 +313,18 @@ private: /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { - uint32_t Res = (Value)&0xFFFFFFFF; + uint32_t Res = Value & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + /// MIPS64 ELF + RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } - RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { + RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) { int64_t Addend = getELFAddend(R); uint64_t Res = (Value + Addend); return RelocToApply(Res, 8); diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 3a3823159c92..537997ac6318 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -115,8 +115,6 @@ public: typedef content_iterator<BasicSymbolRef> basic_symbol_iterator; -const uint64_t UnknownAddress = ~0ULL; - class SymbolicFile : public Binary { public: ~SymbolicFile() override; diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index b26af61a7c70..3c5ee06969d0 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -655,6 +655,7 @@ namespace COFF { }; enum CodeViewIdentifiers { + DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1, DEBUG_SECTION_MAGIC = 0x4, DEBUG_SYMBOL_SUBSECTION = 0xF1, DEBUG_LINE_TABLE_SUBSECTION = 0xF2, diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index ed809211ea97..379d06a65741 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -790,7 +790,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); +extern template class basic_parser<bool>; //-------------------------------------------------- // parser<boolOrDefault> @@ -816,7 +816,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); +extern template class basic_parser<boolOrDefault>; //-------------------------------------------------- // parser<int> @@ -838,7 +838,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); +extern template class basic_parser<int>; //-------------------------------------------------- // parser<unsigned> @@ -860,7 +860,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); +extern template class basic_parser<unsigned>; //-------------------------------------------------- // parser<unsigned long long> @@ -885,7 +885,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); +extern template class basic_parser<unsigned long long>; //-------------------------------------------------- // parser<double> @@ -907,7 +907,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); +extern template class basic_parser<double>; //-------------------------------------------------- // parser<float> @@ -929,7 +929,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); +extern template class basic_parser<float>; //-------------------------------------------------- // parser<std::string> @@ -954,7 +954,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); +extern template class basic_parser<std::string>; //-------------------------------------------------- // parser<char> @@ -979,7 +979,7 @@ public: void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>); +extern template class basic_parser<char>; //-------------------------------------------------- // PrintOptionDiff @@ -1254,11 +1254,11 @@ public: } }; -EXTERN_TEMPLATE_INSTANTIATION(class opt<unsigned>); -EXTERN_TEMPLATE_INSTANTIATION(class opt<int>); -EXTERN_TEMPLATE_INSTANTIATION(class opt<std::string>); -EXTERN_TEMPLATE_INSTANTIATION(class opt<char>); -EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>); +extern template class opt<unsigned>; +extern template class opt<int>; +extern template class opt<std::string>; +extern template class opt<char>; +extern template class opt<bool>; //===----------------------------------------------------------------------===// // list_storage class diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 67ef23d43c99..141639839cc2 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -174,19 +174,6 @@ #define LLVM_UNLIKELY(EXPR) (EXPR) #endif -// C++ doesn't support 'extern template' of template specializations. GCC does, -// but requires __extension__ before it. In the header, use this: -// EXTERN_TEMPLATE_INSTANTIATION(class foo<bar>); -// in the .cpp file, use this: -// TEMPLATE_INSTANTIATION(class foo<bar>); -#ifdef __GNUC__ -#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X -#define TEMPLATE_INSTANTIATION(X) template X -#else -#define EXTERN_TEMPLATE_INSTANTIATION(X) -#define TEMPLATE_INSTANTIATION(X) -#endif - /// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, /// mark a method "not for inlining". #if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index 0f097f287286..08e277ad5ce1 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -280,13 +280,19 @@ public: }; /// \brief Look up the stored data for a particular key. - iterator find(const external_key_type &EKey, Info *InfoPtr = 0) { - if (!InfoPtr) - InfoPtr = &InfoObj; - - using namespace llvm::support; + iterator find(const external_key_type &EKey, Info *InfoPtr = nullptr) { const internal_key_type &IKey = InfoObj.GetInternalKey(EKey); hash_value_type KeyHash = InfoObj.ComputeHash(IKey); + return find_hashed(IKey, KeyHash, InfoPtr); + } + + /// \brief Look up the stored data for a particular key with a known hash. + iterator find_hashed(const internal_key_type &IKey, hash_value_type KeyHash, + Info *InfoPtr = nullptr) { + using namespace llvm::support; + + if (!InfoPtr) + InfoPtr = &InfoObj; // Each bucket is just an offset into the hash table file. offset_type Idx = KeyHash & (NumBuckets - 1); diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index d2e8b95d74f3..40bf6fb20c9f 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -71,7 +71,7 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx); -MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, +MCSymbolizer *createMCSymbolizer(const Triple &TT, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo); @@ -92,17 +92,18 @@ public: typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, const Triple &TT); - typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, + typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(const Triple &TT, + Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info); - typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(const Triple &TT); typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(const Triple &TT, StringRef CPU, StringRef Features); typedef TargetMachine *(*TargetMachineCtorTy)( - const Target &T, StringRef TT, StringRef CPU, StringRef Features, + const Target &T, const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); // If it weren't for layering issues (this header is in llvm/Support, but @@ -150,7 +151,7 @@ public: typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(const Triple &TT, MCContext &Ctx); typedef MCSymbolizer *(*MCSymbolizerCtorTy)( - StringRef TT, LLVMOpInfoCallback GetOpInfo, + const Triple &TT, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo); @@ -300,12 +301,12 @@ public: /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. /// - MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, + MCCodeGenInfo *createMCCodeGenInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL) const { if (!MCCodeGenInfoCtorFn) return nullptr; - return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); + return MCCodeGenInfoCtorFn(Triple(TT), RM, CM, OL); } /// createMCInstrInfo - Create a MCInstrInfo implementation. @@ -326,10 +327,10 @@ public: /// createMCRegInfo - Create a MCRegisterInfo implementation. /// - MCRegisterInfo *createMCRegInfo(StringRef Triple) const { + MCRegisterInfo *createMCRegInfo(StringRef TT) const { if (!MCRegInfoCtorFn) return nullptr; - return MCRegInfoCtorFn(Triple); + return MCRegInfoCtorFn(Triple(TT)); } /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. @@ -351,20 +352,20 @@ public: /// createTargetMachine - Create a target specific machine implementation /// for the specified \p Triple. /// - /// \param Triple This argument is used to determine the target machine + /// \param TT This argument is used to determine the target machine /// feature set; it should always be provided. Generally this should be /// either the target triple from the module, or the target triple of the /// host if that does not exist. TargetMachine * - createTargetMachine(StringRef Triple, StringRef CPU, StringRef Features, + createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, Reloc::Model RM = Reloc::Default, CodeModel::Model CM = CodeModel::Default, CodeGenOpt::Level OL = CodeGenOpt::Default) const { if (!TargetMachineCtorFn) return nullptr; - return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, - OL); + return TargetMachineCtorFn(*this, Triple(TT), CPU, Features, Options, RM, + CM, OL); } /// createMCAsmBackend - Create a target specific assembly parser. @@ -529,7 +530,8 @@ public: std::unique_ptr<MCRelocationInfo> &&RelInfo) const { MCSymbolizerCtorTy Fn = MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; - return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)); + return Fn(Triple(TT), GetOpInfo, SymbolLookUp, DisInfo, Ctx, + std::move(RelInfo)); } /// @} @@ -924,7 +926,7 @@ template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo { } private: - static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/, + static MCCodeGenInfo *Allocator(const Triple & /*TT*/, Reloc::Model /*RM*/, CodeModel::Model /*CM*/, CodeGenOpt::Level /*OL*/) { return new MCCodeGenInfoImpl(); @@ -1023,7 +1025,7 @@ template <class MCRegisterInfoImpl> struct RegisterMCRegInfo { } private: - static MCRegisterInfo *Allocator(StringRef /*TT*/) { + static MCRegisterInfo *Allocator(const Triple & /*TT*/) { return new MCRegisterInfoImpl(); } }; @@ -1090,11 +1092,11 @@ template <class TargetMachineImpl> struct RegisterTargetMachine { } private: - static TargetMachine *Allocator(const Target &T, StringRef TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL) { - return new TargetMachineImpl(T, Triple(TT), CPU, FS, Options, RM, CM, OL); + static TargetMachine *Allocator(const Target &T, const Triple &TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, Reloc::Model RM, + CodeModel::Model CM, CodeGenOpt::Level OL) { + return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); } }; diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index b59317112c44..28e512c86941 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -165,8 +165,10 @@ public: if (Size > (size_t)(OutBufEnd - OutBufCur)) return write(Str.data(), Size); - memcpy(OutBufCur, Str.data(), Size); - OutBufCur += Size; + if (Size) { + memcpy(OutBufCur, Str.data(), Size); + OutBufCur += Size; + } return *this; } diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 717a2a4ba62a..b4642c991192 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1222,11 +1222,11 @@ public: /// get the corresponding DefInit. DefInit *getDefInit(); - const std::vector<Init *> &getTemplateArgs() const { + ArrayRef<Init *> getTemplateArgs() const { return TemplateArgs; } - const std::vector<RecordVal> &getValues() const { return Values; } - const std::vector<Record*> &getSuperClasses() const { return SuperClasses; } + ArrayRef<RecordVal> getValues() const { return Values; } + ArrayRef<Record *> getSuperClasses() const { return SuperClasses; } ArrayRef<SMRange> getSuperClassRanges() const { return SuperClassRanges; } bool isTemplateArg(Init *Name) const { diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 61234991be44..e0aea181a639 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -872,7 +872,7 @@ def LOAD_STACK_GUARD : Instruction { let hasSideEffects = 0; bit isPseudo = 1; } -def FRAME_ALLOC : Instruction { +def LOCAL_ESCAPE : Instruction { // This instruction is really just a label. It has to be part of the chain so // that it doesn't get dropped from the DAG, but it produces nothing and has // no side effects. @@ -1014,7 +1014,7 @@ class InstAlias<string Asm, dag Result, int Emit = 1> { // Predicates - Predicates that must be true for this to match. list<Predicate> Predicates = []; - // If the instruction specified in Result has defined an AsmMatchConverter + // If the instruction specified in Result has defined an AsmMatchConverter // then setting this to 1 will cause the alias to use the AsmMatchConverter // function when converting the OperandVector into an MCInst instead of the // function that is generated by the dag Result. diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index 0e317247a59f..3af2227410f7 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -19,6 +19,7 @@ #include <vector> namespace llvm { + class BitVector; class CalleeSavedInfo; class MachineFunction; class RegScavenger; @@ -226,13 +227,15 @@ public: return 0; } - /// processFunctionBeforeCalleeSavedScan - This method is called immediately - /// before PrologEpilogInserter scans the physical registers used to determine - /// what callee saved registers should be spilled. This method is optional. - virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS = nullptr) const { - - } + /// This method determines which of the registers reported by + /// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved. + /// The default implementation checks populates the \p SavedRegs bitset with + /// all registers which are modified in the function, targets may override + /// this function to save additional registers. + /// This method also sets up the register scavenger ensuring there is a free + /// register or a frameindex available. + virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, + RegScavenger *RS = nullptr) const; /// processFunctionBeforeFrameFinalized - This method is called immediately /// before the specified function's frame layout (MF.getFrameInfo()) is diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 277487fee6bc..4412d9b3c68e 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -161,27 +161,27 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } - const DataLayout *getDataLayout() const { return TM.getDataLayout(); } - bool isBigEndian() const { return !IsLittleEndian; } - bool isLittleEndian() const { return IsLittleEndian; } virtual bool useSoftFloat() const { return false; } /// Return the pointer type for the given address space, defaults to /// the pointer type from the data layout. /// FIXME: The default needs to be removed once all the code is updated. - virtual MVT getPointerTy(uint32_t /*AS*/ = 0) const; - unsigned getPointerSizeInBits(uint32_t AS = 0) const; - unsigned getPointerTypeSizeInBits(Type *Ty) const; - virtual MVT getScalarShiftAmountTy(EVT LHSTy) const; + MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const { + return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); + } + + /// EVT is not used in-tree, but is used by out-of-tree target. + /// A documentation for this function would be nice... + virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const; - EVT getShiftAmountTy(EVT LHSTy) const; + EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const; /// Returns the type to be used for the index operand of: /// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT, /// ISD::INSERT_SUBVECTOR, and ISD::EXTRACT_SUBVECTOR - virtual MVT getVectorIdxTy() const { - return getPointerTy(); + virtual MVT getVectorIdxTy(const DataLayout &DL) const { + return getPointerTy(DL); } /// Return true if the select operation is expensive for this target. @@ -327,7 +327,8 @@ public: } /// Return the ValueType of the result of SETCC operations. - virtual EVT getSetCCResultType(LLVMContext &Context, EVT VT) const; + virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, + EVT VT) const; /// Return the ValueType for comparison libcalls. Comparions libcalls include /// floating point comparion calls, and Ordered/Unordered check calls on @@ -715,17 +716,18 @@ public: /// operations except for the pointer size. If AllowUnknown is true, this /// will return MVT::Other for types with no EVT counterpart (e.g. structs), /// otherwise it will assert. - EVT getValueType(Type *Ty, bool AllowUnknown = false) const { + EVT getValueType(const DataLayout &DL, Type *Ty, + bool AllowUnknown = false) const { // Lower scalar pointers to native pointer types. if (PointerType *PTy = dyn_cast<PointerType>(Ty)) - return getPointerTy(PTy->getAddressSpace()); + return getPointerTy(DL, PTy->getAddressSpace()); if (Ty->isVectorTy()) { VectorType *VTy = cast<VectorType>(Ty); Type *Elm = VTy->getElementType(); // Lower vectors of pointers to native pointer types. if (PointerType *PT = dyn_cast<PointerType>(Elm)) { - EVT PointerTy(getPointerTy(PT->getAddressSpace())); + EVT PointerTy(getPointerTy(DL, PT->getAddressSpace())); Elm = PointerTy.getTypeForEVT(Ty->getContext()); } @@ -736,14 +738,15 @@ public: } /// Return the MVT corresponding to this LLVM type. See getValueType. - MVT getSimpleValueType(Type *Ty, bool AllowUnknown = false) const { - return getValueType(Ty, AllowUnknown).getSimpleVT(); + MVT getSimpleValueType(const DataLayout &DL, Type *Ty, + bool AllowUnknown = false) const { + return getValueType(DL, Ty, AllowUnknown).getSimpleVT(); } /// Return the desired alignment for ByVal or InAlloca aggregate function /// arguments in the caller parameter area. This is the actual alignment, not /// its logarithm. - virtual unsigned getByValTypeAlignment(Type *Ty) const; + virtual unsigned getByValTypeAlignment(Type *Ty, const DataLayout &DL) const; /// Return the type of registers that this ValueType will eventually require. MVT getRegisterType(MVT VT) const { @@ -818,8 +821,8 @@ public: /// When splitting a value of the specified type into parts, does the Lo /// or Hi part come first? This usually follows the endianness, except /// for ppcf128, where the Hi part always comes first. - bool hasBigEndianPartOrdering(EVT VT) const { - return isBigEndian() || VT == MVT::ppcf128; + bool hasBigEndianPartOrdering(EVT VT, const DataLayout &DL) const { + return DL.isBigEndian() || VT == MVT::ppcf128; } /// If true, the target has custom DAG combine transformations that it can @@ -1006,7 +1009,8 @@ public: int InstructionOpcodeToISD(unsigned Opcode) const; /// Estimate the cost of type-legalization and the legalized type. - std::pair<unsigned, MVT> getTypeLegalizationCost(Type *Ty) const; + std::pair<unsigned, MVT> getTypeLegalizationCost(const DataLayout &DL, + Type *Ty) const; /// @} @@ -1460,8 +1464,8 @@ public: /// If the address space cannot be determined, it will be -1. /// /// TODO: Remove default argument - virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty, - unsigned AddrSpace) const; + virtual bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, + Type *Ty, unsigned AddrSpace) const; /// \brief Return the cost of the scaling factor used in the addressing mode /// represented by AM for this target, for a load/store of the specified type. @@ -1470,10 +1474,10 @@ public: /// If the AM is not supported, it returns a negative value. /// TODO: Handle pre/postinc as well. /// TODO: Remove default argument - virtual int getScalingFactorCost(const AddrMode &AM, Type *Ty, - unsigned AS = 0) const { + virtual int getScalingFactorCost(const DataLayout &DL, const AddrMode &AM, + Type *Ty, unsigned AS = 0) const { // Default: assume that any scaling factor used in a legal AM is free. - if (isLegalAddressingMode(AM, Ty, AS)) + if (isLegalAddressingMode(DL, AM, Ty, AS)) return 0; return -1; } @@ -1734,9 +1738,6 @@ public: private: const TargetMachine &TM; - /// True if this is a little endian target. - bool IsLittleEndian; - /// Tells the code generator not to expand operations into sequences that use /// the select operations if possible. bool SelectIsExpensive; @@ -2414,6 +2415,7 @@ public: ArgListTy &getArgs() { return Args; } + }; /// This function lowers an abstract call to a function into an actual call. @@ -2485,7 +2487,8 @@ public: /// Return the register ID of the name passed in. Used by named register /// global variables extension. There is no target-independent behaviour /// so the default action is to bail. - virtual unsigned getRegisterByName(const char* RegName, EVT VT) const { + virtual unsigned getRegisterByName(const char* RegName, EVT VT, + SelectionDAG &DAG) const { report_fatal_error("Named registers not implemented for this target"); } @@ -2657,7 +2660,8 @@ public: /// specific constraints and their prefixes, and also tie in the associated /// operand values. If this returns an empty vector, and if the constraint /// string itself isn't empty, there was an error parsing. - virtual AsmOperandInfoVector ParseConstraints(const TargetRegisterInfo *TRI, + virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, + const TargetRegisterInfo *TRI, ImmutableCallSite CS) const; /// Examine constraint type and operand type and determine a weight value. @@ -2679,7 +2683,7 @@ public: SelectionDAG *DAG = nullptr) const; /// Given a constraint, return the type of constraint it is for this target. - virtual ConstraintType getConstraintType(const std::string &Constraint) const; + virtual ConstraintType getConstraintType(StringRef Constraint) const; /// Given a physical register constraint (e.g. {edx}), return the register /// number and the register class for the register. @@ -2692,10 +2696,9 @@ public: /// returns a register number of 0 and a null register class pointer. virtual std::pair<unsigned, const TargetRegisterClass *> getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - const std::string &Constraint, MVT VT) const; + StringRef Constraint, MVT VT) const; - virtual unsigned - getInlineAsmMemConstraint(const std::string &ConstraintCode) const { + virtual unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const { if (ConstraintCode == "i") return InlineAsm::Constraint_i; else if (ConstraintCode == "m") @@ -2823,9 +2826,9 @@ public: /// Given an LLVM IR type and return type attributes, compute the return value /// EVTs and flags, and optionally also the offsets, if the return value is /// being lowered to memory. -void GetReturnInfo(Type* ReturnType, AttributeSet attr, +void GetReturnInfo(Type *ReturnType, AttributeSet attr, SmallVectorImpl<ISD::OutputArg> &Outs, - const TargetLowering &TLI); + const TargetLowering &TLI, const DataLayout &DL); } // end llvm namespace diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 64a923b80edf..06a2b13836ed 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -212,8 +212,8 @@ public: /// supported, or false on success. virtual bool addPassesToEmitFile( PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, - bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, - AnalysisID /*StopAfter*/ = nullptr, + bool /*DisableVerify*/ = true, AnalysisID /*StartBefore*/ = nullptr, + AnalysisID /*StartAfter*/ = nullptr, AnalysisID /*StopAfter*/ = nullptr, MachineFunctionInitializer * /*MFInitializer*/ = nullptr) { return true; } @@ -260,8 +260,8 @@ public: /// emitted. Typically this will involve several steps of code generation. bool addPassesToEmitFile( PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, - bool DisableVerify = true, AnalysisID StartAfter = nullptr, - AnalysisID StopAfter = nullptr, + bool DisableVerify = true, AnalysisID StartBefore = nullptr, + AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr, MachineFunctionInitializer *MFInitializer = nullptr) override; /// Add passes to the specified pass manager to get machine code emitted with diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index 1f9a5d4ecaf0..50197191109d 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -118,10 +118,10 @@ enum { /// collectors and deoptimizations in either the callee or caller. STATEPOINT = 20, - /// Instruction that records the offset of a function's frame allocation in a - /// label. Created by the llvm.frameallocate intrinsic. It has two arguments: - /// the symbol for the label and the frame index of the stack allocation. - FRAME_ALLOC = 21, + /// Instruction that records the offset of a local stack allocation passed to + /// llvm.localescape. It has two arguments: the symbol for the label and the + /// frame index of the local stack allocation. + LOCAL_ESCAPE = 21, /// Loading instruction that may page fault, bundled with associated /// information on how to handle such a page fault. It is intended to support diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index bacdd950705b..53db5aa84292 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -20,8 +20,6 @@ namespace llvm { -class DataLayout; - //===----------------------------------------------------------------------===// /// TargetSelectionDAGInfo - Targets can subclass this to parameterize the /// SelectionDAG lowering and instruction selection process. @@ -30,13 +28,8 @@ class TargetSelectionDAGInfo { TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) = delete; void operator=(const TargetSelectionDAGInfo &) = delete; - const DataLayout *DL; - -protected: - const DataLayout *getDataLayout() const { return DL; } - public: - explicit TargetSelectionDAGInfo(const DataLayout *DL); + explicit TargetSelectionDAGInfo() = default; virtual ~TargetSelectionDAGInfo(); /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index e42c56add7b1..07c0c66bfa18 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -44,9 +44,17 @@ template <typename T> class SmallVectorImpl; class TargetSubtargetInfo : public MCSubtargetInfo { TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; void operator=(const TargetSubtargetInfo &) = delete; + TargetSubtargetInfo() = delete; protected: // Can only create subclasses... - TargetSubtargetInfo(); + TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, + ArrayRef<SubtargetFeatureKV> PF, + ArrayRef<SubtargetFeatureKV> PD, + const SubtargetInfoKV *ProcSched, + const MCWriteProcResEntry *WPR, + const MCWriteLatencyEntry *WL, + const MCReadAdvanceEntry *RA, const InstrStage *IS, + const unsigned *OC, const unsigned *FP); public: // AntiDepBreakMode - Type of anti-dependence breaking that should diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index fbd999cbc946..2ea47301bb4c 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -71,6 +71,12 @@ ModulePass *createGlobalOptimizerPass(); ModulePass *createGlobalDCEPass(); //===----------------------------------------------------------------------===// +/// This transform is designed to eliminate available external globals +/// (functions or global variables) +/// +ModulePass *createEliminateAvailableExternallyPass(); + +//===----------------------------------------------------------------------===// /// createGVExtractionPass - If deleteFn is true, this pass deletes /// the specified global values. Otherwise, it deletes as much of the module as /// possible, except for the global values specified. diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 5d574ae0bf0f..1334dd0da23c 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -121,6 +121,7 @@ public: bool VerifyInput; bool VerifyOutput; bool MergeFunctions; + bool PrepareForLTO; private: /// ExtensionList - This is list of all of the extensions that are registered. diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index cb187ec103d0..2caa9a2462df 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -45,6 +45,7 @@ class LoopInfo; class AllocaInst; class AliasAnalysis; class AssumptionCacheTracker; +class DominatorTree; /// CloneModule - Return an exact copy of the specified module /// @@ -233,6 +234,21 @@ bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, bool InsertLifetime = true); +/// \brief Clones a loop \p OrigLoop. Returns the loop and the blocks in \p +/// Blocks. +/// +/// Updates LoopInfo and DominatorTree assuming the loop is dominated by block +/// \p LoopDomBB. Insert the new blocks before block specified in \p Before. +Loop *cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, + Loop *OrigLoop, ValueToValueMapTy &VMap, + const Twine &NameSuffix, LoopInfo *LI, + DominatorTree *DT, + SmallVectorImpl<BasicBlock *> &Blocks); + +/// \brief Remaps instructions in \p Blocks using the mapping in \p VMap. +void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks, + ValueToValueMapTy &VMap); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/LoopVersioning.h b/include/llvm/Transforms/Utils/LoopVersioning.h new file mode 100644 index 000000000000..009fba48c6a3 --- /dev/null +++ b/include/llvm/Transforms/Utils/LoopVersioning.h @@ -0,0 +1,100 @@ +//===- LoopVersioning.h - Utility to version a loop -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a utility class to perform loop versioning. The versioned +// loop speculates that otherwise may-aliasing memory accesses don't overlap and +// emits checks to prove this. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_LOOPVERSIONING_H +#define LLVM_TRANSFORMS_UTILS_LOOPVERSIONING_H + +#include "llvm/Transforms/Utils/ValueMapper.h" + +namespace llvm { + +class Loop; +class LoopAccessInfo; +class LoopInfo; + +/// \brief This class emits a version of the loop where run-time checks ensure +/// that may-alias pointers can't overlap. +/// +/// It currently only supports single-exit loops and assumes that the loop +/// already has a preheader. +class LoopVersioning { +public: + LoopVersioning(const LoopAccessInfo &LAI, Loop *L, LoopInfo *LI, + DominatorTree *DT, + const SmallVector<int, 8> *PtrToPartition = nullptr); + + /// \brief Returns true if we need memchecks to disambiguate may-aliasing + /// accesses. + bool needsRuntimeChecks() const; + + /// \brief Performs the CFG manipulation part of versioning the loop including + /// the DominatorTree and LoopInfo updates. + /// + /// The loop that was used to construct the class will be the "versioned" loop + /// i.e. the loop that will receive control if all the memchecks pass. + /// + /// This allows the loop transform pass to operate on the same loop regardless + /// of whether versioning was necessary or not: + /// + /// for each loop L: + /// analyze L + /// if versioning is necessary version L + /// transform L + void versionLoop(Pass *P); + + /// \brief Adds the necessary PHI nodes for the versioned loops based on the + /// loop-defined values used outside of the loop. + /// + /// This needs to be called after versionLoop if there are defs in the loop + /// that are used outside the loop. FIXME: this should be invoked internally + /// by versionLoop and made private. + void addPHINodes(const SmallVectorImpl<Instruction *> &DefsUsedOutside); + + /// \brief Returns the versioned loop. Control flows here if pointers in the + /// loop don't alias (i.e. all memchecks passed). (This loop is actually the + /// same as the original loop that we got constructed with.) + Loop *getVersionedLoop() { return VersionedLoop; } + + /// \brief Returns the fall-back loop. Control flows here if pointers in the + /// loop may alias (i.e. one of the memchecks failed). + Loop *getNonVersionedLoop() { return NonVersionedLoop; } + +private: + /// \brief The original loop. This becomes the "versioned" one. I.e., + /// control flows here if pointers in the loop don't alias. + Loop *VersionedLoop; + /// \brief The fall-back loop. I.e. control flows here if pointers in the + /// loop may alias (memchecks failed). + Loop *NonVersionedLoop; + + /// \brief For each memory pointer it contains the partitionId it is used in. + /// If nullptr, no partitioning is used. + /// + /// The I-th entry corresponds to I-th entry in LAI.getRuntimePointerCheck(). + /// If the pointer is used in multiple partitions the entry is set to -1. + const SmallVector<int, 8> *PtrToPartition; + + /// \brief This maps the instructions from VersionedLoop to their counterpart + /// in NonVersionedLoop. + ValueToValueMapTy VMap; + + /// \brief Analyses used. + const LoopAccessInfo &LAI; + LoopInfo *LI; + DominatorTree *DT; +}; +} + +#endif diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index ad0727a0e0e5..44d137dffd22 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -71,11 +71,6 @@ void AliasAnalysis::deleteValue(Value *V) { AA->deleteValue(V); } -void AliasAnalysis::copyValue(Value *From, Value *To) { - assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); - AA->copyValue(From, To); -} - void AliasAnalysis::addEscapingUse(Use &U) { assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); AA->addEscapingUse(U); diff --git a/lib/Analysis/AliasDebugger.cpp b/lib/Analysis/AliasDebugger.cpp index 1ef49fc02fef..e5107b3bc827 100644 --- a/lib/Analysis/AliasDebugger.cpp +++ b/lib/Analysis/AliasDebugger.cpp @@ -124,10 +124,6 @@ namespace { assert(Vals.find(V) != Vals.end() && "Never seen value in AA before"); AliasAnalysis::deleteValue(V); } - void copyValue(Value *From, Value *To) override { - Vals.insert(To); - AliasAnalysis::copyValue(From, To); - } }; } diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp index bf8cda1ffaec..54d0f4304e1f 100644 --- a/lib/Analysis/AliasSetTracker.cpp +++ b/lib/Analysis/AliasSetTracker.cpp @@ -544,9 +544,6 @@ void AliasSetTracker::deleteValue(Value *PtrVal) { // the tracker already knows about a value, it will ignore the request. // void AliasSetTracker::copyValue(Value *From, Value *To) { - // Notify the alias analysis implementation that this value is copied. - AA.copyValue(From, To); - // First, look up the PointerRec for this pointer. PointerMapType::iterator I = PointerMap.find_as(From); if (I == PointerMap.end()) diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 8e812252fdfe..68f766edb301 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -685,6 +685,9 @@ BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { if (CS.onlyReadsMemory()) Min = OnlyReadsMemory; + if (CS.onlyAccessesArgMemory()) + Min = ModRefBehavior(Min & OnlyAccessesArgumentPointees); + // The AliasAnalysis base class has some smarts, lets use them. return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); } @@ -710,6 +713,9 @@ BasicAliasAnalysis::getModRefBehavior(const Function *F) { if (F->onlyReadsMemory()) Min = OnlyReadsMemory; + if (F->onlyAccessesArgMemory()) + Min = ModRefBehavior(Min & OnlyAccessesArgumentPointees); + const TargetLibraryInfo &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); if (isMemsetPattern16(F, TLI)) diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 2f4c6a92f9af..02a5aef03223 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -1234,6 +1234,8 @@ bool llvm::canConstantFoldCallTo(const Function *F) { case Intrinsic::floor: case Intrinsic::ceil: case Intrinsic::sqrt: + case Intrinsic::sin: + case Intrinsic::cos: case Intrinsic::pow: case Intrinsic::powi: case Intrinsic::bswap: @@ -1450,6 +1452,10 @@ static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID, return ConstantFoldFP(floor, V, Ty); case Intrinsic::ceil: return ConstantFoldFP(ceil, V, Ty); + case Intrinsic::sin: + return ConstantFoldFP(sin, V, Ty); + case Intrinsic::cos: + return ConstantFoldFP(cos, V, Ty); } if (!TLI) diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index f1ddde252924..18d45dd6a396 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -42,94 +42,111 @@ STATISTIC(NumReadMemFunctions, "Number of functions that only read memory"); STATISTIC(NumIndirectGlobalVars, "Number of indirect global objects"); namespace { - /// FunctionRecord - One instance of this structure is stored for every - /// function in the program. Later, the entries for these functions are - /// removed if the function is found to call an external function (in which - /// case we know nothing about it. - struct FunctionRecord { - /// GlobalInfo - Maintain mod/ref info for all of the globals without - /// addresses taken that are read or written (transitively) by this - /// function. - std::map<const GlobalValue*, unsigned> GlobalInfo; - - /// MayReadAnyGlobal - May read global variables, but it is not known which. - bool MayReadAnyGlobal; - - unsigned getInfoForGlobal(const GlobalValue *GV) const { - unsigned Effect = MayReadAnyGlobal ? AliasAnalysis::Ref : 0; - std::map<const GlobalValue*, unsigned>::const_iterator I = +/// FunctionRecord - One instance of this structure is stored for every +/// function in the program. Later, the entries for these functions are +/// removed if the function is found to call an external function (in which +/// case we know nothing about it. +struct FunctionRecord { + /// GlobalInfo - Maintain mod/ref info for all of the globals without + /// addresses taken that are read or written (transitively) by this + /// function. + std::map<const GlobalValue *, unsigned> GlobalInfo; + + /// MayReadAnyGlobal - May read global variables, but it is not known which. + bool MayReadAnyGlobal; + + unsigned getInfoForGlobal(const GlobalValue *GV) const { + unsigned Effect = MayReadAnyGlobal ? AliasAnalysis::Ref : 0; + std::map<const GlobalValue *, unsigned>::const_iterator I = GlobalInfo.find(GV); - if (I != GlobalInfo.end()) - Effect |= I->second; - return Effect; - } + if (I != GlobalInfo.end()) + Effect |= I->second; + return Effect; + } - /// FunctionEffect - Capture whether or not this function reads or writes to - /// ANY memory. If not, we can do a lot of aggressive analysis on it. - unsigned FunctionEffect; + /// FunctionEffect - Capture whether or not this function reads or writes to + /// ANY memory. If not, we can do a lot of aggressive analysis on it. + unsigned FunctionEffect; - FunctionRecord() : MayReadAnyGlobal (false), FunctionEffect(0) {} - }; + FunctionRecord() : MayReadAnyGlobal(false), FunctionEffect(0) {} +}; - /// GlobalsModRef - The actual analysis pass. - class GlobalsModRef : public ModulePass, public AliasAnalysis { - /// NonAddressTakenGlobals - The globals that do not have their addresses - /// taken. - std::set<const GlobalValue*> NonAddressTakenGlobals; +/// GlobalsModRef - The actual analysis pass. +class GlobalsModRef : public ModulePass, public AliasAnalysis { + /// NonAddressTakenGlobals - The globals that do not have their addresses + /// taken. + std::set<const GlobalValue *> NonAddressTakenGlobals; - /// IndirectGlobals - The memory pointed to by this global is known to be - /// 'owned' by the global. - std::set<const GlobalValue*> IndirectGlobals; + /// IndirectGlobals - The memory pointed to by this global is known to be + /// 'owned' by the global. + std::set<const GlobalValue *> IndirectGlobals; - /// AllocsForIndirectGlobals - If an instruction allocates memory for an - /// indirect global, this map indicates which one. - std::map<const Value*, const GlobalValue*> AllocsForIndirectGlobals; + /// AllocsForIndirectGlobals - If an instruction allocates memory for an + /// indirect global, this map indicates which one. + std::map<const Value *, const GlobalValue *> AllocsForIndirectGlobals; - /// FunctionInfo - For each function, keep track of what globals are - /// modified or read. - std::map<const Function*, FunctionRecord> FunctionInfo; + /// FunctionInfo - For each function, keep track of what globals are + /// modified or read. + std::map<const Function *, FunctionRecord> FunctionInfo; - public: - static char ID; - GlobalsModRef() : ModulePass(ID) { - initializeGlobalsModRefPass(*PassRegistry::getPassRegistry()); - } +public: + static char ID; + GlobalsModRef() : ModulePass(ID) { + initializeGlobalsModRefPass(*PassRegistry::getPassRegistry()); + } - bool runOnModule(Module &M) override { - InitializeAliasAnalysis(this, &M.getDataLayout()); + bool runOnModule(Module &M) override { + InitializeAliasAnalysis(this, &M.getDataLayout()); - // Find non-addr taken globals. - AnalyzeGlobals(M); + // Find non-addr taken globals. + AnalyzeGlobals(M); - // Propagate on CG. - AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M); - return false; - } + // Propagate on CG. + AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M); + return false; + } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AliasAnalysis::getAnalysisUsage(AU); - AU.addRequired<CallGraphWrapperPass>(); - AU.setPreservesAll(); // Does not transform code - } + void getAnalysisUsage(AnalysisUsage &AU) const override { + AliasAnalysis::getAnalysisUsage(AU); + AU.addRequired<CallGraphWrapperPass>(); + AU.setPreservesAll(); // Does not transform code + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const MemoryLocation &LocA, + const MemoryLocation &LocB) override; + ModRefResult getModRefInfo(ImmutableCallSite CS, + const MemoryLocation &Loc) override; + ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) override { + return AliasAnalysis::getModRefInfo(CS1, CS2); + } - //------------------------------------------------ - // Implement the AliasAnalysis API - // - AliasResult alias(const MemoryLocation &LocA, - const MemoryLocation &LocB) override; - ModRefResult getModRefInfo(ImmutableCallSite CS, - const MemoryLocation &Loc) override; - ModRefResult getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) override { - return AliasAnalysis::getModRefInfo(CS1, CS2); + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(const Function *F) override { + ModRefBehavior Min = UnknownModRefBehavior; + + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + Min = DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + Min = OnlyReadsMemory; } - /// getModRefBehavior - Return the behavior of the specified function if - /// called from the specified call site. The call site may be null in which - /// case the most generic behavior of this function should be returned. - ModRefBehavior getModRefBehavior(const Function *F) override { - ModRefBehavior Min = UnknownModRefBehavior; + return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min); + } + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override { + ModRefBehavior Min = UnknownModRefBehavior; + if (const Function *F = CS.getCalledFunction()) if (FunctionRecord *FR = getFunctionInfo(F)) { if (FR->FunctionEffect == 0) Min = DoesNotAccessMemory; @@ -137,68 +154,50 @@ namespace { Min = OnlyReadsMemory; } - return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min); - } - - /// getModRefBehavior - Return the behavior of the specified function if - /// called from the specified call site. The call site may be null in which - /// case the most generic behavior of this function should be returned. - ModRefBehavior getModRefBehavior(ImmutableCallSite CS) override { - ModRefBehavior Min = UnknownModRefBehavior; - - if (const Function* F = CS.getCalledFunction()) - if (FunctionRecord *FR = getFunctionInfo(F)) { - if (FR->FunctionEffect == 0) - Min = DoesNotAccessMemory; - else if ((FR->FunctionEffect & Mod) == 0) - Min = OnlyReadsMemory; - } + return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); + } - return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); - } + void deleteValue(Value *V) override; + void addEscapingUse(Use &U) override; + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + void *getAdjustedAnalysisPointer(AnalysisID PI) override { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis *)this; + return this; + } - void deleteValue(Value *V) override; - void copyValue(Value *From, Value *To) override; - void addEscapingUse(Use &U) override; - - /// getAdjustedAnalysisPointer - This method is used when a pass implements - /// an analysis interface through multiple inheritance. If needed, it - /// should override this to adjust the this pointer as needed for the - /// specified pass info. - void *getAdjustedAnalysisPointer(AnalysisID PI) override { - if (PI == &AliasAnalysis::ID) - return (AliasAnalysis*)this; - return this; - } - - private: - /// getFunctionInfo - Return the function info for the function, or null if - /// we don't have anything useful to say about it. - FunctionRecord *getFunctionInfo(const Function *F) { - std::map<const Function*, FunctionRecord>::iterator I = +private: + /// getFunctionInfo - Return the function info for the function, or null if + /// we don't have anything useful to say about it. + FunctionRecord *getFunctionInfo(const Function *F) { + std::map<const Function *, FunctionRecord>::iterator I = FunctionInfo.find(F); - if (I != FunctionInfo.end()) - return &I->second; - return nullptr; - } + if (I != FunctionInfo.end()) + return &I->second; + return nullptr; + } - void AnalyzeGlobals(Module &M); - void AnalyzeCallGraph(CallGraph &CG, Module &M); - bool AnalyzeUsesOfPointer(Value *V, std::vector<Function*> &Readers, - std::vector<Function*> &Writers, - GlobalValue *OkayStoreDest = nullptr); - bool AnalyzeIndirectGlobalMemory(GlobalValue *GV); - }; + void AnalyzeGlobals(Module &M); + void AnalyzeCallGraph(CallGraph &CG, Module &M); + bool AnalyzeUsesOfPointer(Value *V, std::vector<Function *> &Readers, + std::vector<Function *> &Writers, + GlobalValue *OkayStoreDest = nullptr); + bool AnalyzeIndirectGlobalMemory(GlobalValue *GV); +}; } char GlobalsModRef::ID = 0; -INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, - "globalsmodref-aa", "Simple mod/ref analysis for globals", - false, true, false) +INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, "globalsmodref-aa", + "Simple mod/ref analysis for globals", false, true, + false) INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) -INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, - "globalsmodref-aa", "Simple mod/ref analysis for globals", - false, true, false) +INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, "globalsmodref-aa", + "Simple mod/ref analysis for globals", false, true, + false) Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); } @@ -207,7 +206,7 @@ Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); } /// (really, their address passed to something nontrivial), record this fact, /// and record the functions that they are used directly in. void GlobalsModRef::AnalyzeGlobals(Module &M) { - std::vector<Function*> Readers, Writers; + std::vector<Function *> Readers, Writers; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->hasLocalLinkage()) { if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { @@ -215,11 +214,12 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { NonAddressTakenGlobals.insert(I); ++NumNonAddrTakenFunctions; } - Readers.clear(); Writers.clear(); + Readers.clear(); + Writers.clear(); } - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; + ++I) if (I->hasLocalLinkage()) { if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { // Remember that we are tracking this global, and the mod/ref fns @@ -228,7 +228,7 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { for (unsigned i = 0, e = Readers.size(); i != e; ++i) FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref; - if (!I->isConstant()) // No need to keep track of writers to constants + if (!I->isConstant()) // No need to keep track of writers to constants for (unsigned i = 0, e = Writers.size(); i != e; ++i) FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod; ++NumNonAddrTakenGlobalVars; @@ -238,7 +238,8 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { AnalyzeIndirectGlobalMemory(I)) ++NumIndirectGlobalVars; } - Readers.clear(); Writers.clear(); + Readers.clear(); + Writers.clear(); } } @@ -249,10 +250,11 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { /// /// If OkayStoreDest is non-null, stores into this global are allowed. bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, - std::vector<Function*> &Readers, - std::vector<Function*> &Writers, + std::vector<Function *> &Readers, + std::vector<Function *> &Writers, GlobalValue *OkayStoreDest) { - if (!V->getType()->isPointerTy()) return true; + if (!V->getType()->isPointerTy()) + return true; for (Use &U : V->uses()) { User *I = U.getUser(); @@ -262,7 +264,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, if (V == SI->getOperand(1)) { Writers.push_back(SI->getParent()->getParent()); } else if (SI->getOperand(1) != OkayStoreDest) { - return true; // Storing the pointer + return true; // Storing the pointer } } else if (Operator::getOpcode(I) == Instruction::GetElementPtr) { if (AnalyzeUsesOfPointer(I, Readers, Writers)) @@ -282,7 +284,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, } } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(I)) { if (!isa<ConstantPointerNull>(ICI->getOperand(1))) - return true; // Allow comparison against null. + return true; // Allow comparison against null. } else { return true; } @@ -301,7 +303,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { // Keep track of values related to the allocation of the memory, f.e. the // value produced by the malloc call and any casts. - std::vector<Value*> AllocRelatedValues; + std::vector<Value *> AllocRelatedValues; // Walk the user list of the global. If we find anything other than a direct // load or store, bail out. @@ -310,13 +312,14 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { // The pointer loaded from the global can only be used in simple ways: // we allow addressing of it and loading storing to it. We do *not* allow // storing the loaded pointer somewhere else or passing to a function. - std::vector<Function*> ReadersWriters; + std::vector<Function *> ReadersWriters; if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters)) - return false; // Loaded pointer escapes. + return false; // Loaded pointer escapes. // TODO: Could try some IP mod/ref of the loaded pointer. } else if (StoreInst *SI = dyn_cast<StoreInst>(U)) { // Storing the global itself. - if (SI->getOperand(0) == GV) return false; + if (SI->getOperand(0) == GV) + return false; // If storing the null pointer, ignore it. if (isa<ConstantPointerNull>(SI->getOperand(0))) @@ -327,13 +330,13 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { GV->getParent()->getDataLayout()); if (!isAllocLikeFn(Ptr, TLI)) - return false; // Too hard to analyze. + return false; // Too hard to analyze. // Analyze all uses of the allocation. If any of them are used in a // non-simple way (e.g. stored to another global) bail out. - std::vector<Function*> ReadersWriters; + std::vector<Function *> ReadersWriters; if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV)) - return false; // Loaded pointer escapes. + return false; // Loaded pointer escapes. // Remember that this allocation is related to the indirect global. AllocRelatedValues.push_back(Ptr); @@ -360,7 +363,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { // We do a bottom-up SCC traversal of the call graph. In other words, we // visit all callees before callers (leaf-first). - for (scc_iterator<CallGraph*> I = scc_begin(&CG); !I.isAtEnd(); ++I) { + for (scc_iterator<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) { const std::vector<CallGraphNode *> &SCC = *I; assert(!SCC.empty() && "SCC with no functions?"); @@ -437,9 +440,10 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { } // Scan the function bodies for explicit loads or stores. - for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i) + for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef; + ++i) for (inst_iterator II = inst_begin(SCC[i]->getFunction()), - E = inst_end(SCC[i]->getFunction()); + E = inst_end(SCC[i]->getFunction()); II != E && FunctionEffect != ModRef; ++II) if (LoadInst *LI = dyn_cast<LoadInst>(&*II)) { FunctionEffect |= Ref; @@ -474,8 +478,6 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { } } - - /// alias - If one of the pointers is to a global that we are tracking, and the /// other is some random pointer, we know there cannot be an alias, because the /// address of the global isn't taken. @@ -492,8 +494,10 @@ AliasResult GlobalsModRef::alias(const MemoryLocation &LocA, if (GV1 || GV2) { // If the global's address is taken, pretend we don't know it's a pointer to // the global. - if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = nullptr; - if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = nullptr; + if (GV1 && !NonAddressTakenGlobals.count(GV1)) + GV1 = nullptr; + if (GV2 && !NonAddressTakenGlobals.count(GV2)) + GV2 = nullptr; // If the two pointers are derived from two different non-addr-taken // globals, or if one is and the other isn't, we know these can't alias. @@ -554,7 +558,6 @@ GlobalsModRef::getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) { return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, Loc)); } - //===----------------------------------------------------------------------===// // Methods to update the analysis as a result of the client transformation. // @@ -565,9 +568,10 @@ void GlobalsModRef::deleteValue(Value *V) { // any AllocRelatedValues for it. if (IndirectGlobals.erase(GV)) { // Remove any entries in AllocsForIndirectGlobals for this global. - for (std::map<const Value*, const GlobalValue*>::iterator - I = AllocsForIndirectGlobals.begin(), - E = AllocsForIndirectGlobals.end(); I != E; ) { + for (std::map<const Value *, const GlobalValue *>::iterator + I = AllocsForIndirectGlobals.begin(), + E = AllocsForIndirectGlobals.end(); + I != E;) { if (I->second == GV) { AllocsForIndirectGlobals.erase(I++); } else { @@ -585,16 +589,12 @@ void GlobalsModRef::deleteValue(Value *V) { AliasAnalysis::deleteValue(V); } -void GlobalsModRef::copyValue(Value *From, Value *To) { - AliasAnalysis::copyValue(From, To); -} - void GlobalsModRef::addEscapingUse(Use &U) { // For the purposes of this analysis, it is conservatively correct to treat // a newly escaping value equivalently to a deleted one. We could perhaps // be more precise by processing the new use and attempting to update our // saved analysis results to accommodate it. deleteValue(U); - + AliasAnalysis::addEscapingUse(U); } diff --git a/lib/Analysis/IPA/InlineCost.cpp b/lib/Analysis/IPA/InlineCost.cpp index 349b9cac2c2d..c0d2e375cb04 100644 --- a/lib/Analysis/IPA/InlineCost.cpp +++ b/lib/Analysis/IPA/InlineCost.cpp @@ -783,7 +783,7 @@ bool CallAnalyzer::visitCallSite(CallSite CS) { case Intrinsic::memmove: // SROA can usually chew through these intrinsics, but they aren't free. return false; - case Intrinsic::frameescape: + case Intrinsic::localescape: HasFrameEscape = true; return false; } @@ -1424,11 +1424,11 @@ bool InlineCostAnalysis::isInlineViable(Function &F) { cast<CallInst>(CS.getInstruction())->canReturnTwice()) return false; - // Disallow inlining functions that call @llvm.frameescape. Doing this + // Disallow inlining functions that call @llvm.localescape. Doing this // correctly would require major changes to the inliner. if (CS.getCalledFunction() && CS.getCalledFunction()->getIntrinsicID() == - llvm::Intrinsic::frameescape) + llvm::Intrinsic::localescape) return false; } } diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp index b88b2496b875..926787d3be91 100644 --- a/lib/Analysis/IVUsers.cpp +++ b/lib/Analysis/IVUsers.cpp @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/IVUsers.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/CodeMetrics.h" +#include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ValueTracking.h" @@ -34,6 +36,7 @@ using namespace llvm; char IVUsers::ID = 0; INITIALIZE_PASS_BEGIN(IVUsers, "iv-users", "Induction Variable Users", false, true) +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) @@ -137,6 +140,11 @@ bool IVUsers::AddUsersImpl(Instruction *I, if (Width > 64 || !DL.isLegalInteger(Width)) return false; + // Don't attempt to promote ephemeral values to indvars. They will be removed + // later anyway. + if (EphValues.count(I)) + return false; + // Get the symbolic expression for this instruction. const SCEV *ISE = SE->getSCEV(I); @@ -244,6 +252,7 @@ IVUsers::IVUsers() } void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<AssumptionCacheTracker>(); AU.addRequired<LoopInfoWrapperPass>(); AU.addRequired<DominatorTreeWrapperPass>(); AU.addRequired<ScalarEvolution>(); @@ -253,10 +262,16 @@ void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { L = l; + AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache( + *L->getHeader()->getParent()); LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); SE = &getAnalysis<ScalarEvolution>(); + // Collect ephemeral values so that AddUsersIfInteresting skips them. + EphValues.clear(); + CodeMetrics::collectEphemeralValues(L, AC, EphValues); + // Find all uses of induction variables in this loop, and categorize // them by stride. Start by finding all of the PHI nodes in the header for // this loop. If they are induction variables, inspect their uses. diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 12e406bb1a2d..fa42b48b6cdb 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -24,6 +24,7 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/ConstantRange.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" @@ -3046,7 +3047,8 @@ Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const Query &Q, unsigned MaxRecurse) { + FastMathFlags FMF, const Query &Q, + unsigned MaxRecurse) { CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate; assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!"); @@ -3065,6 +3067,14 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, if (Pred == FCmpInst::FCMP_TRUE) return ConstantInt::get(GetCompareTy(LHS), 1); + // UNO/ORD predicates can be trivially folded if NaNs are ignored. + if (FMF.noNaNs()) { + if (Pred == FCmpInst::FCMP_UNO) + return ConstantInt::get(GetCompareTy(LHS), 0); + if (Pred == FCmpInst::FCMP_ORD) + return ConstantInt::get(GetCompareTy(LHS), 1); + } + // fcmp pred x, undef and fcmp pred undef, x // fold to true if unordered, false if ordered if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS)) { @@ -3151,12 +3161,12 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, } Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout &DL, + FastMathFlags FMF, const DataLayout &DL, const TargetLibraryInfo *TLI, const DominatorTree *DT, AssumptionCache *AC, const Instruction *CxtI) { - return ::SimplifyFCmpInst(Predicate, LHS, RHS, Query(DL, TLI, DT, AC, CxtI), - RecursionLimit); + return ::SimplifyFCmpInst(Predicate, LHS, RHS, FMF, + Query(DL, TLI, DT, AC, CxtI), RecursionLimit); } /// SimplifyWithOpReplaced - See if V simplifies when its operand Op is @@ -3511,6 +3521,82 @@ Value *llvm::SimplifyInsertValueInst( RecursionLimit); } +/// SimplifyExtractValueInst - Given operands for an ExtractValueInst, see if we +/// can fold the result. If not, this returns null. +static Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs, + const Query &, unsigned) { + if (auto *CAgg = dyn_cast<Constant>(Agg)) + return ConstantFoldExtractValueInstruction(CAgg, Idxs); + + // extractvalue x, (insertvalue y, elt, n), n -> elt + unsigned NumIdxs = Idxs.size(); + for (auto *IVI = dyn_cast<InsertValueInst>(Agg); IVI != nullptr; + IVI = dyn_cast<InsertValueInst>(IVI->getAggregateOperand())) { + ArrayRef<unsigned> InsertValueIdxs = IVI->getIndices(); + unsigned NumInsertValueIdxs = InsertValueIdxs.size(); + unsigned NumCommonIdxs = std::min(NumInsertValueIdxs, NumIdxs); + if (InsertValueIdxs.slice(0, NumCommonIdxs) == + Idxs.slice(0, NumCommonIdxs)) { + if (NumIdxs == NumInsertValueIdxs) + return IVI->getInsertedValueOperand(); + break; + } + } + + return nullptr; +} + +Value *llvm::SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs, + const DataLayout &DL, + const TargetLibraryInfo *TLI, + const DominatorTree *DT, + AssumptionCache *AC, + const Instruction *CxtI) { + return ::SimplifyExtractValueInst(Agg, Idxs, Query(DL, TLI, DT, AC, CxtI), + RecursionLimit); +} + +/// SimplifyExtractElementInst - Given operands for an ExtractElementInst, see if we +/// can fold the result. If not, this returns null. +static Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, const Query &, + unsigned) { + if (auto *CVec = dyn_cast<Constant>(Vec)) { + if (auto *CIdx = dyn_cast<Constant>(Idx)) + return ConstantFoldExtractElementInstruction(CVec, CIdx); + + // The index is not relevant if our vector is a splat. + if (auto *Splat = CVec->getSplatValue()) + return Splat; + + if (isa<UndefValue>(Vec)) + return UndefValue::get(Vec->getType()->getVectorElementType()); + } + + // If extracting a specified index from the vector, see if we can recursively + // find a previously computed scalar that was inserted into the vector. + if (auto *IdxC = dyn_cast<ConstantInt>(Idx)) { + unsigned IndexVal = IdxC->getZExtValue(); + unsigned VectorWidth = Vec->getType()->getVectorNumElements(); + + // If this is extracting an invalid index, turn this into undef, to avoid + // crashing the code below. + if (IndexVal >= VectorWidth) + return UndefValue::get(Vec->getType()->getVectorElementType()); + + if (Value *Elt = findScalarElement(Vec, IndexVal)) + return Elt; + } + + return nullptr; +} + +Value *llvm::SimplifyExtractElementInst( + Value *Vec, Value *Idx, const DataLayout &DL, const TargetLibraryInfo *TLI, + const DominatorTree *DT, AssumptionCache *AC, const Instruction *CxtI) { + return ::SimplifyExtractElementInst(Vec, Idx, Query(DL, TLI, DT, AC, CxtI), + RecursionLimit); +} + /// SimplifyPHINode - See if we can fold the given phi. If not, returns null. static Value *SimplifyPHINode(PHINode *PN, const Query &Q) { // If all of the PHI's incoming values are the same then replace the PHI node @@ -3670,7 +3756,7 @@ static Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const Query &Q, unsigned MaxRecurse) { if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate)) return SimplifyICmpInst(Predicate, LHS, RHS, Q, MaxRecurse); - return SimplifyFCmpInst(Predicate, LHS, RHS, Q, MaxRecurse); + return SimplifyFCmpInst(Predicate, LHS, RHS, FastMathFlags(), Q, MaxRecurse); } Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, @@ -3900,9 +3986,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout &DL, I->getOperand(1), DL, TLI, DT, AC, I); break; case Instruction::FCmp: - Result = - SimplifyFCmpInst(cast<FCmpInst>(I)->getPredicate(), I->getOperand(0), - I->getOperand(1), DL, TLI, DT, AC, I); + Result = SimplifyFCmpInst(cast<FCmpInst>(I)->getPredicate(), + I->getOperand(0), I->getOperand(1), + I->getFastMathFlags(), DL, TLI, DT, AC, I); break; case Instruction::Select: Result = SimplifySelectInst(I->getOperand(0), I->getOperand(1), @@ -3920,6 +4006,18 @@ Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout &DL, IV->getIndices(), DL, TLI, DT, AC, I); break; } + case Instruction::ExtractValue: { + auto *EVI = cast<ExtractValueInst>(I); + Result = SimplifyExtractValueInst(EVI->getAggregateOperand(), + EVI->getIndices(), DL, TLI, DT, AC, I); + break; + } + case Instruction::ExtractElement: { + auto *EEI = cast<ExtractElementInst>(I); + Result = SimplifyExtractElementInst( + EEI->getVectorOperand(), EEI->getIndexOperand(), DL, TLI, DT, AC, I); + break; + } case Instruction::PHI: Result = SimplifyPHINode(cast<PHINode>(I), Query(DL, TLI, DT, AC, I)); break; diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index b11cd7e84a6d..becbae4c5b50 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -48,6 +48,13 @@ static cl::opt<unsigned, true> RuntimeMemoryCheckThreshold( cl::location(VectorizerParams::RuntimeMemoryCheckThreshold), cl::init(8)); unsigned VectorizerParams::RuntimeMemoryCheckThreshold; +/// \brief The maximum iterations used to merge memory checks +static cl::opt<unsigned> MemoryCheckMergeThreshold( + "memory-check-merge-threshold", cl::Hidden, + cl::desc("Maximum number of comparisons done when trying to merge " + "runtime memory checks. (default = 100)"), + cl::init(100)); + /// Maximum SIMD width. const unsigned VectorizerParams::MaxVectorWidth = 64; @@ -112,35 +119,182 @@ const SCEV *llvm::replaceSymbolicStrideSCEV(ScalarEvolution *SE, return SE->getSCEV(Ptr); } -void LoopAccessInfo::RuntimePointerCheck::insert( - ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, - unsigned ASId, const ValueToValueMap &Strides) { +void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr, + unsigned DepSetId, unsigned ASId, + const ValueToValueMap &Strides) { // Get the stride replaced scev. const SCEV *Sc = replaceSymbolicStrideSCEV(SE, Strides, Ptr); const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc); assert(AR && "Invalid addrec expression"); const SCEV *Ex = SE->getBackedgeTakenCount(Lp); const SCEV *ScEnd = AR->evaluateAtIteration(Ex, *SE); - Pointers.push_back(Ptr); - Starts.push_back(AR->getStart()); - Ends.push_back(ScEnd); - IsWritePtr.push_back(WritePtr); - DependencySetId.push_back(DepSetId); - AliasSetId.push_back(ASId); + Pointers.emplace_back(Ptr, AR->getStart(), ScEnd, WritePtr, DepSetId, ASId, + Sc); +} + +bool RuntimePointerChecking::needsChecking( + const CheckingPtrGroup &M, const CheckingPtrGroup &N, + const SmallVectorImpl<int> *PtrPartition) const { + for (unsigned I = 0, EI = M.Members.size(); EI != I; ++I) + for (unsigned J = 0, EJ = N.Members.size(); EJ != J; ++J) + if (needsChecking(M.Members[I], N.Members[J], PtrPartition)) + return true; + return false; +} + +/// Compare \p I and \p J and return the minimum. +/// Return nullptr in case we couldn't find an answer. +static const SCEV *getMinFromExprs(const SCEV *I, const SCEV *J, + ScalarEvolution *SE) { + const SCEV *Diff = SE->getMinusSCEV(J, I); + const SCEVConstant *C = dyn_cast<const SCEVConstant>(Diff); + + if (!C) + return nullptr; + if (C->getValue()->isNegative()) + return J; + return I; +} + +bool RuntimePointerChecking::CheckingPtrGroup::addPointer(unsigned Index) { + const SCEV *Start = RtCheck.Pointers[Index].Start; + const SCEV *End = RtCheck.Pointers[Index].End; + + // Compare the starts and ends with the known minimum and maximum + // of this set. We need to know how we compare against the min/max + // of the set in order to be able to emit memchecks. + const SCEV *Min0 = getMinFromExprs(Start, Low, RtCheck.SE); + if (!Min0) + return false; + + const SCEV *Min1 = getMinFromExprs(End, High, RtCheck.SE); + if (!Min1) + return false; + + // Update the low bound expression if we've found a new min value. + if (Min0 == Start) + Low = Start; + + // Update the high bound expression if we've found a new max value. + if (Min1 != End) + High = End; + + Members.push_back(Index); + return true; } -bool LoopAccessInfo::RuntimePointerCheck::needsChecking( +void RuntimePointerChecking::groupChecks( + MemoryDepChecker::DepCandidates &DepCands, bool UseDependencies) { + // We build the groups from dependency candidates equivalence classes + // because: + // - We know that pointers in the same equivalence class share + // the same underlying object and therefore there is a chance + // that we can compare pointers + // - We wouldn't be able to merge two pointers for which we need + // to emit a memcheck. The classes in DepCands are already + // conveniently built such that no two pointers in the same + // class need checking against each other. + + // We use the following (greedy) algorithm to construct the groups + // For every pointer in the equivalence class: + // For each existing group: + // - if the difference between this pointer and the min/max bounds + // of the group is a constant, then make the pointer part of the + // group and update the min/max bounds of that group as required. + + CheckingGroups.clear(); + + // If we don't have the dependency partitions, construct a new + // checking pointer group for each pointer. + if (!UseDependencies) { + for (unsigned I = 0; I < Pointers.size(); ++I) + CheckingGroups.push_back(CheckingPtrGroup(I, *this)); + return; + } + + unsigned TotalComparisons = 0; + + DenseMap<Value *, unsigned> PositionMap; + for (unsigned Index = 0; Index < Pointers.size(); ++Index) + PositionMap[Pointers[Index].PointerValue] = Index; + + // We need to keep track of what pointers we've already seen so we + // don't process them twice. + SmallSet<unsigned, 2> Seen; + + // Go through all equivalence classes, get the the "pointer check groups" + // and add them to the overall solution. We use the order in which accesses + // appear in 'Pointers' to enforce determinism. + for (unsigned I = 0; I < Pointers.size(); ++I) { + // We've seen this pointer before, and therefore already processed + // its equivalence class. + if (Seen.count(I)) + continue; + + MemoryDepChecker::MemAccessInfo Access(Pointers[I].PointerValue, + Pointers[I].IsWritePtr); + + SmallVector<CheckingPtrGroup, 2> Groups; + auto LeaderI = DepCands.findValue(DepCands.getLeaderValue(Access)); + + // Because DepCands is constructed by visiting accesses in the order in + // which they appear in alias sets (which is deterministic) and the + // iteration order within an equivalence class member is only dependent on + // the order in which unions and insertions are performed on the + // equivalence class, the iteration order is deterministic. + for (auto MI = DepCands.member_begin(LeaderI), ME = DepCands.member_end(); + MI != ME; ++MI) { + unsigned Pointer = PositionMap[MI->getPointer()]; + bool Merged = false; + // Mark this pointer as seen. + Seen.insert(Pointer); + + // Go through all the existing sets and see if we can find one + // which can include this pointer. + for (CheckingPtrGroup &Group : Groups) { + // Don't perform more than a certain amount of comparisons. + // This should limit the cost of grouping the pointers to something + // reasonable. If we do end up hitting this threshold, the algorithm + // will create separate groups for all remaining pointers. + if (TotalComparisons > MemoryCheckMergeThreshold) + break; + + TotalComparisons++; + + if (Group.addPointer(Pointer)) { + Merged = true; + break; + } + } + + if (!Merged) + // We couldn't add this pointer to any existing set or the threshold + // for the number of comparisons has been reached. Create a new group + // to hold the current pointer. + Groups.push_back(CheckingPtrGroup(Pointer, *this)); + } + + // We've computed the grouped checks for this partition. + // Save the results and continue with the next one. + std::copy(Groups.begin(), Groups.end(), std::back_inserter(CheckingGroups)); + } +} + +bool RuntimePointerChecking::needsChecking( unsigned I, unsigned J, const SmallVectorImpl<int> *PtrPartition) const { + const PointerInfo &PointerI = Pointers[I]; + const PointerInfo &PointerJ = Pointers[J]; + // No need to check if two readonly pointers intersect. - if (!IsWritePtr[I] && !IsWritePtr[J]) + if (!PointerI.IsWritePtr && !PointerJ.IsWritePtr) return false; // Only need to check pointers between two different dependency sets. - if (DependencySetId[I] == DependencySetId[J]) + if (PointerI.DependencySetId == PointerJ.DependencySetId) return false; // Only need to check pointers in the same alias set. - if (AliasSetId[I] != AliasSetId[J]) + if (PointerI.AliasSetId != PointerJ.AliasSetId) return false; // If PtrPartition is set omit checks between pointers of the same partition. @@ -153,45 +307,75 @@ bool LoopAccessInfo::RuntimePointerCheck::needsChecking( return true; } -void LoopAccessInfo::RuntimePointerCheck::print( +void RuntimePointerChecking::print( raw_ostream &OS, unsigned Depth, const SmallVectorImpl<int> *PtrPartition) const { - unsigned NumPointers = Pointers.size(); - if (NumPointers == 0) - return; OS.indent(Depth) << "Run-time memory checks:\n"; + unsigned N = 0; - for (unsigned I = 0; I < NumPointers; ++I) - for (unsigned J = I + 1; J < NumPointers; ++J) - if (needsChecking(I, J, PtrPartition)) { - OS.indent(Depth) << N++ << ":\n"; - OS.indent(Depth + 2) << *Pointers[I]; - if (PtrPartition) - OS << " (Partition: " << (*PtrPartition)[I] << ")"; - OS << "\n"; - OS.indent(Depth + 2) << *Pointers[J]; - if (PtrPartition) - OS << " (Partition: " << (*PtrPartition)[J] << ")"; - OS << "\n"; + for (unsigned I = 0; I < CheckingGroups.size(); ++I) + for (unsigned J = I + 1; J < CheckingGroups.size(); ++J) + if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition)) { + OS.indent(Depth) << "Check " << N++ << ":\n"; + OS.indent(Depth + 2) << "Comparing group " << I << ":\n"; + + for (unsigned K = 0; K < CheckingGroups[I].Members.size(); ++K) { + OS.indent(Depth + 2) + << *Pointers[CheckingGroups[I].Members[K]].PointerValue << "\n"; + if (PtrPartition) + OS << " (Partition: " + << (*PtrPartition)[CheckingGroups[I].Members[K]] << ")" + << "\n"; + } + + OS.indent(Depth + 2) << "Against group " << J << ":\n"; + + for (unsigned K = 0; K < CheckingGroups[J].Members.size(); ++K) { + OS.indent(Depth + 2) + << *Pointers[CheckingGroups[J].Members[K]].PointerValue << "\n"; + if (PtrPartition) + OS << " (Partition: " + << (*PtrPartition)[CheckingGroups[J].Members[K]] << ")" + << "\n"; + } } + + OS.indent(Depth) << "Grouped accesses:\n"; + for (unsigned I = 0; I < CheckingGroups.size(); ++I) { + OS.indent(Depth + 2) << "Group " << I << ":\n"; + OS.indent(Depth + 4) << "(Low: " << *CheckingGroups[I].Low + << " High: " << *CheckingGroups[I].High << ")\n"; + for (unsigned J = 0; J < CheckingGroups[I].Members.size(); ++J) { + OS.indent(Depth + 6) << "Member: " + << *Pointers[CheckingGroups[I].Members[J]].Expr + << "\n"; + } + } } -unsigned LoopAccessInfo::RuntimePointerCheck::getNumberOfChecks( +unsigned RuntimePointerChecking::getNumberOfChecks( const SmallVectorImpl<int> *PtrPartition) const { - unsigned NumPointers = Pointers.size(); + + unsigned NumPartitions = CheckingGroups.size(); unsigned CheckCount = 0; - for (unsigned I = 0; I < NumPointers; ++I) - for (unsigned J = I + 1; J < NumPointers; ++J) - if (needsChecking(I, J, PtrPartition)) + for (unsigned I = 0; I < NumPartitions; ++I) + for (unsigned J = I + 1; J < NumPartitions; ++J) + if (needsChecking(CheckingGroups[I], CheckingGroups[J], PtrPartition)) CheckCount++; return CheckCount; } -bool LoopAccessInfo::RuntimePointerCheck::needsAnyChecking( +bool RuntimePointerChecking::needsAnyChecking( const SmallVectorImpl<int> *PtrPartition) const { - return getNumberOfChecks(PtrPartition) != 0; + unsigned NumPointers = Pointers.size(); + + for (unsigned I = 0; I < NumPointers; ++I) + for (unsigned J = I + 1; J < NumPointers; ++J) + if (needsChecking(I, J, PtrPartition)) + return true; + return false; } namespace { @@ -207,7 +391,8 @@ public: AccessAnalysis(const DataLayout &Dl, AliasAnalysis *AA, LoopInfo *LI, MemoryDepChecker::DepCandidates &DA) - : DL(Dl), AST(*AA), LI(LI), DepCands(DA), IsRTCheckNeeded(false) {} + : DL(Dl), AST(*AA), LI(LI), DepCands(DA), + IsRTCheckAnalysisNeeded(false) {} /// \brief Register a load and whether it is only read from. void addLoad(MemoryLocation &Loc, bool IsReadOnly) { @@ -226,11 +411,12 @@ public: } /// \brief Check whether we can check the pointers at runtime for - /// non-intersection. Returns true when we have 0 pointers - /// (a check on 0 pointers for non-intersection will always return true). - bool canCheckPtrAtRT(LoopAccessInfo::RuntimePointerCheck &RtCheck, - bool &NeedRTCheck, ScalarEvolution *SE, Loop *TheLoop, - const ValueToValueMap &Strides, + /// non-intersection. + /// + /// Returns true if we need no check or if we do and we can generate them + /// (i.e. the pointers have computable bounds). + bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE, + Loop *TheLoop, const ValueToValueMap &Strides, bool ShouldCheckStride = false); /// \brief Goes over all memory accesses, checks whether a RT check is needed @@ -239,8 +425,11 @@ public: processMemAccesses(); } - bool isRTCheckNeeded() { return IsRTCheckNeeded; } - + /// \brief Initial processing of memory accesses determined that we need to + /// perform dependency checking. + /// + /// Note that this can later be cleared if we retry memcheck analysis without + /// dependency checking (i.e. ShouldRetryWithRuntimeCheck). bool isDependencyCheckNeeded() { return !CheckDeps.empty(); } /// We decided that no dependence analysis would be used. Reset the state. @@ -255,7 +444,7 @@ private: typedef SetVector<MemAccessInfo> PtrAccessSet; /// \brief Go over all memory access and check whether runtime pointer checks - /// are needed /// and build sets of dependency check candidates. + /// are needed and build sets of dependency check candidates. void processMemAccesses(); /// Set of all accesses. @@ -280,7 +469,14 @@ private: /// dependence check. MemoryDepChecker::DepCandidates &DepCands; - bool IsRTCheckNeeded; + /// \brief Initial processing of memory accesses determined that we may need + /// to add memchecks. Perform the analysis to determine the necessary checks. + /// + /// Note that, this is different from isDependencyCheckNeeded. When we retry + /// memcheck analysis without dependency checking + /// (i.e. ShouldRetryWithRuntimeCheck), isDependencyCheckNeeded is cleared + /// while this remains set if we have potentially dependent accesses. + bool IsRTCheckAnalysisNeeded; }; } // end anonymous namespace @@ -296,16 +492,16 @@ static bool hasComputableBounds(ScalarEvolution *SE, return AR->isAffine(); } -bool AccessAnalysis::canCheckPtrAtRT( - LoopAccessInfo::RuntimePointerCheck &RtCheck, bool &NeedRTCheck, - ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &StridesMap, - bool ShouldCheckStride) { +bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck, + ScalarEvolution *SE, Loop *TheLoop, + const ValueToValueMap &StridesMap, + bool ShouldCheckStride) { // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. bool CanDoRT = true; - NeedRTCheck = false; - if (!IsRTCheckNeeded) return true; + bool NeedRTCheck = false; + if (!IsRTCheckAnalysisNeeded) return true; bool IsDepCheckNeeded = isDependencyCheckNeeded(); @@ -313,6 +509,9 @@ bool AccessAnalysis::canCheckPtrAtRT( // Accesses between different groups doesn't need to be checked. unsigned ASId = 1; for (auto &AS : AST) { + int NumReadPtrChecks = 0; + int NumWritePtrChecks = 0; + // We assign consecutive id to access from different dependence sets. // Accesses within the same set don't need a runtime check. unsigned RunningDepId = 1; @@ -323,6 +522,11 @@ bool AccessAnalysis::canCheckPtrAtRT( bool IsWrite = Accesses.count(MemAccessInfo(Ptr, true)); MemAccessInfo Access(Ptr, IsWrite); + if (IsWrite) + ++NumWritePtrChecks; + else + ++NumReadPtrChecks; + if (hasComputableBounds(SE, StridesMap, Ptr) && // When we run after a failing dependency check we have to make sure // we don't have wrapping pointers. @@ -341,7 +545,7 @@ bool AccessAnalysis::canCheckPtrAtRT( // Each access has its own dependence set. DepId = RunningDepId++; - RtCheck.insert(SE, TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap); + RtCheck.insert(TheLoop, Ptr, IsWrite, DepId, ASId, StridesMap); DEBUG(dbgs() << "LAA: Found a runtime check ptr:" << *Ptr << '\n'); } else { @@ -350,15 +554,21 @@ bool AccessAnalysis::canCheckPtrAtRT( } } + // If we have at least two writes or one write and a read then we need to + // check them. But there is no need to checks if there is only one + // dependence set for this alias set. + // + // Note that this function computes CanDoRT and NeedRTCheck independently. + // For example CanDoRT=false, NeedRTCheck=false means that we have a pointer + // for which we couldn't find the bounds but we don't actually need to emit + // any checks so it does not matter. + if (!(IsDepCheckNeeded && CanDoRT && RunningDepId == 2)) + NeedRTCheck |= (NumWritePtrChecks >= 2 || (NumReadPtrChecks >= 1 && + NumWritePtrChecks >= 1)); + ++ASId; } - // We need a runtime check if there are any accesses that need checking. - // However, some accesses cannot be checked (for example because we - // can't determine their bounds). In these cases we would need a check - // but wouldn't be able to add it. - NeedRTCheck = !CanDoRT || RtCheck.needsAnyChecking(nullptr); - // If the pointers that we would use for the bounds comparison have different // address spaces, assume the values aren't directly comparable, so we can't // use them for the runtime check. We also have to assume they could @@ -368,14 +578,15 @@ bool AccessAnalysis::canCheckPtrAtRT( for (unsigned i = 0; i < NumPointers; ++i) { for (unsigned j = i + 1; j < NumPointers; ++j) { // Only need to check pointers between two different dependency sets. - if (RtCheck.DependencySetId[i] == RtCheck.DependencySetId[j]) + if (RtCheck.Pointers[i].DependencySetId == + RtCheck.Pointers[j].DependencySetId) continue; // Only need to check pointers in the same alias set. - if (RtCheck.AliasSetId[i] != RtCheck.AliasSetId[j]) + if (RtCheck.Pointers[i].AliasSetId != RtCheck.Pointers[j].AliasSetId) continue; - Value *PtrI = RtCheck.Pointers[i]; - Value *PtrJ = RtCheck.Pointers[j]; + Value *PtrI = RtCheck.Pointers[i].PointerValue; + Value *PtrJ = RtCheck.Pointers[j].PointerValue; unsigned ASi = PtrI->getType()->getPointerAddressSpace(); unsigned ASj = PtrJ->getType()->getPointerAddressSpace(); @@ -387,7 +598,18 @@ bool AccessAnalysis::canCheckPtrAtRT( } } - return CanDoRT; + if (NeedRTCheck && CanDoRT) + RtCheck.groupChecks(DepCands, IsDepCheckNeeded); + + DEBUG(dbgs() << "LAA: We need to do " << RtCheck.getNumberOfChecks(nullptr) + << " pointer comparisons.\n"); + + RtCheck.Need = NeedRTCheck; + + bool CanDoRTIfNeeded = !NeedRTCheck || CanDoRT; + if (!CanDoRTIfNeeded) + RtCheck.reset(); + return CanDoRTIfNeeded; } void AccessAnalysis::processMemAccesses() { @@ -470,7 +692,7 @@ void AccessAnalysis::processMemAccesses() { // catch "a[i] = a[i] + " without having to do a dependence check). if ((IsWrite || IsReadOnlyPtr) && SetHasWrite) { CheckDeps.insert(Access); - IsRTCheckNeeded = true; + IsRTCheckAnalysisNeeded = true; } if (IsWrite) @@ -600,7 +822,7 @@ int llvm::isStridedPtr(ScalarEvolution *SE, Value *Ptr, const Loop *Lp, // Check the step is constant. const SCEV *Step = AR->getStepRecurrence(*SE); - // Calculate the pointer stride and check if it is consecutive. + // Calculate the pointer stride and check if it is constant. const SCEVConstant *C = dyn_cast<SCEVConstant>(Step); if (!C) { DEBUG(dbgs() << "LAA: Bad stride - Not a constant strided " << *Ptr << @@ -805,11 +1027,11 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, DEBUG(dbgs() << "LAA: Distance for " << *InstMap[AIdx] << " to " << *InstMap[BIdx] << ": " << *Dist << "\n"); - // Need consecutive accesses. We don't want to vectorize + // Need accesses with constant stride. We don't want to vectorize // "A[B[i]] += ..." and similar code or pointer arithmetic that could wrap in // the address space. if (!StrideAPtr || !StrideBPtr || StrideAPtr != StrideBPtr){ - DEBUG(dbgs() << "Non-consecutive pointer access\n"); + DEBUG(dbgs() << "Pointer access with non-constant stride\n"); return Dependence::Unknown; } @@ -859,8 +1081,10 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx, unsigned Stride = std::abs(StrideAPtr); if (Stride > 1 && - areStridedAccessesIndependent(Distance, Stride, TypeByteSize)) + areStridedAccessesIndependent(Distance, Stride, TypeByteSize)) { + DEBUG(dbgs() << "LAA: Strided accesses are independent\n"); return Dependence::NoDep; + } // Bail out early if passed-in parameters make vectorization not feasible. unsigned ForcedFactor = (VectorizerParams::VectorizationFactor ? @@ -1098,8 +1322,8 @@ void LoopAccessInfo::analyzeLoop(const ValueToValueMap &Strides) { unsigned NumReads = 0; unsigned NumReadWrites = 0; - PtrRtCheck.Pointers.clear(); - PtrRtCheck.Need = false; + PtrRtChecking.Pointers.clear(); + PtrRtChecking.Need = false; const bool IsAnnotatedParallel = TheLoop->isAnnotatedParallel(); @@ -1258,28 +1482,17 @@ void LoopAccessInfo::analyzeLoop(const ValueToValueMap &Strides) { // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. - bool NeedRTCheck; - bool CanDoRT = Accesses.canCheckPtrAtRT(PtrRtCheck, - NeedRTCheck, SE, - TheLoop, Strides); - - DEBUG(dbgs() << "LAA: We need to do " - << PtrRtCheck.getNumberOfChecks(nullptr) - << " pointer comparisons.\n"); - - // Check that we found the bounds for the pointer. - if (CanDoRT) - DEBUG(dbgs() << "LAA: We can perform a memory runtime check if needed.\n"); - else if (NeedRTCheck) { + bool CanDoRTIfNeeded = + Accesses.canCheckPtrAtRT(PtrRtChecking, SE, TheLoop, Strides); + if (!CanDoRTIfNeeded) { emitAnalysis(LoopAccessReport() << "cannot identify array bounds"); - DEBUG(dbgs() << "LAA: We can't vectorize because we can't find " << - "the array bounds.\n"); - PtrRtCheck.reset(); + DEBUG(dbgs() << "LAA: We can't vectorize because we can't find " + << "the array bounds.\n"); CanVecMem = false; return; } - PtrRtCheck.Need = NeedRTCheck; + DEBUG(dbgs() << "LAA: We can perform a memory runtime check if needed.\n"); CanVecMem = true; if (Accesses.isDependencyCheckNeeded()) { @@ -1290,23 +1503,21 @@ void LoopAccessInfo::analyzeLoop(const ValueToValueMap &Strides) { if (!CanVecMem && DepChecker.shouldRetryWithRuntimeCheck()) { DEBUG(dbgs() << "LAA: Retrying with memory checks\n"); - NeedRTCheck = true; // Clear the dependency checks. We assume they are not needed. Accesses.resetDepChecks(DepChecker); - PtrRtCheck.reset(); - PtrRtCheck.Need = true; + PtrRtChecking.reset(); + PtrRtChecking.Need = true; - CanDoRT = Accesses.canCheckPtrAtRT(PtrRtCheck, NeedRTCheck, SE, - TheLoop, Strides, true); + CanDoRTIfNeeded = + Accesses.canCheckPtrAtRT(PtrRtChecking, SE, TheLoop, Strides, true); // Check that we found the bounds for the pointer. - if (NeedRTCheck && !CanDoRT) { + if (!CanDoRTIfNeeded) { emitAnalysis(LoopAccessReport() << "cannot check memory dependencies at runtime"); DEBUG(dbgs() << "LAA: Can't vectorize with memory checks\n"); - PtrRtCheck.reset(); CanVecMem = false; return; } @@ -1317,8 +1528,8 @@ void LoopAccessInfo::analyzeLoop(const ValueToValueMap &Strides) { if (CanVecMem) DEBUG(dbgs() << "LAA: No unsafe dependent memory operations in loop. We" - << (NeedRTCheck ? "" : " don't") - << " need a runtime memory check.\n"); + << (PtrRtChecking.Need ? "" : " don't") + << " need runtime memory checks.\n"); else { emitAnalysis(LoopAccessReport() << "unsafe dependent memory operations in loop"); @@ -1357,35 +1568,38 @@ static Instruction *getFirstInst(Instruction *FirstInst, Value *V, std::pair<Instruction *, Instruction *> LoopAccessInfo::addRuntimeCheck( Instruction *Loc, const SmallVectorImpl<int> *PtrPartition) const { - if (!PtrRtCheck.Need) + if (!PtrRtChecking.Need) return std::make_pair(nullptr, nullptr); - unsigned NumPointers = PtrRtCheck.Pointers.size(); - SmallVector<TrackingVH<Value> , 2> Starts; - SmallVector<TrackingVH<Value> , 2> Ends; + SmallVector<TrackingVH<Value>, 2> Starts; + SmallVector<TrackingVH<Value>, 2> Ends; LLVMContext &Ctx = Loc->getContext(); SCEVExpander Exp(*SE, DL, "induction"); Instruction *FirstInst = nullptr; - for (unsigned i = 0; i < NumPointers; ++i) { - Value *Ptr = PtrRtCheck.Pointers[i]; + for (unsigned i = 0; i < PtrRtChecking.CheckingGroups.size(); ++i) { + const RuntimePointerChecking::CheckingPtrGroup &CG = + PtrRtChecking.CheckingGroups[i]; + Value *Ptr = PtrRtChecking.Pointers[CG.Members[0]].PointerValue; const SCEV *Sc = SE->getSCEV(Ptr); if (SE->isLoopInvariant(Sc, TheLoop)) { - DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" << - *Ptr <<"\n"); + DEBUG(dbgs() << "LAA: Adding RT check for a loop invariant ptr:" << *Ptr + << "\n"); Starts.push_back(Ptr); Ends.push_back(Ptr); } else { - DEBUG(dbgs() << "LAA: Adding RT check for range:" << *Ptr << '\n'); unsigned AS = Ptr->getType()->getPointerAddressSpace(); // Use this type for pointer arithmetic. Type *PtrArithTy = Type::getInt8PtrTy(Ctx, AS); + Value *Start = nullptr, *End = nullptr; - Value *Start = Exp.expandCodeFor(PtrRtCheck.Starts[i], PtrArithTy, Loc); - Value *End = Exp.expandCodeFor(PtrRtCheck.Ends[i], PtrArithTy, Loc); + DEBUG(dbgs() << "LAA: Adding RT check for range:\n"); + Start = Exp.expandCodeFor(CG.Low, PtrArithTy, Loc); + End = Exp.expandCodeFor(CG.High, PtrArithTy, Loc); + DEBUG(dbgs() << "Start: " << *CG.Low << " End: " << *CG.High << "\n"); Starts.push_back(Start); Ends.push_back(End); } @@ -1394,9 +1608,14 @@ std::pair<Instruction *, Instruction *> LoopAccessInfo::addRuntimeCheck( IRBuilder<> ChkBuilder(Loc); // Our instructions might fold to a constant. Value *MemoryRuntimeCheck = nullptr; - for (unsigned i = 0; i < NumPointers; ++i) { - for (unsigned j = i+1; j < NumPointers; ++j) { - if (!PtrRtCheck.needsChecking(i, j, PtrPartition)) + for (unsigned i = 0; i < PtrRtChecking.CheckingGroups.size(); ++i) { + for (unsigned j = i + 1; j < PtrRtChecking.CheckingGroups.size(); ++j) { + const RuntimePointerChecking::CheckingPtrGroup &CGI = + PtrRtChecking.CheckingGroups[i]; + const RuntimePointerChecking::CheckingPtrGroup &CGJ = + PtrRtChecking.CheckingGroups[j]; + + if (!PtrRtChecking.needsChecking(CGI, CGJ, PtrPartition)) continue; unsigned AS0 = Starts[i]->getType()->getPointerAddressSpace(); @@ -1447,7 +1666,7 @@ LoopAccessInfo::LoopAccessInfo(Loop *L, ScalarEvolution *SE, const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI, const ValueToValueMap &Strides) - : DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL), + : PtrRtChecking(SE), DepChecker(SE, L), TheLoop(L), SE(SE), DL(DL), TLI(TLI), AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0), MaxSafeDepDistBytes(-1U), CanVecMem(false), StoreToLoopInvariantAddress(false) { @@ -1457,7 +1676,7 @@ LoopAccessInfo::LoopAccessInfo(Loop *L, ScalarEvolution *SE, void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const { if (CanVecMem) { - if (PtrRtCheck.Need) + if (PtrRtChecking.Need) OS.indent(Depth) << "Memory dependences are safe with run-time checks\n"; else OS.indent(Depth) << "Memory dependences are safe\n"; @@ -1476,7 +1695,7 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const { OS.indent(Depth) << "Too many interesting dependences, not recorded\n"; // List the pair of accesses need run-time checks to prove independence. - PtrRtCheck.print(OS, Depth); + PtrRtChecking.print(OS, Depth); OS << "\n"; OS.indent(Depth) << "Store to invariant address was " diff --git a/lib/Analysis/NoAliasAnalysis.cpp b/lib/Analysis/NoAliasAnalysis.cpp index 7617622b9ab6..322a9a80de4c 100644 --- a/lib/Analysis/NoAliasAnalysis.cpp +++ b/lib/Analysis/NoAliasAnalysis.cpp @@ -72,7 +72,6 @@ namespace { } void deleteValue(Value *V) override {} - void copyValue(Value *From, Value *To) override {} void addEscapingUse(Use &U) override {} /// getAdjustedAnalysisPointer - This method is used when a pass implements diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp index 520d1e5ef87d..7d1c3fbef68a 100644 --- a/lib/Analysis/TargetTransformInfo.cpp +++ b/lib/Analysis/TargetTransformInfo.cpp @@ -28,12 +28,12 @@ namespace { /// /// This is used when no target specific information is available. struct NoTTIImpl : TargetTransformInfoImplCRTPBase<NoTTIImpl> { - explicit NoTTIImpl(const DataLayout *DL) + explicit NoTTIImpl(const DataLayout &DL) : TargetTransformInfoImplCRTPBase<NoTTIImpl>(DL) {} }; } -TargetTransformInfo::TargetTransformInfo(const DataLayout *DL) +TargetTransformInfo::TargetTransformInfo(const DataLayout &DL) : TTIImpl(new Model<NoTTIImpl>(NoTTIImpl(DL))) {} TargetTransformInfo::~TargetTransformInfo() {} @@ -304,7 +304,7 @@ TargetIRAnalysis::Result TargetIRAnalysis::run(Function &F) { char TargetIRAnalysis::PassID; TargetIRAnalysis::Result TargetIRAnalysis::getDefaultTTI(Function &F) { - return Result(&F.getParent()->getDataLayout()); + return Result(F.getParent()->getDataLayout()); } // Register the basic pass. diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index c45005f343d3..fa0d7798cae9 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -1464,7 +1464,7 @@ void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, // If the object is defined in the current Module, we'll be giving // it the preferred alignment. Otherwise, we have to assume that it // may only have the minimum ABI alignment. - if (!GVar->isDeclaration() && !GVar->isWeakForLinker()) + if (GVar->isStrongDefinitionForLinker()) Align = DL.getPreferredAlignment(GVar); else Align = DL.getABITypeAlignment(ObjectType); diff --git a/lib/Analysis/VectorUtils.cpp b/lib/Analysis/VectorUtils.cpp index 96fddd103cc5..67f68dc8391e 100644 --- a/lib/Analysis/VectorUtils.cpp +++ b/lib/Analysis/VectorUtils.cpp @@ -11,7 +11,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/VectorUtils.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Value.h" /// \brief Identify if the intrinsic is trivially vectorizable. /// This method returns true if the intrinsic's argument types are all @@ -211,3 +217,195 @@ llvm::Intrinsic::ID llvm::getIntrinsicIDForCall(CallInst *CI, return Intrinsic::not_intrinsic; } + +/// \brief Find the operand of the GEP that should be checked for consecutive +/// stores. This ignores trailing indices that have no effect on the final +/// pointer. +unsigned llvm::getGEPInductionOperand(const GetElementPtrInst *Gep) { + const DataLayout &DL = Gep->getModule()->getDataLayout(); + unsigned LastOperand = Gep->getNumOperands() - 1; + unsigned GEPAllocSize = DL.getTypeAllocSize( + cast<PointerType>(Gep->getType()->getScalarType())->getElementType()); + + // Walk backwards and try to peel off zeros. + while (LastOperand > 1 && + match(Gep->getOperand(LastOperand), llvm::PatternMatch::m_Zero())) { + // Find the type we're currently indexing into. + gep_type_iterator GEPTI = gep_type_begin(Gep); + std::advance(GEPTI, LastOperand - 1); + + // If it's a type with the same allocation size as the result of the GEP we + // can peel off the zero index. + if (DL.getTypeAllocSize(*GEPTI) != GEPAllocSize) + break; + --LastOperand; + } + + return LastOperand; +} + +/// \brief If the argument is a GEP, then returns the operand identified by +/// getGEPInductionOperand. However, if there is some other non-loop-invariant +/// operand, it returns that instead. +llvm::Value *llvm::stripGetElementPtr(llvm::Value *Ptr, ScalarEvolution *SE, + Loop *Lp) { + GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr); + if (!GEP) + return Ptr; + + unsigned InductionOperand = getGEPInductionOperand(GEP); + + // Check that all of the gep indices are uniform except for our induction + // operand. + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) + if (i != InductionOperand && + !SE->isLoopInvariant(SE->getSCEV(GEP->getOperand(i)), Lp)) + return Ptr; + return GEP->getOperand(InductionOperand); +} + +/// \brief If a value has only one user that is a CastInst, return it. +llvm::Value *llvm::getUniqueCastUse(llvm::Value *Ptr, Loop *Lp, Type *Ty) { + llvm::Value *UniqueCast = nullptr; + for (User *U : Ptr->users()) { + CastInst *CI = dyn_cast<CastInst>(U); + if (CI && CI->getType() == Ty) { + if (!UniqueCast) + UniqueCast = CI; + else + return nullptr; + } + } + return UniqueCast; +} + +/// \brief Get the stride of a pointer access in a loop. Looks for symbolic +/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise. +llvm::Value *llvm::getStrideFromPointer(llvm::Value *Ptr, ScalarEvolution *SE, + Loop *Lp) { + const PointerType *PtrTy = dyn_cast<PointerType>(Ptr->getType()); + if (!PtrTy || PtrTy->isAggregateType()) + return nullptr; + + // Try to remove a gep instruction to make the pointer (actually index at this + // point) easier analyzable. If OrigPtr is equal to Ptr we are analzying the + // pointer, otherwise, we are analyzing the index. + llvm::Value *OrigPtr = Ptr; + + // The size of the pointer access. + int64_t PtrAccessSize = 1; + + Ptr = stripGetElementPtr(Ptr, SE, Lp); + const SCEV *V = SE->getSCEV(Ptr); + + if (Ptr != OrigPtr) + // Strip off casts. + while (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V)) + V = C->getOperand(); + + const SCEVAddRecExpr *S = dyn_cast<SCEVAddRecExpr>(V); + if (!S) + return nullptr; + + V = S->getStepRecurrence(*SE); + if (!V) + return nullptr; + + // Strip off the size of access multiplication if we are still analyzing the + // pointer. + if (OrigPtr == Ptr) { + const DataLayout &DL = Lp->getHeader()->getModule()->getDataLayout(); + DL.getTypeAllocSize(PtrTy->getElementType()); + if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(V)) { + if (M->getOperand(0)->getSCEVType() != scConstant) + return nullptr; + + const APInt &APStepVal = + cast<SCEVConstant>(M->getOperand(0))->getValue()->getValue(); + + // Huge step value - give up. + if (APStepVal.getBitWidth() > 64) + return nullptr; + + int64_t StepVal = APStepVal.getSExtValue(); + if (PtrAccessSize != StepVal) + return nullptr; + V = M->getOperand(1); + } + } + + // Strip off casts. + Type *StripedOffRecurrenceCast = nullptr; + if (const SCEVCastExpr *C = dyn_cast<SCEVCastExpr>(V)) { + StripedOffRecurrenceCast = C->getType(); + V = C->getOperand(); + } + + // Look for the loop invariant symbolic value. + const SCEVUnknown *U = dyn_cast<SCEVUnknown>(V); + if (!U) + return nullptr; + + llvm::Value *Stride = U->getValue(); + if (!Lp->isLoopInvariant(Stride)) + return nullptr; + + // If we have stripped off the recurrence cast we have to make sure that we + // return the value that is used in this loop so that we can replace it later. + if (StripedOffRecurrenceCast) + Stride = getUniqueCastUse(Stride, Lp, StripedOffRecurrenceCast); + + return Stride; +} + +/// \brief Given a vector and an element number, see if the scalar value is +/// already around as a register, for example if it were inserted then extracted +/// from the vector. +llvm::Value *llvm::findScalarElement(llvm::Value *V, unsigned EltNo) { + assert(V->getType()->isVectorTy() && "Not looking at a vector?"); + VectorType *VTy = cast<VectorType>(V->getType()); + unsigned Width = VTy->getNumElements(); + if (EltNo >= Width) // Out of range access. + return UndefValue::get(VTy->getElementType()); + + if (Constant *C = dyn_cast<Constant>(V)) + return C->getAggregateElement(EltNo); + + if (InsertElementInst *III = dyn_cast<InsertElementInst>(V)) { + // If this is an insert to a variable element, we don't know what it is. + if (!isa<ConstantInt>(III->getOperand(2))) + return nullptr; + unsigned IIElt = cast<ConstantInt>(III->getOperand(2))->getZExtValue(); + + // If this is an insert to the element we are looking for, return the + // inserted value. + if (EltNo == IIElt) + return III->getOperand(1); + + // Otherwise, the insertelement doesn't modify the value, recurse on its + // vector input. + return findScalarElement(III->getOperand(0), EltNo); + } + + if (ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(V)) { + unsigned LHSWidth = SVI->getOperand(0)->getType()->getVectorNumElements(); + int InEl = SVI->getMaskValue(EltNo); + if (InEl < 0) + return UndefValue::get(VTy->getElementType()); + if (InEl < (int)LHSWidth) + return findScalarElement(SVI->getOperand(0), InEl); + return findScalarElement(SVI->getOperand(1), InEl - LHSWidth); + } + + // Extract a value from a vector add operation with a constant zero. + Value *Val = nullptr; Constant *Con = nullptr; + if (match(V, + llvm::PatternMatch::m_Add(llvm::PatternMatch::m_Value(Val), + llvm::PatternMatch::m_Constant(Con)))) { + if (Con->getAggregateElement(EltNo)->isNullValue()) + return findScalarElement(Val, EltNo); + } + + // Otherwise, we don't know. + return nullptr; +} diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 88f359d4fd5c..5c4bab734b2b 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -593,6 +593,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(attributes); KEYWORD(alwaysinline); + KEYWORD(argmemonly); KEYWORD(builtin); KEYWORD(byval); KEYWORD(inalloca); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index b3c7fa087d40..1c6e7bd18d0e 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -946,35 +946,42 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B, B.addStackAlignmentAttr(Alignment); continue; } - case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; - case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; - case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; - case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; - case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; - case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; - case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; - case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; - case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; - case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; - case lltok::kw_noimplicitfloat: B.addAttribute(Attribute::NoImplicitFloat); break; - case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; - case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; - case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; - case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; - case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; - case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; - case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returns_twice: B.addAttribute(Attribute::ReturnsTwice); break; - case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; - case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; - case lltok::kw_sspstrong: B.addAttribute(Attribute::StackProtectStrong); break; - case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; - case lltok::kw_sanitize_address: B.addAttribute(Attribute::SanitizeAddress); break; - case lltok::kw_sanitize_thread: B.addAttribute(Attribute::SanitizeThread); break; - case lltok::kw_sanitize_memory: B.addAttribute(Attribute::SanitizeMemory); break; - case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; + case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; + case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; + case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; + case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; + case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; + case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; + case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; + case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; + case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; + case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; + case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; + case lltok::kw_noimplicitfloat: + B.addAttribute(Attribute::NoImplicitFloat); break; + case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; + case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; + case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; + case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; + case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; + case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; + case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; + case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; + case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; + case lltok::kw_returns_twice: + B.addAttribute(Attribute::ReturnsTwice); break; + case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; + case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; + case lltok::kw_sspstrong: + B.addAttribute(Attribute::StackProtectStrong); break; + case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; + case lltok::kw_sanitize_address: + B.addAttribute(Attribute::SanitizeAddress); break; + case lltok::kw_sanitize_thread: + B.addAttribute(Attribute::SanitizeThread); break; + case lltok::kw_sanitize_memory: + B.addAttribute(Attribute::SanitizeMemory); break; + case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; // Error handling. case lltok::kw_inreg: @@ -1258,6 +1265,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) { case lltok::kw_alignstack: case lltok::kw_alwaysinline: + case lltok::kw_argmemonly: case lltok::kw_builtin: case lltok::kw_inlinehint: case lltok::kw_jumptable: @@ -1334,6 +1342,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) { case lltok::kw_alignstack: case lltok::kw_alwaysinline: + case lltok::kw_argmemonly: case lltok::kw_builtin: case lltok::kw_cold: case lltok::kw_inlinehint: @@ -2873,8 +2882,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (ValTy->isVectorTy() != BaseType->isVectorTy()) return Error(ID.Loc, "getelementptr index type missmatch"); if (ValTy->isVectorTy()) { - unsigned ValNumEl = cast<VectorType>(ValTy)->getNumElements(); - unsigned PtrNumEl = cast<VectorType>(BaseType)->getNumElements(); + unsigned ValNumEl = ValTy->getVectorNumElements(); + unsigned PtrNumEl = BaseType->getVectorNumElements(); if (ValNumEl != PtrNumEl) return Error( ID.Loc, @@ -4534,8 +4543,17 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_and: case lltok::kw_or: case lltok::kw_xor: return ParseLogical(Inst, PFS, KeywordVal); - case lltok::kw_icmp: - case lltok::kw_fcmp: return ParseCompare(Inst, PFS, KeywordVal); + case lltok::kw_icmp: return ParseCompare(Inst, PFS, KeywordVal); + case lltok::kw_fcmp: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); + int Res = ParseCompare(Inst, PFS, KeywordVal); + if (Res != 0) + return Res; + if (FMF.any()) + Inst->setFastMathFlags(FMF); + return 0; + } + // Casts. case lltok::kw_trunc: case lltok::kw_zext: @@ -5572,6 +5590,11 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { SmallVector<Value*, 16> Indices; bool AteExtraComma = false; + // GEP returns a vector of pointers if at least one of parameters is a vector. + // All vector parameters should have the same vector width. + unsigned GEPWidth = BaseType->isVectorTy() ? + BaseType->getVectorNumElements() : 0; + while (EatIfPresent(lltok::comma)) { if (Lex.getKind() == lltok::MetadataVar) { AteExtraComma = true; @@ -5580,14 +5603,13 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { if (ParseTypeAndValue(Val, EltLoc, PFS)) return true; if (!Val->getType()->getScalarType()->isIntegerTy()) return Error(EltLoc, "getelementptr index must be an integer"); - if (Val->getType()->isVectorTy() != Ptr->getType()->isVectorTy()) - return Error(EltLoc, "getelementptr index type missmatch"); + if (Val->getType()->isVectorTy()) { - unsigned ValNumEl = cast<VectorType>(Val->getType())->getNumElements(); - unsigned PtrNumEl = cast<VectorType>(Ptr->getType())->getNumElements(); - if (ValNumEl != PtrNumEl) + unsigned ValNumEl = Val->getType()->getVectorNumElements(); + if (GEPWidth && GEPWidth != ValNumEl) return Error(EltLoc, "getelementptr vector index has a wrong number of elements"); + GEPWidth = ValNumEl; } Indices.push_back(Val); } diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 2487d1208133..691f085f0c9f 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -100,6 +100,7 @@ namespace lltok { // Attributes: kw_attributes, kw_alwaysinline, + kw_argmemonly, kw_sanitize_address, kw_builtin, kw_byval, diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 09f0b689bdc3..c04e8b9f1f37 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -697,6 +697,21 @@ static Comdat::SelectionKind getDecodedComdatSelectionKind(unsigned Val) { } } +static FastMathFlags getDecodedFastMathFlags(unsigned Val) { + FastMathFlags FMF; + if (0 != (Val & FastMathFlags::UnsafeAlgebra)) + FMF.setUnsafeAlgebra(); + if (0 != (Val & FastMathFlags::NoNaNs)) + FMF.setNoNaNs(); + if (0 != (Val & FastMathFlags::NoInfs)) + FMF.setNoInfs(); + if (0 != (Val & FastMathFlags::NoSignedZeros)) + FMF.setNoSignedZeros(); + if (0 != (Val & FastMathFlags::AllowReciprocal)) + FMF.setAllowReciprocal(); + return FMF; +} + static void upgradeDLLImportExportLinkage(llvm::GlobalValue *GV, unsigned Val) { switch (Val) { case 5: GV->setDLLStorageClass(GlobalValue::DLLImportStorageClass); break; @@ -1075,6 +1090,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) { return Attribute::Alignment; case bitc::ATTR_KIND_ALWAYS_INLINE: return Attribute::AlwaysInline; + case bitc::ATTR_KIND_ARGMEMONLY: + return Attribute::ArgMemOnly; case bitc::ATTR_KIND_BUILTIN: return Attribute::Builtin; case bitc::ATTR_KIND_BY_VAL: @@ -3472,17 +3489,7 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { if (Record[OpNum] & (1 << bitc::PEO_EXACT)) cast<BinaryOperator>(I)->setIsExact(true); } else if (isa<FPMathOperator>(I)) { - FastMathFlags FMF; - if (0 != (Record[OpNum] & FastMathFlags::UnsafeAlgebra)) - FMF.setUnsafeAlgebra(); - if (0 != (Record[OpNum] & FastMathFlags::NoNaNs)) - FMF.setNoNaNs(); - if (0 != (Record[OpNum] & FastMathFlags::NoInfs)) - FMF.setNoInfs(); - if (0 != (Record[OpNum] & FastMathFlags::NoSignedZeros)) - FMF.setNoSignedZeros(); - if (0 != (Record[OpNum] & FastMathFlags::AllowReciprocal)) - FMF.setAllowReciprocal(); + FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]); if (FMF.any()) I->setFastMathFlags(FMF); } @@ -3739,14 +3746,25 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) { unsigned OpNum = 0; Value *LHS, *RHS; if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || - popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) || - OpNum+1 != Record.size()) + popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS)) + return error("Invalid record"); + + unsigned PredVal = Record[OpNum]; + bool IsFP = LHS->getType()->isFPOrFPVectorTy(); + FastMathFlags FMF; + if (IsFP && Record.size() > OpNum+1) + FMF = getDecodedFastMathFlags(Record[++OpNum]); + + if (OpNum+1 != Record.size()) return error("Invalid record"); if (LHS->getType()->isFPOrFPVectorTy()) - I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS); + I = new FCmpInst((FCmpInst::Predicate)PredVal, LHS, RHS); else - I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS); + I = new ICmpInst((ICmpInst::Predicate)PredVal, LHS, RHS); + + if (FMF.any()) + I->setFastMathFlags(FMF); InstructionList.push_back(I); break; } @@ -4458,14 +4476,11 @@ std::error_code BitcodeReader::materialize(GlobalValue *GV) { // Upgrade any old intrinsic calls in the function. for (auto &I : UpgradedIntrinsics) { - if (I.first != I.second) { - for (auto UI = I.first->user_begin(), UE = I.first->user_end(); - UI != UE;) { - User *U = *UI; - ++UI; - if (CallInst *CI = dyn_cast<CallInst>(U)) - UpgradeIntrinsicCall(CI, I.second); - } + for (auto UI = I.first->user_begin(), UE = I.first->user_end(); UI != UE;) { + User *U = *UI; + ++UI; + if (CallInst *CI = dyn_cast<CallInst>(U)) + UpgradeIntrinsicCall(CI, I.second); } } @@ -4533,15 +4548,13 @@ std::error_code BitcodeReader::materializeModule(Module *M) { // module is materialized because there could always be another function body // with calls to the old function. for (auto &I : UpgradedIntrinsics) { - if (I.first != I.second) { - for (auto *U : I.first->users()) { - if (CallInst *CI = dyn_cast<CallInst>(U)) - UpgradeIntrinsicCall(CI, I.second); - } - if (!I.first->use_empty()) - I.first->replaceAllUsesWith(I.second); - I.first->eraseFromParent(); + for (auto *U : I.first->users()) { + if (CallInst *CI = dyn_cast<CallInst>(U)) + UpgradeIntrinsicCall(CI, I.second); } + if (!I.first->use_empty()) + I.first->replaceAllUsesWith(I.second); + I.first->eraseFromParent(); } UpgradedIntrinsics.clear(); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 622f7eaf0784..1a70ba5ac127 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -162,6 +162,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) { return bitc::ATTR_KIND_ALIGNMENT; case Attribute::AlwaysInline: return bitc::ATTR_KIND_ALWAYS_INLINE; + case Attribute::ArgMemOnly: + return bitc::ATTR_KIND_ARGMEMONLY; case Attribute::Builtin: return bitc::ATTR_KIND_BUILTIN; case Attribute::ByVal: @@ -1759,13 +1761,17 @@ static void WriteInstruction(const Instruction &I, unsigned InstID, pushValue(I.getOperand(2), InstID, Vals, VE); break; case Instruction::ICmp: - case Instruction::FCmp: + case Instruction::FCmp: { // compare returning Int1Ty or vector of Int1Ty Code = bitc::FUNC_CODE_INST_CMP2; PushValueAndType(I.getOperand(0), InstID, Vals, VE); pushValue(I.getOperand(1), InstID, Vals, VE); Vals.push_back(cast<CmpInst>(I).getPredicate()); + uint64_t Flags = GetOptimizationFlags(&I); + if (Flags != 0) + Vals.push_back(Flags); break; + } case Instruction::Ret: { diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp index 3224fac25cb4..98d4c8afc7b9 100644 --- a/lib/CodeGen/Analysis.cpp +++ b/lib/CodeGen/Analysis.cpp @@ -81,27 +81,27 @@ unsigned llvm::ComputeLinearIndex(Type *Ty, /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// -void llvm::ComputeValueVTs(const TargetLowering &TLI, Type *Ty, - SmallVectorImpl<EVT> &ValueVTs, +void llvm::ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, + Type *Ty, SmallVectorImpl<EVT> &ValueVTs, SmallVectorImpl<uint64_t> *Offsets, uint64_t StartingOffset) { // Given a struct type, recursively traverse the elements. if (StructType *STy = dyn_cast<StructType>(Ty)) { - const StructLayout *SL = TLI.getDataLayout()->getStructLayout(STy); + const StructLayout *SL = DL.getStructLayout(STy); for (StructType::element_iterator EB = STy->element_begin(), EI = EB, EE = STy->element_end(); EI != EE; ++EI) - ComputeValueVTs(TLI, *EI, ValueVTs, Offsets, + ComputeValueVTs(TLI, DL, *EI, ValueVTs, Offsets, StartingOffset + SL->getElementOffset(EI - EB)); return; } // Given an array type, recursively traverse the elements. if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { Type *EltTy = ATy->getElementType(); - uint64_t EltSize = TLI.getDataLayout()->getTypeAllocSize(EltTy); + uint64_t EltSize = DL.getTypeAllocSize(EltTy); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) - ComputeValueVTs(TLI, EltTy, ValueVTs, Offsets, + ComputeValueVTs(TLI, DL, EltTy, ValueVTs, Offsets, StartingOffset + i * EltSize); return; } @@ -109,7 +109,7 @@ void llvm::ComputeValueVTs(const TargetLowering &TLI, Type *Ty, if (Ty->isVoidTy()) return; // Base case: we can get an EVT for this LLVM IR type. - ValueVTs.push_back(TLI.getValueType(Ty)); + ValueVTs.push_back(TLI.getValueType(DL, Ty)); if (Offsets) Offsets->push_back(StartingOffset); } @@ -233,7 +233,8 @@ static bool isNoopBitcast(Type *T1, Type *T2, static const Value *getNoopInput(const Value *V, SmallVectorImpl<unsigned> &ValLoc, unsigned &DataBits, - const TargetLoweringBase &TLI) { + const TargetLoweringBase &TLI, + const DataLayout &DL) { while (true) { // Try to look through V1; if V1 is not an instruction, it can't be looked // through. @@ -255,16 +256,16 @@ static const Value *getNoopInput(const Value *V, // Make sure this isn't a truncating or extending cast. We could // support this eventually, but don't bother for now. if (!isa<VectorType>(I->getType()) && - TLI.getPointerTy().getSizeInBits() == - cast<IntegerType>(Op->getType())->getBitWidth()) + DL.getPointerSizeInBits() == + cast<IntegerType>(Op->getType())->getBitWidth()) NoopInput = Op; } else if (isa<PtrToIntInst>(I)) { // Look through ptrtoint. // Make sure this isn't a truncating or extending cast. We could // support this eventually, but don't bother for now. if (!isa<VectorType>(I->getType()) && - TLI.getPointerTy().getSizeInBits() == - cast<IntegerType>(I->getType())->getBitWidth()) + DL.getPointerSizeInBits() == + cast<IntegerType>(I->getType())->getBitWidth()) NoopInput = Op; } else if (isa<TruncInst>(I) && TLI.allowTruncateForTailCall(Op->getType(), I->getType())) { @@ -331,14 +332,15 @@ static bool slotOnlyDiscardsData(const Value *RetVal, const Value *CallVal, SmallVectorImpl<unsigned> &RetIndices, SmallVectorImpl<unsigned> &CallIndices, bool AllowDifferingSizes, - const TargetLoweringBase &TLI) { + const TargetLoweringBase &TLI, + const DataLayout &DL) { // Trace the sub-value needed by the return value as far back up the graph as // possible, in the hope that it will intersect with the value produced by the // call. In the simple case with no "returned" attribute, the hope is actually // that we end up back at the tail call instruction itself. unsigned BitsRequired = UINT_MAX; - RetVal = getNoopInput(RetVal, RetIndices, BitsRequired, TLI); + RetVal = getNoopInput(RetVal, RetIndices, BitsRequired, TLI, DL); // If this slot in the value returned is undef, it doesn't matter what the // call puts there, it'll be fine. @@ -350,7 +352,7 @@ static bool slotOnlyDiscardsData(const Value *RetVal, const Value *CallVal, // a "returned" attribute, the search will be blocked immediately and the loop // a Noop. unsigned BitsProvided = UINT_MAX; - CallVal = getNoopInput(CallVal, CallIndices, BitsProvided, TLI); + CallVal = getNoopInput(CallVal, CallIndices, BitsProvided, TLI, DL); // There's no hope if we can't actually trace them to (the same part of!) the // same value. @@ -606,7 +608,8 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F, // Finally, we can check whether the value produced by the tail call at this // index is compatible with the value we return. if (!slotOnlyDiscardsData(RetVal, CallVal, TmpRetPath, TmpCallPath, - AllowDifferingSizes, TLI)) + AllowDifferingSizes, TLI, + F->getParent()->getDataLayout())) return false; CallEmpty = !nextRealType(CallSubTypes, CallPath); diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index 4cb460a7bbfc..0bad7954b980 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -69,24 +69,32 @@ void ARMException::beginFunction(const MachineFunction *MF) { /// void ARMException::endFunction(const MachineFunction *MF) { ARMTargetStreamer &ATS = getTargetStreamer(); + const Function *F = MF->getFunction(); + const Function *Per = nullptr; + if (F->hasPersonalityFn()) + Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts()); + assert(!MMI->getPersonality() || Per == MMI->getPersonality()); + bool forceEmitPersonality = + F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + F->needsUnwindTableEntry(); + bool shouldEmitPersonality = forceEmitPersonality || + !MMI->getLandingPads().empty(); if (!Asm->MF->getFunction()->needsUnwindTableEntry() && - MMI->getLandingPads().empty()) + !shouldEmitPersonality) ATS.emitCantUnwind(); - else { - if (!MMI->getLandingPads().empty()) { - // Emit references to personality. - if (const Function *Personality = MMI->getPersonality()) { - MCSymbol *PerSym = Asm->getSymbol(Personality); - Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); - ATS.emitPersonality(PerSym); - } - - // Emit .handlerdata directive. - ATS.emitHandlerData(); - - // Emit actual exception table - emitExceptionTable(); + else if (shouldEmitPersonality) { + // Emit references to personality. + if (Per) { + MCSymbol *PerSym = Asm->getSymbol(Per); + Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global); + ATS.emitPersonality(PerSym); } + + // Emit .handlerdata directive. + ATS.emitHandlerData(); + + // Emit actual exception table + emitExceptionTable(); } if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 8a7e9f991611..125047e7bbb5 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -19,7 +19,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ConstantFolding.h" -#include "llvm/Analysis/JumpInstrTableInfo.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -820,7 +819,7 @@ void AsmPrinter::EmitFunctionBody() { emitCFIInstruction(MI); break; - case TargetOpcode::FRAME_ALLOC: + case TargetOpcode::LOCAL_ESCAPE: emitFrameAlloc(MI); break; @@ -1024,7 +1023,7 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit visibility info for declarations for (const Function &F : M) { - if (!F.isDeclaration()) + if (!F.isDeclarationForLinker()) continue; GlobalValue::VisibilityTypes V = F.getVisibility(); if (V == GlobalValue::DefaultVisibility) diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 0bc873e326be..2c212c7ecee1 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -89,6 +89,7 @@ void DwarfCFIException::endModule() { void DwarfCFIException::beginFunction(const MachineFunction *MF) { shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; + const Function *F = MF->getFunction(); // If any landing pads survive, we need an EH table. bool hasLandingPads = !MMI->getLandingPads().empty(); @@ -104,10 +105,24 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); - const Function *Per = MMI->getPersonality(); - - shouldEmitPersonality = hasLandingPads && - PerEncoding != dwarf::DW_EH_PE_omit && Per; + const Function *Per = nullptr; + if (F->hasPersonalityFn()) + Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts()); + assert(!MMI->getPersonality() || Per == MMI->getPersonality()); + + // Emit a personality function even when there are no landing pads + bool forceEmitPersonality = + // ...if a personality function is explicitly specified + F->hasPersonalityFn() && + // ... and it's not known to be a noop in the absence of invokes + !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + // ... and we're not explicitly asked not to emit it + F->needsUnwindTableEntry(); + + shouldEmitPersonality = + (forceEmitPersonality || + (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && + Per; unsigned LSDAEncoding = TLOF.getLSDAEncoding(); shouldEmitLSDA = shouldEmitPersonality && @@ -123,6 +138,11 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) { if (!shouldEmitPersonality) return; + // If we are forced to emit this personality, make sure to record + // it because it might not appear in any landingpad + if (forceEmitPersonality) + MMI->addPersonality(Per); + const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 1c3e2aec64ab..01f34c6eb81c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -49,7 +49,7 @@ class DwarfUnit; class MachineModuleInfo; //===----------------------------------------------------------------------===// -/// \brief This class is used to record source line correspondence. +/// This class is used to record source line correspondence. class SrcLineInfo { unsigned Line; // Source line number. unsigned Column; // Source column. @@ -161,7 +161,7 @@ public: return dwarf::DW_TAG_variable; } - /// \brief Return true if DbgVariable is artificial. + /// Return true if DbgVariable is artificial. bool isArtificial() const { |