CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
543 lines
15 KiB
ReStructuredText
543 lines
15 KiB
ReStructuredText
=======
|
|
Remarks
|
|
=======
|
|
|
|
.. contents::
|
|
:local:
|
|
|
|
Introduction to the LLVM remark diagnostics
|
|
===========================================
|
|
|
|
LLVM is able to emit diagnostics from passes describing whether an optimization
|
|
has been performed or missed for a particular reason, which should give more
|
|
insight to users about what the compiler did during the compilation pipeline.
|
|
|
|
There are three main remark types:
|
|
|
|
``Passed``
|
|
|
|
Remarks that describe a successful optimization performed by the compiler.
|
|
|
|
:Example:
|
|
|
|
::
|
|
|
|
foo inlined into bar with (cost=always): always inline attribute
|
|
|
|
``Missed``
|
|
|
|
Remarks that describe an attempt to an optimization by the compiler that
|
|
could not be performed.
|
|
|
|
:Example:
|
|
|
|
::
|
|
|
|
foo not inlined into bar because it should never be inlined
|
|
(cost=never): noinline function attribute
|
|
|
|
``Analysis``
|
|
|
|
Remarks that describe the result of an analysis, that can bring more
|
|
information to the user regarding the generated code.
|
|
|
|
:Example:
|
|
|
|
::
|
|
|
|
16 stack bytes in function
|
|
|
|
::
|
|
|
|
10 instructions in function
|
|
|
|
Enabling optimization remarks
|
|
=============================
|
|
|
|
There are two modes that are supported for enabling optimization remarks in
|
|
LLVM: through remark diagnostics, or through serialized remarks.
|
|
|
|
See also the clang flags
|
|
`-Rpass <https://clang.llvm.org/docs/UsersManual.html#options-to-emit-optimization-reports>`_
|
|
and
|
|
`-fsave-optimization-record <http://clang.llvm.org/docs/UsersManual.html#cmdoption-f-no-save-optimization-record>`_.
|
|
|
|
Remark diagnostics
|
|
------------------
|
|
|
|
Optimization remarks can be emitted as diagnostics. These diagnostics will be
|
|
propagated to front-ends if desired, or emitted by tools like :doc:`llc
|
|
<CommandGuide/llc>` or :doc:`opt <CommandGuide/opt>`.
|
|
|
|
.. option:: -pass-remarks=<regex>
|
|
|
|
Enables optimization remarks from passes whose name match the given (POSIX)
|
|
regular expression.
|
|
|
|
.. option:: -pass-remarks-missed=<regex>
|
|
|
|
Enables missed optimization remarks from passes whose name match the given
|
|
(POSIX) regular expression.
|
|
|
|
.. option:: -pass-remarks-analysis=<regex>
|
|
|
|
Enables optimization analysis remarks from passes whose name match the given
|
|
(POSIX) regular expression.
|
|
|
|
Serialized remarks
|
|
------------------
|
|
|
|
While diagnostics are useful during development, it is often more useful to
|
|
refer to optimization remarks post-compilation, typically during performance
|
|
analysis.
|
|
|
|
For that, LLVM can serialize the remarks produced for each compilation unit to
|
|
a file that can be consumed later.
|
|
|
|
By default, the format of the serialized remarks is :ref:`YAML
|
|
<yamlremarks>`, and it can be accompanied by a :ref:`section <remarkssection>`
|
|
in the object files to easily retrieve it.
|
|
|
|
:doc:`llc <CommandGuide/llc>` and :doc:`opt <CommandGuide/opt>` support the
|
|
following options:
|
|
|
|
|
|
``Basic options``
|
|
|
|
.. option:: -pass-remarks-output=<filename>
|
|
|
|
Enables the serialization of remarks to a file specified in <filename>.
|
|
|
|
By default, the output is serialized to :ref:`YAML <yamlremarks>`.
|
|
|
|
.. option:: -pass-remarks-format=<format>
|
|
|
|
Specifies the output format of the serialized remarks.
|
|
|
|
Supported formats:
|
|
|
|
* :ref:`yaml <yamlremarks>` (default)
|
|
* :ref:`bitstream <bitstreamremarks>`
|
|
|
|
``Content configuration``
|
|
|
|
.. option:: -pass-remarks-filter=<regex>
|
|
|
|
Only passes whose name match the given (POSIX) regular expression will be
|
|
serialized to the final output.
|
|
|
|
.. option:: -pass-remarks-with-hotness
|
|
|
|
With PGO, include profile count in optimization remarks.
|
|
|
|
.. option:: -pass-remarks-hotness-threshold
|
|
|
|
The minimum profile count required for an optimization remark to be
|
|
emitted.
|
|
|
|
Other tools that support remarks:
|
|
|
|
:program:`llvm-lto`
|
|
|
|
.. option:: -lto-pass-remarks-output=<filename>
|
|
.. option:: -lto-pass-remarks-filter=<regex>
|
|
.. option:: -lto-pass-remarks-format=<format>
|
|
.. option:: -lto-pass-remarks-with-hotness
|
|
.. option:: -lto-pass-remarks-hotness-threshold
|
|
|
|
:program:`gold-plugin` and :program:`lld`
|
|
|
|
.. option:: -opt-remarks-filename=<filename>
|
|
.. option:: -opt-remarks-filter=<regex>
|
|
.. option:: -opt-remarks-format=<format>
|
|
.. option:: -opt-remarks-with-hotness
|
|
|
|
.. _yamlremarks:
|
|
|
|
YAML remarks
|
|
============
|
|
|
|
A typical remark serialized to YAML looks like this:
|
|
|
|
.. code-block:: yaml
|
|
|
|
--- !<TYPE>
|
|
Pass: <pass>
|
|
Name: <name>
|
|
DebugLoc: { File: <file>, Line: <line>, Column: <column> }
|
|
Function: <function>
|
|
Hotness: <hotness>
|
|
Args:
|
|
- <key>: <value>
|
|
DebugLoc: { File: <arg-file>, Line: <arg-line>, Column: <arg-column> }
|
|
|
|
The following entries are mandatory:
|
|
|
|
* ``<TYPE>``: can be ``Passed``, ``Missed``, ``Analysis``,
|
|
``AnalysisFPCommute``, ``AnalysisAliasing``, ``Failure``.
|
|
* ``<pass>``: the name of the pass that emitted this remark.
|
|
* ``<name>``: the name of the remark coming from ``<pass>``.
|
|
* ``<function>``: the mangled name of the function.
|
|
|
|
If a ``DebugLoc`` entry is specified, the following fields are required:
|
|
|
|
* ``<file>``
|
|
* ``<line>``
|
|
* ``<column>``
|
|
|
|
If an ``arg`` entry is specified, the following fields are required:
|
|
|
|
* ``<key>``
|
|
* ``<value>``
|
|
|
|
If a ``DebugLoc`` entry is specified within an ``arg`` entry, the following
|
|
fields are required:
|
|
|
|
* ``<arg-file>``
|
|
* ``<arg-line>``
|
|
* ``<arg-column>``
|
|
|
|
.. _optviewer:
|
|
|
|
YAML metadata
|
|
-------------
|
|
|
|
The metadata used together with the YAML format is:
|
|
|
|
* a magic number: "REMARKS\\0"
|
|
* the version number: a little-endian uint64_t
|
|
* 8 zero bytes. This space was previously used to encode the size of a string
|
|
table. String table support for YAML remarks has been removed, use the
|
|
bitstream format instead.
|
|
|
|
Optional:
|
|
|
|
* the absolute file path to the serialized remark diagnostics: a
|
|
null-terminated string.
|
|
|
|
When the metadata is serialized separately from the remarks, the file path
|
|
should be present and point to the file where the remarks are serialized to.
|
|
|
|
In case the metadata only acts as a header to the remarks, the file path can be
|
|
omitted.
|
|
|
|
.. _bitstreamremarks:
|
|
|
|
LLVM bitstream remarks
|
|
======================
|
|
|
|
This format is using :doc:`LLVM bitstream <BitCodeFormat>` to serialize remarks
|
|
and their associated metadata.
|
|
|
|
A bitstream remark stream can be identified by the magic number ``"RMRK"`` that
|
|
is placed at the very beginning.
|
|
|
|
The format for serializing remarks is composed of two different block types:
|
|
|
|
.. _bitstreamremarksmetablock:
|
|
|
|
META_BLOCK
|
|
----------
|
|
|
|
The block providing information about the rest of the content in the stream.
|
|
|
|
Exactly one block is expected. Having multiple metadata blocks is an error.
|
|
|
|
This block can contain the following records:
|
|
|
|
.. _bitstreamremarksrecordmetacontainerinfo:
|
|
|
|
``RECORD_META_CONTAINER_INFO``
|
|
|
|
The container version and type.
|
|
|
|
Version: u32
|
|
|
|
Type: u2
|
|
|
|
.. _bitstreamremarksrecordmetaremarkversion:
|
|
|
|
``RECORD_META_REMARK_VERSION``
|
|
|
|
The version of the remark entries. This can change independently from the
|
|
container version.
|
|
|
|
Version: u32
|
|
|
|
.. _bitstreamremarksrecordmetastrtab:
|
|
|
|
``RECORD_META_STRTAB``
|
|
|
|
The string table used by the remark entries. The format of the string table
|
|
is a sequence of strings separated by ``\0``.
|
|
|
|
.. _bitstreamremarksrecordmetaexternalfile:
|
|
|
|
``RECORD_META_EXTERNAL_FILE``
|
|
|
|
The external remark file path that contains the remark blocks associated
|
|
with this metadata. This is an absolute path.
|
|
|
|
.. _bitstreamremarksremarkblock:
|
|
|
|
REMARK_BLOCK
|
|
------------
|
|
|
|
The block describing a remark entry.
|
|
|
|
0 or more blocks per file are allowed. Each block will depend on the
|
|
:ref:`META_BLOCK <bitstreamremarksmetablock>` in order to be parsed correctly.
|
|
|
|
This block can contain the following records:
|
|
|
|
``RECORD_REMARK_HEADER``
|
|
|
|
The header of the remark. This contains all the mandatory information about
|
|
a remark.
|
|
|
|
+---------------+---------------------------+
|
|
| Type | u3 |
|
|
+---------------+---------------------------+
|
|
| Remark name | VBR6 (string table index) |
|
|
+---------------+---------------------------+
|
|
| Pass name | VBR6 (string table index) |
|
|
+---------------+---------------------------+
|
|
| Function name | VBR6 (string table index) |
|
|
+---------------+---------------------------+
|
|
|
|
``RECORD_REMARK_DEBUG_LOC``
|
|
|
|
The source location for the corresponding remark. This record is optional.
|
|
|
|
+--------+---------------------------+
|
|
| File | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
| Line | u32 |
|
|
+--------+---------------------------+
|
|
| Column | u32 |
|
|
+--------+---------------------------+
|
|
|
|
``RECORD_REMARK_HOTNESS``
|
|
|
|
The hotness of the remark. This record is optional.
|
|
|
|
+---------------+---------------------+
|
|
| Hotness | VBR8 (string table index) |
|
|
+---------------+---------------------+
|
|
|
|
``RECORD_REMARK_ARG_WITH_DEBUGLOC``
|
|
|
|
A remark argument with an associated debug location.
|
|
|
|
+--------+---------------------------+
|
|
| Key | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
| Value | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
| File | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
| Line | u32 |
|
|
+--------+---------------------------+
|
|
| Column | u32 |
|
|
+--------+---------------------------+
|
|
|
|
``RECORD_REMARK_ARG_WITHOUT_DEBUGLOC``
|
|
|
|
A remark argument with an associated debug location.
|
|
|
|
+--------+---------------------------+
|
|
| Key | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
| Value | VBR7 (string table index) |
|
|
+--------+---------------------------+
|
|
|
|
The remark container
|
|
--------------------
|
|
|
|
The bitstream remark container supports multiple types:
|
|
|
|
.. _bitstreamremarksfileexternal:
|
|
|
|
``RemarksFileExternal: a link to an external remarks file``
|
|
|
|
This container type expects only a :ref:`META_BLOCK <bitstreamremarksmetablock>` containing only:
|
|
|
|
* :ref:`RECORD_META_CONTAINER_INFO <bitstreamremarksrecordmetacontainerinfo>`
|
|
* :ref:`RECORD_META_STRTAB <bitstreamremarksrecordmetastrtab>`
|
|
* :ref:`RECORD_META_EXTERNAL_FILE <bitstreamremarksrecordmetaexternalfile>`
|
|
|
|
Typically, this is emitted in a section in the object files, allowing
|
|
clients to retrieve remarks and their associated metadata directly from
|
|
intermediate products.
|
|
|
|
The container versions of the external separate container should match in order to
|
|
have a well-formed file.
|
|
|
|
.. _bitstreamremarksfile:
|
|
|
|
``RemarksFile: a standalone remarks file``
|
|
|
|
This container type expects a :ref:`META_BLOCK <bitstreamremarksmetablock>` containing only:
|
|
|
|
* :ref:`RECORD_META_CONTAINER_INFO <bitstreamremarksrecordmetacontainerinfo>`
|
|
* :ref:`RECORD_META_REMARK_VERSION <bitstreamremarksrecordmetaremarkversion>`
|
|
|
|
Then, this container type expects 1 or more :ref:`REMARK_BLOCK <bitstreamremarksremarkblock>`.
|
|
If no remarks are emitted, the meta blocks are also not emitted, so the file is empty.
|
|
|
|
After the remark blocks, another :ref:`META_BLOCK <bitstreamremarksmetablock>` is emitted, containing:
|
|
* :ref:`RECORD_META_STRTAB <bitstreamremarksrecordmetastrtab>`
|
|
|
|
When the parser reads this container type, it jumps to the end of the file
|
|
to read the string table before parsing the individual remarks.
|
|
|
|
Standalone remarks files can be referenced by the
|
|
:ref:`RECORD_META_EXTERNAL_FILE <bitstreamremarksrecordmetaexternalfile>`
|
|
entry in the :ref:`RemarksFileExternal
|
|
<bitstreamremarksfileexternal>` container.
|
|
|
|
.. FIXME: Add complete output of :program:`llvm-bcanalyzer` on the different container types (once format changes are completed)
|
|
|
|
opt-viewer
|
|
==========
|
|
|
|
The ``opt-viewer`` directory contains a collection of tools that visualize and
|
|
summarize serialized remarks.
|
|
|
|
The tools only support the ``yaml`` format.
|
|
|
|
.. _optviewerpy:
|
|
|
|
opt-viewer.py
|
|
-------------
|
|
|
|
Output a HTML page which gives visual feedback on compiler interactions with
|
|
your program.
|
|
|
|
:Examples:
|
|
|
|
::
|
|
|
|
$ opt-viewer.py my_yaml_file.opt.yaml
|
|
|
|
::
|
|
|
|
$ opt-viewer.py my_build_dir/
|
|
|
|
|
|
opt-stats.py
|
|
------------
|
|
|
|
Output statistics about the optimization remarks in the input set.
|
|
|
|
:Example:
|
|
|
|
::
|
|
|
|
$ opt-stats.py my_yaml_file.opt.yaml
|
|
|
|
Total number of remarks 3
|
|
|
|
|
|
Top 10 remarks by pass:
|
|
inline 33%
|
|
asm-printer 33%
|
|
prologepilog 33%
|
|
|
|
Top 10 remarks:
|
|
asm-printer/InstructionCount 33%
|
|
inline/NoDefinition 33%
|
|
prologepilog/StackSize 33%
|
|
|
|
opt-diff.py
|
|
-----------
|
|
|
|
Produce a new YAML file which contains all of the changes in optimizations
|
|
between two YAML files.
|
|
|
|
Typically, this tool should be used to do diffs between:
|
|
|
|
* new compiler + fixed source vs old compiler + fixed source
|
|
* fixed compiler + new source vs fixed compiler + old source
|
|
|
|
This diff file can be displayed using :ref:`opt-viewer.py <optviewerpy>`.
|
|
|
|
:Example:
|
|
|
|
::
|
|
|
|
$ opt-diff.py my_opt_yaml1.opt.yaml my_opt_yaml2.opt.yaml -o my_opt_diff.opt.yaml
|
|
$ opt-viewer.py my_opt_diff.opt.yaml
|
|
|
|
.. _remarkssection:
|
|
|
|
Emitting remark diagnostics in the object file
|
|
==============================================
|
|
|
|
A section containing metadata on remark diagnostics will be emitted for the
|
|
following formats:
|
|
|
|
* ``bitstream``
|
|
|
|
This can be overridden by using the flag ``-remarks-section=<bool>``.
|
|
|
|
The section is named:
|
|
|
|
* ``__LLVM,__remarks`` (MachO)
|
|
|
|
C API
|
|
=====
|
|
|
|
LLVM provides a library that can be used to parse remarks through a shared
|
|
library named ``libRemarks``.
|
|
|
|
The typical usage through the C API is like the following:
|
|
|
|
.. code-block:: c
|
|
|
|
LLVMRemarkParserRef Parser = LLVMRemarkParserCreateYAML(Buf, Size);
|
|
LLVMRemarkEntryRef Remark = NULL;
|
|
while ((Remark = LLVMRemarkParserGetNext(Parser))) {
|
|
// use Remark
|
|
LLVMRemarkEntryDispose(Remark); // Release memory.
|
|
}
|
|
bool HasError = LLVMRemarkParserHasError(Parser);
|
|
LLVMRemarkParserDispose(Parser);
|
|
|
|
Remark streamers
|
|
================
|
|
|
|
The ``RemarkStreamer`` interface is used to unify the serialization
|
|
capabilities of remarks across all the components that can generate remarks.
|
|
|
|
All remark serialization should go through the main remark streamer, the
|
|
``llvm::remarks::RemarkStreamer`` set up in the ``LLVMContext``. The interface
|
|
takes remark objects converted to ``llvm::remarks::Remark``, and takes care of
|
|
serializing it to the requested format, using the requested type of metadata,
|
|
etc.
|
|
|
|
Typically, a specialized remark streamer will hold a reference to the one set
|
|
up in the ``LLVMContext``, and will operate on its own type of diagnostics.
|
|
|
|
For example, LLVM IR passes will emit ``llvm::DiagnosticInfoOptimization*``
|
|
that get converted to ``llvm::remarks::Remark`` objects. Then, clang could set
|
|
up its own specialized remark streamer that takes ``clang::Diagnostic``
|
|
objects. This can allow various components of the frontend to emit remarks
|
|
using the same techniques as the LLVM remarks.
|
|
|
|
This gives us the following advantages:
|
|
|
|
* Composition: during the compilation pipeline, multiple components can set up
|
|
their specialized remark streamers that all emit remarks through the same
|
|
main streamer.
|
|
* Re-using the remark infrastructure in ``lib/Remarks``.
|
|
* Using the same file and format for the remark emitters created throughout the
|
|
compilation.
|
|
|
|
at the cost of an extra layer of abstraction.
|
|
|
|
.. FIXME: add documentation for llvm-opt-report.
|
|
.. FIXME: add documentation for Passes supporting optimization remarks
|
|
.. FIXME: add documentation for IR Passes
|
|
.. FIXME: add documentation for CodeGen Passes
|