[docs] Migrate 20 LLVM docs to markdown (#201465)

An LLM assisted in the rewrite. I didn't use pandoc or any other tools,
and I think there are fewer artifacts. I validated these docs by opening
all 20 HTML files in my browser.

Files:
- DebuggingLLVM.md
- FAQ.md
- CompilerWriterInfo.md
- GettingStartedVS.md
- NewPassManager.md
- MemorySSA.md
- LoopTerminology.md
- Lexicon.md
- MIRLangRef.md
- CoverageMappingFormat.md
- InstrProfileFormat.md
- BitCodeFormat.md
- Atomics.md
- GarbageCollection.md
- AliasAnalysis.md
- LibFuzzer.md
- Extensions.md
- CommandLine.md
- ExceptionHandling.md
- Coroutines.md

Tracking issue: #201242
This commit is contained in:
Reid Kleckner 2026-06-05 15:26:28 -07:00 committed by GitHub
parent 638f3ae61d
commit cab8d8c9e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 6467 additions and 7161 deletions

View file

@ -1,12 +1,10 @@
==================================
LLVM Alias Analysis Infrastructure
==================================
# LLVM Alias Analysis Infrastructure
.. contents::
:local:
```{contents}
:local:
```
Introduction
============
## Introduction
Alias Analysis (aka Pointer Analysis) is a class of techniques which attempt to
determine whether or not two pointers ever can point to the same object in
@ -14,12 +12,11 @@ memory. There are many different algorithms for alias analysis and many
different ways of classifying them: flow-sensitive vs. flow-insensitive,
context-sensitive vs. context-insensitive, field-sensitive
vs. field-insensitive, unification-based vs. subset-based, etc. Traditionally,
alias analyses respond to a query with a `Must, May, or No`_ alias response,
alias analyses respond to a query with a {ref}`Must, May, or No <Must, May, or No>` alias response,
indicating that two pointers always point to the same object, might point to the
same object, or are known to never point to the same object.
The LLVM `AliasAnalysis
<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`__ class is the
The LLVM [AliasAnalysis](https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html) class is the
primary interface used by clients and implementations of alias analyses in the
LLVM system. This class is the common interface between clients of alias
analysis information and the implementations providing it, and is designed to
@ -33,91 +30,87 @@ This document contains information necessary to successfully implement this
interface, use it, and to test both sides. It also explains some of the finer
points about what exactly results mean.
``AliasAnalysis`` Class Overview
================================
## `AliasAnalysis` Class Overview
The `AliasAnalysis <https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`__
The [AliasAnalysis](https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html)
class defines the interface that the various alias analysis implementations
should support. This class exports two important enums: ``AliasResult`` and
``ModRefResult`` which represent the result of an alias query or a mod/ref
should support. This class exports two important enums: `AliasResult` and
`ModRefResult` which represent the result of an alias query or a mod/ref
query, respectively.
The ``AliasAnalysis`` interface exposes information about memory, represented in
The `AliasAnalysis` interface exposes information about memory, represented in
several different ways. In particular, memory objects are represented as a
starting address and size, and function calls are represented as the actual
``call`` or ``invoke`` instructions that perform the call. The
``AliasAnalysis`` interface also exposes some helper methods which allow you to
`call` or `invoke` instructions that perform the call. The
`AliasAnalysis` interface also exposes some helper methods which allow you to
get mod/ref information for arbitrary instructions.
All ``AliasAnalysis`` interfaces require that in queries involving multiple
values, values which are not :ref:`constants <constants>` are all
All `AliasAnalysis` interfaces require that in queries involving multiple
values, values which are not {ref}`constants <constants>` are all
defined within the same function.
Representation of Pointers
--------------------------
### Representation of Pointers
Most importantly, the ``AliasAnalysis`` class provides several methods which are
Most importantly, the `AliasAnalysis` class provides several methods which are
used to query whether or not two memory objects alias, whether function calls
can modify or read a memory object, etc. For all of these queries, memory
objects are represented as a pair of their starting address (a symbolic LLVM
``Value*``) and a static size.
`Value*`) and a static size.
Representing memory objects as a starting address and a size is critically
important for correct Alias Analyses. For example, consider this (silly, but
possible) C code:
.. code-block:: c++
```c++
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
C[0] = A[i]; /* One byte store */
C[1] = A[9-i]; /* One byte store */
}
```
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
C[0] = A[i]; /* One byte store */
C[1] = A[9-i]; /* One byte store */
}
In this case, the ``basic-aa`` pass will disambiguate the stores to ``C[0]`` and
``C[1]`` because they are accesses to two distinct locations one byte apart, and
In this case, the `basic-aa` pass will disambiguate the stores to `C[0]` and
`C[1]` because they are accesses to two distinct locations one byte apart, and
the accesses are each one byte. In this case, the Loop Invariant Code Motion
(LICM) pass can use store motion to remove the stores from the loop. In
contrast, the following code:
.. code-block:: c++
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
((short*)C)[0] = A[i]; /* Two byte store! */
C[1] = A[9-i]; /* One byte store */
}
```c++
int i;
char C[2];
char A[10];
/* ... */
for (i = 0; i != 10; ++i) {
((short*)C)[0] = A[i]; /* Two byte store! */
C[1] = A[9-i]; /* One byte store */
}
```
In this case, the two stores to C do alias each other, because the access to the
``&C[0]`` element is a two byte access. If size information wasn't available in
`&C[0]` element is a two byte access. If size information wasn't available in
the query, even the first case would have to conservatively assume that the
accesses alias.
.. _alias:
(alias)=
The ``alias`` method
--------------------
### The `alias` method
The ``alias`` method is the primary interface used to determine whether or not
The `alias` method is the primary interface used to determine whether or not
two memory objects alias each other. It takes two memory objects as input and
returns MustAlias, PartialAlias, MayAlias, or NoAlias as appropriate.
Like all ``AliasAnalysis`` interfaces, the ``alias`` method requires that either
Like all `AliasAnalysis` interfaces, the `alias` method requires that either
the two pointer values be defined within the same function, or at least one of
the values is a :ref:`constant <constants>`.
the values is a {ref}`constant <constants>`.
.. _Must, May, or No:
(Must, May, or No)=
Must, May, and No Alias Responses
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### Must, May, and No Alias Responses
The ``NoAlias`` response may be used when there is never an immediate dependence
The `NoAlias` response may be used when there is never an immediate dependence
between any memory reference *based* on one pointer and any memory reference
*based on* the other. The most obvious example is when the two pointers point to
non-overlapping memory ranges. Another is when the two pointers are only ever
@ -125,223 +118,208 @@ used for reading memory. Another is when the memory is freed and reallocated
between accesses through one pointer and accesses through the other --- in this
case, there is a dependence, but it's mediated by the free and reallocation.
An exception to this is with the :ref:`noalias <noalias>` keyword;
An exception to this is with the {ref}`noalias <noalias>` keyword;
the "irrelevant" dependencies are ignored.
The ``MayAlias`` response is used whenever the two pointers might refer to the
The `MayAlias` response is used whenever the two pointers might refer to the
same object.
The ``PartialAlias`` response is used when the two memory objects are known to
The `PartialAlias` response is used when the two memory objects are known to
be overlapping in some way, regardless of whether they start at the same address
or not.
The ``MustAlias`` response may only be returned if the two memory objects are
guaranteed to always start at exactly the same location. A ``MustAlias``
The `MustAlias` response may only be returned if the two memory objects are
guaranteed to always start at exactly the same location. A `MustAlias`
response does not imply that the pointers compare equal.
The ``getModRefInfo`` methods
-----------------------------
### The `getModRefInfo` methods
The ``getModRefInfo`` methods return information about whether the execution of
The `getModRefInfo` methods return information about whether the execution of
an instruction can read or modify a memory location. Mod/Ref information is
always conservative: if an instruction **might** read or write a location,
``ModRef`` is returned.
`ModRef` is returned.
The ``AliasAnalysis`` class also provides a ``getModRefInfo`` method for testing
dependencies between function calls. This method takes two call sites (``CS1``
& ``CS2``), returns ``NoModRef`` if neither call writes to memory read or
written by the other, ``Ref`` if ``CS1`` reads memory written by ``CS2``,
``Mod`` if ``CS1`` writes to memory read or written by ``CS2``, or ``ModRef`` if
``CS1`` might read or write memory written to by ``CS2``. Note that this
The `AliasAnalysis` class also provides a `getModRefInfo` method for testing
dependencies between function calls. This method takes two call sites (`CS1`
& `CS2`), returns `NoModRef` if neither call writes to memory read or
written by the other, `Ref` if `CS1` reads memory written by `CS2`,
`Mod` if `CS1` writes to memory read or written by `CS2`, or `ModRef` if
`CS1` might read or write memory written to by `CS2`. Note that this
relation is not commutative.
Other useful ``AliasAnalysis`` methods
--------------------------------------
### Other useful `AliasAnalysis` methods
Several other tidbits of information are often collected by various alias
analysis implementations and can be put to good use by various clients.
The ``getModRefInfoMask`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `getModRefInfoMask` method
The ``getModRefInfoMask`` method returns a bound on Mod/Ref information for
The `getModRefInfoMask` method returns a bound on Mod/Ref information for
the supplied pointer, based on knowledge about whether the pointer points to
globally-constant memory (for which it returns ``NoModRef``) or
locally-invariant memory (for which it returns ``Ref``). Globally-constant
globally-constant memory (for which it returns `NoModRef`) or
locally-invariant memory (for which it returns `Ref`). Globally-constant
memory includes functions, constant global variables, and the null pointer.
Locally-invariant memory is memory that we know is invariant for the lifetime
of its SSA value, but not necessarily for the life of the program: for example,
the memory pointed to by ``readonly`` ``noalias`` parameters is known-invariant
the memory pointed to by `readonly` `noalias` parameters is known-invariant
for the duration of the corresponding function call. Given Mod/Ref information
``MRI`` for a memory location ``Loc``, ``MRI`` can be refined with a statement
like ``MRI &= AA.getModRefInfoMask(Loc);``. Another useful idiom is
``isModSet(AA.getModRefInfoMask(Loc))``; this checks to see if the given
`MRI` for a memory location `Loc`, `MRI` can be refined with a statement
like `MRI &= AA.getModRefInfoMask(Loc);`. Another useful idiom is
`isModSet(AA.getModRefInfoMask(Loc))`; this checks to see if the given
location can be modified at all. For convenience, there is also a method
``pointsToConstantMemory(Loc)``; this is synonymous with
``isNoModRef(AA.getModRefInfoMask(Loc))``.
`pointsToConstantMemory(Loc)`; this is synonymous with
`isNoModRef(AA.getModRefInfoMask(Loc))`.
.. _never access memory or only read memory:
(never access memory or only read memory)=
The ``doesNotAccessMemory`` and ``onlyReadsMemory`` methods
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `doesNotAccessMemory` and `onlyReadsMemory` methods
These methods are used to provide very simple mod/ref information for function
calls. The ``doesNotAccessMemory`` method returns true for a function if the
calls. The `doesNotAccessMemory` method returns true for a function if the
analysis can prove that the function never reads or writes to memory, or if the
function only reads from constant memory. Functions with this property are
side-effect free and only depend on their input arguments, allowing them to be
eliminated if they form common subexpressions or be hoisted out of loops. Many
common functions behave this way (e.g., ``sin`` and ``cos``) but many others do
not (e.g., ``acos``, which modifies the ``errno`` variable).
common functions behave this way (e.g., `sin` and `cos`) but many others do
not (e.g., `acos`, which modifies the `errno` variable).
The ``onlyReadsMemory`` method returns true for a function if analysis can prove
The `onlyReadsMemory` method returns true for a function if analysis can prove
that (at most) the function only reads from non-volatile memory. Functions with
this property are side-effect free, only depending on their input arguments and
the state of memory when they are called. This property allows calls to these
functions to be eliminated and moved around, as long as there is no store
instruction that changes the contents of memory. Note that all functions that
satisfy the ``doesNotAccessMemory`` method also satisfy ``onlyReadsMemory``.
satisfy the `doesNotAccessMemory` method also satisfy `onlyReadsMemory`.
Writing a new ``AliasAnalysis`` Implementation
==============================================
## Writing a new `AliasAnalysis` Implementation
Writing a new alias analysis implementation for LLVM is quite straightforward.
There are already several implementations that you can use for examples, and the
following information should help fill in any details. For example, take a
look at the `various alias analysis implementations`_ included with LLVM.
look at the {ref}`various alias analysis implementations` included with LLVM.
Different Pass styles
---------------------
### Different Pass styles
The first step is to determine what type of :doc:`LLVM pass <WritingAnLLVMPass>`
The first step is to determine what type of {doc}`LLVM pass <WritingAnLLVMPass>`
you need to use for your Alias Analysis. As is the case with most other
analyses and transformations, the answer should be fairly obvious from what type
of problem you are trying to solve:
#. If you require interprocedural analysis, it should be a ``Pass``.
#. If you are a function-local analysis, subclass ``FunctionPass``.
#. If you don't need to look at the program at all, subclass ``ImmutablePass``.
1. If you require interprocedural analysis, it should be a `Pass`.
1. If you are a function-local analysis, subclass `FunctionPass`.
1. If you don't need to look at the program at all, subclass `ImmutablePass`.
In addition to the pass that you subclass, you should also inherit from the
``AliasAnalysis`` interface, of course, and use the ``RegisterAnalysisGroup``
template to register as an implementation of ``AliasAnalysis``.
`AliasAnalysis` interface, of course, and use the `RegisterAnalysisGroup`
template to register as an implementation of `AliasAnalysis`.
Required initialization calls
-----------------------------
### Required initialization calls
Your subclass of ``AliasAnalysis`` is required to invoke two methods on the
``AliasAnalysis`` base class: ``getAnalysisUsage`` and
``InitializeAliasAnalysis``. In particular, your implementation of
``getAnalysisUsage`` should explicitly call into the
``AliasAnalysis::getAnalysisUsage`` method in addition to declaring
Your subclass of `AliasAnalysis` is required to invoke two methods on the
`AliasAnalysis` base class: `getAnalysisUsage` and
`InitializeAliasAnalysis`. In particular, your implementation of
`getAnalysisUsage` should explicitly call into the
`AliasAnalysis::getAnalysisUsage` method in addition to declaring
any pass dependencies your pass has. Thus you should have something like this:
.. code-block:: c++
```c++
void getAnalysisUsage(AnalysisUsage &AU) const {
AliasAnalysis::getAnalysisUsage(AU);
// declare your dependencies here.
}
```
void getAnalysisUsage(AnalysisUsage &AU) const {
AliasAnalysis::getAnalysisUsage(AU);
// declare your dependencies here.
}
Additionally, you must invoke the `InitializeAliasAnalysis` method from your
analysis run method (`run` for a `Pass`, `runOnFunction` for a
`FunctionPass`, or `InitializePass` for an `ImmutablePass`). For example
(as part of a `Pass`):
Additionally, you must invoke the ``InitializeAliasAnalysis`` method from your
analysis run method (``run`` for a ``Pass``, ``runOnFunction`` for a
``FunctionPass``, or ``InitializePass`` for an ``ImmutablePass``). For example
(as part of a ``Pass``):
```c++
bool run(Module &M) {
InitializeAliasAnalysis(this);
// Perform analysis here...
return false;
}
```
.. code-block:: c++
### Interfaces which may be specified
bool run(Module &M) {
InitializeAliasAnalysis(this);
// Perform analysis here...
return false;
}
Interfaces which may be specified
---------------------------------
All of the `AliasAnalysis
<https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html>`__ virtual methods
default to providing :ref:`chaining <aliasanalysis-chaining>` to another alias
All of the [AliasAnalysis](https://llvm.org/doxygen/classllvm_1_1AliasAnalysis.html) virtual methods
default to providing {ref}`chaining <aliasanalysis-chaining>` to another alias
analysis implementation, which ends up returning conservatively correct
information (returning "May" Alias and "Mod/Ref" for alias and mod/ref queries
respectively). Depending on the capabilities of the analysis you are
implementing, you just override the interfaces you can improve.
.. _aliasanalysis-chaining:
(aliasanalysis-chaining)=
``AliasAnalysis`` chaining behavior
-----------------------------------
### `AliasAnalysis` chaining behavior
Every alias analysis pass chains to another alias analysis implementation (for
example, the user can specify "``-basic-aa -ds-aa -licm``" to get the maximum
example, the user can specify "`-basic-aa -ds-aa -licm`" to get the maximum
benefit from both alias analyses). The alias analysis class automatically
takes care of most of this for methods that you don't override. For methods
that you do override, in code paths that return a conservative MayAlias or
Mod/Ref result, simply return whatever the superclass computes. For example:
.. code-block:: c++
```c++
AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
if (...)
return NoAlias;
...
AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
if (...)
return NoAlias;
...
// Couldn't determine a must or no-alias result.
return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}
// Couldn't determine a must or no-alias result.
return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}
```
In addition to analysis queries, you must make sure to unconditionally pass LLVM
`update notification`_ methods to the superclass as well if you override them,
{ref}`update notification` methods to the superclass as well if you override them,
which allows all alias analyses in a change to be updated.
.. _update notification:
(update notification)=
Updating analysis results for transformations
---------------------------------------------
### Updating analysis results for transformations
Alias analysis information is initially computed for a static snapshot of the
program, but clients will use this information to make transformations to the
code. All but the most trivial forms of alias analysis will need to have their
analysis results updated to reflect the changes made by these transformations.
The ``AliasAnalysis`` interface exposes four methods which are used to
The `AliasAnalysis` interface exposes four methods which are used to
communicate program changes from the clients to the analysis implementations.
Various alias analysis implementations should use these methods to ensure that
their internal data structures are kept up-to-date as the program changes (for
example, when an instruction is deleted), and clients of alias analysis must be
sure to call these interfaces appropriately.
The ``deleteValue`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `deleteValue` method
The ``deleteValue`` method is called by transformations when they remove an
The `deleteValue` method is called by transformations when they remove an
instruction or any other value from the program (including values that do not
use pointers). Typically alias analyses keep data structures that have entries
for each value in the program. When this method is called, they should remove
any entries for the specified value, if they exist.
The ``copyValue`` method
^^^^^^^^^^^^^^^^^^^^^^^^
#### The `copyValue` method
The ``copyValue`` method is used when a new value is introduced into the
The `copyValue` method is used when a new value is introduced into the
program. There is no way to introduce a value into the program that did not
exist before (this doesn't make sense for a safe compiler transformation), so
this is the only way to introduce a new value. This method indicates that the
new value has exactly the same properties as the value being copied.
The ``replaceWithNewValue`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `replaceWithNewValue` method
This method is a simple helper method that is provided to make clients easier to
use. It is implemented by copying the old analysis information to the new
value, then deleting the old value. This method cannot be overridden by alias
analysis implementations.
The ``addEscapingUse`` method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `addEscapingUse` method
The ``addEscapingUse`` method is used when the uses of a pointer value have
The `addEscapingUse` method is used when the uses of a pointer value have
changed in ways that may invalidate precomputed analysis information.
Implementations may either use this callback to provide conservative responses
for points whose uses have changed since analysis time, or may recompute some or
@ -350,12 +328,11 @@ all of their internal state to continue providing accurate responses.
In general, any new use of a pointer value is considered an escaping use, and
must be reported through this callback, *except* for the uses below:
* A ``bitcast`` or ``getelementptr`` of the pointer
* A ``store`` through the pointer (but not a ``store`` *of* the pointer)
* A ``load`` through the pointer
* A `bitcast` or `getelementptr` of the pointer
* A `store` through the pointer (but not a `store` *of* the pointer)
* A `load` through the pointer
Efficiency Issues
-----------------
### Efficiency Issues
From the LLVM perspective, the only thing you need to do to provide an efficient
alias analysis is to make sure that alias analysis **queries** are serviced
@ -364,108 +341,103 @@ method) is only performed once, but many (perhaps duplicate) queries may be
performed. Because of this, try to move as much computation to the run method
as possible (within reason).
Limitations
-----------
### Limitations
The AliasAnalysis infrastructure has several limitations which make writing a
new ``AliasAnalysis`` implementation difficult.
new `AliasAnalysis` implementation difficult.
There is no way to override the default alias analysis. It would be very useful
to be able to do something like "``opt -my-aa -O2``" and have it use ``-my-aa``
to be able to do something like "`opt -my-aa -O2`" and have it use `-my-aa`
for all passes which need AliasAnalysis, but there is currently no support for
that, short of changing the source code and recompiling. Similarly, there is
also no way of setting a chain of analyses as the default.
There is no way for transform passes to declare that they preserve
``AliasAnalysis`` implementations. The ``AliasAnalysis`` interface includes
``deleteValue`` and ``copyValue`` methods which are intended to allow a pass to
`AliasAnalysis` implementations. The `AliasAnalysis` interface includes
`deleteValue` and `copyValue` methods which are intended to allow a pass to
keep an AliasAnalysis consistent; however, there's no way for a pass to declare
in its ``getAnalysisUsage`` that it does so. Some passes attempt to use
``AU.addPreserved<AliasAnalysis>``; however, this doesn't actually have any
in its `getAnalysisUsage` that it does so. Some passes attempt to use
`AU.addPreserved<AliasAnalysis>`; however, this doesn't actually have any
effect.
Similarly, the ``opt -p`` option introduces ``ModulePass`` passes between each
pass, which prevents the use of ``FunctionPass`` alias analysis passes.
Similarly, the `opt -p` option introduces `ModulePass` passes between each
pass, which prevents the use of `FunctionPass` alias analysis passes.
The ``AliasAnalysis`` API does have functions for notifying implementations when
The `AliasAnalysis` API does have functions for notifying implementations when
values are deleted or copied; however, these aren't sufficient. There are many
other ways that LLVM IR can be modified which could be relevant to
``AliasAnalysis`` implementations which can not be expressed.
`AliasAnalysis` implementations which can not be expressed.
The ``AliasAnalysisDebugger`` utility seems to suggest that ``AliasAnalysis``
implementations can expect that they will be informed of any relevant ``Value``
before it appears in an alias query. However, popular clients such as ``GVN``
The `AliasAnalysisDebugger` utility seems to suggest that `AliasAnalysis`
implementations can expect that they will be informed of any relevant `Value`
before it appears in an alias query. However, popular clients such as `GVN`
don't support this, and are known to trigger errors when run with the
``AliasAnalysisDebugger``.
`AliasAnalysisDebugger`.
The ``AliasSetTracker`` class (which is used by ``LICM``) makes a
The `AliasSetTracker` class (which is used by `LICM`) makes a
non-deterministic number of alias queries. This can cause debugging techniques
involving pausing execution after a predetermined number of queries to be
unreliable.
Many alias queries can be reformulated in terms of other alias queries. When
multiple ``AliasAnalysis`` queries are chained together, it would make sense to
multiple `AliasAnalysis` queries are chained together, it would make sense to
start those queries from the beginning of the chain, with care taken to avoid
infinite looping; however, currently an implementation which wants to do this can
only start such queries from itself.
Using alias analysis results
============================
## Using alias analysis results
There are several different ways to use alias analysis results. In order of
preference, these are:
Using the ``MemoryDependenceAnalysis`` Pass
-------------------------------------------
### Using the `MemoryDependenceAnalysis` Pass
The ``memdep`` pass uses alias analysis to provide high-level dependence
The `memdep` pass uses alias analysis to provide high-level dependence
information about memory-using instructions. This will tell you which store
feeds into a load, for example. It uses caching and other techniques to be
efficient, and is used by Dead Store Elimination, GVN, and memcpy optimizations.
.. _AliasSetTracker:
(AliasSetTracker)=
Using the ``AliasSetTracker`` class
-----------------------------------
### Using the `AliasSetTracker` class
Many transformations need information about alias **sets** that are active in
some scope, rather than information about pairwise aliasing. The
`AliasSetTracker <https://llvm.org/doxygen/classllvm_1_1AliasSetTracker.html>`__
[AliasSetTracker](https://llvm.org/doxygen/classllvm_1_1AliasSetTracker.html)
class is used to efficiently build these Alias Sets from the pairwise alias
analysis information provided by the ``AliasAnalysis`` interface.
analysis information provided by the `AliasAnalysis` interface.
First you initialize the AliasSetTracker by using the "``add``" methods to add
First you initialize the AliasSetTracker by using the "`add`" methods to add
information about various potentially aliasing instructions in the scope you are
interested in. Once all of the alias sets are completed, your pass should
simply iterate through the constructed alias sets, using the ``AliasSetTracker``
``begin()``/``end()`` methods.
simply iterate through the constructed alias sets, using the `AliasSetTracker`
`begin()`/`end()` methods.
The ``AliasSet``\s formed by the ``AliasSetTracker`` are guaranteed to be
The `AliasSet`s formed by the `AliasSetTracker` are guaranteed to be
disjoint, calculate mod/ref information and volatility for the set, and keep
track of whether or not all of the pointers in the set are Must aliases. The
AliasSetTracker also makes sure that sets are properly folded due to call
instructions, and can provide a list of pointers in each set.
As an example user of this, the `Loop Invariant Code Motion
<doxygen/structLICM.html>`_ pass uses ``AliasSetTracker``\s to calculate alias
sets for each loop nest. If an ``AliasSet`` in a loop is not modified, then all
As an example user of this, the [Loop Invariant Code Motion](https://llvm.org/doxygen/structLICM.html)
pass uses `AliasSetTracker`s to calculate alias
sets for each loop nest. If an `AliasSet` in a loop is not modified, then all
load instructions from that set may be hoisted out of the loop. If any alias
sets are stored to **and** are must alias sets, then the stores may be sunk
to outside of the loop, promoting the memory location to a register for the
duration of the loop nest. Both of these transformations only apply if the
pointer argument is loop-invariant.
The AliasSetTracker implementation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The AliasSetTracker implementation
The AliasSetTracker class is implemented to be as efficient as possible. It
uses the union-find algorithm to efficiently merge AliasSets when a pointer is
inserted into the AliasSetTracker that aliases multiple sets. The primary data
structure is a hash table mapping pointers to the AliasSet they are in.
The AliasSetTracker class must maintain a list of all of the LLVM ``Value*``\s
The AliasSetTracker class must maintain a list of all of the LLVM `Value*`s
that are in each AliasSet. Since the hash table already has entries for each
LLVM ``Value*`` of interest, the AliasesSets thread the linked list through
LLVM `Value*` of interest, the AliasesSets thread the linked list through
these hash-table nodes to avoid having to allocate memory unnecessarily, and to
make merging alias sets extremely efficient (the linked list merge is constant
time).
@ -474,51 +446,46 @@ You shouldn't need to understand these details if you are just a client of the
AliasSetTracker, but if you look at the code, hopefully this brief description
will help make sense of why things are designed the way they are.
Using the ``AliasAnalysis`` interface directly
----------------------------------------------
### Using the `AliasAnalysis` interface directly
If neither of these utility classes are what your pass needs, you should use the
interfaces exposed by the ``AliasAnalysis`` class directly. Try to use the
interfaces exposed by the `AliasAnalysis` class directly. Try to use the
higher-level methods when possible (e.g., use mod/ref information instead of the
`alias`_ method directly if possible) to get the best precision and efficiency.
{ref}`alias` method directly if possible) to get the best precision and efficiency.
Existing alias analysis implementations and clients
===================================================
## Existing alias analysis implementations and clients
If you're going to be working with the LLVM alias analysis infrastructure, you
should know what clients and implementations of alias analysis are available.
In particular, if you are implementing an alias analysis, you should be aware of
`the clients`_ that are useful for monitoring and evaluating different
{ref}`the clients` that are useful for monitoring and evaluating different
implementations.
.. _various alias analysis implementations:
(various alias analysis implementations)=
Available ``AliasAnalysis`` implementations
-------------------------------------------
### Available `AliasAnalysis` implementations
This section lists the various implementations of the ``AliasAnalysis``
interface. All of these :ref:`chain <aliasanalysis-chaining>` to other
This section lists the various implementations of the `AliasAnalysis`
interface. All of these {ref}`chain <aliasanalysis-chaining>` to other
alias analysis implementations.
The ``-basic-aa`` pass
^^^^^^^^^^^^^^^^^^^^^^
#### The `-basic-aa` pass
The ``-basic-aa`` pass is an aggressive local analysis that *knows* many
The `-basic-aa` pass is an aggressive local analysis that *knows* many
important facts:
* Distinct globals, stack allocations, and heap allocations can never alias.
* Globals, stack allocations, and heap allocations never alias the null pointer.
* Different fields of a structure do not alias.
* Indexes into arrays with statically differing subscripts cannot alias.
* Many common standard C library functions `never access memory or only read
memory`_.
* Pointers that obviously point to constant globals "``pointToConstantMemory``".
* Many common standard C library functions {ref}`never access memory or only read
memory <never access memory or only read memory>`.
* Pointers that obviously point to constant globals "`pointToConstantMemory`".
* Function calls cannot modify or reference stack allocations if they never
escape from the function that allocates them (a common case for automatic
arrays).
The ``-globalsmodref-aa`` pass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `-globalsmodref-aa` pass
This pass implements a simple context-sensitive mod/ref and alias analysis for
internal global variables that don't "have their address taken". If a global
@ -532,73 +499,67 @@ information for call instructions. This allows the optimizer to know that calls
to a function do not clobber or read the value of the global, allowing loads and
stores to be eliminated.
.. note::
```{note}
This pass is somewhat limited in its scope (only support non-address taken
globals), but is very quick analysis.
```
This pass is somewhat limited in its scope (only support non-address taken
globals), but is very quick analysis.
#### The `-steens-aa` pass
The ``-steens-aa`` pass
^^^^^^^^^^^^^^^^^^^^^^^
The ``-steens-aa`` pass implements a variation on the well-known "Steensgaard's
The `-steens-aa` pass implements a variation on the well-known "Steensgaard's
algorithm" for interprocedural alias analysis. Steensgaard's algorithm is a
unification-based, flow-insensitive, context-insensitive, and field-insensitive
alias analysis that is also very scalable (effectively linear time).
The LLVM ``-steens-aa`` pass implements a "speculatively field-**sensitive**"
The LLVM `-steens-aa` pass implements a "speculatively field-**sensitive**"
version of Steensgaard's algorithm using the Data Structure Analysis framework.
This gives it substantially more precision than the standard algorithm while
maintaining excellent analysis scalability.
.. note::
```{note}
`-steens-aa` is available in the optional "poolalloc" module. It is not part
of the LLVM core.
```
``-steens-aa`` is available in the optional "poolalloc" module. It is not part
of the LLVM core.
#### The `-ds-aa` pass
The ``-ds-aa`` pass
^^^^^^^^^^^^^^^^^^^
The ``-ds-aa`` pass implements the full Data Structure Analysis algorithm. Data
The `-ds-aa` pass implements the full Data Structure Analysis algorithm. Data
Structure Analysis is a modular unification-based, flow-insensitive,
context-**sensitive**, and speculatively field-**sensitive** alias
analysis that is also quite scalable, usually at ``O(n * log(n))``.
analysis that is also quite scalable, usually at `O(n * log(n))`.
This algorithm is capable of responding to a full variety of alias analysis
queries, and can provide context-sensitive mod/ref information as well. The
only major facility not implemented so far is support for must-alias
information.
.. note::
```{note}
`-ds-aa` is available in the optional "poolalloc" module. It is not part of
the LLVM core.
```
``-ds-aa`` is available in the optional "poolalloc" module. It is not part of
the LLVM core.
#### The `-scev-aa` pass
The ``-scev-aa`` pass
^^^^^^^^^^^^^^^^^^^^^
The ``-scev-aa`` pass implements AliasAnalysis queries by translating them into
The `-scev-aa` pass implements AliasAnalysis queries by translating them into
ScalarEvolution queries. This gives it a more complete understanding of
``getelementptr`` instructions and loop induction variables than other alias
`getelementptr` instructions and loop induction variables than other alias
analyses have.
Alias analysis driven transformations
-------------------------------------
### Alias analysis driven transformations
LLVM includes several alias-analysis driven transformations which can be used
with any of the implementations above.
The ``-adce`` pass
^^^^^^^^^^^^^^^^^^
#### The `-adce` pass
The ``-adce`` pass, which implements Aggressive Dead Code Elimination, uses the
``AliasAnalysis`` interface to delete calls to functions that do not have
The `-adce` pass, which implements Aggressive Dead Code Elimination, uses the
`AliasAnalysis` interface to delete calls to functions that do not have
side-effects and are not used.
The ``-licm`` pass
^^^^^^^^^^^^^^^^^^
#### The `-licm` pass
The ``-licm`` pass implements various Loop Invariant Code Motion related
transformations. It uses the ``AliasAnalysis`` interface for several different
The `-licm` pass implements various Loop Invariant Code Motion related
transformations. It uses the `AliasAnalysis` interface for several different
transformations:
* It uses mod/ref information to hoist or sink load instructions out of loops if
@ -611,61 +572,55 @@ transformations:
to in loops to live in a register instead. It can do this if there are no may
aliases to the loaded/stored memory location.
The ``-argpromotion`` pass
^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `-argpromotion` pass
The ``-argpromotion`` pass promotes by-reference arguments to be passed in
The `-argpromotion` pass promotes by-reference arguments to be passed in
by-value instead. In particular, if pointer arguments are only loaded from, it
passes in the value loaded instead of the address to the function. This pass
uses alias information to make sure that the value loaded from the argument
pointer is not modified between the entry of the function and any load of the
pointer.
The ``-gvn``, ``-memcpyopt``, and ``-dse`` passes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### The `-gvn`, `-memcpyopt`, and `-dse` passes
These passes use AliasAnalysis information to reason about loads and stores.
.. _the clients:
(the clients)=
Clients for debugging and evaluation of implementations
-------------------------------------------------------
### Clients for debugging and evaluation of implementations
These passes are useful for evaluating the various alias analysis
implementations. You can use them with commands like:
.. code-block:: bash
```console
% opt -ds-aa -aa-eval foo.bc -disable-output -stats
```
% opt -ds-aa -aa-eval foo.bc -disable-output -stats
#### The `print<alias-sets>` pass
The ``print<alias-sets>`` pass
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The `print<alias-sets>` pass is exposed as part of the `opt` tool to print
out the Alias Sets formed by the {ref}`AliasSetTracker` class. This is useful if
you're using the `AliasSetTracker` class. To use it, use something like:
The ``print<alias-sets>`` pass is exposed as part of the ``opt`` tool to print
out the Alias Sets formed by the `AliasSetTracker`_ class. This is useful if
you're using the ``AliasSetTracker`` class. To use it, use something like:
```console
% opt -passes='print<alias-sets>' -disable-output
```
.. code-block:: bash
#### The `-aa-eval` pass
% opt -passes='print<alias-sets>' -disable-output
The ``-aa-eval`` pass
^^^^^^^^^^^^^^^^^^^^^
The ``-aa-eval`` pass simply iterates through all pairs of pointers in a
The `-aa-eval` pass simply iterates through all pairs of pointers in a
function and asks an alias analysis whether or not the pointers alias. This
gives an indication of the precision of the alias analysis. Statistics are
printed indicating the percent of no/may/must aliases found (a more precise
algorithm will have a lower number of may aliases).
Memory Dependence Analysis
==========================
## Memory Dependence Analysis
.. note::
We are currently in the process of migrating things from
``MemoryDependenceAnalysis`` to :doc:`MemorySSA`. Please try to use
that instead.
```{note}
We are currently in the process of migrating things from
`MemoryDependenceAnalysis` to {doc}`MemorySSA`. Please try to use
that instead.
```
If you're just looking to be a client of alias analysis information, consider
using the Memory Dependence Analysis interface instead. MemDep is a lazy,

View file

@ -1,12 +1,16 @@
==============================================
LLVM Atomic Instructions and Concurrency Guide
==============================================
---
myst:
enable_extensions:
- deflist
---
.. contents::
:local:
# LLVM Atomic Instructions and Concurrency Guide
Introduction
============
```{contents}
:local:
```
## Introduction
LLVM supports instructions which are well-defined in the presence of threads and
asynchronous signals.
@ -14,27 +18,29 @@ asynchronous signals.
The atomic instructions are designed specifically to provide readable IR and
optimized code generation for the following:
* The C++ ``<atomic>`` header and C ``<stdatomic.h>`` headers. These
* The C++ `<atomic>` header and C `<stdatomic.h>` headers. These
were originally added in C++11 and C11. The memory model has been
subsequently adjusted to correct errors in the initial
specification, so LLVM currently intends to implement the version
specified by C++20. (See the `C++20 draft standard
<https://isocpp.org/files/papers/N4860.pdf>`_ or the unofficial
`latest C++ draft <https://eel.is/c++draft/>`_. A `C2x draft
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf>`_ is
specified by C++20. (See the [C++20 draft standard]
or the unofficial [latest C++ draft]. A [C2x draft] is
also available, though the text has not yet been updated with the
errata corrected by C++20.)
* Proper semantics for Java-style memory, for both ``volatile`` and regular
shared variables. (`Java Specification
<http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html>`_)
* Proper semantics for Java-style memory, for both `volatile` and regular
shared variables. ([Java Specification])
* gcc-compatible ``__sync_*`` builtins. (`Description
<https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html>`_)
* gcc-compatible `__sync_*` builtins. ([Description])
* Other scenarios with atomic semantics, including ``static`` variables with
* Other scenarios with atomic semantics, including `static` variables with
non-trivial constructors in C++.
[C++20 draft standard]: https://isocpp.org/files/papers/N4860.pdf
[latest C++ draft]: https://eel.is/c++draft/
[C2x draft]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf
[Java Specification]: http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html
[Description]: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fsync-Builtins.html
Atomic and volatile in the IR are orthogonal; "volatile" is the C/C++ volatile,
which ensures that every volatile load and store happens and is performed in the
stated order. A couple examples: if a SequentiallyConsistent store is
@ -50,13 +56,12 @@ with instructions with special semantics in the presence of concurrency. This
is not intended to be a precise guide to the semantics; the details can get
extremely complicated and unreadable, and are not usually necessary.
.. _Optimization outside atomic:
(Optimization outside atomic)=
Optimization outside atomic
===========================
## Optimization outside atomic
The basic ``'load'`` and ``'store'`` allow a variety of optimizations, but can
lead to undefined results in a concurrent environment; see `NotAtomic`_. This
The basic `'load'` and `'store'` allow a variety of optimizations, but can
lead to undefined results in a concurrent environment; see {ref}`NotAtomic`. This
section specifically goes into the one optimizer restriction which applies in
concurrent environments, which gets a bit more of an extended description
because any optimization dealing with stores needs to be aware of it.
@ -67,8 +72,7 @@ one exception: if a variable might be visible to another thread or signal
handler, a store cannot be inserted along a path where it might not execute
otherwise. Take the following example:
.. code-block:: c
```c
/* C code, for readability; run through clang -O2 -S -emit-llvm to get
equivalent IR */
int x;
@ -78,11 +82,11 @@ otherwise. Take the following example:
x += 1;
}
}
```
The following is equivalent in non-concurrent situations:
.. code-block:: c
```c
int x;
void f(int* a) {
int xtemp = x;
@ -92,33 +96,33 @@ The following is equivalent in non-concurrent situations:
}
x = xtemp;
}
```
However, LLVM is not allowed to transform the former to the latter: it could
indirectly introduce undefined behavior if another thread can access ``x`` at
the same time. That thread would read ``undef`` instead of the value it was
indirectly introduce undefined behavior if another thread can access `x` at
the same time. That thread would read `undef` instead of the value it was
expecting, which can lead to undefined behavior down the line. (This example is
particularly of interest because before the concurrency model was implemented,
LLVM would perform this transformation.)
Note that speculative loads are allowed; a load which is part of a race returns
``undef``, but does not have undefined behavior.
`undef`, but does not have undefined behavior.
Atomic instructions
===================
## Atomic instructions
For cases where simple loads and stores are not sufficient, LLVM provides
various atomic instructions. The exact guarantees provided depend on the
ordering; see `Atomic orderings`_.
ordering; see {ref}`Atomic orderings`.
``load atomic`` and ``store atomic`` provide the same basic functionality as
`load atomic` and `store atomic` provide the same basic functionality as
non-atomic loads and stores, but provide additional guarantees in situations
where threads and signals are involved.
``cmpxchg`` and ``atomicrmw`` are essentially like an atomic load followed by an
atomic store (where the store is conditional for ``cmpxchg``), but no other
`cmpxchg` and `atomicrmw` are essentially like an atomic load followed by an
atomic store (where the store is conditional for `cmpxchg`), but no other
memory operation can happen on any thread between the load and store.
A ``fence`` provides Acquire and/or Release ordering which is not part
A `fence` provides Acquire and/or Release ordering which is not part
of another operation; it is normally used along with Monotonic memory
operations. A Monotonic load followed by an Acquire fence is roughly
equivalent to an Acquire load, and a Monotonic store following a
@ -132,33 +136,31 @@ target to some degree; atomic instructions are guaranteed to be lock-free, and
therefore an instruction which is wider than the target natively supports can be
impossible to generate.
.. _Atomic orderings:
(Atomic orderings)=
Atomic orderings
================
## Atomic orderings
In order to achieve a balance between performance and necessary guarantees,
there are six levels of atomicity. They are listed in order of strength; each
level includes all the guarantees of the previous level except for
Acquire/Release. (See also `LangRef Ordering <LangRef.html#ordering>`_.)
Acquire/Release. (See also {ref}`LangRef Ordering <ordering>`.)
.. _NotAtomic:
(NotAtomic)=
NotAtomic
---------
### NotAtomic
NotAtomic is the obvious, a load or store which is not atomic. (This isn't
really a level of atomicity, but is listed here for comparison.) This is
essentially a regular load or store. If there is a race on a given memory
location, loads from that location return ``undef``.
location, loads from that location return `undef`.
Relevant standard
This is intended to match shared variables in C/C++, and to be used in any
: This is intended to match shared variables in C/C++, and to be used in any
other context where memory access is necessary, and a race is impossible. (The
precise definition is in `LangRef Memory Model <LangRef.html#memmodel>`_.)
precise definition is in {ref}`LangRef Memory Model <memmodel>`.)
Notes for frontends
The rule is essentially that all memory accessed with basic loads and stores
: The rule is essentially that all memory accessed with basic loads and stores
by multiple threads should be protected by a lock or other synchronization;
otherwise, you are likely to run into undefined behavior. If your frontend is
for a "safe" language like Java, use Unordered to load and store any shared
@ -168,12 +170,12 @@ Notes for frontends
atomics are generally a better solution.)
Notes for optimizers
Introducing loads to shared variables along a codepath where they would not
: Introducing loads to shared variables along a codepath where they would not
otherwise exist is allowed; introducing stores to shared variables is not. See
`Optimization outside atomic`_.
{ref}`Optimization outside atomic`.
Notes for code generation
The one interesting restriction here is that it is not allowed to write to
: The one interesting restriction here is that it is not allowed to write to
bytes outside of the bytes relevant to a store. This is mostly relevant to
unaligned stores: it is not allowed in general to convert an unaligned store
into two aligned stores of the same width as the unaligned store. Backends are
@ -182,8 +184,7 @@ Notes for code generation
architecture which cannot satisfy these restrictions and cares about
concurrency, please send an email to llvm-dev.)
Unordered
---------
### Unordered
Unordered is the lowest level of atomicity. It essentially guarantees that races
produce somewhat sane results instead of having undefined behavior. It also
@ -193,10 +194,10 @@ global lock. Note that code generation will fail for unsupported atomic
operations; if you need such an operation, use explicit locking.
Relevant standard
This is intended to match the Java memory model for shared variables.
: This is intended to match the Java memory model for shared variables.
Notes for frontends
This cannot be used for synchronization, but is useful for Java and other
: This cannot be used for synchronization, but is useful for Java and other
"safe" languages which need to guarantee that the generated code never
exhibits undefined behavior. Note that this guarantee is cheap on common
platforms for loads of a native width, but can be expensive or unavailable for
@ -205,7 +206,7 @@ Notes for frontends
stores.)
Notes for optimizers
In terms of the optimizer, this prohibits any transformation that transforms a
: In terms of the optimizer, this prohibits any transformation that transforms a
single load into multiple loads, transforms a store into multiple stores,
narrows a store, or stores a value which would not be stored otherwise. Some
examples of unsafe optimizations are narrowing an assignment into a bitfield,
@ -215,15 +216,14 @@ Notes for optimizers
that need them.
Notes for code generation
These operations are required to be atomic in the sense that if you use
: These operations are required to be atomic in the sense that if you use
unordered loads and unordered stores, a load cannot see a value which was
never stored. A normal load or store instruction is usually sufficient, but
note that an unordered load or store cannot be split into multiple
instructions (or an instruction which does multiple memory operations, like
``LDRD`` on ARM without LPAE, or not naturally-aligned ``LDRD`` on LPAE ARM).
`LDRD` on ARM without LPAE, or not naturally-aligned `LDRD` on LPAE ARM).
Monotonic
---------
### Monotonic
Monotonic is the weakest level of atomicity that can be used in synchronization
primitives, although it does not provide any general synchronization. It
@ -231,18 +231,18 @@ essentially guarantees that if you take all the operations affecting a specific
address, a consistent ordering exists.
Relevant standard
This corresponds to the C++/C ``memory_order_relaxed``; see those
: This corresponds to the C++/C `memory_order_relaxed`; see those
standards for the exact definition.
Notes for frontends
If you are writing a frontend which uses this directly, use with caution. The
: If you are writing a frontend which uses this directly, use with caution. The
guarantees in terms of synchronization are very weak, so make sure these are
only used in a pattern which you know is correct. Generally, these would
either be used for atomic operations which do not protect other memory (like
an atomic counter), or along with a ``fence``.
an atomic counter), or along with a `fence`.
Notes for optimizers
In terms of the optimizer, this can be treated as a read+write on the relevant
: In terms of the optimizer, this can be treated as a read+write on the relevant
memory location (and alias analysis will take advantage of that). In addition,
it is legal to reorder non-atomic and Unordered loads around Monotonic
loads. CSE/DSE and a few other optimizations are allowed, but Monotonic
@ -250,135 +250,130 @@ Notes for optimizers
optimizations useful.
Notes for code generation
Code generation is essentially the same as that for unordered for loads and
stores. No fences are required. ``cmpxchg`` and ``atomicrmw`` are required
: Code generation is essentially the same as that for unordered for loads and
stores. No fences are required. `cmpxchg` and `atomicrmw` are required
to appear as a single operation.
Acquire
-------
### Acquire
Acquire provides a barrier of the sort necessary to acquire a lock to access
other memory with normal loads and stores.
Relevant standard
This corresponds to the C++/C ``memory_order_acquire``. It should also be
used for C++/C ``memory_order_consume``.
: This corresponds to the C++/C `memory_order_acquire`. It should also be
used for C++/C `memory_order_consume`.
Notes for frontends
If you are writing a frontend which uses this directly, use with caution.
: If you are writing a frontend which uses this directly, use with caution.
Acquire only provides a semantic guarantee when paired with a Release
operation.
Notes for optimizers
Optimizers not aware of atomics can treat this like a nothrow call. It is
: Optimizers not aware of atomics can treat this like a nothrow call. It is
also possible to move stores from before an Acquire load or read-modify-write
operation to after it, and move non-Acquire loads from before an Acquire
operation to after it.
Notes for code generation
Architectures with weak memory ordering (essentially everything relevant today
: Architectures with weak memory ordering (essentially everything relevant today
except x86 and SPARC) require some sort of fence to maintain the Acquire
semantics. The precise fences required varies widely by architecture, but for
a simple implementation, most architectures provide a barrier which is strong
enough for everything (``dmb`` on ARM, ``sync`` on PowerPC, etc.). Putting
enough for everything (`dmb` on ARM, `sync` on PowerPC, etc.). Putting
such a fence after the equivalent Monotonic operation is sufficient to
maintain Acquire semantics for a memory operation.
Release
-------
### Release
Release is similar to Acquire, but with a barrier of the sort necessary to
release a lock.
Relevant standard
This corresponds to the C++/C ``memory_order_release``.
: This corresponds to the C++/C `memory_order_release`.
Notes for frontends
If you are writing a frontend which uses this directly, use with caution.
: If you are writing a frontend which uses this directly, use with caution.
Release only provides a semantic guarantee when paired with an Acquire
operation.
Notes for optimizers
Optimizers not aware of atomics can treat this like a nothrow call. It is
: Optimizers not aware of atomics can treat this like a nothrow call. It is
also possible to move loads from after a Release store or read-modify-write
operation to before it, and move non-Release stores from after a Release
operation to before it.
Notes for code generation
See the section on Acquire; a fence before the relevant operation is usually
: See the section on Acquire; a fence before the relevant operation is usually
sufficient for Release. Note that a store-store fence is not sufficient to
implement Release semantics; store-store fences are generally not exposed to
IR because they are extremely difficult to use correctly.
AcquireRelease
--------------
### AcquireRelease
AcquireRelease (``acq_rel`` in IR) provides both an Acquire and a Release
AcquireRelease (`acq_rel` in IR) provides both an Acquire and a Release
barrier (for fences and operations which both read and write memory).
Relevant standard
This corresponds to the C++/C ``memory_order_acq_rel``.
: This corresponds to the C++/C `memory_order_acq_rel`.
Notes for frontends
If you are writing a frontend which uses this directly, use with caution.
: If you are writing a frontend which uses this directly, use with caution.
Acquire only provides a semantic guarantee when paired with a Release
operation, and vice versa.
Notes for optimizers
In general, optimizers should treat this like a nothrow call; the possible
: In general, optimizers should treat this like a nothrow call; the possible
optimizations are usually not interesting.
Notes for code generation
This operation has Acquire and Release semantics; see the sections on Acquire
: This operation has Acquire and Release semantics; see the sections on Acquire
and Release.
SequentiallyConsistent
----------------------
### SequentiallyConsistent
SequentiallyConsistent (``seq_cst`` in IR) provides Acquire semantics for loads
SequentiallyConsistent (`seq_cst` in IR) provides Acquire semantics for loads
and Release semantics for stores. Additionally, it guarantees that a total
ordering exists between all SequentiallyConsistent operations.
Relevant standard
This corresponds to the C++/C ``memory_order_seq_cst``, Java volatile, and
the gcc-compatible ``__sync_*`` builtins which do not specify otherwise.
: This corresponds to the C++/C `memory_order_seq_cst`, Java volatile, and
the gcc-compatible `__sync_*` builtins which do not specify otherwise.
Notes for frontends
If a frontend is exposing atomic operations, these are much easier to reason
: If a frontend is exposing atomic operations, these are much easier to reason
about for the programmer than other kinds of operations, and using them is
generally a practical performance tradeoff.
Notes for optimizers
Optimizers not aware of atomics can treat this like a nothrow call. For
: Optimizers not aware of atomics can treat this like a nothrow call. For
SequentiallyConsistent loads and stores, the same reorderings are allowed as
for Acquire loads and Release stores, except that SequentiallyConsistent
operations may not be reordered.
Notes for code generation
SequentiallyConsistent loads minimally require the same barriers as Acquire
: SequentiallyConsistent loads minimally require the same barriers as Acquire
operations and SequentiallyConsistent stores require Release
barriers. Additionally, the code generator must enforce ordering between
SequentiallyConsistent stores followed by SequentiallyConsistent loads. This
is usually done by emitting either a full fence before the loads or a full
fence after the stores; which is preferred varies by architecture.
Atomics and IR optimization
===========================
## Atomics and IR optimization
Predicates for optimizer writers to query:
* ``isSimple()``: A load or store which is not volatile or atomic. This is
* `isSimple()`: A load or store which is not volatile or atomic. This is
what, for example, memcpyopt would check for operations it might transform.
* ``isUnordered()``: A load or store which is not volatile and at most
* `isUnordered()`: A load or store which is not volatile and at most
Unordered. This would be checked, for example, by LICM before hoisting an
operation.
* ``mayReadFromMemory()``/``mayWriteToMemory()``: Existing predicate, but note
* `mayReadFromMemory()`/`mayWriteToMemory()`: Existing predicate, but note
that they return true for any operation which is volatile or at least
Monotonic.
* ``isStrongerThan`` / ``isAtLeastOrStrongerThan``: These are predicates on
* `isStrongerThan` / `isAtLeastOrStrongerThan`: These are predicates on
orderings. They can be useful for passes that are aware of atomics, for
example to do DSE across a single atomic access, but not across a
release-acquire pair (see MemoryDependencyAnalysis for an example of this)
@ -394,7 +389,7 @@ it doesn't replace an atomic load or store with a non-atomic operation.
Some examples of how optimizations interact with various kinds of atomic
operations:
* ``memcpyopt``: An atomic operation cannot be optimized into part of a
* `memcpyopt`: An atomic operation cannot be optimized into part of a
memcpy/memset, including unordered loads/stores. It can pull operations
across some atomic operations.
@ -412,13 +407,12 @@ operations:
because it cannot be observed. Similar reasoning allows SROA with
atomic loads and stores.
Atomics and Codegen
===================
## Atomics and Codegen
Atomic operations are represented in the SelectionDAG with ``ATOMIC_*`` opcodes.
Atomic operations are represented in the SelectionDAG with `ATOMIC_*` opcodes.
On architectures which use barrier instructions for all atomic ordering (like
ARM), appropriate fences can be emitted by the AtomicExpand Codegen pass if
``shouldInsertFencesForAtomic()`` returns true.
`shouldInsertFencesForAtomic()` returns true.
The MachineMemOperand for all atomic operations is currently marked as volatile;
this is not correct in the IR sense of volatile, but CodeGen handles anything
@ -428,53 +422,53 @@ One very important property of the atomic operations is that if your backend
supports any inline lock-free atomic operations of a given size, you should
support *ALL* operations of that size in a lock-free manner.
When the target implements atomic ``cmpxchg`` or LL/SC instructions (as most do)
When the target implements atomic `cmpxchg` or LL/SC instructions (as most do)
this is trivial: all the other operations can be implemented on top of those
primitives. However, on many older CPUs (e.g. ARMv5, Sparc V8, Intel 80386) there
are atomic load and store instructions, but no ``cmpxchg`` or LL/SC. As it is
invalid to implement ``atomic load`` using the native instruction, but
``cmpxchg`` using a library call to a function that uses a mutex, ``atomic
load`` must *also* expand to a library call on such architectures, so that it
can remain atomic with regards to a simultaneous ``cmpxchg``, by using the same
are atomic load and store instructions, but no `cmpxchg` or LL/SC. As it is
invalid to implement `atomic load` using the native instruction, but
`cmpxchg` using a library call to a function that uses a mutex, `atomic
load` must *also* expand to a library call on such architectures, so that it
can remain atomic with regards to a simultaneous `cmpxchg`, by using the same
mutex.
AtomicExpandPass can help with that: it will expand all atomic operations to the
proper ``__atomic_*`` libcalls for any size above the maximum set by
``setMaxAtomicSizeInBitsSupported`` (which defaults to 0).
proper `__atomic_*` libcalls for any size above the maximum set by
`setMaxAtomicSizeInBitsSupported` (which defaults to 0).
On x86, all atomic loads generate a ``MOV``. SequentiallyConsistent stores
generate an ``XCHG``, other stores generate a ``MOV``. SequentiallyConsistent
fences generate an ``MFENCE``, other fences do not cause any code to be
generated. ``cmpxchg`` uses the ``LOCK CMPXCHG`` instruction. ``atomicrmw xchg``
uses ``XCHG``, ``atomicrmw add`` and ``atomicrmw sub`` use ``XADD``, and all
other ``atomicrmw`` operations generate a loop with ``LOCK CMPXCHG``. Depending
on the users of the result, some ``atomicrmw`` operations can be translated into
operations like ``LOCK AND``, but that does not work in general.
On x86, all atomic loads generate a `MOV`. SequentiallyConsistent stores
generate an `XCHG`, other stores generate a `MOV`. SequentiallyConsistent
fences generate an `MFENCE`, other fences do not cause any code to be
generated. `cmpxchg` uses the `LOCK CMPXCHG` instruction. `atomicrmw xchg`
uses `XCHG`, `atomicrmw add` and `atomicrmw sub` use `XADD`, and all
other `atomicrmw` operations generate a loop with `LOCK CMPXCHG`. Depending
on the users of the result, some `atomicrmw` operations can be translated into
operations like `LOCK AND`, but that does not work in general.
On ARM (before v8), MIPS, and many other RISC architectures, Acquire, Release,
and SequentiallyConsistent semantics require barrier instructions for every such
operation. Loads and stores generate normal instructions. ``cmpxchg`` and
``atomicrmw`` can be represented using a loop with LL/SC-style instructions
which take some sort of exclusive lock on a cache line (``LDREX`` and ``STREX``
operation. Loads and stores generate normal instructions. `cmpxchg` and
`atomicrmw` can be represented using a loop with LL/SC-style instructions
which take some sort of exclusive lock on a cache line (`LDREX` and `STREX`
on ARM, etc.).
It is often easiest for backends to use AtomicExpandPass to lower some of the
atomic constructs. Here are some lowerings it can do:
* cmpxchg -> loop with load-linked/store-conditional
by overriding ``shouldExpandAtomicCmpXchgInIR()``, ``emitLoadLinked()``,
``emitStoreConditional()``
by overriding `shouldExpandAtomicCmpXchgInIR()`, `emitLoadLinked()`,
`emitStoreConditional()`
* large loads/stores -> ll-sc/cmpxchg
by overriding ``shouldExpandAtomicStoreInIR()``/``shouldExpandAtomicLoadInIR()``
by overriding `shouldExpandAtomicStoreInIR()`/`shouldExpandAtomicLoadInIR()`
* strong atomic accesses -> monotonic accesses + fences by overriding
``shouldInsertFencesForAtomic()``, ``emitLeadingFence()``, and
``emitTrailingFence()``
`shouldInsertFencesForAtomic()`, `emitLeadingFence()`, and
`emitTrailingFence()`
* atomic rmw -> loop with cmpxchg or load-linked/store-conditional
by overriding ``expandAtomicRMWInIR()``
* expansion to __atomic_* libcalls for unsupported sizes.
by overriding `expandAtomicRMWInIR()`
* expansion to `__atomic_*` libcalls for unsupported sizes.
* part-word atomicrmw/cmpxchg -> target-specific intrinsic by overriding
``shouldExpandAtomicRMWInIR``, ``emitMaskedAtomicRMWIntrinsic``,
``shouldExpandAtomicCmpXchgInIR``, and ``emitMaskedAtomicCmpXchgIntrinsic``.
`shouldExpandAtomicRMWInIR`, `emitMaskedAtomicRMWIntrinsic`,
`shouldExpandAtomicCmpXchgInIR`, and `emitMaskedAtomicCmpXchgIntrinsic`.
For an example of these, look at the ARM (first five lowerings) or RISC-V (last
lowering) backend.
@ -491,52 +485,58 @@ AtomicExpandPass can help support lowering of part-word atomicrmw or cmpxchg
using this strategy by producing IR for any shifting and masking that can be
performed outside of the LL/SC loop.
Libcalls: __atomic_*
====================
## Libcalls: `__atomic_*`
There are two kinds of atomic library calls that are generated by LLVM. Please
note that both sets of library functions somewhat confusingly share the names of
builtin functions defined by clang. Despite this, the library functions are
not directly related to the builtins: it is *not* the case that ``__atomic_*``
builtins lower to ``__atomic_*`` library calls and ``__sync_*`` builtins lower
to ``__sync_*`` library calls.
not directly related to the builtins: it is *not* the case that `__atomic_*`
builtins lower to `__atomic_*` library calls and `__sync_*` builtins lower
to `__sync_*` library calls.
The first set of library functions are named ``__atomic_*``. This set has been
"standardized" by GCC, and is described below. (See also `GCC's documentation
<https://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary>`_)
The first set of library functions are named `__atomic_*`. This set has been
"standardized" by GCC, and is described below. (See also [GCC's documentation])
[GCC's documentation]: https://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary
LLVM's AtomicExpandPass will translate atomic operations on data sizes above
``MaxAtomicSizeInBitsSupported`` into calls to these functions.
`MaxAtomicSizeInBitsSupported` into calls to these functions.
There are four generic functions, which can be called with data of any size or
alignment::
alignment:
```
void __atomic_load(size_t size, void *ptr, void *ret, int ordering)
void __atomic_store(size_t size, void *ptr, void *val, int ordering)
void __atomic_exchange(size_t size, void *ptr, void *val, void *ret, int ordering)
bool __atomic_compare_exchange(size_t size, void *ptr, void *expected, void *desired, int success_order, int failure_order)
```
There are also size-specialized versions of the above functions, which can only
be used with *naturally-aligned* pointers of the appropriate size. In the
signatures below, "N" is one of 1, 2, 4, 8, and 16, and "iN" is the appropriate
integer type of that size; if no such integer type exists, the specialization
cannot be used::
cannot be used:
```
iN __atomic_load_N(iN *ptr, iN val, int ordering)
void __atomic_store_N(iN *ptr, iN val, int ordering)
iN __atomic_exchange_N(iN *ptr, iN val, int ordering)
bool __atomic_compare_exchange_N(iN *ptr, iN *expected, iN desired, int success_order, int failure_order)
```
Finally there are some read-modify-write functions, which are only available in
the size-specific variants (any other sizes use a ``__atomic_compare_exchange``
loop)::
the size-specific variants (any other sizes use a `__atomic_compare_exchange`
loop):
```
iN __atomic_fetch_add_N(iN *ptr, iN val, int ordering)
iN __atomic_fetch_sub_N(iN *ptr, iN val, int ordering)
iN __atomic_fetch_and_N(iN *ptr, iN val, int ordering)
iN __atomic_fetch_or_N(iN *ptr, iN val, int ordering)
iN __atomic_fetch_xor_N(iN *ptr, iN val, int ordering)
iN __atomic_fetch_nand_N(iN *ptr, iN val, int ordering)
```
This set of library functions have some interesting implementation requirements
to take note of:
@ -552,9 +552,9 @@ to take note of:
- The set of atomic sizes supported lock-free must be a superset of the sizes
any compiler can emit. That is: if a new compiler introduces support for
inline-lock-free atomics of size N, the ``__atomic_*`` functions must also have a
inline-lock-free atomics of size N, the `__atomic_*` functions must also have a
lock-free implementation for size N. This is a requirement so that code
produced by an old compiler (which will have called the ``__atomic_*`` function)
produced by an old compiler (which will have called the `__atomic_*` function)
interoperates with code produced by the new compiler (which will use native
the atomic instruction).
@ -563,8 +563,7 @@ of these library functions by using the compiler atomic builtins themselves to
implement the operations on naturally-aligned pointers of supported sizes, and a
generic mutex implementation otherwise.
Libcalls: __sync_*
==================
## Libcalls: `__sync_*`
Some targets or OS/target combinations can support lock-free atomics, but for
various reasons, it is not practical to emit the instructions inline.
@ -579,9 +578,8 @@ instructions are not encodable. However, those instructions are available via a
function call to a function with the longer encoding.
Additionally, a few OS/target pairs provide kernel-supported lock-free
atomics. ARM/Linux is an example of this: the kernel `provides
<https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt>`_ a
function which on older CPUs contains a "magically-restartable" atomic sequence
atomics. ARM/Linux is an example of this: the kernel [provides]
a function which on older CPUs contains a "magically-restartable" atomic sequence
(which looks atomic so long as there's only one CPU), and contains actual atomic
instructions on newer multicore models. This sort of functionality can typically
be provided on any architecture, if all CPUs which are missing atomic
@ -590,17 +588,19 @@ case. The only common architecture without that property is SPARC -- SPARCV8 SMP
systems were common, yet it doesn't support any sort of compare-and-swap
operation.
Some targets (like RISC-V) support a ``+forced-atomics`` target feature, which
[provides]: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt
Some targets (like RISC-V) support a `+forced-atomics` target feature, which
enables the use of lock-free atomics even if LLVM is not aware of any specific
OS support for them. In this case, the user is responsible for ensuring that
necessary ``__sync_*`` implementations are available. Code using
``+forced-atomics`` is ABI-incompatible with code not using the feature, if
necessary `__sync_*` implementations are available. Code using
`+forced-atomics` is ABI-incompatible with code not using the feature, if
atomic variables cross the ABI boundary.
In either of these cases, the Target in LLVM can claim support for atomics of an
appropriate size, and then implement some subset of the operations via libcalls
to a ``__sync_*`` function. Such functions *must* not use locks in their
implementation, because unlike the ``__atomic_*`` routines used by
to a `__sync_*` function. Such functions *must* not use locks in their
implementation, because unlike the `__atomic_*` routines used by
AtomicExpandPass, these may be mixed-and-matched with native instructions by the
target lowering.
@ -609,14 +609,15 @@ there is no issue with having multiple copies included in one binary. Thus,
typically these routines are implemented by the statically-linked compiler
runtime support library.
LLVM will emit a call to an appropriate ``__sync_*`` routine if the target
ISelLowering code has set the corresponding ``ATOMIC_CMPXCHG``, ``ATOMIC_SWAP``,
or ``ATOMIC_LOAD_*`` operation to "Expand", and if it has opted-into the
availability of those library functions via a call to ``initSyncLibcalls()``.
LLVM will emit a call to an appropriate `__sync_*` routine if the target
ISelLowering code has set the corresponding `ATOMIC_CMPXCHG`, `ATOMIC_SWAP`,
or `ATOMIC_LOAD_*` operation to "Expand", and if it has opted-into the
availability of those library functions via a call to `initSyncLibcalls()`.
The full set of functions that may be called by LLVM is (for ``N`` being 1, 2,
4, 8, or 16)::
The full set of functions that may be called by LLVM is (for `N` being 1, 2,
4, 8, or 16):
```
iN __sync_val_compare_and_swap_N(iN *ptr, iN expected, iN desired)
iN __sync_lock_test_and_set_N(iN *ptr, iN val)
iN __sync_fetch_and_add_N(iN *ptr, iN val)
@ -629,30 +630,33 @@ The full set of functions that may be called by LLVM is (for ``N`` being 1, 2,
iN __sync_fetch_and_umax_N(iN *ptr, iN val)
iN __sync_fetch_and_min_N(iN *ptr, iN val)
iN __sync_fetch_and_umin_N(iN *ptr, iN val)
```
This list doesn't include any function for atomic load or store; all known
architectures support atomic loads and stores directly (possibly by emitting a
fence on either side of a normal load or store.)
There's also, somewhat separately, the possibility to lower ``ATOMIC_FENCE`` to
``__sync_synchronize()``. This may happen or not happen independent of all the
above, controlled purely by ``setOperationAction(ISD::ATOMIC_FENCE, ...)``.
There's also, somewhat separately, the possibility to lower `ATOMIC_FENCE` to
`__sync_synchronize()`. This may happen or not happen independent of all the
above, controlled purely by `setOperationAction(ISD::ATOMIC_FENCE, ...)`.
On AArch64, a variant of the __sync_* routines is used which contain the memory
On AArch64, a variant of the `__sync_*` routines is used which contain the memory
order as part of the function name. These routines may determine at runtime
whether the single-instruction atomic operations which were introduced as part
of AArch64 Large System Extensions "LSE" instruction set are available, or if
it needs to fall back to an LL/SC loop. The following helper functions are
implemented in both ``compiler-rt`` and ``libgcc`` libraries
(``N`` is one of 1, 2, 4, 8, and ``M`` is one of 1, 2, 4, 8 and 16, and
``ORDER`` is one of 'relax', 'acq', 'rel', 'acq_rel')::
implemented in both `compiler-rt` and `libgcc` libraries
(`N` is one of 1, 2, 4, 8, and `M` is one of 1, 2, 4, 8 and 16, and
`ORDER` is one of 'relax', 'acq', 'rel', 'acq_rel'):
```
iM __aarch64_casM_ORDER(iM expected, iM desired, iM *ptr)
iN __aarch64_swpN_ORDER(iN val, iN *ptr)
iN __aarch64_ldaddN_ORDER(iN val, iN *ptr)
iN __aarch64_ldclrN_ORDER(iN val, iN *ptr)
iN __aarch64_ldeorN_ORDER(iN val, iN *ptr)
iN __aarch64_ldsetN_ORDER(iN val, iN *ptr)
```
Please note, if LSE instruction set is specified for AArch64 target, then
out-of-line atomics calls are not generated and single-instruction atomic

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,214 +1,186 @@
========================================================
Architecture & Platform Information for Compiler Writers
========================================================
# Architecture & Platform Information for Compiler Writers
.. contents::
:local:
```{contents}
:local:
```
.. note::
```{note}
This document is a work-in-progress. Additions and clarifications are
welcome.
```
This document is a work-in-progress. Additions and clarifications are
welcome.
## Hardware
Hardware
========
### AArch64 & ARM
AArch64 & ARM
-------------
* [ARMv8-A Architecture Reference Manual](https://developer.arm.com/docs/ddi0487/latest) This document covers both AArch64 and ARM instructions
* `ARMv8-A Architecture Reference Manual <https://developer.arm.com/docs/ddi0487/latest>`_ This document covers both AArch64 and ARM instructions
* [ARMv7-A Architecture Reference Manual](https://developer.arm.com/docs/ddi0406/latest) This has some useful info on what is supported by older architecture versions.
* `ARMv7-A Architecture Reference Manual <https://developer.arm.com/docs/ddi0406/latest>`_ This has some useful info on what is supported by older architecture versions.
* [ARMv7-M Architecture Reference Manual](https://developer.arm.com/docs/ddi0403/latest) This covers the Thumb2-only microcontrollers
* `ARMv7-M Architecture Reference Manual <https://developer.arm.com/docs/ddi0403/latest>`_ This covers the Thumb2-only microcontrollers
* [ARMv6-M Architecture Reference Manual](https://developer.arm.com/docs/ddi0419/latest) This covers the Thumb1-only microcontrollers
* `ARMv6-M Architecture Reference Manual <https://developer.arm.com/docs/ddi0419/latest>`_ This covers the Thumb1-only microcontrollers
* [ARM C Language Extensions](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf)
* `ARM C Language Extensions <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf>`_
* [ARM NEON Intrinsics Reference](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073b/IHI0073B_arm_neon_intrinsics_ref.pdf)
* `ARM NEON Intrinsics Reference <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073b/IHI0073B_arm_neon_intrinsics_ref.pdf>`_
* AArch32 [ABI Addenda and Errata](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf)
* AArch32 `ABI Addenda and Errata <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf>`_
* [Cortex-A57 Software Optimization Guide](http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf)
* `Cortex-A57 Software Optimization Guide <http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf>`_
* [Run-time ABI for the ARM Architecture](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf) This documents the `__aeabi_*` helper functions.
* `Run-time ABI for the ARM Architecture <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf>`_ This documents the __aeabi_* helper functions.
### Itanium (ia64)
Itanium (ia64)
--------------
* [Itanium documentation](http://developer.intel.com/design/itanium2/documentation.htm)
* `Itanium documentation <http://developer.intel.com/design/itanium2/documentation.htm>`_
### Lanai
Lanai
-----
* [Lanai Instruction Set Architecture](http://g.co/lanai/isa)
* `Lanai Instruction Set Architecture <http://g.co/lanai/isa>`_
### MIPS
MIPS
----
* [MIPS Processor Architecture](https://www.mips.com/products/)
* `MIPS Processor Architecture <https://www.mips.com/products/>`_
* [MIPS 64-bit ELF Object File Specification](https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf)
* `MIPS 64-bit ELF Object File Specification <https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf>`_
### PowerPC
PowerPC
-------
#### IBM - Official manuals and docs
IBM - Official manuals and docs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* [Power Instruction Set Architecture, Version 3.0B](https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0)
* `Power Instruction Set Architecture, Version 3.0B <https://openpowerfoundation.org/?resource_lib=power-isa-version-3-0>`_
* [POWER9 Processor User's Manual](https://openpowerfoundation.org/?resource_lib=power9-processor-users-manual)
* `POWER9 Processor User's Manual <https://openpowerfoundation.org/?resource_lib=power9-processor-users-manual>`_
* [Power Instruction Set Architecture, Version 2.07B](https://openpowerfoundation.org/?resource_lib=ibm-power-isa-version-2-07-b)
* `Power Instruction Set Architecture, Version 2.07B <https://openpowerfoundation.org/?resource_lib=ibm-power-isa-version-2-07-b>`_
* [POWER8 Processor User's Manual](https://openpowerfoundation.org/?resource_lib=power8-processor-users-manual)
* `POWER8 Processor User's Manual <https://openpowerfoundation.org/?resource_lib=power8-processor-users-manual>`_
* [Power Instruction Set Architecture, Versions 2.03 through 2.06 (Internet Archive)](https://web.archive.org/web/20121124005736/https://www.power.org/technology-introduction/standards-specifications)
* `Power Instruction Set Architecture, Versions 2.03 through 2.06 (Internet Archive) <https://web.archive.org/web/20121124005736/https://www.power.org/technology-introduction/standards-specifications>`_
* [IBM AIX 7.2 POWER Assembly Reference](https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/assembler/alangref_kickoff.html)
* `IBM AIX 7.2 POWER Assembly Reference <https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/assembler/alangref_kickoff.html>`_
* [IBM AIX/5L for POWER Assembly Reference](http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixassem/alangref/alangreftfrm.htm)
* `IBM AIX/5L for POWER Assembly Reference <http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixassem/alangref/alangreftfrm.htm>`_
#### Embedded PowerPC Processors manuals and docs
Embedded PowerPC Processors manuals and docs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* [Book E: Enhanced PowerPC Architecture](https://www.nxp.com/docs/en/user-guide/BOOK_EUM.pdf)
* `Book E: Enhanced PowerPC Architecture <https://www.nxp.com/docs/en/user-guide/BOOK_EUM.pdf>`_
* [EREF: A Programmer's Reference Manual for Freescale Embedded Processors (EREFRM)](https://www.nxp.com/files-static/32bit/doc/ref_manual/EREF_RM.pdf)
* `EREF: A Programmer's Reference Manual for Freescale Embedded Processors (EREFRM) <https://www.nxp.com/files-static/32bit/doc/ref_manual/EREF_RM.pdf>`_
* [Signal Processing Engine (SPE) Programming Environments Manual: A Supplement to the EREF](https://www.nxp.com/docs/en/reference-manual/SPEPEM.pdf)
* `Signal Processing Engine (SPE) Programming Environments Manual: A Supplement to the EREF <https://www.nxp.com/docs/en/reference-manual/SPEPEM.pdf>`_
* [Variable-Length Encoding (VLE) Programming Environments Manual: A Supplement to the EREF](https://www.nxp.com/docs/en/reference-manual/VLEPEM.pdf)
* `Variable-Length Encoding (VLE) Programming Environments Manual: A Supplement to the EREF <https://www.nxp.com/docs/en/reference-manual/VLEPEM.pdf>`_
#### Other documents, collections, notes
Other documents, collections, notes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* [PowerPC Compiler Writer's Guide](http://www.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF7785256996007558C6)
* [Intro to PowerPC Architecture](http://www.ibm.com/developerworks/linux/library/l-powarch/)
* [Various IBM specifications and white papers](https://www.power.org/documentation/?document_company=105&document_category=all&publish_year=all&grid_order=DESC&grid_sort=title)
* [PowerPC ABI documents](http://penguinppc.org/dev/#library)
* [PowerPC64 alignment of long doubles (from GCC)](http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00997.html)
* [Long branch stubs for powerpc64-linux (from binutils)](http://sources.redhat.com/ml/binutils/2002-04/msg00573.html)
* `PowerPC Compiler Writer's Guide <http://www.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF7785256996007558C6>`_
* `Intro to PowerPC Architecture <http://www.ibm.com/developerworks/linux/library/l-powarch/>`_
* `Various IBM specifications and white papers <https://www.power.org/documentation/?document_company=105&document_category=all&publish_year=all&grid_order=DESC&grid_sort=title>`_
* `PowerPC ABI documents <http://penguinppc.org/dev/#library>`_
* `PowerPC64 alignment of long doubles (from GCC) <http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00997.html>`_
* `Long branch stubs for powerpc64-linux (from binutils) <http://sources.redhat.com/ml/binutils/2002-04/msg00573.html>`_
### AMDGPU
AMDGPU
------
Refer to {doc}`AMDGPUUsage` for additional documentation.
Refer to :doc:`AMDGPUUsage` for additional documentation.
### RISC-V
* [RISC-V User-Level ISA Specification](https://riscv.org/specifications/)
RISC-V
------
* `RISC-V User-Level ISA Specification <https://riscv.org/specifications/>`_
### C-SKY
* [C-SKY Architecture User Guide](https://github.com/c-sky/csky-doc/blob/master/CSKY%20Architecture%20user_guide.pdf)
* [C-SKY V2 ABI](https://github.com/c-sky/csky-doc/blob/master/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf)
C-SKY
------
* `C-SKY Architecture User Guide <https://github.com/c-sky/csky-doc/blob/master/CSKY%20Architecture%20user_guide.pdf>`_
* `C-SKY V2 ABI <https://github.com/c-sky/csky-doc/blob/master/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf>`_
### LoongArch
* [LoongArch Reference Manual - Volume 1: Basic Architecture](https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html)
* [LoongArch ELF ABI specification](https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html)
LoongArch
---------
* `LoongArch Reference Manual - Volume 1: Basic Architecture <https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html>`_
* `LoongArch ELF ABI specification <https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html>`_
### SPARC
SPARC
-----
* [SPARC standards](http://sparc.org/standards)
* [SPARC V9 ABI](http://sparc.org/standards/64.psabi.1.35.ps.Z)
* [SPARC V8 ABI](http://sparc.org/standards/psABI3rd.pdf)
* `SPARC standards <http://sparc.org/standards>`_
* `SPARC V9 ABI <http://sparc.org/standards/64.psabi.1.35.ps.Z>`_
* `SPARC V8 ABI <http://sparc.org/standards/psABI3rd.pdf>`_
### SystemZ
SystemZ
-------
* [z/Architecture Principles of Operation (registration required, free sign-up)](http://www-01.ibm.com/support/docview.wss?uid=isg2b9de5f05a9d57819852571c500428f9a)
* `z/Architecture Principles of Operation (registration required, free sign-up) <http://www-01.ibm.com/support/docview.wss?uid=isg2b9de5f05a9d57819852571c500428f9a>`_
### VE
VE
--
* [NEC SX-Aurora TSUBASA ISA Guide](https://www.hpc.nec/documents/guide/pdfs/Aurora_ISA_guide.pdf)
* [NEC SX-Aurora TSUBASA manuals and documentation](https://www.hpc.nec/documentation)
* `NEC SX-Aurora TSUBASA ISA Guide <https://www.hpc.nec/documents/guide/pdfs/Aurora_ISA_guide.pdf>`_
* `NEC SX-Aurora TSUBASA manuals and documentation <https://www.hpc.nec/documentation>`_
### X86
X86
---
* [AMD processor manuals](http://developer.amd.com/resources/developer-guides-manuals/)
* [Intel 64 and IA-32 manuals](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html)
* [Intel Itanium documentation](http://www.intel.com/design/itanium/documentation.htm?iid=ipp_srvr_proc_itanium2+techdocs)
* [X86 and X86-64 SysV psABI](https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI)
* [Calling conventions for different C++ compilers and operating systems](http://www.agner.org/optimize/calling_conventions.pdf)
* `AMD processor manuals <http://developer.amd.com/resources/developer-guides-manuals/>`_
* `Intel 64 and IA-32 manuals <http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html>`_
* `Intel Itanium documentation <http://www.intel.com/design/itanium/documentation.htm?iid=ipp_srvr_proc_itanium2+techdocs>`_
* `X86 and X86-64 SysV psABI <https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI>`_
* `Calling conventions for different C++ compilers and operating systems <http://www.agner.org/optimize/calling_conventions.pdf>`_
### XCore
XCore
-----
* [The XMOS XS1 Architecture (ISA)](https://www.xmos.ai/download/The-XMOS-XS1-Architecture%281.0%29.pdf)
* [The XMOS XS2 Architecture (ISA)](https://www.xmos.ai/download/xCORE-200:-The-XMOS-XS2-Architecture-%28ISA%29%281.1%29.pdf)
* [Tools Development Guide (includes ABI)](https://www.xmos.ai/download/Tools-Development-Guide%282.1%29.pdf)
* `The XMOS XS1 Architecture (ISA) <https://www.xmos.ai/download/The-XMOS-XS1-Architecture%281.0%29.pdf>`_
* `The XMOS XS2 Architecture (ISA) <https://www.xmos.ai/download/xCORE-200:-The-XMOS-XS2-Architecture-%28ISA%29%281.1%29.pdf>`_
* `Tools Development Guide (includes ABI) <https://www.xmos.ai/download/Tools-Development-Guide%282.1%29.pdf>`_
### Hexagon
Hexagon
-------
* [Hexagon Programmer's Reference Manuals and Hexagon ABI Specification (registration required, free sign-up)](https://developer.qualcomm.com/software/hexagon-dsp-sdk/tools)
* `Hexagon Programmer's Reference Manuals and Hexagon ABI Specification (registration required, free sign-up) <https://developer.qualcomm.com/software/hexagon-dsp-sdk/tools>`_
### Other relevant lists
Other relevant lists
--------------------
* [GCC reading list](http://gcc.gnu.org/readings.html)
* `GCC reading list <http://gcc.gnu.org/readings.html>`_
## ABI
ABI
===
* [System V Application Binary Interface](http://www.sco.com/developers/gabi/latest/contents.html)
* [Itanium C++ ABI](http://itanium-cxx-abi.github.io/cxx-abi/) (This is used for all non-Windows targets.)
* `System V Application Binary Interface <http://www.sco.com/developers/gabi/latest/contents.html>`_
* `Itanium C++ ABI <http://itanium-cxx-abi.github.io/cxx-abi/>`_ (This is used for all non-Windows targets.)
### Linux
Linux
-----
* [Linux extensions to gabi](https://github.com/hjl-tools/linux-abi/wiki/Linux-Extensions-to-gABI)
* [64-Bit ELF V2 ABI Specification: Power Architecture](https://openpowerfoundation.org/?resource_lib=64-bit-elf-v2-abi-specification-power-architecture)
* `Linux extensions to gabi <https://github.com/hjl-tools/linux-abi/wiki/Linux-Extensions-to-gABI>`_
* `64-Bit ELF V2 ABI Specification: Power Architecture <https://openpowerfoundation.org/?resource_lib=64-bit-elf-v2-abi-specification-power-architecture>`_
* [OpenPOWER ELFv2 Errata: ELFv2 ABI Version 1.4](https://openpowerfoundation.org/?resource_lib=openpower-elfv2-errata-elfv2-abi-version-1-4)
* [PowerPC 64-bit ELF ABI Supplement](http://www.linuxbase.org/spec/ELF/ppc64/)
* [Procedure Call Standard for the AArch64 Architecture](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf)
* [Procedure Call Standard for the ARM Architecture](https://developer.arm.com/docs/ihi0042/latest)
* [ELF for the ARM Architecture](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf)
* [ELF for the ARM 64-bit Architecture (AArch64)](http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf)
* [System z ELF ABI Supplement](http://legacy.redhat.com/pub/redhat/linux/7.1/es/os/s390x/doc/lzsabi0.pdf)
* `OpenPOWER ELFv2 Errata: ELFv2 ABI Version 1.4 <https://openpowerfoundation.org/?resource_lib=openpower-elfv2-errata-elfv2-abi-version-1-4>`_
* `PowerPC 64-bit ELF ABI Supplement <http://www.linuxbase.org/spec/ELF/ppc64/>`_
* `Procedure Call Standard for the AArch64 Architecture <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf>`_
* `Procedure Call Standard for the ARM Architecture <https://developer.arm.com/docs/ihi0042/latest>`_
* `ELF for the ARM Architecture <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf>`_
* `ELF for the ARM 64-bit Architecture (AArch64) <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056a/IHI0056A_aaelf64.pdf>`_
* `System z ELF ABI Supplement <http://legacy.redhat.com/pub/redhat/linux/7.1/es/os/s390x/doc/lzsabi0.pdf>`_
### macOS
macOS
-----
* [Mach-O Runtime Architecture](http://developer.apple.com/documentation/Darwin/RuntimeArchitecture-date.html)
* [Notes on Mach-O ABI](http://www.unsanity.org/archives/000044.php)
* [ARM64 Function Calling Conventions](https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html)
* `Mach-O Runtime Architecture <http://developer.apple.com/documentation/Darwin/RuntimeArchitecture-date.html>`_
* `Notes on Mach-O ABI <http://www.unsanity.org/archives/000044.php>`_
* `ARM64 Function Calling Conventions <https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html>`_
### Windows
Windows
-------
* [Microsoft PE/COFF Specification](http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx)
* [ARM64 exception handling](https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling)
* [ARM exception handling](https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling)
* [Overview of ARM64 ABI conventions](https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions)
* [Overview of ARM32 ABI Conventions](https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions)
* `Microsoft PE/COFF Specification <http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx>`_
* `ARM64 exception handling <https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling>`_
* `ARM exception handling <https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling>`_
* `Overview of ARM64 ABI conventions <https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions>`_
* `Overview of ARM32 ABI Conventions <https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions>`_
## NVPTX
NVPTX
=====
* `CUDA Documentation <http://docs.nvidia.com/cuda/index.html>`_ includes the PTX
* [CUDA Documentation](http://docs.nvidia.com/cuda/index.html) includes the PTX
ISA and Driver API documentation
SPIR-V
======
## SPIR-V
* `SPIR-V documentation <https://www.khronos.org/registry/SPIR-V/>`_
* [SPIR-V documentation](https://www.khronos.org/registry/SPIR-V/)
Miscellaneous Resources
=======================
## Miscellaneous Resources
* `Executable File Formats <https://wiki.osdev.org/Category:Executable_Formats>`_
* [Executable File Formats](https://wiki.osdev.org/Category:Executable_Formats)
has a list of various executable file formats.
* `GCC prefetch project <http://gcc.gnu.org/projects/prefetch.html>`_ page has a
* [GCC prefetch project](http://gcc.gnu.org/projects/prefetch.html) page has a
good survey of the prefetching capabilities of a variety of modern
processors.

File diff suppressed because it is too large Load diff

View file

@ -1,25 +1,20 @@
.. role:: raw-html(raw)
:format: html
# LLVM Code Coverage Mapping Format
=================================
LLVM Code Coverage Mapping Format
=================================
```{contents}
:local:
```
.. contents::
:local:
Introduction
============
## Introduction
LLVM's code coverage mapping format is used to provide code coverage
analysis using LLVM's and Clang's instrumentation based profiling
(Clang's ``-fprofile-instr-generate`` option).
(Clang's `-fprofile-instr-generate` option).
This document is aimed at those who would like to know how LLVM's code coverage
mapping works under the hood. A prior knowledge of how Clang's profile guided
optimization works is useful, but not required. For those interested in using
LLVM to provide code coverage analysis for their own programs, see the `Clang
documentation <https://clang.llvm.org/docs/SourceBasedCodeCoverage.html>`.
LLVM to provide code coverage analysis for their own programs, see the [Clang
documentation](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html).
We start by briefly describing LLVM's code coverage mapping format and the
way that Clang and LLVM's code coverage tool work with this format. After
@ -27,8 +22,7 @@ the basics are down, more advanced features of the coverage mapping format
are discussed - such as the data structures, LLVM IR representation and
the binary encoding.
High Level Overview
===================
## High Level Overview
LLVM's code coverage mapping format is designed to be a self contained
data format that can be embedded into the LLVM IR and into object files.
@ -39,7 +33,7 @@ after running the instrumented version of the program.
The mapping data is used in two places in the code coverage process:
1. When clang compiles a source file with ``-fcoverage-mapping``, it
1. When clang compiles a source file with `-fcoverage-mapping`, it
generates the mapping information that describes the mapping between the
source ranges and the profiling instrumentation counters.
This information gets embedded into the LLVM IR and conveniently
@ -59,8 +53,7 @@ instead of emitting mapping information for each statement in a function, the
frontend is allowed to group the statements with the same execution count into
regions of code, and emit the mapping information only for those regions.
Advanced Concepts
=================
## Advanced Concepts
The remainder of this guide is meant to give you insight into the way the
coverage mapping format works.
@ -71,23 +64,22 @@ For each function that requires code coverage, the frontend has to create
coverage mapping data that can map between the source code ranges and
the profile instrumentation counters for that function.
Mapping Region
--------------
### Mapping Region
The function's coverage mapping data contains an array of mapping regions.
A mapping region stores the `source code range`_ that is covered by this region,
the `file id <coverage file id_>`_, the `coverage mapping counter`_ and
A mapping region stores the {ref}`source code range` that is covered by this region,
the {ref}`file id <coverage file id>`, the {ref}`coverage mapping counter` and
the region's kind.
There are several kinds of mapping regions:
* Code regions associate portions of source code and `coverage mapping
counters`_. They make up the majority of the mapping regions. They are used
* Code regions associate portions of source code and {ref}`coverage mapping counters <coverage mapping counters>`.
They make up the majority of the mapping regions. They are used
by the code coverage tool to compute the execution counts for lines,
highlight the regions of code that were never executed, and to obtain
the various code coverage statistics for a function.
For example:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int main(int argc, const char *argv[]) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:40 to 9:2</span>
<pre class='highlight' style='line-height:initial;'><span>int main(int argc, const char *argv[]) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:40 to 9:2</span>
<span style='background-color:#4A789C'> </span>
<span style='background-color:#4A789C'> if (argc &gt; 1) </span><span style='background-color:#85C1F5'>{ </span> <span class='c1'>// Code Region from 3:17 to 5:4</span>
<span style='background-color:#85C1F5'> printf("%s\n", argv[1]); </span>
@ -96,46 +88,49 @@ There are several kinds of mapping regions:
<span style='background-color:#F6D55D'> }</span><span style='background-color:#4A789C'> </span>
<span style='background-color:#4A789C'> return 0; </span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
* Skipped regions are used to represent source ranges that were skipped
by Clang's preprocessor. They don't associate with
`coverage mapping counters`_, as the frontend knows that they are never
{ref}`coverage mapping counters`, as the frontend knows that they are never
executed. They are used by the code coverage tool to mark the skipped lines
inside a function as non-code lines that don't have execution counts.
For example:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int main() </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:12 to 6:2</span>
<pre class='highlight' style='line-height:initial;'><span>int main() </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:12 to 6:2</span>
<span style='background-color:#85C1F5'>#ifdef DEBUG </span> <span class='c1'>// Skipped Region from 2:1 to 4:2</span>
<span style='background-color:#85C1F5'> printf("Hello world"); </span>
<span style='background-color:#85C1F5'>#</span><span style='background-color:#4A789C'>endif </span>
<span style='background-color:#4A789C'> return 0; </span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
* Expansion regions are used to represent Clang's macro expansions. They
have an additional property - *expanded file id*. This property can be
used by the code coverage tool to find the mapping regions that are created
as a result of this macro expansion, by checking if their file id matches the
expanded file id. They don't associate with `coverage mapping counters`_,
expanded file id. They don't associate with {ref}`coverage mapping counters`,
as the code coverage tool can determine the execution count for this region
by looking up the execution count of the first region with a corresponding
file id.
For example:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int func(int x) </span><span style='background-color:#4A789C'>{ </span>
<pre class='highlight' style='line-height:initial;'><span>int func(int x) </span><span style='background-color:#4A789C'>{ </span>
<span style='background-color:#4A789C'> #define MAX(x,y) </span><span style='background-color:#85C1F5'>((x) &gt; (y)? </span><span style='background-color:#F6D55D'>(x)</span><span style='background-color:#85C1F5'> : </span><span style='background-color:#F4BA70'>(y)</span><span style='background-color:#85C1F5'>)</span><span style='background-color:#4A789C'> </span>
<span style='background-color:#4A789C'> return </span><span style='background-color:#7FCA9F'>MAX</span><span style='background-color:#4A789C'>(x, 42); </span> <span class='c1'>// Expansion Region from 3:10 to 3:13</span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
* Branch regions associate instrumentable branch conditions in the source code
with a `coverage mapping counter`_ to track how many times an individual
condition evaluated to 'true' and another `coverage mapping counter`_ to
with a {ref}`coverage mapping counter` to track how many times an individual
condition evaluated to 'true' and another {ref}`coverage mapping counter` to
track how many times that condition evaluated to false. Instrumentable
branch conditions may comprise larger boolean expressions using boolean
logical operators. The 'true' and 'false' cases reflect unique branch paths
that can be traced back to the source code.
For example:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int func(int x, int y) {
<pre class='highlight' style='line-height:initial;'><span>int func(int x, int y) {
<span> if (<span style='background-color:#4A789C'>(x &gt; 1)</span> || <span style='background-color:#4A789C'>(y &gt; 3)</span>) {</span> <span class='c1'>// Branch Region from 3:6 to 3:12</span>
<span> </span><span class='c1'>// Branch Region from 3:17 to 3:23</span>
<span> printf("%d\n", x); </span>
@ -144,7 +139,7 @@ There are several kinds of mapping regions:
<span> }</span>
<span> return 0; </span>
<span>}</span>
</pre>`
</pre>
* Decision regions associate multiple branch regions with a boolean
expression in the source code. This information also includes the number of
@ -159,37 +154,34 @@ There are several kinds of mapping regions:
*llvm-cov* to reconstruct the control flow around the conditions in order to
comprehend the full list of potential executable test vectors.
.. _source code range:
(source code range)=
Source Range:
^^^^^^^^^^^^^
#### Source Range:
The source range record contains the starting and ending location of a certain
mapping region. Both locations include the line and the column numbers.
.. _coverage file id:
(coverage file id)=
File ID:
^^^^^^^^
#### File ID:
The file id an integer value that tells us
in which source file or macro expansion is this region located.
It enables Clang to produce mapping information for the code
defined inside macros, like this example demonstrates:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>void func(const char *str) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:28 to 6:2 with file id 0</span>
<pre class='highlight' style='line-height:initial;'><span>void func(const char *str) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Code Region from 1:28 to 6:2 with file id 0</span>
<span style='background-color:#4A789C'> #define PUT </span><span style='background-color:#85C1F5'>printf("%s\n", str)</span><span style='background-color:#4A789C'> </span> <span class='c1'>// 2 Code Regions from 2:15 to 2:34 with file ids 1 and 2</span>
<span style='background-color:#4A789C'> if(*str) </span>
<span style='background-color:#4A789C'> </span><span style='background-color:#F6D55D'>PUT</span><span style='background-color:#4A789C'>; </span> <span class='c1'>// Expansion Region from 4:5 to 4:8 with file id 0 that expands a macro with file id 1</span>
<span style='background-color:#4A789C'> </span><span style='background-color:#F6D55D'>PUT</span><span style='background-color:#4A789C'>; </span> <span class='c1'>// Expansion Region from 5:3 to 5:6 with file id 0 that expands a macro with file id 2</span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
.. _coverage mapping counter:
.. _coverage mapping counters:
(coverage mapping counter)=
(coverage mapping counters)=
Counter:
^^^^^^^^
#### Counter:
A coverage mapping counter can represent a reference to the profile
instrumentation counter. The execution count for a region with such counter
@ -204,7 +196,7 @@ subtracting them from one another.
In the example below, a subtraction expression is used to compute the execution
count for the compound statement that follows the *else* keyword:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int main(int argc, const char *argv[]) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Region's counter is a reference to the profile counter #0</span>
<pre class='highlight' style='line-height:initial;'><span>int main(int argc, const char *argv[]) </span><span style='background-color:#4A789C'>{ </span> <span class='c1'>// Region's counter is a reference to the profile counter #0</span>
<span style='background-color:#4A789C'> </span>
<span style='background-color:#4A789C'> if (argc &gt; 1) </span><span style='background-color:#85C1F5'>{ </span> <span class='c1'>// Region's counter is a reference to the profile counter #1</span>
<span style='background-color:#85C1F5'> printf("%s\n", argv[1]); </span><span> </span>
@ -213,17 +205,17 @@ count for the compound statement that follows the *else* keyword:
<span style='background-color:#F6D55D'> }</span><span style='background-color:#4A789C'> </span>
<span style='background-color:#4A789C'> return 0; </span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
Finally, a coverage mapping counter can also represent an execution count of
of zero. The zero counter is used to provide coverage mapping for
unreachable statements and expressions, like in the example below:
:raw-html:`<pre class='highlight' style='line-height:initial;'><span>int main() </span><span style='background-color:#4A789C'>{ </span>
<pre class='highlight' style='line-height:initial;'><span>int main() </span><span style='background-color:#4A789C'>{ </span>
<span style='background-color:#4A789C'> return 0; </span>
<span style='background-color:#4A789C'> </span><span style='background-color:#85C1F5'>printf("Hello world!\n")</span><span style='background-color:#4A789C'>; </span> <span class='c1'>// Unreachable region's counter is zero</span>
<span style='background-color:#4A789C'>}</span>
</pre>`
</pre>
The zero counters allow the code coverage tool to display proper line execution
counts for the unreachable lines and highlight the unreachable code.
@ -235,8 +227,7 @@ code and refer to two coverage mapping counters, one to track the number of
times the branch condition evaluated to "true", and one to track the number of
times the branch condition evaluated to "false".
LLVM IR Representation
======================
## LLVM IR Representation
The coverage mapping data is stored in the LLVM IR using a global constant
structure variable called *__llvm_coverage_mapping* with the *IPSK_covmap*
@ -244,16 +235,16 @@ section specifier (i.e. ".lcovmap$M" on Windows and "__llvm_covmap" elsewhere).
For example, let’s consider a C file and how it gets compiled to LLVM:
.. _coverage mapping sample:
(coverage mapping sample)=
.. code-block:: c
int foo() {
return 42;
}
int bar() {
return 13;
}
```c
int foo() {
return 42;
}
int bar() {
return 13;
}
```
The coverage mapping variable generated by Clang has 2 fields:
@ -265,19 +256,19 @@ The variable has 8-byte alignment because ld64 cannot always pack symbols from
different object files tightly (the word-level alignment assumption is baked in
too deeply).
.. code-block:: llvm
@__llvm_coverage_mapping = internal constant { { i32, i32, i32, i32 }, [32 x i8] }
```llvm
@__llvm_coverage_mapping = internal constant { { i32, i32, i32, i32 }, [32 x i8] }
{
{ i32, i32, i32, i32 } ; Coverage map header
{
{ i32, i32, i32, i32 } ; Coverage map header
{
i32 0, ; Always 0. In prior versions, the number of affixed function records
i32 32, ; The length of the string that contains the encoded translation unit filenames
i32 0, ; Always 0. In prior versions, the length of the affixed string that contains the encoded coverage mapping data
i32 3, ; Coverage mapping format version
},
[32 x i8] c"..." ; Encoded data (dissected later)
}, section "__llvm_covmap", align 8
i32 0, ; Always 0. In prior versions, the number of affixed function records
i32 32, ; The length of the string that contains the encoded translation unit filenames
i32 0, ; Always 0. In prior versions, the length of the affixed string that contains the encoded coverage mapping data
i32 3, ; Coverage mapping format version
},
[32 x i8] c"..." ; Encoded data (dissected later)
}, section "__llvm_covmap", align 8
```
The current version of the format is version 6.
@ -311,25 +302,24 @@ column end locations was introduced to indicate gap regions.
In version 1, the function record for *foo* was defined as follows:
.. code-block:: llvm
{ i8*, i32, i32, i64 } { i8* getelementptr inbounds ([3 x i8]* @__profn_foo, i32 0, i32 0), ; Function's name
i32 3, ; Function's name length
i32 9, ; Function's encoded coverage mapping data string length
i64 0 ; Function's structural hash
}
```llvm
{ i8*, i32, i32, i64 } { i8* getelementptr inbounds ([3 x i8]* @__profn_foo, i32 0, i32 0), ; Function's name
i32 3, ; Function's name length
i32 9, ; Function's encoded coverage mapping data string length
i64 0 ; Function's structural hash
}
```
In version 2, the function record for *foo* was defined as follows:
.. code-block:: llvm
```llvm
{ i64, i32, i64 } {
i64 0x5cf8c24cdb18bdac, ; Function's name MD5
i32 9, ; Function's encoded coverage mapping data string length
i64 0 ; Function's structural hash
```
{ i64, i32, i64 } {
i64 0x5cf8c24cdb18bdac, ; Function's name MD5
i32 9, ; Function's encoded coverage mapping data string length
i64 0 ; Function's structural hash
Coverage Mapping Header:
------------------------
### Coverage Mapping Header:
As shown above, the coverage mapping header has the following fields:
@ -341,33 +331,31 @@ As shown above, the coverage mapping header has the following fields:
* The format version. The current version is 6 (encoded as a 5).
.. _function records:
(function records)=
Function record:
----------------
### Function record:
A function record is a structure of the following type:
.. code-block:: llvm
{ i64, i32, i64, i64, [? x i8] }
```llvm
{ i64, i32, i64, i64, [? x i8] }
```
It contains the function name's MD5, the length of the encoded mapping data for
that function, the function's structural hash value, the hash of the filenames
in the function's translation unit, and the encoded mapping data.
Dissecting the sample:
^^^^^^^^^^^^^^^^^^^^^^
#### Dissecting the sample:
Here's an overview of the encoded data that was stored in the
IR for the `coverage mapping sample`_ that was shown earlier:
IR for the {ref}`coverage mapping sample <coverage mapping sample>` that was shown earlier:
* The IR contains the following string constant that represents the encoded
coverage mapping data for the sample translation unit:
.. code-block:: llvm
c"\01\15\1Dx\DA\13\D1\0F-N-*\D6/+\CE\D6/\C9-\D0O\CB\CF\D7K\06\00N+\07]"
```llvm
c"\01\15\1Dx\DA\13\D1\0F-N-*\D6/+\CE\D6/\C9-\D0O\CB\CF\D7K\06\00N+\07]"
```
* The string contains values that are encoded in the LEB128 format, which is
used throughout for storing integers. It also contains a compressed payload.
@ -380,32 +368,23 @@ IR for the `coverage mapping sample`_ that was shown earlier:
* The coverage mapping from the first function record is encoded in this string:
.. code-block:: llvm
c"\01\00\00\01\01\01\0C\02\02"
```llvm
c"\01\00\00\01\01\01\0C\02\02"
```
This string consists of the following bytes:
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x01`` | The number of file ids used by this function. There is only one file id used by the mapping data in this function. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x00`` | An index into the filenames array which corresponds to the file "/Users/alex/test.c". |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x00`` | The number of counter expressions used by this function. This function doesn't use any expressions. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x01`` | The number of mapping regions that are stored in an array for the function's file id #0. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x01`` | The coverage mapping counter for the first region in this function. The value of 1 tells us that it's a coverage |
| | mapping counter that is a reference to the profile instrumentation counter with an index of 0. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x01`` | The starting line of the first mapping region in this function. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x0C`` | The starting column of the first mapping region in this function. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x02`` | The ending line of the first mapping region in this function. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| ``0x02`` | The ending column of the first mapping region in this function. |
+----------+-------------------------------------------------------------------------------------------------------------------------+
| Byte | Meaning |
| --- | --- |
| `0x01` | The number of file ids used by this function. There is only one file id used by the mapping data in this function. |
| `0x00` | An index into the filenames array which corresponds to the file "/Users/alex/test.c". |
| `0x00` | The number of counter expressions used by this function. This function doesn't use any expressions. |
| `0x01` | The number of mapping regions that are stored in an array for the function's file id #0. |
| `0x01` | The coverage mapping counter for the first region in this function. The value of 1 tells us that it's a coverage mapping counter that is a reference to the profile instrumentation counter with an index of 0. |
| `0x01` | The starting line of the first mapping region in this function. |
| `0x0C` | The starting column of the first mapping region in this function. |
| `0x02` | The ending line of the first mapping region in this function. |
| `0x02` | The ending column of the first mapping region in this function. |
* The length of the substring that contains the encoded coverage mapping data
for the second function record is also 9. It's structured like the mapping data
@ -414,76 +393,69 @@ IR for the `coverage mapping sample`_ that was shown earlier:
* The two trailing bytes are zeroes and are used to pad the coverage mapping
data to give it the 8-byte alignment.
Encoding
========
## Encoding
The per-function coverage mapping data is encoded as a stream of bytes,
with a simple structure. The structure consists of the encoding
`types <cvmtypes_>`_ like variable-length unsigned integers, that
are used to encode `File ID Mapping`_, `Counter Expressions`_ and
the `Mapping Regions`_.
{ref}`types <cvmtypes>` like variable-length unsigned integers, that
are used to encode {ref}`File ID Mapping`, {ref}`Counter Expressions` and
the {ref}`Mapping Regions`.
The format of the structure follows:
``[file id mapping, counter expressions, mapping regions]``
`[file id mapping, counter expressions, mapping regions]`
The translation unit filenames are encoded using the same encoding
`types <cvmtypes_>`_ as the per-function coverage mapping data, with the
{ref}`types <cvmtypes>` as the per-function coverage mapping data, with the
following structure:
``[numFilenames : LEB128, filename0 : string, filename1 : string, ...]``
`[numFilenames : LEB128, filename0 : string, filename1 : string, ...]`
.. _cvmtypes:
(cvmtypes)=
Types
-----
### Types
This section describes the basic types that are used by the encoding format
and can appear after ``:`` in the ``[foo : type]`` description.
and can appear after `:` in the `[foo : type]` description.
.. _LEB128:
(LEB128)=
LEB128
^^^^^^
#### LEB128
LEB128 is an unsigned integer value that is encoded using DWARF's LEB128
encoding, optimizing for the case where values are small
(1 byte for values less than 128).
.. _CoverageStrings:
(CoverageStrings)=
Strings
^^^^^^^
#### Strings
``[length : LEB128, characters...]``
`[length : LEB128, characters...]`
String values are encoded with a `LEB value <LEB128_>`_ for the length
String values are encoded with a {ref}`LEB value <LEB128>` for the length
of the string and a sequence of bytes for its characters.
.. _file id mapping:
(file id mapping)=
File ID Mapping
---------------
### File ID Mapping
``[numIndices : LEB128, filenameIndex0 : LEB128, filenameIndex1 : LEB128, ...]``
`[numIndices : LEB128, filenameIndex0 : LEB128, filenameIndex1 : LEB128, ...]`
File id mapping in a function's coverage mapping stream
contains the indices into the translation unit's filenames array.
Counter
-------
### Counter
``[value : LEB128]``
`[value : LEB128]`
A `coverage mapping counter`_ is stored in a single `LEB value <LEB128_>`_.
It is composed of two things --- the `tag <counter-tag_>`_
which is stored in the lowest 2 bits, and the `counter data`_ which is stored
A {ref}`coverage mapping counter` is stored in a single {ref}`LEB value <LEB128>`.
It is composed of two things --- the {ref}`tag <counter-tag>`
which is stored in the lowest 2 bits, and the {ref}`counter data` which is stored
in the remaining bits.
.. _counter-tag:
(counter-tag)=
Tag:
^^^^
#### Tag:
The counter's tag encodes the counter's kind
and, if the counter is an expression, the expression's kind.
@ -497,10 +469,9 @@ The possible tag values are:
* 3 - The counter is an addition expression.
.. _counter data:
(counter data)=
Data:
^^^^^
#### Data:
The counter's data is interpreted in the following manner:
@ -509,24 +480,22 @@ The counter's data is interpreted in the following manner:
* When the counter is an expression, then the counter's data
is the index into the array of counter expressions.
.. _Counter Expressions:
(Counter Expressions)=
Counter Expressions
-------------------
### Counter Expressions
``[numExpressions : LEB128, expr0LHS : LEB128, expr0RHS : LEB128, expr1LHS : LEB128, expr1RHS : LEB128, ...]``
`[numExpressions : LEB128, expr0LHS : LEB128, expr0RHS : LEB128, expr1LHS : LEB128, expr1RHS : LEB128, ...]`
Counter expressions consist of two counters as they
represent binary arithmetic operations.
The expression's kind is determined from the `tag <counter-tag_>`_ of the
The expression's kind is determined from the {ref}`tag <counter-tag>` of the
counter that references this expression.
.. _Mapping Regions:
(Mapping Regions)=
Mapping Regions
---------------
### Mapping Regions
``[numRegionArrays : LEB128, regionsForFile0, regionsForFile1, ...]``
`[numRegionArrays : LEB128, regionsForFile0, regionsForFile1, ...]`
The mapping regions are stored in an array of sub-arrays where every
region in a particular sub-array has the same file id.
@ -535,34 +504,31 @@ The file id for a sub-array of regions is the index of that
sub-array in the main array e.g. The first sub-array will have the file id
of 0.
Sub-Array of Regions
^^^^^^^^^^^^^^^^^^^^
#### Sub-Array of Regions
``[numRegions : LEB128, region0, region1, ...]``
`[numRegions : LEB128, region0, region1, ...]`
The mapping regions for a specific file id are stored in an array that is
sorted in an ascending order by the region's starting location.
Mapping Region
^^^^^^^^^^^^^^
#### Mapping Region
``[header, source range]``
`[header, source range]`
The mapping region record contains two sub-records ---
the `header`_, which stores the counter and/or the region's kind,
and the `source range`_ that contains the starting and ending
the {ref}`header`, which stores the counter and/or the region's kind,
and the {ref}`source range` that contains the starting and ending
location of this region.
.. _header:
(header)=
Header
^^^^^^
#### Header
``[counter]``
`[counter]`
or
``[pseudo-counter]``
`[pseudo-counter]`
The header encodes the region's counter and the region's kind. A branch region
will encode two counters.
@ -571,18 +537,16 @@ The value of the counter's tag distinguishes between the counters and
pseudo-counters --- if the tag is zero, than this header contains a
pseudo-counter, otherwise this header contains an ordinary counter.
Counter:
""""""""
##### Counter:
A mapping region whose header has a counter with a non-zero tag is
a code region.
Pseudo-Counter:
"""""""""""""""
##### Pseudo-Counter:
``[value : LEB128]``
`[value : LEB128]`
A pseudo-counter is stored in a single `LEB value <LEB128_>`_, just like
A pseudo-counter is stored in a single {ref}`LEB value <LEB128>`, just like
the ordinary counter. It has the following interpretation:
* bits 0-1: tag, which is always 0.
@ -600,12 +564,11 @@ the ordinary counter. It has the following interpretation:
* 2 - This mapping region is a skipped region.
* 4 - This mapping region is a branch region.
.. _source range:
(source range)=
Source Range
^^^^^^^^^^^^
#### Source Range
``[deltaLineStart : LEB128, columnStart : LEB128, numLines : LEB128, columnEnd : LEB128]``
`[deltaLineStart : LEB128, columnStart : LEB128, numLines : LEB128, columnEnd : LEB128]`
The source range record contains the following fields:
@ -624,69 +587,65 @@ The source range record contains the following fields:
the current mapping region is a gap area. A count for a gap area is only used
as the line execution count if there are no other regions on a line.
Testing Format
==============
## Testing Format
.. warning::
This section is for the LLVM developers who are working on ``llvm-cov`` only.
```{warning}
This section is for the LLVM developers who are working on `llvm-cov` only.
```
``llvm-cov`` uses a special file format (called ``.covmapping`` below) for
`llvm-cov` uses a special file format (called `.covmapping` below) for
testing purposes. This format is private and should have no use for general
users. As a developer, you can get such files by the ``convert-for-testing``
subcommand of ``llvm-cov``.
users. As a developer, you can get such files by the `convert-for-testing`
subcommand of `llvm-cov`.
The structure of the ``.covmapping`` files follows:
The structure of the `.covmapping` files follows:
``[magicNumber : u64, version : u64, profileNames, coverageMapping, coverageRecords]``
`[magicNumber : u64, version : u64, profileNames, coverageMapping, coverageRecords]`
Magic Number and Version
------------------------
### Magic Number and Version
The magic is ``0x6d766f636d766c6c``, which is the ASCII string
``llvmcovm`` in little-endian.
The magic is `0x6d766f636d766c6c`, which is the ASCII string
`llvmcovm` in little-endian.
There are two versions for now:
- Version1, encoded as ``0x6174616474736574`` (ASCII string ``testdata``).
- Version1, encoded as `0x6174616474736574` (ASCII string `testdata`).
- Version2, encoded as 1.
The only difference between Version1 and Version2 is in the encoding of the
``coverageMapping`` fields, which is explained later.
`coverageMapping` fields, which is explained later.
Profile Names
-------------
### Profile Names
``profileNames``, ``coverageMapping`` and ``coverageRecords`` are 3 sections
`profileNames`, `coverageMapping` and `coverageRecords` are 3 sections
extracted from the original binary file.
``profileNames`` encodes the size, address and the raw data of the section:
`profileNames` encodes the size, address and the raw data of the section:
``[profileNamesSize : LEB128, profileNamesAddr : LEB128, profileNamesData : bytes]``
`[profileNamesSize : LEB128, profileNamesAddr : LEB128, profileNamesData : bytes]`
Coverage Mapping
----------------
### Coverage Mapping
This field is padded with zero bytes to make it 8-byte aligned.
``coverageMapping`` contains the records of the source files. In version 1,
`coverageMapping` contains the records of the source files. In version 1,
only one record is stored:
``[padding : bytes, coverageMappingData : bytes]``
`[padding : bytes, coverageMappingData : bytes]`
Version 2 relaxes this restriction by encoding the size of
``coverageMappingData`` as a LEB128 number before the data:
`coverageMappingData` as a LEB128 number before the data:
``[coverageMappingSize : LEB128, padding : bytes, coverageMappingData : bytes]``
`[coverageMappingSize : LEB128, padding : bytes, coverageMappingData : bytes]`
The current version is 2.
Coverage Records
----------------
### Coverage Records
This field is padded with zero bytes to make it 8-byte aligned.
``coverageRecords`` is encoded as:
`coverageRecords` is encoded as:
``[padding : bytes, coverageRecordsData : bytes]``
`[padding : bytes, coverageRecordsData : bytes]`
The rest data in the file is considered as the ``coverageRecordsData``.
The rest data in the file is considered as the `coverageRecordsData`.

View file

@ -1,125 +1,123 @@
==============
Debugging LLVM
==============
# Debugging LLVM
This document is a collection of tips and tricks for debugging LLVM
using a source-level debugger. The assumption is that you are trying to
figure out the root cause of a miscompilation in the program that you
are compiling.
Extract and rerun the compile command
=====================================
## Extract and rerun the compile command
Extract the Clang command that produces the buggy code. The way to do
this depends on the build system used by your program.
- For Ninja-based build systems, you can pass ``-t commands`` to Ninja
- For Ninja-based build systems, you can pass `-t commands` to Ninja
and filter the output by the targeted source file name. For example:
``ninja -t commands myprogram | grep path/to/file.cpp``.
`ninja -t commands myprogram | grep path/to/file.cpp`.
- For Bazel-based build systems using Bazel 9 or newer, you can pass
``--output=commands`` to the ``bazel aquery`` subcommand for
a similar result. For example: ``bazel aquery --output=commands
'deps(//myprogram)' | grep path/to/file.cpp``. Build commands must
`--output=commands` to the `bazel aquery` subcommand for
a similar result. For example: `bazel aquery --output=commands
'deps(//myprogram)' | grep path/to/file.cpp`. Build commands must
generally be run from a subdirectory of the source directory named
``bazel-$PROJECTNAME``. Bazel typically makes the target paths of
``-o`` and ``-MF`` read-only when running commands outside of a build,
`bazel-$PROJECTNAME`. Bazel typically makes the target paths of
`-o` and `-MF` read-only when running commands outside of a build,
so it may be necessary to change or remove these flags.
- A method that should work with any build system is to build your program
under `Bear <https://github.com/rizsotto/Bear>`_ and look for the
compile command in the resulting ``compile_commands.json`` file.
under [Bear] and look for the
compile command in the resulting `compile_commands.json` file.
Once you have the command you can use the following steps to debug
it. Note that any flags mentioned later in this document are LLVM flags
so they must be prefixed with ``-mllvm`` when passed to the Clang driver,
e.g. ``-mllvm -print-after-all``.
so they must be prefixed with `-mllvm` when passed to the Clang driver,
e.g. `-mllvm -print-after-all`.
Understanding the source of the issue
=====================================
## Understanding the source of the issue
If you have a miscompilation introduced by a pass, it is
frequently possible to identify the pass where things go wrong
by searching a pass-by-pass printout, which is enabled using the
``-print-after-all`` flag. Pipe stderr into ``less`` (append ``2>&1 |
less`` to command line) and use text search to move between passes
(e.g. type ``/Dump After<Enter>``, ``n`` to move to next pass,
``N`` to move to previous pass). If the name of the function
`-print-after-all` flag. Pipe stderr into `less` (append `2>&1 |
less` to command line) and use text search to move between passes
(e.g. type `/Dump After<Enter>`, `n` to move to next pass,
`N` to move to previous pass). If the name of the function
containing the buggy IR is known, you can filter the output by passing
``-filter-print-funcs=functionname``. You can sometimes pass ``-debug`` to
get useful details about what passes are doing. See also `PrintPasses.cpp
<https://github.com/llvm/llvm-project/blob/main/llvm/lib/IR/PrintPasses.cpp>`_
`-filter-print-funcs=functionname`. You can sometimes pass `-debug` to
get useful details about what passes are doing. See also [PrintPasses.cpp]
for more useful options.
Creating a debug build of LLVM
==============================
## Creating a debug build of LLVM
The subsequent debugging steps require a debug build of LLVM. Pass the
``-DCMAKE_BUILD_TYPE=Debug`` to CMake in a separate build tree to create
`-DCMAKE_BUILD_TYPE=Debug` to CMake in a separate build tree to create
a debug build.
Understanding where an instruction came from
============================================
## Understanding where an instruction came from
A common debugging task involves understanding which part of the code
introduced a buggy instruction. The pass-by-pass dump is sometimes enough,
but for complex or unfamiliar passes, more information is often required.
The first step is to record a run of the debug build of Clang under `rr
<https://rr-project.org>`_ passing the LLVM flag ``-print-inst-addrs``
together with ``-print-after-all`` and any desired filters. This will
The first step is to record a run of the debug build of Clang under [rr]
passing the LLVM flag `-print-inst-addrs`
together with `-print-after-all` and any desired filters. This will
cause each instruction printed by LLVM to be suffixed with a comment
showing the address of the ``Instruction`` object. You can then replay
the run of Clang with ``rr replay``. Because ``rr`` is deterministic,
showing the address of the `Instruction` object. You can then replay
the run of Clang with `rr replay`. Because `rr` is deterministic,
the instruction will receive the same address during the replay, so
you can break on the instruction's construction using a conditional
breakpoint that checks for the address printed by LLVM, with commands
such as the following:
.. code-block:: text
b Instruction::Instruction if this == 0x12345678
```text
b Instruction::Instruction if this == 0x12345678
```
When the breakpoint is hit, you will likely be at the location where
the instruction was created, so you can unwind the stack with ``bt``
the instruction was created, so you can unwind the stack with `bt`
to see the stack trace. It is also possible that an instruction was
created multiple times at the same address, so you may need to continue
until reaching the desired location, but in the author's experience this
is unlikely to occur.
Similar flags exist for the backend: ``-print-sdnode-addrs`` for
printing ``SDNode`` addresses, and ``-print-mi-addrs`` for printing
``MachineInstr`` addresses.
Similar flags exist for the backend: `-print-sdnode-addrs` for
printing `SDNode` addresses, and `-print-mi-addrs` for printing
`MachineInstr` addresses.
Identifying the source locations of instructions
================================================
## Identifying the source locations of instructions
To identify the source location that caused a particular instruction
to be created, you can pass the LLVM flag ``-print-inst-debug-locs``
to be created, you can pass the LLVM flag `-print-inst-debug-locs`
and each instruction printed by LLVM is suffixed with the file and line
number of the instruction according to the debug information. Note that
this requires debug information to be enabled (e.g. pass ``-g`` to Clang).
this requires debug information to be enabled (e.g. pass `-g` to Clang).
LLDB Data Formatters
====================
## LLDB Data Formatters
A handful of `LLDB data formatters
<https://lldb.llvm.org/resources/dataformatters.html>`__ are
A handful of [LLDB data formatters] are
provided for some of the core LLVM libraries. To use them, execute the
following (or add it to your ``~/.lldbinit``)::
following (or add it to your `~/.lldbinit`):
command script import /path/to/llvm/utils/lldbDataFormatters.py
```text
command script import /path/to/llvm/utils/lldbDataFormatters.py
```
GDB pretty printers
===================
## GDB pretty printers
A handful of `GDB pretty printers
<https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html>`__ are
A handful of [GDB pretty printers] are
provided for some of the core LLVM libraries. To use them, execute the
following (or add it to your ``~/.gdbinit``)::
following (or add it to your `~/.gdbinit`):
source /path/to/llvm/utils/gdb-scripts/prettyprinters.py
```text
source /path/to/llvm/utils/gdb-scripts/prettyprinters.py
```
It also might be handy to enable the `print pretty
<https://sourceware.org/gdb/current/onlinedocs/gdb.html/Print-Settings.html>`__
It also might be handy to enable the [print pretty]
option to avoid data structures being printed as a big block of text.
[Bear]: https://github.com/rizsotto/Bear
[PrintPasses.cpp]: https://github.com/llvm/llvm-project/blob/main/llvm/lib/IR/PrintPasses.cpp
[rr]: https://rr-project.org
[LLDB data formatters]: https://lldb.llvm.org/resources/dataformatters.html
[GDB pretty printers]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html
[print pretty]: https://sourceware.org/gdb/current/onlinedocs/gdb.html/Print-Settings.html

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,45 +1,44 @@
================================
Frequently Asked Questions (FAQ)
================================
# Frequently Asked Questions (FAQ)
.. contents::
:local:
```{contents}
:local:
```
License
=======
## License
### Can I modify LLVM source code and redistribute the modified source?
Can I modify LLVM source code and redistribute the modified source?
-------------------------------------------------------------------
Yes. The modified source distribution must retain the copyright notice and
follow the conditions listed in the `Apache License v2.0 with LLVM Exceptions
<https://github.com/llvm/llvm-project/blob/main/llvm/LICENSE.TXT>`_.
follow the conditions listed in the [Apache License v2.0 with LLVM
Exceptions][llvm-license].
[llvm-license]: https://github.com/llvm/llvm-project/blob/main/llvm/LICENSE.TXT
Can I modify the LLVM source code and redistribute binaries or other tools based on it, without redistributing the source?
--------------------------------------------------------------------------------------------------------------------------
### Can I modify the LLVM source code and redistribute binaries or other tools based on it, without redistributing the source?
Yes. This is why we distribute LLVM under a less restrictive license than GPL,
as explained in the first question above.
Can I use AI coding tools, such as GitHub co-pilot, to write LLVM patches?
--------------------------------------------------------------------------
### Can I use AI coding tools, such as GitHub co-pilot, to write LLVM patches?
Yes, as long as the resulting work can be licensed under the project license, as
covered in the :doc:`DeveloperPolicy`. Using an AI tool to reproduce copyrighted
covered in the {doc}`DeveloperPolicy`. Using an AI tool to reproduce copyrighted
work does not rinse it of copyright and grant you the right to relicense it.
Source Code
===========
## Source Code
### In what language is LLVM written?
In what language is LLVM written?
---------------------------------
All of the LLVM tools and libraries are written in C++ with extensive use of
the STL.
How portable is the LLVM source code?
-------------------------------------
### How portable is the LLVM source code?
The LLVM source code should be portable to most modern Unix-like operating
systems. LLVM also has excellent support on Windows systems.
Most of the code is written in standard C++ with operating system
@ -47,45 +46,42 @@ services abstracted to a support library. The tools required to build and
test LLVM have been ported to a plethora of platforms.
What API do I use to store a value to one of the virtual registers in LLVM IR's SSA representation?
---------------------------------------------------------------------------------------------------
### What API do I use to store a value to one of the virtual registers in LLVM IR's SSA representation?
In short: you can't. It's actually kind of a silly question once you understand
what's going on. Basically, in code like:
.. code-block:: llvm
```llvm
%result = add i32 %foo, %bar
```
%result = add i32 %foo, %bar
, ``%result`` is just a name given to the ``Value`` of the ``add``
instruction. In other words, ``%result`` *is* the add instruction. The
, `%result` is just a name given to the `Value` of the `add`
instruction. In other words, `%result` *is* the add instruction. The
"assignment" doesn't explicitly "store" anything to any "virtual register";
the "``=``" is more like the mathematical sense of equality.
the "`=`" is more like the mathematical sense of equality.
Longer explanation: In order to generate a textual representation of the
IR, some kind of name has to be given to each instruction so that other
instructions can textually reference it. However, the isomorphic in-memory
representation that you manipulate from C++ has no such restriction since
instructions can simply keep pointers to any other ``Value``'s that they
reference. In fact, the names of dummy numbered temporaries like ``%1`` are
instructions can simply keep pointers to any other `Value`'s that they
reference. In fact, the names of dummy numbered temporaries like `%1` are
not explicitly represented in the in-memory representation at all (see
``Value::getName()``).
`Value::getName()`).
Source Languages
================
## Source Languages
What source languages are supported?
------------------------------------
### What source languages are supported?
LLVM currently has full support for C and C++ source languages through
`Clang <https://clang.llvm.org/>`_. Many other language frontends have
[Clang](https://clang.llvm.org/). Many other language frontends have
been written using LLVM; an incomplete list is available at
`projects with LLVM <https://llvm.org/ProjectsWithLLVM/>`_.
[projects with LLVM](https://llvm.org/ProjectsWithLLVM/).
I'd like to write a self-hosting LLVM compiler. How should I interface with the LLVM middle-end optimizers and back-end code generators?
----------------------------------------------------------------------------------------------------------------------------------------
### I'd like to write a self-hosting LLVM compiler. How should I interface with the LLVM middle-end optimizers and back-end code generators?
Your compiler front-end will communicate with LLVM by creating a module in the
LLVM intermediate representation (IR) format. Assuming you want to write your
language's compiler in the language itself (rather than C++), there are 3
@ -94,33 +90,33 @@ major ways to tackle generating LLVM IR from a front-end:
1. **Call into the LLVM libraries using your language's FFI (foreign
function interface).**
* *for:* best tracks changes to the LLVM IR, .ll syntax, and .bc format
* *for:* best tracks changes to the LLVM IR, .ll syntax, and .bc format
* *for:* enables running LLVM optimization passes without an emit/parse
overhead
* *for:* enables running LLVM optimization passes without an emit/parse
overhead
* *for:* adapts well to a JIT context
* *for:* adapts well to a JIT context
* *against:* lots of ugly glue code to write
* *against:* lots of ugly glue code to write
2. **Emit LLVM assembly from your compiler's native language.**
* *for:* very straightforward to get started
* *for:* very straightforward to get started
* *against:* the .ll parser is slower than the bitcode reader when
interfacing to the middle end
* *against:* the .ll parser is slower than the bitcode reader when
interfacing to the middle end
* *against:* it may be harder to track changes to the IR
* *against:* it may be harder to track changes to the IR
3. **Emit LLVM bitcode from your compiler's native language.**
* *for:* can use the more-efficient bitcode reader when interfacing to the
middle end
* *for:* can use the more-efficient bitcode reader when interfacing to the
middle end
* *against:* you'll have to re-engineer the LLVM IR object model and bitcode
writer in your language
* *against:* you'll have to re-engineer the LLVM IR object model and bitcode
writer in your language
* *against:* it may be harder to track changes to the IR
* *against:* it may be harder to track changes to the IR
If you go with the first option, the C bindings in include/llvm-c should help
a lot, since most languages have strong support for interfacing with C. The
@ -128,24 +124,23 @@ most common hurdle with calling C from managed code is interfacing with the
garbage collector. The C interface was designed to require very little memory
management, and so is straightforward in this regard.
What support is there for a higher-level source language constructs for building a compiler?
--------------------------------------------------------------------------------------------
### What support is there for a higher-level source language constructs for building a compiler?
Currently, there isn't much. LLVM supports an intermediate representation
which is useful for code representation but will not support the high-level
(abstract syntax tree) representation needed by most compilers. There are no
facilities for lexical nor semantic analysis.
I don't understand the ``GetElementPtr`` instruction. Help!
-----------------------------------------------------------
See `The Often Misunderstood GEP Instruction <GetElementPtr.html>`_.
### I don't understand the `GetElementPtr` instruction. Help!
See {doc}`The Often Misunderstood GEP Instruction <GetElementPtr>`.
Using the C and C++ Front Ends
==============================
## Using the C and C++ Front Ends
### Can I compile C or C++ code to platform-independent LLVM bitcode?
Can I compile C or C++ code to platform-independent LLVM bitcode?
-----------------------------------------------------------------
No. C and C++ are inherently platform-dependent languages. The most obvious
example of this is the preprocessor. A very common way that C code is made
portable is by using the preprocessor to include platform-specific code. In
@ -153,8 +148,8 @@ practice, information about other platforms is lost after preprocessing, so
the result is inherently dependent on the platform that the preprocessing was
targeting.
Another example is ``sizeof``. It's common for ``sizeof(long)`` to vary
between platforms. In most C front-ends, ``sizeof`` is expanded to a
Another example is `sizeof`. It's common for `sizeof(long)` to vary
between platforms. In most C front-ends, `sizeof` is expanded to a
constant immediately, thus hard-wiring a platform-specific detail.
Also, since many platforms define their ABIs in terms of C, and since LLVM is
@ -162,32 +157,31 @@ lower-level than C, front-ends currently must emit platform-specific IR in
order to have the result conform to the platform ABI.
Questions about code generated by the demo page
===============================================
## Questions about code generated by the demo page
What is this ``llvm.global_ctors`` and ``_GLOBAL__I_a...`` stuff that happens when I ``#include <iostream>``?
-------------------------------------------------------------------------------------------------------------
If you ``#include`` the ``<iostream>`` header into a C++ translation unit,
the file will probably use the ``std::cin``/``std::cout``/... global objects.
### What is this `llvm.global_ctors` and `_GLOBAL__I_a...` stuff that happens when I `#include <iostream>`?
If you `#include` the `<iostream>` header into a C++ translation unit,
the file will probably use the `std::cin`/`std::cout`/... global objects.
However, C++ does not guarantee an order of initialization between static
objects in different translation units, so if a static ctor/dtor in your .cpp
file used ``std::cout``, for example, the object would not necessarily be
file used `std::cout`, for example, the object would not necessarily be
automatically initialized before your use.
To make ``std::cout`` and friends work correctly in these scenarios, the STL
To make `std::cout` and friends work correctly in these scenarios, the STL
that we use declares a static object that gets created in every translation
unit that includes ``<iostream>``. This object has a static constructor
unit that includes `<iostream>`. This object has a static constructor
and destructor that initializes and destroys the global iostream objects
before they could possibly be used in the file. The code that you see in the
``.ll`` file corresponds to the constructor and destructor registration code.
`.ll` file corresponds to the constructor and destructor registration code.
If you would like to make it easier to *understand* the LLVM code generated
by the compiler in the demo page, consider using ``printf()`` instead of
``iostream``\s to print values.
by the compiler in the demo page, consider using `printf()` instead of
`iostream`s to print values.
Where did all of my code go??
-----------------------------
### Where did all of my code go??
If you are using the LLVM demo page, you may often wonder what happened to
all of the code that you typed in. Remember that the demo script is running
the code through the LLVM optimizers, so if your code doesn't actually do
@ -196,52 +190,52 @@ anything useful, it might all be deleted.
To prevent this, make sure that the code is actually needed. For example, if
you are computing some expression, return the value from the function instead
of leaving it in a local variable. If you really want to constrain the
optimizer, you can read from and assign to ``volatile`` global variables.
optimizer, you can read from and assign to `volatile` global variables.
What is this "``undef``" thing that shows up in my code?
--------------------------------------------------------
``undef`` is the LLVM way of representing a value that is not defined. You
### What is this "`undef`" thing that shows up in my code?
`undef` is the LLVM way of representing a value that is not defined. You
can get these if you do not initialize a variable before you use it. For
example, the C function:
.. code-block:: c
```c
int X() { int i; return i; }
```
int X() { int i; return i; }
Is compiled to "``ret i32 undef``" because "``i``" never has a value specified
Is compiled to "`ret i32 undef`" because "`i`" never has a value specified
for it.
Why does instcombine + simplifycfg turn a call to a function with a mismatched calling convention into "unreachable"? Why not make the verifier reject it?
----------------------------------------------------------------------------------------------------------------------------------------------------------
### Why does instcombine + simplifycfg turn a call to a function with a mismatched calling convention into "unreachable"? Why not make the verifier reject it?
This is a common problem encountered by authors of front-ends that are using
custom calling conventions: you need to make sure to set the right calling
convention on both the function and on each call to the function. For
example, this code:
.. code-block:: llvm
define fastcc void @foo() {
ret void
}
define void @bar() {
call void @foo()
ret void
}
```llvm
define fastcc void @foo() {
ret void
}
define void @bar() {
call void @foo()
ret void
}
```
Is optimized to:
.. code-block:: llvm
```llvm
define fastcc void @foo() {
ret void
}
define void @bar() {
unreachable
}
```
define fastcc void @foo() {
ret void
}
define void @bar() {
unreachable
}
... with "``opt -instcombine -simplifycfg``". This often bites people because
... with "`opt -instcombine -simplifycfg`". This often bites people because
"all their code disappears". Setting the calling convention on the caller and
callee is required for indirect calls to work, so people often ask why not
make the verifier reject this sort of thing.
@ -253,89 +247,89 @@ create this sort of construct (in dead code). The sorts of things that can
cause this to happen are fairly contrived, but we still need to accept them.
Here's an example:
.. code-block:: llvm
```llvm
define fastcc void @foo() {
ret void
}
define internal void @bar(void()* %FP, i1 %cond) {
br i1 %cond, label %T, label %F
T:
call void %FP()
ret void
F:
call fastcc void %FP()
ret void
}
define void @test() {
%X = or i1 false, false
call void @bar(void()* @foo, i1 %X)
ret void
}
```
define fastcc void @foo() {
ret void
}
define internal void @bar(void()* %FP, i1 %cond) {
br i1 %cond, label %T, label %F
T:
call void %FP()
ret void
F:
call fastcc void %FP()
ret void
}
define void @test() {
%X = or i1 false, false
call void @bar(void()* @foo, i1 %X)
ret void
}
In this example, "test" always passes ``@foo``/``false`` into ``bar``, which
In this example, "test" always passes `@foo`/`false` into `bar`, which
ensures that it is dynamically called with the right calling convention (thus, the
code is perfectly well defined). If you run this through the inliner, you
get this (the explicit "or" is there so that the inliner doesn't dead code
eliminate a bunch of stuff):
.. code-block:: llvm
```llvm
define fastcc void @foo() {
ret void
}
define void @test() {
%X = or i1 false, false
br i1 %X, label %T.i, label %F.i
T.i:
call void @foo()
br label %bar.exit
F.i:
call fastcc void @foo()
br label %bar.exit
bar.exit:
ret void
}
```
define fastcc void @foo() {
ret void
}
define void @test() {
%X = or i1 false, false
br i1 %X, label %T.i, label %F.i
T.i:
call void @foo()
br label %bar.exit
F.i:
call fastcc void @foo()
br label %bar.exit
bar.exit:
ret void
}
Here you can see that the inlining pass made an undefined call to ``@foo``
Here you can see that the inlining pass made an undefined call to `@foo`
with the wrong calling convention. We really don't want to make the inliner
have to know about this sort of thing, so it needs to be valid code. In this
case, dead code elimination can trivially remove the undefined code. However,
if ``%X`` was an input argument to ``@test``, the inliner would produce this:
if `%X` was an input argument to `@test`, the inliner would produce this:
.. code-block:: llvm
```llvm
define fastcc void @foo() {
ret void
}
define fastcc void @foo() {
ret void
}
define void @test(i1 %X) {
br i1 %X, label %T.i, label %F.i
T.i:
call void @foo()
br label %bar.exit
F.i:
call fastcc void @foo()
br label %bar.exit
bar.exit:
ret void
}
```
define void @test(i1 %X) {
br i1 %X, label %T.i, label %F.i
T.i:
call void @foo()
br label %bar.exit
F.i:
call fastcc void @foo()
br label %bar.exit
bar.exit:
ret void
}
The interesting thing about this is that ``%X`` *must* be false for the
The interesting thing about this is that `%X` *must* be false for the
code to be well-defined, but no amount of dead code elimination will be able
to delete the broken call as unreachable. However, since
``instcombine``/``simplifycfg`` turns the undefined call into unreachable, we
`instcombine`/`simplifycfg` turns the undefined call into unreachable, we
end up with a branch on a condition that goes to unreachable: a branch to
unreachable can never happen, so "``-inline -instcombine -simplifycfg``" is
unreachable can never happen, so "`-inline -instcombine -simplifycfg`" is
able to produce:
.. code-block:: llvm
define fastcc void @foo() {
ret void
}
define void @test(i1 %X) {
F.i:
call fastcc void @foo()
ret void
}
```llvm
define fastcc void @foo() {
ret void
}
define void @test(i1 %X) {
F.i:
call fastcc void @foo()
ret void
}
```

View file

@ -1,19 +1,16 @@
=====================================
Garbage Collection with LLVM
=====================================
# Garbage Collection with LLVM
.. contents::
:local:
```{contents}
:local:
```
Abstract
========
## Abstract
This document covers how to integrate LLVM into a compiler for a language which
supports garbage collection. **Note that LLVM itself does not provide a
garbage collector.** You must provide your own.
Quick Start
============
## Quick Start
First, you should pick a collector strategy. LLVM includes a number of built-in
ones, but you can also implement a loadable plugin with a custom definition.
@ -24,21 +21,21 @@ of the collector itself.
Next, mark your generated functions as using your chosen collector strategy.
From C++, you can call:
.. code-block:: c++
```c++
F.setGC(<collector description name>);
```
This will produce IR like the following fragment:
.. code-block:: llvm
```llvm
define void @foo() gc "<collector description name>" { ... }
```
When generating LLVM IR for your functions, you will need to:
* Use ``@llvm.gcread`` and/or ``@llvm.gcwrite`` in place of standard load and
* Use `@llvm.gcread` and/or `@llvm.gcwrite` in place of standard load and
store instructions. These intrinsics are used to represent load and store
barriers. If your collector does not require such barriers, you can skip
this step.
@ -59,23 +56,21 @@ When generating LLVM IR for your functions, you will need to:
You will need to identify roots (i.e. references to heap objects your collector
needs to know about) in your generated IR, so that LLVM can encode them into
your final stack maps. Depending on the collector strategy chosen, this is
accomplished by using either the ``@llvm.gcroot`` intrinsics or a
``gc.statepoint`` relocation sequence.
accomplished by using either the `@llvm.gcroot` intrinsics or a
`gc.statepoint` relocation sequence.
Don't forget to create a root for each intermediate value that is generated when
evaluating an expression. In ``h(f(), g())``, the result of ``f()`` could
easily be collected if evaluating ``g()`` triggers a collection.
evaluating an expression. In `h(f(), g())`, the result of `f()` could
easily be collected if evaluating `g()` triggers a collection.
Finally, you need to link your runtime library with the generated program
executable (for a static compiler) or ensure the appropriate symbols are
available for the runtime linker (for a JIT compiler).
Introduction
============
## Introduction
What is Garbage Collection?
---------------------------
### What is Garbage Collection?
Garbage collection is a widely used technique that frees the programmer from
having to know the lifetimes of heap objects, making software easier to produce
@ -86,15 +81,14 @@ conservative and accurate.
Conservative garbage collection often does not require any special support from
either the language or the compiler: it can handle non-type-safe programming
languages (such as C/C++) and does not require any special information from the
compiler. The `Boehm collector
<https://hboehm.info/gc/>`__ is an example of a
compiler. The [Boehm collector](https://hboehm.info/gc/) is an example of a
state-of-the-art conservative collector.
Accurate garbage collection requires the ability to identify all pointers in the
program at run-time (which requires that the source-language be type-safe in
most cases). Identifying pointers at run-time requires compiler support to
locate all places that hold live pointer variables at run-time, including the
:ref:`processor stack and registers <gcroot>`.
{ref}`processor stack and registers <gcroot>`.
Conservative garbage collection is attractive because it does not require any
special compiler support, but it does have problems. In particular, because the
@ -115,11 +109,9 @@ techniques dominates any low-level losses.
This document describes the mechanisms and interfaces provided by LLVM to
support accurate garbage collection.
Goals and non-goals
-------------------
### Goals and non-goals
LLVM's intermediate representation provides :ref:`garbage collection intrinsics
<gc_intrinsics>` that offer support for a broad class of collector models. For
LLVM's intermediate representation provides {ref}`garbage collection intrinsics <gc_intrinsics>` that offer support for a broad class of collector models. For
instance, the intrinsics permit:
* semi-space collectors
@ -145,7 +137,7 @@ be part of your language's runtime library. LLVM provides a framework for
describing the garbage collector's requirements to the compiler. In particular,
LLVM provides support for generating stack maps at call sites, polling for a
safepoint, and emitting load and store barriers. You can also extend LLVM -
possibly through a loadable :ref:`code generation plugins <plugin>` - to
possibly through a loadable {ref}`code generation plugins <plugin>` - to
generate code and data structures which conform to the *binary interface*
specified by the *runtime library*. This is similar to the relationship between
LLVM and DWARF debugging info, for example. The difference primarily lies in
@ -191,27 +183,24 @@ extension points. If you don't already have a specific binary interface
you need to support, we recommend trying to use one of these built-in collector
strategies.
.. _gc_intrinsics:
(gc_intrinsics)=
LLVM IR Features
================
## LLVM IR Features
This section describes the garbage collection facilities provided by the
:doc:`LLVM intermediate representation <LangRef>`. The exact behavior of these
IR features is specified by the selected :ref:`GC strategy description
<plugin>`.
{doc}`LLVM intermediate representation <LangRef>`. The exact behavior of these
IR features is specified by the selected {ref}`GC strategy description <plugin>`.
Specifying GC code generation: ``gc "..."``
-------------------------------------------
.. code-block:: text
### Specifying GC code generation: `gc "..."`
```text
define <returntype> @name(...) gc "name" { ... }
```
The ``gc`` function attribute is used to specify the desired GC strategy to the
compiler. Its programmatic equivalent is the ``setGC`` method of ``Function``.
The `gc` function attribute is used to specify the desired GC strategy to the
compiler. Its programmatic equivalent is the `setGC` method of `Function`.
Setting ``gc "name"`` on a function triggers a search for a matching subclass
Setting `gc "name"` on a function triggers a search for a matching subclass
of GCStrategy. Some collector strategies are built in. You can add others
using either the loadable plugin mechanism, or by patching your copy of LLVM.
It is the selected GC strategy which defines the exact nature of the code
@ -220,35 +209,32 @@ generated to support GC. If none is found, the compiler will raise an error.
Specifying the GC style on a per-function basis allows LLVM to link together
programs that use different garbage collection algorithms (or none at all).
.. _gcroot:
(gcroot)=
Identifying GC roots on the stack
----------------------------------
### Identifying GC roots on the stack
LLVM currently supports two different mechanisms for describing references in
compiled code at safepoints. ``llvm.gcroot`` is the older mechanism;
``gc.statepoint`` has been added more recently. At the moment, you can choose
either implementation (on a per :ref:`GC strategy <plugin>` basis). Longer
term, we will probably either migrate away from ``llvm.gcroot`` entirely, or
compiled code at safepoints. `llvm.gcroot` is the older mechanism;
`gc.statepoint` has been added more recently. At the moment, you can choose
either implementation (on a per {ref}`GC strategy <plugin>` basis). Longer
term, we will probably either migrate away from `llvm.gcroot` entirely, or
substantially merge their implementations. Note that most new development
work is focused on ``gc.statepoint``.
work is focused on `gc.statepoint`.
Using ``gc.statepoint``
^^^^^^^^^^^^^^^^^^^^^^^^
:doc:`This page <Statepoints>` contains detailed documentation for
``gc.statepoint``.
#### Using `gc.statepoint`
{doc}`This page <Statepoints>` contains detailed documentation for
`gc.statepoint`.
Using ``llvm.gcwrite``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: llvm
#### Using `llvm.gcwrite`
```llvm
void @llvm.gcroot(i8** %ptrloc, i8* %metadata)
```
The ``llvm.gcroot`` intrinsic is used to inform LLVM that a stack variable
The `llvm.gcroot` intrinsic is used to inform LLVM that a stack variable
references an object on the heap and is to be tracked for garbage collection.
The exact impact on generated code is specified by the Function's selected
:ref:`GC strategy <plugin>`. All calls to ``llvm.gcroot`` **must** reside
{ref}`GC strategy <plugin>`. All calls to `llvm.gcroot` **must** reside
inside the first basic block.
The first argument **must** be a value referring to an alloca instruction or a
@ -258,35 +244,34 @@ address. If your target collector uses tags, use a null pointer for metadata.
A compiler which performs manual SSA construction **must** ensure that SSA
values representing GC references are stored into the alloca passed to the
respective ``gcroot`` before every call site and reloaded after every call.
A compiler which uses mem2reg to raise imperative code using ``alloca`` into
SSA form need only add a call to ``@llvm.gcroot`` for those variables which
respective `gcroot` before every call site and reloaded after every call.
A compiler which uses mem2reg to raise imperative code using `alloca` into
SSA form need only add a call to `@llvm.gcroot` for those variables which
are pointers into the GC heap.
It is also important to mark intermediate values with ``llvm.gcroot``. For
example, consider ``h(f(), g())``. Beware leaking the result of ``f()`` in the
case that ``g()`` triggers a collection. Note that stack variables must be
initialized and marked with ``llvm.gcroot`` in the function's prologue.
It is also important to mark intermediate values with `llvm.gcroot`. For
example, consider `h(f(), g())`. Beware leaking the result of `f()` in the
case that `g()` triggers a collection. Note that stack variables must be
initialized and marked with `llvm.gcroot` in the function's prologue.
The ``%metadata`` argument can be used to avoid requiring heap objects to have
'isa' pointers or tag bits. [Appel89_, Goldberg91_, Tolmach94_] If specified,
The `%metadata` argument can be used to avoid requiring heap objects to have
'isa' pointers or tag bits. [[Appel89](#appel89), [Goldberg91](#goldberg91), [Tolmach94](#tolmach94)] If specified,
its value will be tracked along with the location of the pointer in the stack
frame.
Consider the following fragment of Java code:
.. code-block:: java
```java
{
Object X; // A null-initialized reference to an object
...
}
```
This block (which may be located in the middle of a function or in a loop nest),
could be compiled to this LLVM code:
.. code-block:: llvm
```llvm
Entry:
;; In the entry block for the function, allocate the
;; stack space for X, which is an LLVM pointer.
@ -310,9 +295,9 @@ could be compiled to this LLVM code:
;; it, to indicate that the value is no longer live.
store %Object* null, %Object** %X
...
```
Reading and writing references in the heap
------------------------------------------
### Reading and writing references in the heap
Some collectors need to be informed when the mutator (the program that needs
garbage collection) either reads a pointer from or writes a pointer to a field
@ -324,11 +309,10 @@ computation, so the overall performance impact of the barrier is tolerable.
Barriers often require access to the *object pointer* rather than the *derived
pointer* (which is a pointer to the field within the object). Accordingly,
these intrinsics take both pointers as separate arguments for completeness. In
this snippet, ``%object`` is the object pointer, and ``%derived`` is the derived
this snippet, `%object` is the object pointer, and `%derived` is the derived
pointer:
.. code-block:: llvm
```llvm
;; An array type.
%class.Array = type { %class.Object, i32, [0 x %class.Object*] }
...
@ -338,73 +322,70 @@ pointer:
;; Compute the derived pointer.
%derived = getelementptr %object, i32 0, i32 2, i32 %n
```
LLVM does not enforce this relationship between the object and derived pointer
(although a particular :ref:`collector strategy <plugin>` might). However, it
(although a particular {ref}`collector strategy <plugin>` might). However, it
would be an unusual collector that violated it.
The use of these intrinsics is naturally optional if the target GC does not
require the corresponding barrier. The GC strategy used with such a collector
should replace the intrinsic calls with the corresponding ``load`` or
``store`` instruction if they are used.
should replace the intrinsic calls with the corresponding `load` or
`store` instruction if they are used.
One known deficiency with the current design is that the barrier intrinsics do
not include the size or alignment of the underlying operation performed. It is
currently assumed that the operation is of pointer size and the alignment is
assumed to be the target machine's default alignment.
Write barrier: ``llvm.gcwrite``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: llvm
#### Write barrier: `llvm.gcwrite`
```llvm
void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived)
```
For write barriers, LLVM provides the ``llvm.gcwrite`` intrinsic function. It
has exactly the same semantics as a non-volatile ``store`` to the derived
For write barriers, LLVM provides the `llvm.gcwrite` intrinsic function. It
has exactly the same semantics as a non-volatile `store` to the derived
pointer (the third argument). The exact code generated is specified by the
Function's selected :ref:`GC strategy <plugin>`.
Function's selected {ref}`GC strategy <plugin>`.
Many important algorithms require write barriers, including generational and
concurrent collectors. Additionally, write barriers could be used to implement
reference counting.
Read barrier: ``llvm.gcread``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: llvm
#### Read barrier: `llvm.gcread`
```llvm
i8* @llvm.gcread(i8* %object, i8** %derived)
```
For read barriers, LLVM provides the ``llvm.gcread`` intrinsic function. It has
exactly the same semantics as a non-volatile ``load`` from the derived pointer
For read barriers, LLVM provides the `llvm.gcread` intrinsic function. It has
exactly the same semantics as a non-volatile `load` from the derived pointer
(the second argument). The exact code generated is specified by the Function's
selected :ref:`GC strategy <plugin>`.
selected {ref}`GC strategy <plugin>`.
Read barriers are needed by fewer algorithms than write barriers, and may have a
greater performance impact since pointer reads are more frequent than writes.
.. _plugin:
(plugin)=
.. _builtin-gc-strategies:
(builtin-gc-strategies)=
Built-In GC Strategies
======================
## Built-In GC Strategies
LLVM includes built-in support for several varieties of garbage collectors.
The Shadow Stack GC
----------------------
### The Shadow Stack GC
To use this collector strategy, mark your functions with:
.. code-block:: c++
```c++
F.setGC("shadow-stack");
```
Unlike many GC algorithms which rely on a cooperative code generator to compile
stack maps, this algorithm carefully maintains a linked list of stack roots
[:ref:`Henderson2002 <henderson02>`]. This so-called "shadow stack" mirrors the
[[Henderson2002](#henderson02)]. This so-called "shadow stack" mirrors the
machine stack. Maintaining this data structure is slower than using a stack map
compiled into the executable as constant data, but has a significant portability
advantage because it requires no special support from the target code generator,
@ -417,13 +398,13 @@ The tradeoff for this simplicity and portability is:
* Not thread-safe.
Still, it's an easy way to get started. After your compiler and runtime are up
and running, writing a :ref:`plugin <plugin>` will allow you to take advantage
of :ref:`more advanced GC features <collector-algos>` of LLVM in order to
and running, writing a {ref}`plugin <plugin>` will allow you to take advantage
of {ref}`more advanced GC features <collector-algos>` of LLVM in order to
improve performance.
The shadow stack doesn't imply a memory allocation algorithm. A semispace
collector or building atop ``malloc`` are great places to start, and can be
collector or building atop `malloc` are great places to start, and can be
implemented with very little code.
When it comes time to collect, however, your runtime needs to traverse the stack
@ -431,8 +412,7 @@ roots, and for this it needs to integrate with the shadow stack. Luckily, doing
so is very simple. (This code is heavily commented to help you understand the
data structure, but there are only 20 lines of meaningful code.)
.. code-block:: c++
```c++
/// The map for a single function's stack frame. One of these is
/// compiled as constant data into the executable for each function.
///
@ -479,58 +459,55 @@ data structure, but there are only 20 lines of meaningful code.)
Visitor(&R->Roots[i], NULL);
}
}
```
The 'Erlang' and 'OCaml' GCs
-----------------------------
### The 'Erlang' and 'OCaml' GCs
LLVM ships with two example collectors which leverage the ``gcroot``
LLVM ships with two example collectors which leverage the `gcroot`
mechanisms. To our knowledge, these are not actually used by any language
runtime, but they do provide a reasonable starting point for someone interested
in writing a ``gcroot`` compatible GC plugin. In particular, these are the
in writing a `gcroot` compatible GC plugin. In particular, these are the
only in-tree examples of how to produce a custom binary stack map format using
a ``gcroot`` strategy.
a `gcroot` strategy.
As their names imply, the binary format produced is intended to model that
used by the Erlang and OCaml compilers respectively.
.. _statepoint_example_gc:
(statepoint_example_gc)=
The Statepoint Example GC
-------------------------
.. code-block:: c++
### The Statepoint Example GC
```c++
F.setGC("statepoint-example");
```
This GC provides an example of how one might use the infrastructure provided
by ``gc.statepoint``. This example GC is compatible with the
:ref:`PlaceSafepoints` and :ref:`RewriteStatepointsForGC` utility passes
which simplify ``gc.statepoint`` sequence insertion. If you need to build a
custom GC strategy around the ``gc.statepoints`` mechanisms, it is recommended
by `gc.statepoint`. This example GC is compatible with the
{ref}`PlaceSafepoints` and {ref}`RewriteStatepointsForGC` utility passes
which simplify `gc.statepoint` sequence insertion. If you need to build a
custom GC strategy around the `gc.statepoints` mechanisms, it is recommended
that you use this one as a starting point.
This GC strategy does not support read or write barriers. As a result, these
intrinsics are lowered to normal loads and stores.
The stack map format generated by this GC strategy can be found in the
:ref:`stackmap-section` using a format documented :ref:`here
<statepoint-stackmap-format>`. This format is intended to be the standard
{ref}`stackmap-section` using a format documented {ref}`here <statepoint-stackmap-format>`. This format is intended to be the standard
format supported by LLVM going forward.
The CoreCLR GC
-------------------------
.. code-block:: c++
### The CoreCLR GC
```c++
F.setGC("coreclr");
```
This GC leverages the ``gc.statepoint`` mechanism to support the
`CoreCLR <https://github.com/dotnet/coreclr>`__ runtime.
This GC leverages the `gc.statepoint` mechanism to support the
[CoreCLR](https://github.com/dotnet/coreclr) runtime.
Support for this GC strategy is a work in progress. This strategy will
differ from
:ref:`statepoint-example GC<statepoint_example_gc>` strategy in
{ref}`statepoint-example GC <statepoint_example_gc>` strategy in
certain aspects like:
* Base-pointers of interior pointers are not explicitly
@ -541,8 +518,7 @@ certain aspects like:
* Safe-point polls are only needed before loop-back edges
and before tail-calls (not needed at function-entry).
Custom GC Strategies
====================
## Custom GC Strategies
If none of the built-in GC strategy descriptions met your needs above, you will
need to define a custom GCStrategy and possibly, a custom LLVM pass to perform
@ -557,38 +533,36 @@ you need a patched build, please ask for advice on llvm-dev. There may be an
easy way we can extend the support to make it work for your use case without
requiring a custom build.
Collector Requirements
----------------------
### Collector Requirements
You should be able to leverage any existing collector library that includes the following elements:
#. A memory allocator which exposes an allocation function your compiled
1. A memory allocator which exposes an allocation function your compiled
code can call.
#. A binary format for the stack map. A stack map describes the location
1. A binary format for the stack map. A stack map describes the location
of references at a safepoint and is used by precise collectors to identify
references within a stack frame on the machine stack. Note that collectors
which conservatively scan the stack don't require such a structure.
#. A stack crawler to discover functions on the call stack, and enumerate the
1. A stack crawler to discover functions on the call stack, and enumerate the
references listed in the stack map for each call site.
#. A mechanism for identifying references in global locations (e.g. global
1. A mechanism for identifying references in global locations (e.g. global
variables).
#. If your collector requires them, an LLVM IR implementation of your collector's
1. If your collector requires them, an LLVM IR implementation of your collector's
load and store barriers. Note that since many collectors don't require
barriers at all, LLVM defaults to lowering such barriers to normal loads
and stores unless you arrange otherwise.
Implementing a collector plugin
-------------------------------
### Implementing a collector plugin
User code specifies which GC code generation to use with the ``gc`` function
attribute or, equivalently, with the ``setGC`` method of ``Function``.
User code specifies which GC code generation to use with the `gc` function
attribute or, equivalently, with the `setGC` method of `Function`.
To implement a GC plugin, it is necessary to subclass ``llvm::GCStrategy``,
To implement a GC plugin, it is necessary to subclass `llvm::GCStrategy`,
which can be accomplished in a few lines of boilerplate code. LLVM's
infrastructure provides access to several important algorithms. For an
uncontroversial collector, all that remains may be to compile LLVM's computed
@ -598,13 +572,11 @@ runtime library). This can be accomplished in about 100 lines of code.
This is not the appropriate place to implement a garbage collected heap or a
garbage collector itself. That code should exist in the language's runtime
library. The compiler plugin is responsible for generating code which conforms
to the binary interface defined by the library, most essentially the :ref:`stack map
<stack-map>`.
to the binary interface defined by the library, most essentially the {ref}`stack map <stack-map>`.
To subclass ``llvm::GCStrategy`` and register it with the compiler:
.. code-block:: c++
To subclass `llvm::GCStrategy` and register it with the compiler:
```c++
// lib/MyGC/MyGC.cpp - Example LLVM GC plugin
#include "llvm/CodeGen/GCStrategy.h"
@ -622,13 +594,14 @@ To subclass ``llvm::GCStrategy`` and register it with the compiler:
GCRegistry::Add<MyGC>
X("mygc", "My bespoke garbage collector.");
}
```
This boilerplate collector does nothing. More specifically:
* ``llvm.gcread`` calls are replaced with the corresponding ``load``
* `llvm.gcread` calls are replaced with the corresponding `load`
instruction.
* ``llvm.gcwrite`` calls are replaced with the corresponding ``store``
* `llvm.gcwrite` calls are replaced with the corresponding `store`
instruction.
* No safe points are added to the code.
@ -638,8 +611,7 @@ This boilerplate collector does nothing. More specifically:
Using the LLVM makefiles, this code
can be compiled as a plugin using a simple makefile:
.. code-block:: make
```make
# lib/MyGC/Makefile
LEVEL := ../..
@ -647,132 +619,91 @@ can be compiled as a plugin using a simple makefile:
LOADABLE_MODULE = 1
include $(LEVEL)/Makefile.common
```
Once the plugin is compiled, code using it may be compiled using ``llc
-load=MyGC.so`` (though MyGC.so may have some other platform-specific
Once the plugin is compiled, code using it may be compiled using `llc`
`-load=MyGC.so` (though MyGC.so may have some other platform-specific
extension):
::
```console
$ cat sample.ll
define void @f() gc "mygc" {
entry:
ret void
}
$ llvm-as < sample.ll | llc -load=MyGC.so
```
It is also possible to statically link the collector plugin into tools, such as
a language-specific compiler front-end.
.. _collector-algos:
(collector-algos)=
Overview of available features
------------------------------
### Overview of available features
``GCStrategy`` provides a range of features through which a plugin may do useful
`GCStrategy` provides a range of features through which a plugin may do useful
work. Some of these are callbacks, some are algorithms that can be enabled,
disabled, or customized. This matrix summarizes the supported (and planned)
features and correlates them with the collection techniques which typically
require them.
.. |v| unicode:: 0x2714
:trim:
.. |x| unicode:: 0x2718
:trim:
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| Algorithm | Done | Shadow | refcount | mark- | copying | incremental | threaded | concurrent |
| | | stack | | sweep | | | | |
+============+======+========+==========+=======+=========+=============+==========+============+
| stack map | |v| | | | |x| | |x| | |x| | |x| | |x| |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| initialize | |v| | |x| | |x| | |x| | |x| | |x| | |x| | |x| |
| roots | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| derived | NO | | | | | | **N**\* | **N**\* |
| pointers | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| **custom | |v| | | | | | | | |
| lowering** | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *gcroot* | |v| | |x| | |x| | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *gcwrite* | |v| | | |x| | | | |x| | | |x| |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *gcread* | |v| | | | | | | | |x| |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| **safe | | | | | | | | |
| points** | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *in | |v| | | | |x| | |x| | |x| | |x| | |x| |
| calls* | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *before | |v| | | | | | | |x| | |x| |
| calls* | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *for | NO | | | | | | **N** | **N** |
| loops* | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *before | |v| | | | | | | |x| | |x| |
| escape* | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| emit code | NO | | | | | | **N** | **N** |
| at safe | | | | | | | | |
| points | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| **output** | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *assembly* | |v| | | | |x| | |x| | |x| | |x| | |x| |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *JIT* | NO | | | **?** | **?** | **?** | **?** | **?** |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| *obj* | NO | | | **?** | **?** | **?** | **?** | **?** |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| live | NO | | | **?** | **?** | **?** | **?** | **?** |
| analysis | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| register | NO | | | **?** | **?** | **?** | **?** | **?** |
| map | | | | | | | | |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| \* Derived pointers only pose a hazard to copying collections. |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| **?** denotes a feature which could be utilized if available. |
+------------+------+--------+----------+-------+---------+-------------+----------+------------+
| Algorithm | Done | Shadow stack | refcount | mark-sweep | copying | incremental | threaded | concurrent |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| stack map | ✓ | | | ✘ | ✘ | ✘ | ✘ | ✘ |
| initialize<br>roots | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ |
| derived<br>pointers | NO | | | | | | **N**\* | **N**\* |
| **custom<br>lowering** | ✓ | | | | | | | |
| *gcroot* | ✓ | ✘ | ✘ | | | | | |
| *gcwrite* | ✓ | | ✘ | | | ✘ | | ✘ |
| *gcread* | ✓ | | | | | | | ✘ |
| **safe<br>points** | | | | | | | | |
| *in<br>calls* | ✓ | | | ✘ | ✘ | ✘ | ✘ | ✘ |
| *before<br>calls* | ✓ | | | | | | ✘ | ✘ |
| *for<br>loops* | NO | | | | | | **N** | **N** |
| *before<br>escape* | ✓ | | | | | | ✘ | ✘ |
| emit code<br>at safe<br>points | NO | | | | | | **N** | **N** |
| **output** | | | | | | | | |
| *assembly* | ✓ | | | ✘ | ✘ | ✘ | ✘ | ✘ |
| *JIT* | NO | | | **?** | **?** | **?** | **?** | **?** |
| *obj* | NO | | | **?** | **?** | **?** | **?** | **?** |
| live<br>analysis | NO | | | **?** | **?** | **?** | **?** | **?** |
| register<br>map | NO | | | **?** | **?** | **?** | **?** | **?** |
| \* Derived pointers only pose a hazard to copying collections. | | | | | | | | |
| **?** denotes a feature which could be utilized if available. | | | | | | | | |
To be clear, the collection techniques above are defined as:
Shadow Stack
The mutator carefully maintains a linked list of stack roots.
: The mutator carefully maintains a linked list of stack roots.
Reference Counting
The mutator maintains a reference count for each object and frees an object
: The mutator maintains a reference count for each object and frees an object
when its count falls to zero.
Mark-Sweep
When the heap is exhausted, the collector marks reachable objects starting
: When the heap is exhausted, the collector marks reachable objects starting
from the roots, then deallocates unreachable objects in a sweep phase.
Copying
As reachability analysis proceeds, the collector copies objects from one heap
: As reachability analysis proceeds, the collector copies objects from one heap
area to another, compacting them in the process. Copying collectors enable
highly efficient "bump pointer" allocation and can improve locality of
reference.
Incremental
(Including generational collectors.) Incremental collectors generally have all
: (Including generational collectors.) Incremental collectors generally have all
the properties of a copying collector (regardless of whether the mature heap
is compacting), but bring the added complexity of requiring write barriers.
Threaded
Denotes a multithreaded mutator; the collector must still stop the mutator
: Denotes a multithreaded mutator; the collector must still stop the mutator
("stop the world") before beginning reachability analysis. Stopping a
multithreaded mutator is a complicated problem. It generally requires highly
platform-specific code in the runtime, and the production of carefully
designed machine code at safe points.
Concurrent
In this technique, the mutator and the collector run concurrently, with the
: In this technique, the mutator and the collector run concurrently, with the
goal of eliminating pause times. In a *cooperative* collector, the mutator
further aids with collection should a pause occur, allowing collection to take
advantage of multiprocessor hosts. The "stop the world" problem of threaded
@ -784,37 +715,35 @@ suitable for a wide variety of collectors, but does not currently extend to
multithreaded programs. This will be added in the future as there is
interest.
.. _stack-map:
(stack-map)=
Computing stack maps
--------------------
### Computing stack maps
LLVM automatically computes a stack map. One of the most important features
of a ``GCStrategy`` is to compile this information into the executable in
of a `GCStrategy` is to compile this information into the executable in
the binary representation expected by the runtime library.
The stack map consists of the location and identity of each GC root in the
each function in the module. For each root:
* ``RootNum``: The index of the root.
* `RootNum`: The index of the root.
* ``StackOffset``: The offset of the object relative to the frame pointer.
* `StackOffset`: The offset of the object relative to the frame pointer.
* ``RootMetadata``: The value passed as the ``%metadata`` parameter to the
``@llvm.gcroot`` intrinsic.
* `RootMetadata`: The value passed as the `%metadata` parameter to the
`@llvm.gcroot` intrinsic.
Also, for the function as a whole:
* ``getFrameSize()``: The overall size of the function's initial stack frame,
* `getFrameSize()`: The overall size of the function's initial stack frame,
not accounting for any dynamic allocation.
* ``roots_size()``: The count of roots in the function.
* `roots_size()`: The count of roots in the function.
To access the stack map, use ``GCFunctionMetadata::roots_begin()`` and
-``end()`` from the :ref:`GCMetadataPrinter <assembly>`:
.. code-block:: c++
To access the stack map, use `GCFunctionMetadata::roots_begin()` and
-`end()` from the {ref}`GCMetadataPrinter <assembly>`:
```c++
for (iterator I = begin(), E = end(); I != E; ++I) {
GCFunctionInfo *FI = *I;
unsigned FrameSize = FI->getFrameSize();
@ -828,26 +757,25 @@ To access the stack map, use ``GCFunctionMetadata::roots_begin()`` and
Constant *RootMetadata = RI->Metadata;
}
}
```
If the ``llvm.gcroot`` intrinsic is eliminated before code generation by a
If the `llvm.gcroot` intrinsic is eliminated before code generation by a
custom lowering pass, LLVM will compute an empty stack map. This may be useful
for collector plugins which implement reference counting or a shadow stack.
.. _init-roots:
(init-roots)=
Initializing roots to null
---------------------------
### Initializing roots to null
It is recommended that frontends initialize roots explicitly to avoid
potentially confusing the optimizer. This prevents the GC from visiting
uninitialized pointers, which will almost certainly cause it to crash.
As a fallback, LLVM will automatically initialize each root to ``null``
As a fallback, LLVM will automatically initialize each root to `null`
upon entry to the function. Support for this mode in code generation is
largely a legacy detail to keep old collector implementations working.
Custom lowering of intrinsics
------------------------------
### Custom lowering of intrinsics
For GCs which use barriers or unusual treatment of stack roots, the
implementor is responsible for providing a custom pass to lower the
@ -860,10 +788,9 @@ ShadowStackGCLowering pass.
There is currently no way to register such a custom lowering pass
without building a custom copy of LLVM.
.. _safe-points:
(safe-points)=
Generating safe points
-----------------------
### Generating safe points
LLVM provides support for associating stackmaps with the return address of
a call. Any loop or return safepoints required by a given collector design
@ -871,10 +798,9 @@ can be modeled via calls to runtime routines, or potentially patchable call
sequences. Using gcroot, all call instructions are inferred to be possible
safepoints and will thus have an associated stackmap.
.. _assembly:
(assembly)=
Emitting assembly code: ``GCMetadataPrinter``
---------------------------------------------
### Emitting assembly code: `GCMetadataPrinter`
LLVM allows a plugin to print arbitrary assembly code before and after the rest
of a module's assembly code. At the end of the module, the GC can compile the
@ -883,22 +809,21 @@ yet computed.)
Since AsmWriter and CodeGen are separate components of LLVM, a separate abstract
base class and registry is provided for printing assembly code, the
``GCMetadaPrinter`` and ``GCMetadataPrinterRegistry``. The AsmWriter will look
for such a subclass if the ``GCStrategy`` sets ``UsesMetadata``:
.. code-block:: c++
`GCMetadaPrinter` and `GCMetadataPrinterRegistry`. The AsmWriter will look
for such a subclass if the `GCStrategy` sets `UsesMetadata`:
```c++
MyGC::MyGC() {
UsesMetadata = true;
}
```
This separation allows JIT-only clients to be smaller.
Note that LLVM does not currently have analogous APIs to support code generation
in the JIT, nor using the object writers.
.. code-block:: c++
```c++
// lib/MyGC/MyGCPrinter.cpp - Example LLVM GC printer
#include "llvm/CodeGen/GCMetadataPrinter.h"
@ -917,14 +842,14 @@ in the JIT, nor using the object writers.
GCMetadataPrinterRegistry::Add<MyGCPrinter>
X("mygc", "My bespoke garbage collector.");
}
```
The collector should use ``AsmPrinter`` to print portable assembly code. The
The collector should use `AsmPrinter` to print portable assembly code. The
collector itself contains the stack map for the entire module, and may access
the ``GCFunctionInfo`` using its own ``begin()`` and ``end()`` methods. Here's
the `GCFunctionInfo` using its own `begin()` and `end()` methods. Here's
a realistic example:
.. code-block:: c++
```c++
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DataLayout.h"
@ -1002,27 +927,26 @@ a realistic example:
}
}
}
```
References
==========
## References
.. _appel89:
(appel89)=
[Appel89] Runtime Tags Aren't Necessary. Andrew W. Appel. Lisp and Symbolic
Computation 19(7):703-705, July 1989.
.. _goldberg91:
(goldberg91)=
[Goldberg91] Tag-free garbage collection for strongly typed programming
languages. Benjamin Goldberg. ACM SIGPLAN PLDI'91.
.. _tolmach94:
(tolmach94)=
[Tolmach94] Tag-free garbage collection using explicit type parameters. Andrew
Tolmach. Proceedings of the 1994 ACM conference on LISP and functional
programming.
.. _henderson02:
(henderson02)=
[Henderson2002] `Accurate Garbage Collection in an Uncooperative Environment
<http://citeseer.ist.psu.edu/henderson02accurate.html>`__
[Henderson2002] [Accurate Garbage Collection in an Uncooperative Environment](http://citeseer.ist.psu.edu/henderson02accurate.html)

View file

@ -1,14 +1,11 @@
==================================================================
Getting Started with the LLVM System using Microsoft Visual Studio
==================================================================
# Getting Started with the LLVM System using Microsoft Visual Studio
```{contents}
:local:
```
.. contents::
:local:
## Overview
Overview
========
Welcome to LLVM on Windows! This document only covers LLVM on Windows using
Visual Studio, not WSL, mingw or cygwin. In order to get started, you first need
to know some basic information.
@ -19,7 +16,7 @@ to use LLVM. It contains an assembler, disassembler, bitcode analyzer, and
bitcode optimizer. It also contains basic regression tests that can be used to
test the LLVM tools and the Clang front end.
The second piece is the `Clang <https://clang.llvm.org/>`_ front end. This
The second piece is the [Clang](https://clang.llvm.org/) front end. This
component compiles C, C++, Objective C, and Objective C++ code into LLVM
bitcode. Clang typically uses LLVM libraries to optimize the bitcode and emit
machine code. LLVM fully supports the COFF object file format, which is
@ -28,14 +25,14 @@ compatible with all other existing Windows toolchains.
This document does not discuss other LLVM projects.
Requirements
============
## Requirements
Before you begin to use the LLVM system, review the requirements given
below. This may save you some trouble by knowing ahead of time what hardware
and software you will need.
Hardware
--------
### Hardware
Any system that can adequately run Visual Studio 2019 is fine. The LLVM
source tree, including the git index, consumes approximately 3GB.
Object files, libraries, and executables consume approximately 5GB in
@ -43,44 +40,44 @@ Release mode and much more in Debug mode. An SSD drive and >16GB RAM are
recommended.
Software
--------
You will need `Visual Studio <https://visualstudio.microsoft.com/>`_ 2019 or
### Software
You will need [Visual Studio](https://visualstudio.microsoft.com/) 2019 or
later, with the latest Update installed. Visual Studio Community Edition
suffices.
You will also need the `CMake <http://www.cmake.org/>`_ build system since it
You will also need the [CMake](http://www.cmake.org/) build system since it
generates the project files you will use to build with. CMake is bundled with
Visual Studio 2019 so a separate installation is not required. If you do install
CMake separately, Visual Studio 2022 will require CMake Version 3.21 or later.
If you would like to run the LLVM tests you will need `Python
<http://www.python.org/>`_. Version 3.8 and newer are known to work. You can
If you would like to run the LLVM tests you will need [Python](http://www.python.org/).
Version 3.8 and newer are known to work. You can
install Python with Visual Studio 2019, from the Microsoft store or from
the `Python web site <http://www.python.org/>`_. We recommend the latter since it
the [Python web site](http://www.python.org/). We recommend the latter since it
allows you to adjust installation options.
You will need `Git for Windows <https://git-scm.com/>`_ with bash tools, too.
You will need [Git for Windows](https://git-scm.com/) with bash tools, too.
Git for Windows is also bundled with Visual Studio 2019.
Getting Started
===============
## Getting Started
Here's the short story for getting up and running quickly with LLVM.
These instructions were tested with Visual Studio 2019 and Python 3.9.6:
1. Download and install `Visual Studio <https://visualstudio.microsoft.com/>`_.
1. Download and install [Visual Studio](https://visualstudio.microsoft.com/).
2. In the Visual Studio installer, Workloads tab, select the
**Desktop development with C++** workload. Under Individual components tab,
select **Git for Windows**.
3. Complete the Visual Studio installation.
4. Download and install the latest `Python 3 release <http://www.python.org/>`_.
4. Download and install the latest [Python 3 release](http://www.python.org/).
5. In the first install screen, select both **Install launcher for all users**
and **Add Python to the PATH**. This will allow installing psutil for all
users for the regression tests and make Python available from the command
line.
6. In the second install screen, select (again) **Install for all users** and
if you want to develop `lldb <https://lldb.llvm.org/>`_, selecting
if you want to develop [lldb](https://lldb.llvm.org/), selecting
**Download debug binaries** is useful.
7. Complete the Python installation.
8. Run a "Developer Command Prompt for VS 2019" **as administrator**. This command
@ -88,176 +85,177 @@ These instructions were tested with Visual Studio 2019 and Python 3.9.6:
the installed tools.
9. In the terminal window, type the commands:
.. code-block:: bat
```bat
c:
cd \
```
c:
cd \
You may install the llvm sources in a location other than ``c:\llvm`` but do not
install into a path containing spaces (e.g., ``c:\Documents and Settings\...``)
as it will fail.
You may install the llvm sources in a location other than `c:\llvm` but do not
install into a path containing spaces (e.g., `c:\Documents and Settings\...`)
as it will fail.
10. Register the Microsoft Debug Interface Access (DIA) DLLs:
.. code-block:: bat
```bat
regsvr32 "%VSINSTALLDIR%\DIA SDK\bin\msdia140.dll"
regsvr32 "%VSINSTALLDIR%\DIA SDK\bin\amd64\msdia140.dll"
```
regsvr32 "%VSINSTALLDIR%\DIA SDK\bin\msdia140.dll"
regsvr32 "%VSINSTALLDIR%\DIA SDK\bin\amd64\msdia140.dll"
The DIA library is required for LLVM PDB tests and
`LLDB development <https://lldb.llvm.org/resources/build.html>`_.
The DIA library is required for LLVM PDB tests and
[LLDB development](https://lldb.llvm.org/resources/build.html).
11. Install psutil and obtain the LLVM source code:
.. code-block:: bat
```bat
pip install psutil
git clone https://github.com/llvm/llvm-project.git llvm
```
pip install psutil
git clone https://github.com/llvm/llvm-project.git llvm
Instead of ``git clone`` you may download a compressed source distribution
from the `releases page <https://github.com/llvm/llvm-project/releases>`_.
Select the last link: ``Source code (zip)`` and unpack the downloaded file using
Windows Explorer built-in zip support or any other unzip tool.
Instead of `git clone` you may download a compressed source distribution
from the [releases page](https://github.com/llvm/llvm-project/releases).
Select the last link: `Source code (zip)` and unpack the downloaded file using
Windows Explorer built-in zip support or any other unzip tool.
12. Finally, configure LLVM using CMake:
.. code-block:: bat
```bat
cmake -S llvm\llvm -B build -DLLVM_ENABLE_PROJECTS=clang -DLLVM_TARGETS_TO_BUILD=X86 -Thost=x64
exit
```
cmake -S llvm\llvm -B build -DLLVM_ENABLE_PROJECTS=clang -DLLVM_TARGETS_TO_BUILD=X86 -Thost=x64
exit
```{note}
By default, the Visual Studio project files generated by CMake use the
32-bit toolset. If you are developing on a 64-bit version of Windows and
want to use the 64-bit toolset, pass the `-Thost=x64` flag when
generating the Visual Studio solution. This requires CMake 3.8.0 or later.
.. note::
By default, the Visual Studio project files generated by CMake use the
32-bit toolset. If you are developing on a 64-bit version of Windows and
want to use the 64-bit toolset, pass the ``-Thost=x64`` flag when
generating the Visual Studio solution. This requires CMake 3.8.0 or later.
For Windows on Arm the equivalent is `-Thost=ARM64`, but this the default
for those hosts, so you do not have to use this option.
```
For Windows on Arm the equivalent is ``-Thost=ARM64``, but this the default
for those hosts, so you do not have to use this option.
`LLVM_ENABLE_PROJECTS` specifies any additional LLVM projects you want to
build while `LLVM_TARGETS_TO_BUILD` selects the compiler targets. If
`LLVM_TARGETS_TO_BUILD` is omitted by default all targets are built
slowing compilation and using more disk space.
See the {doc}`LLVM CMake guide <CMake>` for detailed information about
how to configure the LLVM build.
``LLVM_ENABLE_PROJECTS`` specifies any additional LLVM projects you want to
build while ``LLVM_TARGETS_TO_BUILD`` selects the compiler targets. If
``LLVM_TARGETS_TO_BUILD`` is omitted by default all targets are built
slowing compilation and using more disk space.
See the :doc:`LLVM CMake guide <CMake>` for detailed information about
how to configure the LLVM build.
The `cmake` command line tool is bundled with Visual Studio but its GUI is
not. You may install [CMake](http://www.cmake.org/) to use its GUI to change
CMake variables or modify the above command line.
The ``cmake`` command line tool is bundled with Visual Studio but its GUI is
not. You may install `CMake <http://www.cmake.org/>`_ to use its GUI to change
CMake variables or modify the above command line.
* Once CMake is installed then the simplest way is to just start the
CMake GUI, select the directory where you have LLVM extracted to, and
the default options should all be fine. One option you may really
want to change, regardless of anything else, might be the
``CMAKE_INSTALL_PREFIX`` setting to select a directory to INSTALL to
once compiling is complete, although installation is not mandatory for
using LLVM. Another important option is ``LLVM_TARGETS_TO_BUILD``,
which controls the LLVM target architectures that are included on the
build.
* CMake generates project files for all build types. To select a specific
build type, use the Configuration manager from the VS IDE or the
``/property:Configuration`` command-line option when using MSBuild.
* Once CMake is installed then the simplest way is to just start the
CMake GUI, select the directory where you have LLVM extracted to, and
the default options should all be fine. One option you may really
want to change, regardless of anything else, might be the
`CMAKE_INSTALL_PREFIX` setting to select a directory to INSTALL to
once compiling is complete, although installation is not mandatory for
using LLVM. Another important option is `LLVM_TARGETS_TO_BUILD`,
which controls the LLVM target architectures that are included on the
build.
* CMake generates project files for all build types. To select a specific
build type, use the Configuration manager from the VS IDE or the
`/property:Configuration` command-line option when using MSBuild.
13. Start Visual Studio and select configuration:
In the directory you created the project files will have an ``llvm.sln``
file, just double-click on that to open Visual Studio. The default Visual
Studio configuration is **Debug** which is slow and generates a huge amount
of debug information on disk. For now, we recommend selecting **Release**
configuration for the LLVM project which will build the fastest or
**RelWithDebInfo** which is also several time larger than Release.
Another technique is to build all of LLVM in Release mode and change
compiler flags, disabling optimization and enabling debug information, only
for specific libraries or source files you actually need to debug.
In the directory you created the project files will have an `llvm.sln`
file, just double-click on that to open Visual Studio. The default Visual
Studio configuration is **Debug** which is slow and generates a huge amount
of debug information on disk. For now, we recommend selecting **Release**
configuration for the LLVM project which will build the fastest or
**RelWithDebInfo** which is also several time larger than Release.
Another technique is to build all of LLVM in Release mode and change
compiler flags, disabling optimization and enabling debug information, only
for specific libraries or source files you actually need to debug.
14. Test LLVM in Visual Studio:
You can run LLVM tests by merely building the project "check-all". The test
results will be shown in the VS output window. Once the build succeeds, you
have verified a working LLVM development environment!
You can run LLVM tests by merely building the project "check-all". The test
results will be shown in the VS output window. Once the build succeeds, you
have verified a working LLVM development environment!
You should not see any unexpected failures, but you will see many unsupported
tests and expected failures:
::
You should not see any unexpected failures, but you will see many unsupported
tests and expected failures:
```
114>Testing Time: 1124.66s
114> Skipped : 39
114> Unsupported : 21649
114> Passed : 51615
114> Expectedly Failed: 93
========== Build: 114 succeeded, 0 failed, 321 up-to-date, 0 skipped ==========``
```
## Alternatives to manual installation
Alternatives to manual installation
===================================
Instead of the steps above, to simplify the installation procedure you can use
`Chocolatey <https://chocolatey.org/>`_ as package manager.
After the `installation <https://chocolatey.org/install>`_ of Chocolatey,
[Chocolatey](https://chocolatey.org/) as package manager.
After the [installation](https://chocolatey.org/install) of Chocolatey,
run these commands in an admin shell to install the required tools:
.. code-block:: bat
choco install -y git cmake python3
pip3 install psutil
```bat
choco install -y git cmake python3
pip3 install psutil
```
There is also a Windows
`Dockerfile <https://github.com/llvm/llvm-zorg/blob/main/buildbot/google/docker/windows-base-vscode2019/Dockerfile>`_
[Dockerfile](https://github.com/llvm/llvm-zorg/blob/main/buildbot/google/docker/windows-base-vscode2019/Dockerfile)
with the entire build toolchain. This can be used to test the build with a
toolchain different from your host installation or to create build servers.
Next steps
==========
## Next steps
1. Read the documentation.
2. Seriously, read the documentation.
3. Remember that you were warned twice about reading the documentation.
Test LLVM on the command line:
------------------------------
### Test LLVM on the command line:
The LLVM tests can be run by changing directory to the llvm source
directory and running:
.. code-block:: bat
```bat
c:\llvm> python ..\build\Release\bin\llvm-lit.py llvm\test
```
c:\llvm> python ..\build\Release\bin\llvm-lit.py llvm\test
This example assumes that Python is in your ``PATH`` variable, which would be
This example assumes that Python is in your `PATH` variable, which would be
after **Add Python to the PATH** was selected during Python installation.
If you had opened a command window prior to Python installation, you would
have to close and reopen it to get the updated ``PATH``.
have to close and reopen it to get the updated `PATH`.
A specific test or test directory can be run with:
.. code-block:: bat
```bat
c:\llvm> python ..\build\Release\bin\llvm-lit.py llvm\test\Transforms\Util
```
c:\llvm> python ..\build\Release\bin\llvm-lit.py llvm\test\Transforms\Util
### Build the LLVM Suite:
Build the LLVM Suite:
---------------------
* The projects may still be built individually, but to build them all do
not just select all of them in batch build (as some are meant as
configuration projects), but rather select and build just the
``ALL_BUILD`` project to build everything, or the ``INSTALL`` project,
which first builds the ``ALL_BUILD`` project, then installs the LLVM
`ALL_BUILD` project to build everything, or the `INSTALL` project,
which first builds the `ALL_BUILD` project, then installs the LLVM
headers, libs, and other useful things to the directory set by the
``CMAKE_INSTALL_PREFIX`` setting when you first configured CMake.
`CMAKE_INSTALL_PREFIX` setting when you first configured CMake.
* The Fibonacci project is a sample program that uses the JIT. Modify the
project's debugging properties to provide a numeric command-line argument
or run it from the command line. The program will print the
corresponding Fibonacci value.
Links
=====
## Links
This document is just an **introduction** to how to use LLVM to do some simple
things... there are many more interesting and complicated things that you can
do that aren't documented here (but we'll gladly accept a patch if you want to
write something up!). For more information about LLVM, check out:
* `LLVM homepage <https://llvm.org/>`_
* `LLVM doxygen tree <https://llvm.org/doxygen/>`_
* [LLVM homepage](https://llvm.org/)
* [LLVM doxygen tree](https://llvm.org/doxygen/)
* Additional information about the LLVM directory structure and tool chain
can be found on the main :doc:`GettingStarted` page.
can be found on the main {doc}`GettingStarted` page.
* If you are having problems building or using LLVM, or if you have any other
general questions about LLVM, please consult the
:doc:`Frequently Asked Questions <FAQ>` page.
{doc}`Frequently Asked Questions <FAQ>` page.

View file

@ -1,371 +1,343 @@
===================================
Instrumentation Profile Format
===================================
# Instrumentation Profile Format
.. contents::
:local:
```{contents}
:local:
```
## Overview
Overview
=========
Clang supports two types of profiling via instrumentation [1]_: frontend-based
and IR-based, and both could support a variety of use cases [2]_ .
Clang supports two types of profiling via instrumentation [^1]: frontend-based
and IR-based, and both could support a variety of use cases [^2] .
This document describes two binary serialization formats (raw and indexed) to
store instrumented profiles with a specific emphasis on IRPGO use case, in the
sense that when specific header fields and payload sections have different ways
of interpretation across use cases, the documentation is based on IRPGO.
.. note::
Frontend-generated profiles are used together with coverage mapping for
`source-based code coverage`_. The `coverage mapping format`_ is different from
profile format.
```{note}
Frontend-generated profiles are used together with coverage mapping for
[source-based code coverage](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html). The [coverage mapping format](https://llvm.org/docs/CoverageMappingFormat.html) is different from
profile format.
```
.. _`source-based code coverage`: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
.. _`coverage mapping format`: https://llvm.org/docs/CoverageMappingFormat.html
Raw Profile Format
===================
## Raw Profile Format
The raw profile is generated by running the instrumented binary. The raw profile
data from an executable or a shared library [3]_ consists of a header and
data from an executable or a shared library [^3] consists of a header and
multiple sections, with each section as a memory dump. The raw profile data needs
to be reasonably compact and fast to generate.
There are no backward or forward version compatibility guarantees for the raw profile
format. That is, compilers and tools `require`_ a specific raw profile version
format. That is, compilers and tools [require](https://github.com/llvm/llvm-project/blob/bffdde8b8e5d9a76a47949cd0f574f3ce656e181/llvm/lib/ProfileData/InstrProfReader.cpp#L551-L558) a specific raw profile version
to parse the profiles.
.. _`require`: https://github.com/llvm/llvm-project/blob/bffdde8b8e5d9a76a47949cd0f574f3ce656e181/llvm/lib/ProfileData/InstrProfReader.cpp#L551-L558
To feed profiles back into compilers for an optimized build (e.g., via
``-fprofile-use`` for IR instrumentation), a raw profile must to be converted into
`-fprofile-use` for IR instrumentation), a raw profile must to be converted into
indexed format.
General Storage Layout
-----------------------
### General Storage Layout
The storage layout of raw profile data format is illustrated below. Basically,
when the raw profile is read into an memory buffer, the actual byte offset of a
section is inferred from the section's order in the layout and size information
of all the sections ahead of it.
::
```
+----+-----------------------+
| | Magic |
| +-----------------------+
| | Version |
| +-----------------------+
H | Size Info for |
E | Section 1 |
A +-----------------------+
D | Size Info for |
E | Section 2 |
R +-----------------------+
| | ... |
| +-----------------------+
| | Size Info for |
| | Section N |
+----+-----------------------+
P | Section 1 |
A +-----------------------+
Y | Section 2 |
L +-----------------------+
O | ... |
A +-----------------------+
D | Section N |
+----+-----------------------+
```
+----+-----------------------+
| | Magic |
| +-----------------------+
| | Version |
| +-----------------------+
H | Size Info for |
E | Section 1 |
A +-----------------------+
D | Size Info for |
E | Section 2 |
R +-----------------------+
| | ... |
| +-----------------------+
| | Size Info for |
| | Section N |
+----+-----------------------+
P | Section 1 |
A +-----------------------+
Y | Section 2 |
L +-----------------------+
O | ... |
A +-----------------------+
D | Section N |
+----+-----------------------+
```{note}
Sections might be padded to meet specific alignment requirements. For
simplicity, header fields and data sections solely for padding purposes are
omitted in the data layout graph above and the rest of this document.
```
### Header
.. note::
Sections might be padded to meet specific alignment requirements. For
simplicity, header fields and data sections solely for padding purposes are
omitted in the data layout graph above and the rest of this document.
**`Magic`**
Magic number encodes profile format (raw, indexed or text). For the raw format,
the magic number also encodes the endianness (big or little) and C pointer
size (4 or 8 bytes) of the platform on which the profile is generated.
Header
-------
A factory method reads the magic number to construct reader properly and returns
error upon unrecognized format. Specifically, the factory method and raw profile
reader implementation make sure that a raw profile file could be read back on
a platform with the opposite endianness and/or the other C pointer size.
``Magic``
Magic number encodes profile format (raw, indexed or text). For the raw format,
the magic number also encodes the endianness (big or little) and C pointer
size (4 or 8 bytes) of the platform on which the profile is generated.
**`Version`**
The lower 32 bits specify the actual version and the most significant 32 bits
specify the variant types of the profile. IR-based instrumentation PGO and
context-sensitive IR-based instrumentation PGO are two variant types.
A factory method reads the magic number to construct reader properly and returns
error upon unrecognized format. Specifically, the factory method and raw profile
reader implementation make sure that a raw profile file could be read back on
a platform with the opposite endianness and/or the other C pointer size.
**`BinaryIdsSize`**
The byte size of [binary id] section.
``Version``
The lower 32 bits specify the actual version and the most significant 32 bits
specify the variant types of the profile. IR-based instrumentation PGO and
context-sensitive IR-based instrumentation PGO are two variant types.
**`NumData`**
The number of profile metadata. The byte size of [profile metadata](#profile-metadata) section
could be computed with this field.
``BinaryIdsSize``
The byte size of `binary id`_ section.
**`NumCounter`**
The number of entries in the profile counter section. The byte size of [counter](#counter)
section could be computed with this field.
``NumData``
The number of profile metadata. The byte size of `profile metadata`_ section
could be computed with this field.
**`NumBitmapBytes`**
The number of bytes in the profile [bitmap](#bitmap) section.
``NumCounter``
The number of entries in the profile counter section. The byte size of `counter`_
section could be computed with this field.
**`NamesSize`**
The number of bytes in the name section.
``NumBitmapBytes``
The number of bytes in the profile `bitmap`_ section.
(CountersDelta)=
``NamesSize``
The number of bytes in the name section.
**`CountersDelta`**
This field records the in-memory address difference between the [profile metadata](#profile-metadata)
and counter section in the instrumented binary, i.e., `start(__llvm_prf_cnts) - start(__llvm_prf_data)`.
.. _`CountersDelta`:
It's used jointly with the [CounterPtr](#CounterPtr) field to compute the counter offset
relative to `start(__llvm_prf_cnts)`. Check out [calculation-of-counter-offset](#calculation-of-counter-offset)
for a visualized explanation.
``CountersDelta``
This field records the in-memory address difference between the `profile metadata`_
and counter section in the instrumented binary, i.e., ``start(__llvm_prf_cnts) - start(__llvm_prf_data)``.
```{note}
The `__llvm_prf_data` object file section might not be loaded into memory
when instrumented binary runs or might not get generated in the instrumented
binary in the first place. In those cases, `CountersDelta` is not used and
other mechanisms are used to match counters with instrumented code. See
[lightweight instrumentation] and [binary profile correlation] for examples.
```
It's used jointly with the `CounterPtr`_ field to compute the counter offset
relative to ``start(__llvm_prf_cnts)``. Check out calculation-of-counter-offset_
for a visualized explanation.
**`BitmapDelta`**
This field records the in-memory address difference between the [profile metadata](#profile-metadata)
and bitmap section in the instrumented binary, i.e., `start(__llvm_prf_bits) - start(__llvm_prf_data)`.
.. note::
The ``__llvm_prf_data`` object file section might not be loaded into memory
when instrumented binary runs or might not get generated in the instrumented
binary in the first place. In those cases, ``CountersDelta`` is not used and
other mechanisms are used to match counters with instrumented code. See
`lightweight instrumentation`_ and `binary profile correlation`_ for examples.
It's used jointly with the [BitmapPtr](#BitmapPtr) to find the bitmap of a profile data
record, in a similar way to how counters are referenced as explained by
[calculation-of-counter-offset](#calculation-of-counter-offset) .
``BitmapDelta``
This field records the in-memory address difference between the `profile metadata`_
and bitmap section in the instrumented binary, i.e., ``start(__llvm_prf_bits) - start(__llvm_prf_data)``.
Similar to [CountersDelta](#CountersDelta) field, this field may not be used in non-PGO variants
of profiles.
It's used jointly with the `BitmapPtr`_ to find the bitmap of a profile data
record, in a similar way to how counters are referenced as explained by
calculation-of-counter-offset_ .
**`NamesDelta`**
Records the in-memory address of name section. Not used except for raw profile
reader error checking.
Similar to `CountersDelta`_ field, this field may not be used in non-PGO variants
of profiles.
**`NumVTables`**
Records the number of instrumented vtable entries in the binary. Used for
[type profiling].
``NamesDelta``
Records the in-memory address of name section. Not used except for raw profile
reader error checking.
**`VNamesSize`**
Records the byte size in the virtual table names section. Used for [type profiling].
``NumVTables``
Records the number of instrumented vtable entries in the binary. Used for
`type profiling`_.
**`ValueKindLast`**
Records the number of value kinds. Macro [VALUE_PROF_KIND](https://github.com/llvm/llvm-project/blob/7e405eb722e40c79b7726201d0f76b5dab34ba0f/compiler-rt/include/profile/InstrProfData.inc#L184-L186) defines the value
kinds with a description of the kind.
``VNamesSize``
Records the byte size in the virtual table names section. Used for `type profiling`_.
### Payload Sections
``ValueKindLast``
Records the number of value kinds. Macro `VALUE_PROF_KIND`_ defines the value
kinds with a description of the kind.
.. _`VALUE_PROF_KIND`: https://github.com/llvm/llvm-project/blob/7e405eb722e40c79b7726201d0f76b5dab34ba0f/compiler-rt/include/profile/InstrProfData.inc#L184-L186
Payload Sections
------------------
Binary Ids
^^^^^^^^^^^
#### Binary Ids
Stores the binary ids of the instrumented binaries to associate binaries with
profiles for source code coverage. See `binary id`_ RFC for the design.
profiles for source code coverage. See [binary id] RFC for the design.
.. _`profile metadata`:
(profile-metadata)=
Profile Metadata
^^^^^^^^^^^^^^^^^^
#### Profile Metadata
This section stores the metadata to map counters and value profiles back to
instrumented code regions (e.g., LLVM IR for IRPGO).
The in-memory representation of the metadata is `__llvm_profile_data`_.
The in-memory representation of the metadata is [__llvm_profile_data](https://github.com/llvm/llvm-project/blob/7c3b67d2038cfb48a80299089f6a1308eee1df7f/compiler-rt/include/profile/InstrProfData.inc#L65-L95).
Some fields are used to reference data from other sections in the profile.
The fields are documented as follows:
.. _`__llvm_profile_data`: https://github.com/llvm/llvm-project/blob/7c3b67d2038cfb48a80299089f6a1308eee1df7f/compiler-rt/include/profile/InstrProfData.inc#L65-L95
**`NameRef`**
The MD5 of the function's PGO name. PGO name has the format
`[<filepath><delimiter>]<mangled-name>` where `<filepath>` and
`<delimiter>` are provided for local-linkage functions to tell possibly
identical functions.
``NameRef``
The MD5 of the function's PGO name. PGO name has the format
``[<filepath><delimiter>]<mangled-name>`` where ``<filepath>`` and
``<delimiter>`` are provided for local-linkage functions to tell possibly
identical functions.
(FuncHash)=
.. _FuncHash:
**`FuncHash`**
A checksum of the function's IR, taking control flow graph and instrumented
value sites into account. See [computeCFGHash](https://github.com/llvm/llvm-project/blob/7c3b67d2038cfb48a80299089f6a1308eee1df7f/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp#L616-L685) for details.
``FuncHash``
A checksum of the function's IR, taking control flow graph and instrumented
value sites into account. See `computeCFGHash`_ for details.
(CounterPtr)=
.. _`computeCFGHash`: https://github.com/llvm/llvm-project/blob/7c3b67d2038cfb48a80299089f6a1308eee1df7f/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp#L616-L685
**`CounterPtr`**
The in-memory address difference between profile data and the start of corresponding
counters. Counter position is stored this way (as a link-time constant) to reduce
instrumented binary size compared with snapshotting the address of symbols directly.
See [commit a1532ed](https://github.com/llvm/llvm-project/commit/a1532ed27582038e2d9588108ba0fe8237f01844) for further information.
.. _`CounterPtr`:
```{note}
`CounterPtr` might represent a different value for non-IRPGO use cases. For
example, for [binary profile correlation], it represents the absolute address of counter.
When in doubt, check source code.
```
``CounterPtr``
The in-memory address difference between profile data and the start of corresponding
counters. Counter position is stored this way (as a link-time constant) to reduce
instrumented binary size compared with snapshotting the address of symbols directly.
See `commit a1532ed`_ for further information.
(BitmapPtr)=
.. _`commit a1532ed`: https://github.com/llvm/llvm-project/commit/a1532ed27582038e2d9588108ba0fe8237f01844
**`BitmapPtr`**
The in-memory address difference between profile data and the start address of
corresponding bitmap.
.. note::
``CounterPtr`` might represent a different value for non-IRPGO use cases. For
example, for `binary profile correlation`_, it represents the absolute address of counter.
When in doubt, check source code.
```{note}
Similar to [CounterPtr](#CounterPtr), this field may represent a different value for non-IRPGO use cases.
```
.. _`BitmapPtr`:
**`FunctionPointer`**
Records the function address when instrumented binary runs. This is used to
map the profiled callee address of indirect calls to the `NameRef` during
conversion from raw to indexed profiles.
``BitmapPtr``
The in-memory address difference between profile data and the start address of
corresponding bitmap.
**`Values`**
Represents value profiles in a two dimensional array. The number of elements
in the first dimension is the number of instrumented value sites across all
kinds. Each element in the first dimension is the head of a linked list, and
the each element in the second dimension is linked list element, carrying
`<profiled-value, count>` as payload. This is used by compiler runtime when
writing out value profiles.
.. note::
Similar to `CounterPtr`_, this field may represent a different value for non-IRPGO use cases.
```{note}
Value profiling is supported by frontend and IR PGO instrumentation,
but it's not supported in all cases (e.g., [lightweight instrumentation]).
```
``FunctionPointer``
Records the function address when instrumented binary runs. This is used to
map the profiled callee address of indirect calls to the ``NameRef`` during
conversion from raw to indexed profiles.
**`NumCounters`**
The number of counters for the instrumented function.
``Values``
Represents value profiles in a two dimensional array. The number of elements
in the first dimension is the number of instrumented value sites across all
kinds. Each element in the first dimension is the head of a linked list, and
the each element in the second dimension is linked list element, carrying
``<profiled-value, count>`` as payload. This is used by compiler runtime when
writing out value profiles.
**`NumValueSites`**
This is an array of counters, and each counter represents the number of
instrumented sites for a kind of value in the function.
.. note::
Value profiling is supported by frontend and IR PGO instrumentation,
but it's not supported in all cases (e.g., `lightweight instrumentation`_).
**`NumBitmapBytes`**
The number of bitmap bytes for the function.
``NumCounters``
The number of counters for the instrumented function.
(counter)=
``NumValueSites``
This is an array of counters, and each counter represents the number of
instrumented sites for a kind of value in the function.
#### Profile Counters
``NumBitmapBytes``
The number of bitmap bytes for the function.
.. _`counter`:
Profile Counters
^^^^^^^^^^^^^^^^^
For PGO [4]_, the counters within an instrumented function of a specific `FuncHash`_
For PGO [^4], the counters within an instrumented function of a specific [FuncHash](#FuncHash)
are stored contiguously and in an order that is consistent with instrumentation points selection.
.. _calculation-of-counter-offset:
(calculation-of-counter-offset)=
As mentioned above, the recorded counter offset is relative to the profile metadata.
So how are function counters located in the raw profile data?
Basically, the profile reader iterates profile metadata (from the `profile metadata`_
Basically, the profile reader iterates profile metadata (from the [profile metadata](#profile-metadata)
section) and makes use of the recorded relative distances, as illustrated below.
::
+ --> start(__llvm_prf_data) --> +---------------------+ ------------+
| | Data 1 | |
| +---------------------+ =====|| |
| | Data 2 | || |
| +---------------------+ || |
| | ... | || |
Counter| +---------------------+ || |
Delta | | Data N | || |
| +---------------------+ || | CounterPtr1
| || |
| CounterPtr2 || |
| || |
| || |
+ --> start(__llvm_prf_cnts) --> +---------------------+ || |
| ... | || |
+---------------------+ -----||----+
| Counter for | ||
| Data 1 | ||
+---------------------+ ||
| ... | ||
+---------------------+ =====||
| Counter for |
| Data 2 |
+---------------------+
| ... |
+---------------------+
| Counter for |
| Data N |
+---------------------+
```
+ --> start(__llvm_prf_data) --> +---------------------+ ------------+
| | Data 1 | |
| +---------------------+ =====|| |
| | Data 2 | || |
| +---------------------+ || |
| | ... | || |
Counter| +---------------------+ || |
Delta | | Data N | || |
| +---------------------+ || | CounterPtr1
| || |
| CounterPtr2 || |
| || |
| || |
+ --> start(__llvm_prf_cnts) --> +---------------------+ || |
| ... | || |
+---------------------+ -----||----+
| Counter for | ||
| Data 1 | ||
+---------------------+ ||
| ... | ||
+---------------------+ =====||
| Counter for |
| Data 2 |
+---------------------+
| ... |
+---------------------+
| Counter for |
| Data N |
+---------------------+
```
In the graph,
* The profile header records ``CounterDelta`` with the value as ``start(__llvm_prf_cnts) - start(__llvm_prf_data)``.
We will call it ``CounterDeltaInitVal`` below for convenience.
* For each profile data record ``ProfileDataN``, ``CounterPtr`` is recorded as
``start(CounterN) - start(ProfileDataN)``, where ``ProfileDataN`` is the N-th
entry in ``__llvm_prf_data``, and ``CounterN`` represents the corresponding
* The profile header records `CounterDelta` with the value as `start(__llvm_prf_cnts) - start(__llvm_prf_data)`.
We will call it `CounterDeltaInitVal` below for convenience.
* For each profile data record `ProfileDataN`, `CounterPtr` is recorded as
`start(CounterN) - start(ProfileDataN)`, where `ProfileDataN` is the N-th
entry in `__llvm_prf_data`, and `CounterN` represents the corresponding
profile counters.
Each time the reader advances to the next data record, it `updates`_ ``CounterDelta``
to minus the size of one ``ProfileData``.
.. _`updates`: https://github.com/llvm/llvm-project/blob/17ff25a58ee4f29816d932fdb75f0d305718069f/llvm/include/llvm/ProfileData/InstrProfReader.h#L439-L444
Each time the reader advances to the next data record, it [updates](https://github.com/llvm/llvm-project/blob/17ff25a58ee4f29816d932fdb75f0d305718069f/llvm/include/llvm/ProfileData/InstrProfReader.h#L439-L444) `CounterDelta`
to minus the size of one `ProfileData`.
For the counter corresponding to the first data record, the byte offset
relative to the start of the counter section is calculated as ``CounterPtr1 - CounterDeltaInitVal``.
When profile reader advances to the second data record, note ``CounterDelta``
is updated to ``CounterDeltaInitVal - sizeof(ProfileData)``.
relative to the start of the counter section is calculated as `CounterPtr1 - CounterDeltaInitVal`.
When profile reader advances to the second data record, note `CounterDelta`
is updated to `CounterDeltaInitVal - sizeof(ProfileData)`.
Thus the byte offset relative to the start of the counter section is calculated
as ``CounterPtr2 - (CounterDeltaInitVal - sizeof(ProfileData))``.
as `CounterPtr2 - (CounterDeltaInitVal - sizeof(ProfileData))`.
.. _`bitmap`:
(bitmap)=
Bitmap
^^^^^^^
This section is used for source-based `Modified Condition/Decision Coverage`_ code coverage. Check out `Bitmap RFC`_
#### Bitmap
This section is used for source-based [Modified Condition/Decision Coverage](https://en.wikipedia.org/wiki/Modified_condition/decision_coverage) code coverage. Check out [Bitmap RFC](https://discourse.llvm.org/t/rfc-source-based-mc-dc-code-coverage/59244)
for the design.
.. _`Modified Condition/Decision Coverage`: https://en.wikipedia.org/wiki/Modified_condition/decision_coverage
.. _`Bitmap RFC`: https://discourse.llvm.org/t/rfc-source-based-mc-dc-code-coverage/59244
(function-names)=
.. _`function names`:
Names
^^^^^^
#### Names
This section contains possibly compressed concatenated string of functions' PGO
names. If compressed, zlib library is used.
Function names serve as keys in the PGO data hash table when raw profiles are
converted into indexed profiles. They are also crucial for ``llvm-profdata`` to
converted into indexed profiles. They are also crucial for `llvm-profdata` to
show the profiles in a human-readable way.
Virtual Table Profile Data
^^^^^^^^^^^^^^^^^^^^^^^^^^^
#### Virtual Table Profile Data
This section is used for `type profiling`_. Each entry corresponds to one virtual
This section is used for [type profiling]. Each entry corresponds to one virtual
table and is defined by the following C++ struct
.. code-block:: c++
struct VTableProfData {
// The start address of the vtable, collected at runtime.
uint64_t StartAddress;
// The byte size of the vtable. `StartAddress` and `ByteSize` specifies an address range to look up.
uint32_t ByteSize;
// The hash of vtable's (PGO) name
uint64_t MD5HashOfName;
};
```c++
struct VTableProfData {
// The start address of the vtable, collected at runtime.
uint64_t StartAddress;
// The byte size of the vtable. `StartAddress` and `ByteSize` specifies an address range to look up.
uint32_t ByteSize;
// The hash of vtable's (PGO) name
uint64_t MD5HashOfName;
};
```
At profile use time, the compiler looks up a profiled address in the sorted vtable
address ranges and maps the address to a specific vtable through hashed name.
Virtual Table Names
^^^^^^^^^^^^^^^^^^^^
#### Virtual Table Names
This section is similar to `function names`_ section above, except it contains the PGO
This section is similar to [function names](#function-names) section above, except it contains the PGO
names of profiled virtual tables. It's a standalone section such that raw profile
readers could directly find each name set by accessing the corresponding profile
data section.
@ -373,23 +345,19 @@ data section.
This section is stored in raw profiles such that `llvm-profdata` could show the
profiles in a human-readable way.
Value Profile Data
^^^^^^^^^^^^^^^^^^^^
#### Value Profile Data
This section contains the profile data for value profiling.
The value profiles corresponding to a profile metadata are serialized contiguously
as one record, and value profile records are stored in the same order as the
respective profile data, such that a raw profile reader `advances`_ the pointer to
profile data and the pointer to value profile records simultaneously [5]_ to find
value profiles for a per function, per `FuncHash`_ profile data.
respective profile data, such that a raw profile reader [advances](https://github.com/llvm/llvm-project/blob/7e15fa9161eda7497a5d6abf0d951a1d12d86550/llvm/include/llvm/ProfileData/InstrProfReader.h#L456-L457) the pointer to
profile data and the pointer to value profile records simultaneously [^5] to find
value profiles for a per function, per [FuncHash](#FuncHash) profile data.
.. _`advances`: https://github.com/llvm/llvm-project/blob/7e15fa9161eda7497a5d6abf0d951a1d12d86550/llvm/include/llvm/ProfileData/InstrProfReader.h#L456-L457
## Indexed Profile Format
Indexed Profile Format
===========================
Indexed profiles are generated from ``llvm-profdata``. In the indexed profiles,
Indexed profiles are generated from `llvm-profdata`. In the indexed profiles,
function data are organized as on-disk hash table such that compilers can
look up profile data for functions in an IR module.
@ -397,135 +365,118 @@ Compilers and tools must retain backward compatibility with indexed profiles.
That is, a tool or a compiler built at newer versions of code must understand
profiles generated by older tools or compilers.
General Storage Layout
-----------------------
### General Storage Layout
The ASCII art depicts the general storage layout of indexed profiles.
Specifically, the indexed profile header describes the byte offset of individual
payload sections.
::
```
+-----------------------+---+
| Magic | |
+-----------------------+ |
| Version | |
+-----------------------+ |
| HashType | H
+-----------------------+ E
| Byte Offset | A
+------ | of section A | D
| +-----------------------+ E
| | Byte Of fset | R
+-----------| of section B | |
| | +-----------------------+ |
| | | ... | |
| | +-----------------------+ |
| | | Byte Offset | |
+---------------| of section Z | |
| | | +-----------------------+---+
| | | | Profile Summary | |
| | | +-----------------------+ P
| | +------>| Section A | A
| | +-----------------------+ Y
| +---------->| Section B | L
| +-----------------------+ O
| | ... | A
| +-----------------------+ D
+-------------->| Section Z | |
+-----------------------+---+
```
+-----------------------+---+
| Magic | |
+-----------------------+ |
| Version | |
+-----------------------+ |
| HashType | H
+-----------------------+ E
| Byte Offset | A
+------ | of section A | D
| +-----------------------+ E
| | Byte Of fset | R
+-----------| of section B | |
| | +-----------------------+ |
| | | ... | |
| | +-----------------------+ |
| | | Byte Offset | |
+---------------| of section Z | |
| | | +-----------------------+---+
| | | | Profile Summary | |
| | | +-----------------------+ P
| | +------>| Section A | A
| | +-----------------------+ Y
| +---------->| Section B | L
| +-----------------------+ O
| | ... | A
| +-----------------------+ D
+-------------->| Section Z | |
+-----------------------+---+
```{note}
Profile summary section is at the beginning of payload. It's right after the
header so its position is implicitly known after reading the header.
```
.. note::
### Header
Profile summary section is at the beginning of payload. It's right after the
header so its position is implicitly known after reading the header.
Header
--------
The `Header struct`_ is the source of truth and struct fields should explain
The [Header struct](https://github.com/llvm/llvm-project/blob/1a2960bab6381f2b288328e2371829b460ac020c/llvm/include/llvm/ProfileData/InstrProf.h#L1053-L1080) is the source of truth and struct fields should explain
what's in the header. At a high level, `*Offset` fields record section byte
offsets, which are used by readers to locate interesting sections and skip
uninteresting ones.
.. note::
```{note}
To maintain backward compatibility of the indexed profiles, existing fields
shouldn't be deleted from struct definition; the field order shouldn't be
modified. New fields should be appended.
```
To maintain backward compatibility of the indexed profiles, existing fields
shouldn't be deleted from struct definition; the field order shouldn't be
modified. New fields should be appended.
### Payload Sections
.. _`Header struct`: https://github.com/llvm/llvm-project/blob/1a2960bab6381f2b288328e2371829b460ac020c/llvm/include/llvm/ProfileData/InstrProf.h#L1053-L1080
Payload Sections
------------------
(CS) Profile Summary
^^^^^^^^^^^^^^^^^^^^^
#### (CS) Profile Summary
This section is right after profile header. It stores the serialized profile
summary. For context-sensitive IR-based instrumentation PGO, this section stores
an additional profile summary corresponding to the context-sensitive profiles.
.. _`function data`:
(function-data)=
Function data
^^^^^^^^^^^^^^^^^^
#### Function data
This section stores functions and their profiling data as an on-disk hash table.
Profile data for functions with the same name are grouped together and share one
hash table entry (the functions may come from different shared libraries for
instance). The profile data for them are organized as a sequence of key-value
pair where the key is `FuncHash`_, and the value is profiled information (represented
by `InstrProfRecord`_) for the function.
pair where the key is [FuncHash](#FuncHash), and the value is profiled information (represented
by [InstrProfRecord](https://github.com/llvm/llvm-project/blob/7e405eb722e40c79b7726201d0f76b5dab34ba0f/llvm/include/llvm/ProfileData/InstrProf.h#L693)) for the function.
.. _`InstrProfRecord`: https://github.com/llvm/llvm-project/blob/7e405eb722e40c79b7726201d0f76b5dab34ba0f/llvm/include/llvm/ProfileData/InstrProf.h#L693
MemProf Profile data
^^^^^^^^^^^^^^^^^^^^^^
#### MemProf Profile data
This section stores function's memory profiling data. See
`MemProf binary serialization format RFC`_ for the design.
[MemProf binary serialization format RFC](https://lists.llvm.org/pipermail/llvm-dev/2021-September/153007.html) for the design.
.. _`MemProf binary serialization format RFC`: https://lists.llvm.org/pipermail/llvm-dev/2021-September/153007.html
#### Binary Ids
The section is used to carry on [binary id] information from raw profiles.
Binary Ids
^^^^^^^^^^^^^^^^^^^^^^
The section is used to carry on `binary id`_ information from raw profiles.
Temporal Profile Traces
^^^^^^^^^^^^^^^^^^^^^^^^
#### Temporal Profile Traces
The section is used to carry on temporal profile information from raw profiles.
See `temporal profiling`_ for the design.
See [temporal profiling] for the design.
Virtual Table Names
^^^^^^^^^^^^^^^^^^^^
#### Virtual Table Names
This section is used to store the names of vtables from raw profile in the indexed
profile.
Unlike function names which are stored as keys of `function data`_ hash table,
Unlike function names which are stored as keys of [function data](#function-data) hash table,
vtable names need to be stored in a standalone section in indexed profiles.
This way, `llvm-profdata` could show the profiled vtable information in a
human-readable way.
Profile Data Usage
=======================================
## Profile Data Usage
``llvm-profdata`` is the command line tool to display and process instrumentation-
based profile data. For supported usages, check out `llvm-profdata documentation <https://llvm.org/docs/CommandGuide/llvm-profdata.html>`_.
`llvm-profdata` is the command line tool to display and process instrumentation-
based profile data. For supported usages, check out [llvm-profdata documentation](https://llvm.org/docs/CommandGuide/llvm-profdata.html).
.. [1] For usage, see https://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation
.. [2] For example, IR-based instrumentation supports `lightweight instrumentation`_
and `temporal profiling`_. Frontend instrumentation could support `single-byte counters`_.
.. [3] A raw profile file could contain the concatenation of multiple raw
[^1]: For usage, see https://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation
[^2]: For example, IR-based instrumentation supports [lightweight instrumentation]
and [temporal profiling]. Frontend instrumentation could support [single-byte counters].
[^3]: A raw profile file could contain the concatenation of multiple raw
profiles, for example, from an executable and its shared libraries. Raw
profile reader could parse all raw profiles from the file correctly.
.. [4] The counter section is used by a few variant types (like temporal
[^4]: The counter section is used by a few variant types (like temporal
profiling) and might have different semantics there.
.. [5] The step size of data pointer is the ``sizeof(ProfileData)``, and the step
[^5]: The step size of data pointer is the `sizeof(ProfileData)`, and the step
size of value profile pointer is calculated based on the number of collected
values.
.. _`lightweight instrumentation`: https://groups.google.com/g/llvm-dev/c/r03Z6JoN7d4
.. _`temporal profiling`: https://discourse.llvm.org/t/rfc-temporal-profiling-extension-for-irpgo/68068
.. _`single-byte counters`: https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
.. _`binary profile correlation`: https://discourse.llvm.org/t/rfc-add-binary-profile-correlation-to-not-load-profile-metadata-sections-into-memory-at-runtime/74565
.. _`binary id`: https://lists.llvm.org/pipermail/llvm-dev/2021-June/151154.html
.. _`type profiling`: https://discourse.llvm.org/t/rfc-dynamic-type-profiling-and-optimizations-in-llvm/74600
[lightweight instrumentation]: https://groups.google.com/g/llvm-dev/c/r03Z6JoN7d4
[temporal profiling]: https://discourse.llvm.org/t/rfc-temporal-profiling-extension-for-irpgo/68068
[single-byte counters]: https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
[binary profile correlation]: https://discourse.llvm.org/t/rfc-add-binary-profile-correlation-to-not-load-profile-metadata-sections-into-memory-at-runtime/74565
[binary id]: https://lists.llvm.org/pipermail/llvm-dev/2021-June/151154.html
[type profiling]: https://discourse.llvm.org/t/rfc-dynamic-type-profiling-and-optimizations-in-llvm/74600

View file

@ -1,22 +1,18 @@
================
The LLVM Lexicon
================
# The LLVM Lexicon
.. note::
```{note}
This document is a work in progress!
```
This document is a work in progress!
## Definitions
Definitions
===========
A
-
### A
**ADCE**
Aggressive Dead Code Elimination
: Aggressive Dead Code Elimination
**AST**
Abstract Syntax Tree.
: Abstract Syntax Tree.
Due to Clang's influence (mostly the fact that parsing and semantic
analysis are so intertwined for C and especially C++), the typical
@ -30,31 +26,29 @@ A
Consult your favorite compiler book or search engine for more details.
B
-
### B
.. _lexicon-bb-vectorization:
(lexicon-bb-vectorization)=
**BB Vectorization**
Basic-Block Vectorization
: Basic-Block Vectorization
**BDCE**
Bit-tracking dead code elimination. Some bit-wise instructions (shifts,
: Bit-tracking dead code elimination. Some bit-wise instructions (shifts,
ands, ors, etc.) "kill" some of their input bits -- that is, they make it
such that those bits can be either zero or one without affecting control or
data flow of a program. The BDCE pass removes instructions that only
compute these dead bits.
**BURS**
Bottom Up Rewriting System --- A method of instruction selection for code
generation. An example is the `BURG
<http://www.program-transformation.org/Transform/BURG>`_ tool.
: Bottom Up Rewriting System --- A method of instruction selection for code
generation. An example is the
[BURG](http://www.program-transformation.org/Transform/BURG) tool.
C
-
### C
**CFI**
This abbreviation has two meanings.
: This abbreviation has two meanings.
Either:
Call Frame Information. Used in DWARF debug info and in C++ unwind info
to show how the function prologue lays out the stack frame.
@ -65,132 +59,126 @@ C
of execution (the control flow) of a program.
**CIE**
Common Information Entry. A kind of CFI used to reduce the size of FDEs.
: Common Information Entry. A kind of CFI used to reduce the size of FDEs.
The compiler creates a CIE which contains the information common across all
the FDEs. Each FDE then points to its CIE.
**CSE**
Common Subexpression Elimination. An optimization that removes common
subexpression computation. For example ``(a+b)*(a+b)`` has two
subexpressions that are the same: ``(a+b)``. This optimization would
: Common Subexpression Elimination. An optimization that removes common
subexpression computation. For example `(a+b)*(a+b)` has two
subexpressions that are the same: `(a+b)`. This optimization would
perform the addition only once and then perform the multiply (but only if
it's computationally correct/safe).
D
-
### D
**DAG**
Directed Acyclic Graph
: Directed Acyclic Graph
.. _derived pointer:
.. _derived pointers:
(derived pointer)=
(derived pointers)=
**Derived Pointer**
A pointer to the interior of an object, such that a garbage collector is
: A pointer to the interior of an object, such that a garbage collector is
unable to use the pointer for reachability analysis. While a derived pointer
is live, the corresponding object pointer must be kept in a root, otherwise
the collector might free the referenced object. With copying collectors,
derived pointers pose an additional hazard that they may be invalidated at
any `safe point`_. This term is used in opposition to `object pointer`_.
any {ref}`safe point <safe point>`. This term is used in opposition to
{ref}`object pointer <object pointer>`.
**DSA**
Data Structure Analysis
: Data Structure Analysis
**DSE**
Dead Store Elimination
: Dead Store Elimination
E
-
### E
**ento**
This namespace houses the
`Clang Static Analyzer <https://clang.llvm.org/docs/ClangStaticAnalyzer.html>`_.
It is an abbreviation of `entomology <https://en.wikipedia.org/wiki/Entomology>`_.
: This namespace houses the
[Clang Static Analyzer](https://clang.llvm.org/docs/ClangStaticAnalyzer.html).
It is an abbreviation of [entomology](https://en.wikipedia.org/wiki/Entomology).
*"Entomology is the scientific study of insects."*
In the past, this namespace had not only the name `GR` (aka. Graph Reachability)
but also `entoSA`.
In the past, this namespace had not only the name `GR` (aka. Graph
Reachability) but also `entoSA`.
F
-
### F
**FCA**
First Class Aggregate
: First Class Aggregate
**FDE**
Frame Description Entry. A kind of CFI used to describe the stack frame of
: Frame Description Entry. A kind of CFI used to describe the stack frame of
one function.
G
-
### G
**GC**
Garbage Collection. The practice of using reachability analysis instead of
: Garbage Collection. The practice of using reachability analysis instead of
explicit memory management to reclaim unused memory.
**GEP**
``GetElementPtr``. An LLVM IR instruction that is used to get the address
: `GetElementPtr`. An LLVM IR instruction that is used to get the address
of a subelement of an aggregate data structure. It is documented in detail
`here <https://llvm.org/docs/GetElementPtr.html>`_.
[here](https://llvm.org/docs/GetElementPtr.html).
**GVN**
Global Value Numbering. GVN is a pass that partitions values computed by a
: Global Value Numbering. GVN is a pass that partitions values computed by a
function into congruence classes. Values ending up in the same congruence
class are guaranteed to be the same for every execution of the program.
In that respect, congruency is a compile-time approximation of equivalence
of values at runtime.
H
-
### H
.. _heap:
(heap)=
**Heap**
In garbage collection, the region of memory which is managed using
: In garbage collection, the region of memory which is managed using
reachability analysis.
I
-
### I
**ICE**
Internal Compiler Error. This abbreviation is used to describe errors
: Internal Compiler Error. This abbreviation is used to describe errors
that occur in LLVM or Clang as they are compiling source code. For example,
if a valid C++ source program were to trigger an assert in Clang when
compiled, that could be referred to as an "ICE".
**ICF**
Identical Code Folding
: Identical Code Folding
**ICP**
Indirect Call Promotion
: Indirect Call Promotion
**IPA**
Inter-Procedural Analysis. Refers to any variety of code analysis that
: Inter-Procedural Analysis. Refers to any variety of code analysis that
occurs between procedures, functions or compilation units (modules).
**IPO**
Inter-Procedural Optimization. Refers to any variety of code optimization
: Inter-Procedural Optimization. Refers to any variety of code optimization
that occurs between procedures, functions or compilation units (modules).
**ISel**
Instruction Selection
: Instruction Selection
L
-
### L
**LCSSA**
Loop-Closed Static Single Assignment Form
: Loop-Closed Static Single Assignment Form
**LGTM**
"Looks Good To Me". In a review thread, this indicates that the
: "Looks Good To Me". In a review thread, this indicates that the
reviewer thinks that the patch is okay to commit.
**LICM**
Loop Invariant Code Motion
: Loop Invariant Code Motion
**LSDA**
Language Specific Data Area. C++ "zero cost" unwinding is built on top a
: Language Specific Data Area. C++ "zero cost" unwinding is built on top a
generic unwinding mechanism. As the unwinder walks each frame, it calls
a "personality" function to do language-specific analysis. Each function's
FDE points to an optional LSDA which is passed to the personality function.
@ -198,115 +186,114 @@ L
statements in that function.
**Load-VN**
Load Value Numbering
: Load Value Numbering
**LTO**
Link-Time Optimization
: Link-Time Optimization
M
-
### M
**MC**
Machine Code
: Machine Code
N
-
.. _nfc:
### N
(nfc)=
**NFC**
"No functional change". Used in a commit message to indicate that a patch
is a pure refactoring/cleanup.
Usually used in the first line, so it is visible without opening the
actual commit email.
: "No functional change". Used in a commit message to indicate that a patch
is a pure refactoring/cleanup.
Usually used in the first line, so it is visible without opening the
actual commit email.
O
-
.. _object pointer:
.. _object pointers:
### O
(object pointer)=
(object pointers)=
**Object Pointer**
A pointer to an object such that the garbage collector is able to trace
: A pointer to an object such that the garbage collector is able to trace
references contained within the object. This term is used in opposition to
`derived pointer`_.
{ref}`derived pointer <derived pointer>`.
P
-
### P
**PGO**
Profile-Guided Optimization
: Profile-Guided Optimization
**PR**
Problem report. A bug filed on `the LLVM Bug Tracking System
<https://bugs.llvm.org/enter_bug.cgi>`_.
: Problem report. A bug filed on
[the LLVM Bug Tracking System](https://bugs.llvm.org/enter_bug.cgi).
**PRE**
Partial Redundancy Elimination
: Partial Redundancy Elimination
R
-
### R
**RAUW**
Replace All Uses With. The functions ``User::replaceUsesOfWith()``,
``Value::replaceAllUsesWith()``, and
``Constant::replaceUsesOfWithOnConstant()`` implement the replacement of one
: Replace All Uses With. The functions `User::replaceUsesOfWith()`,
`Value::replaceAllUsesWith()`, and
`Constant::replaceUsesOfWithOnConstant()` implement the replacement of one
Value with another by iterating over its def/use chain and fixing up all of
the pointers to point to the new value. See
also `def/use chains <ProgrammersManual.html#iterating-over-def-use-use-def-chains>`_.
also
{ref}`def/use chains <iterate_chains>`.
**Reassociation**
Rearranging associative expressions to promote better redundancy elimination
and other optimizations. For example, changing ``(A+B-A)`` into ``(B+A-A)``,
permitting it to be optimized into ``(B+0)`` then ``(B)``.
: Rearranging associative expressions to promote better redundancy elimination
and other optimizations. For example, changing `(A+B-A)` into `(B+A-A)`,
permitting it to be optimized into `(B+0)` then `(B)`.
**RFC**
Request for Comment. An email sent to a project mailing list in order to
solicit feedback on a proposed change. See also: the :doc:`RFC process <RFCProcess>`
documentation.
: Request for Comment. An email sent to a project mailing list in order to
solicit feedback on a proposed change. See also: the {doc}`RFC process
<RFCProcess>` documentation.
.. _roots:
.. _stack roots:
(roots)=
(stack roots)=
**Root**
In garbage collection, a pointer variable lying outside of the `heap`_ from
: In garbage collection, a pointer variable lying outside of the
{ref}`heap <heap>` from
which the collector begins its reachability analysis. In the context of code
generation, "root" almost always refers to a "stack root" --- a local or
temporary variable within an executing function.
**RPO**
Reverse postorder
: Reverse postorder
**RTTI**
Run-time Type Information
: Run-time Type Information
S
-
### S
.. _safe point:
(safe point)=
**Safe Point**
In garbage collection, it is necessary to identify `stack roots`_ so that
: In garbage collection, it is necessary to identify
{ref}`stack roots <stack roots>` so that
reachability analysis may proceed. It may be infeasible to provide this
information for every instruction, so instead the information is
calculated only at designated safe points. With a copying collector,
`derived pointers`_ must not be retained across safe points and `object
pointers`_ must be reloaded from stack roots.
{ref}`derived pointers <derived pointers>` must not be retained across safe
points and {ref}`object pointers <object pointers>` must be reloaded from
stack roots.
**SDISel**
Selection DAG Instruction Selection.
: Selection DAG Instruction Selection.
**SCC**
Strongly Connected Component
: Strongly Connected Component
**SCCP**
Sparse Conditional Constant Propagation
: Sparse Conditional Constant Propagation
**SLP**
Superword-Level Parallelism, same as :ref:`Basic-Block Vectorization
: Superword-Level Parallelism, same as {ref}`Basic-Block Vectorization
<lexicon-bb-vectorization>`.
**Splat**
Splat refers to a vector of identical scalar elements.
: Splat refers to a vector of identical scalar elements.
The term is based on the PowerPC Altivec instructions that provided
this functionality in hardware. For example, "vsplth" and the corresponding
@ -314,25 +301,23 @@ S
action include "duplicate" (ARM) and "broadcast" (x86).
**SRoA**
Scalar Replacement of Aggregates
: Scalar Replacement of Aggregates
**SSA**
Static Single Assignment
: Static Single Assignment
**Stack Map**
In garbage collection, metadata emitted by the code generator which
identifies `roots`_ within the stack frame of an executing function.
: In garbage collection, metadata emitted by the code generator which
identifies {ref}`roots <roots>` within the stack frame of an executing
function.
T
-
### T
**TBAA**
Type-Based Alias Analysis
: Type-Based Alias Analysis
W
-
### W
**WPD**
Whole Program Devirtualization
: Whole Program Devirtualization

File diff suppressed because it is too large Load diff

View file

@ -1,17 +1,14 @@
.. _loop-terminology:
(loop-terminology)=
# LLVM Loop Terminology (and Canonical Forms)
===========================================
LLVM Loop Terminology (and Canonical Forms)
===========================================
```{contents}
:local:
```
.. contents::
:local:
Loop Definition
===============
## Loop Definition
Loops are an important concept for a code optimizer. In LLVM, detection
of loops in a control-flow graph is done by :ref:`loopinfo`. It is based
of loops in a control-flow graph is done by {ref}`loopinfo`. It is based
on the following definition.
A loop is a subset of nodes from the control-flow graph (CFG; where
@ -33,11 +30,10 @@ nodes represent basic blocks) with the following properties:
In computer science literature, this is often called a *natural loop*.
In LLVM, a more generalized definition is called a
:ref:`cycle <cycle-terminology>`.
{ref}`cycle <cycle-terminology>`.
Terminology
-----------
### Terminology
The definition of a loop comes with some additional terminology:
@ -55,12 +51,12 @@ The definition of a loop comes with some additional terminology:
of the loop. The source of such an edge is called an **exiting block**, its
target is an **exit block**.
.. image:: ./loop-terminology.svg
:width: 400 px
```{image} ./loop-terminology.svg
:width: 400 px
```
Important Notes
---------------
### Important Notes
This loop definition has some noteworthy consequences:
@ -80,25 +76,26 @@ This loop definition has some noteworthy consequences:
A single block that has no branch to itself is not considered a loop,
even though it is trivially strongly connected.
.. image:: ./loop-single.svg
:width: 300 px
```{image} ./loop-single.svg
:width: 300 px
```
In this case, the role of header, exiting block and latch fall to the
same node. :ref:`loopinfo` reports this as:
.. code-block:: console
$ opt input.ll -passes='print<loops>'
Loop at depth 1 containing: %for.body<header><latch><exiting>
same node. {ref}`loopinfo` reports this as:
```console
$ opt input.ll -passes='print<loops>'
Loop at depth 1 containing: %for.body<header><latch><exiting>
```
* Loops can be nested inside each other. That is, a loop's node set can
be a subset of another loop with a different loop header. The loop
hierarchy in a function forms a forest: Each top-level loop is the
root of the tree of the loops nested inside it.
.. image:: ./loop-nested.svg
:width: 350 px
```{image} ./loop-nested.svg
:width: 350 px
```
* It is not possible that two loops share only a few of their nodes.
@ -106,43 +103,47 @@ same node. :ref:`loopinfo` reports this as:
the example below the left and right subsets both violate the
maximality condition. Only the merge of both sets is considered a loop.
.. image:: ./loop-nonmaximal.svg
:width: 250 px
```{image} ./loop-nonmaximal.svg
:width: 250 px
```
* It is also possible that two logical loops share a header, but are
considered a single loop by LLVM:
.. code-block:: C
for (int i = 0; i < 128; ++i)
for (int j = 0; j < 128; ++j)
body(i,j);
```c
for (int i = 0; i < 128; ++i)
for (int j = 0; j < 128; ++j)
body(i,j);
```
which might be represented in LLVM-IR as follows. Note that there is
only a single header and hence just a single loop.
.. image:: ./loop-merge.svg
:width: 400 px
```{image} ./loop-merge.svg
:width: 400 px
```
The :ref:`LoopSimplify <loop-terminology-loop-simplify>` pass will
The {ref}`LoopSimplify <loop-terminology-loop-simplify>` pass will
detect the loop and ensure separate headers for the outer and inner loop.
.. image:: ./loop-separate.svg
:width: 400 px
```{image} ./loop-separate.svg
:width: 400 px
```
* A cycle in the CFG does not imply there is a loop. The example below
shows such a CFG, where there is no header node that dominates all
other nodes in the cycle. This is called **irreducible control-flow**.
.. image:: ./loop-irreducible.svg
:width: 150 px
```{image} ./loop-irreducible.svg
:width: 150 px
```
The term reducible results from the ability to collapse the CFG into a
single node by successively replacing one of three base structures with
a single node: A sequential execution of basic blocks, acyclic conditional
branches (or switches), and a basic block looping on itself.
`Wikipedia <https://en.wikipedia.org/wiki/Control-flow_graph#Reducibility>`_
[Wikipedia](https://en.wikipedia.org/wiki/Control-flow_graph#Reducibility)
has a more formal definition, which basically says that every cycle has
a dominating header.
@ -152,11 +153,11 @@ a dominating header.
cyclic control flow in its body; a loop that is not nested inside
another loop can still be part of an outer cycle; and there can be
additional cycles between any two loops where one is contained in the other.
However, an LLVM :ref:`cycle<cycle-terminology>` covers both, loops and
However, an LLVM {ref}`cycle <cycle-terminology>` covers both, loops and
irreducible control flow.
* The `FixIrreducible <https://llvm.org/doxygen/FixIrreducible_8h.html>`_
* The [FixIrreducible](https://llvm.org/doxygen/FixIrreducible_8h.html)
pass can transform irreducible control flow into loops by inserting
new loop headers. It is not included in any default optimization pass
pipeline, but is required for some back-end targets.
@ -171,31 +172,30 @@ a dominating header.
loop (i.e. to a latch or header) is not considered part of the loop.
This is illustrated by the following code.
.. code-block:: C
for (unsigned i = 0; i <= n; ++i) {
if (c1) {
// When reaching this block, we will have exited the loop.
```c
for (unsigned i = 0; i <= n; ++i) {
if (c1) {
// When reaching this block, we will have exited the loop.
do_something();
break;
}
if (c2) {
// abort(), never returns, so we have exited the loop.
abort();
}
if (c3) {
// The unreachable allows the compiler to assume that this will not rejoin the loop.
do_something();
__builtin_unreachable();
}
if (c4) {
// This statically infinite loop is not nested because control-flow will not continue with the for-loop.
while(true) {
do_something();
break;
}
if (c2) {
// abort(), never returns, so we have exited the loop.
abort();
}
if (c3) {
// The unreachable allows the compiler to assume that this will not rejoin the loop.
do_something();
__builtin_unreachable();
}
if (c4) {
// This statically infinite loop is not nested because control-flow will not continue with the for-loop.
while(true) {
do_something();
}
}
}
}
```
* There is no requirement for the control flow to eventually leave the
loop, i.e. a loop can be infinite. A **statically infinite loop** is a
@ -204,10 +204,10 @@ a dominating header.
only under some circumstances, such as when n == UINT_MAX in the code
below.
.. code-block:: C
for (unsigned i = 0; i <= n; ++i)
body(i);
```c
for (unsigned i = 0; i <= n; ++i)
body(i);
```
It is possible for the optimizer to turn a dynamically infinite loop
into a statically infinite loop, for instance when it can prove that the
@ -216,46 +216,46 @@ taken, the optimizer can change the conditional branch into an
unconditional one.
If a is loop is annotated with
:ref:`llvm.loop.mustprogress <langref_llvm_loop_mustprogress>` metadata,
{ref}`llvm.loop.mustprogress <langref_llvm_loop_mustprogress>` metadata,
the compiler is allowed to assume that it will eventually terminate, even
if it cannot prove it. For instance, it may remove a mustprogress-loop
that does not have any side-effect in its body even though the program
could be stuck in that loop forever. Languages such as C and
`C++ <https://eel.is/c++draft/intro.progress#1>`_ have such
[C++](https://eel.is/c++draft/intro.progress#1) have such
forward-progress guarantees for some loops. Also see the
:ref:`mustprogress <langref_mustprogress>` and
:ref:`willreturn <langref_willreturn>` function attributes, as well as
the older :ref:`llvm.sideeffect <llvm_sideeffect>` intrinsic.
{ref}`mustprogress <langref_mustprogress>` and
{ref}`willreturn <langref_willreturn>` function attributes, as well as
the older {ref}`llvm.sideeffect <llvm_sideeffect>` intrinsic.
* The number of executions of the loop header before leaving the loop is
the **loop trip count** (or **iteration count**). If the loop should
not be executed at all, a **loop guard** must skip the entire loop:
.. image:: ./loop-guard.svg
:width: 500 px
```{image} ./loop-guard.svg
:width: 500 px
```
Since the first thing a loop header might do is to check whether there
is another execution and if not, immediately exit without doing any work
(also see :ref:`loop-terminology-loop-rotate`), loop trip count is not
(also see {ref}`loop-terminology-loop-rotate`), loop trip count is not
the best measure of a loop's number of iterations. For instance, the
number of header executions of the code below for a non-positive n
(before loop rotation) is 1, even though the loop body is not executed
at all.
.. code-block:: C
for (int i = 0; i < n; ++i)
body(i);
```c
for (int i = 0; i < n; ++i)
body(i);
```
A better measure is the **backedge-taken count**, which is the number of
times any of the backedges is taken before the loop. It is one less than
the trip count for executions that enter the header.
.. _loopinfo:
(loopinfo)=
LoopInfo
========
## LoopInfo
LoopInfo is the core analysis for obtaining information about loops.
There are few key implications of the definitions given above which
@ -275,18 +275,17 @@ are important for working successfully with this interface.
reachability of the loop.
.. _loop-terminology-loop-simplify:
(loop-terminology-loop-simplify)=
Loop Simplify Form
==================
## Loop Simplify Form
The Loop Simplify Form is a canonical form that makes
several analyses and transformations simpler and more effective.
It is ensured by the LoopSimplify
(:ref:`-loop-simplify <passes-loop-simplify>`) pass and is automatically
({ref}`-loop-simplify <passes-loop-simplify>`) pass and is automatically
added by the pass managers when scheduling a LoopPass.
This pass is implemented in
`LoopSimplify.h <https://llvm.org/doxygen/LoopSimplify_8h_source.html>`_.
[LoopSimplify.h](https://llvm.org/doxygen/LoopSimplify_8h_source.html).
When it is successful, the loop has:
* A preheader.
@ -295,10 +294,9 @@ When it is successful, the loop has:
has a predecessor that is outside the loop. This implies
that all exit blocks are dominated by the loop header.
.. _loop-terminology-lcssa:
(loop-terminology-lcssa)=
Loop Closed SSA (LCSSA)
=======================
## Loop Closed SSA (LCSSA)
A program is in Loop Closed SSA Form if it is in SSA form
and all values that are defined in a loop are used only inside
@ -307,52 +305,52 @@ this loop.
Programs written in LLVM IR are always in SSA form but not necessarily
in LCSSA. To achieve the latter, for each value that is live across the
loop boundary, single entry PHI nodes are inserted to each of the exit blocks
[#lcssa-construction]_ in order to "close" these values inside the loop.
[^lcssa-construction] in order to "close" these values inside the loop.
In particular, consider the following loop:
.. code-block:: C
```c
c = ...;
for (...) {
if (c)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2); // X3 defined
}
c = ...;
for (...) {
if (c)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2); // X3 defined
}
... = X3 + 4; // X3 used, i.e. live
// outside the loop
... = X3 + 4; // X3 used, i.e. live
// outside the loop
```
In the inner loop, the X3 is defined inside the loop, but used
outside of it. In Loop Closed SSA form, this would be represented as follows:
.. code-block:: C
```c
c = ...;
for (...) {
if (c)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2);
}
X4 = phi(X3);
c = ...;
for (...) {
if (c)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2);
}
X4 = phi(X3);
... = X4 + 4;
... = X4 + 4;
```
This is still valid LLVM; the extra phi nodes are purely redundant,
but all LoopPass'es are required to preserve them.
This form is ensured by the LCSSA (:ref:`-lcssa <passes-lcssa>`)
This form is ensured by the LCSSA ({ref}`-lcssa <passes-lcssa>`)
pass and is added automatically by the LoopPassManager when
scheduling a LoopPass.
After the loop optimizations are done, these extra phi nodes
will be deleted by :ref:`-instcombine <passes-instcombine>`.
will be deleted by {ref}`-instcombine <passes-instcombine>`.
Note that an exit block is outside of a loop, so how can such a phi "close"
the value inside the loop since it uses it outside of it ? First of all,
for phi nodes, as
`mentioned in the LangRef <https://llvm.org/docs/LangRef.html#phi-instruction>`_:
[mentioned in the LangRef](https://llvm.org/docs/LangRef.html#phi-instruction):
"the use of each incoming value is deemed to occur on the edge from the
corresponding predecessor block to the current block". Now, an
edge to an exit block is considered outside of the loop because
@ -362,7 +360,7 @@ However, an edge doesn't actually contain any IR, so in source code,
we have to choose a convention of whether the use happens in
the current block or in the respective predecessor. For LCSSA's purpose,
we consider the use happens in the latter (so as to consider the
use inside) [#point-of-use-phis]_.
use inside) [^point-of-use-phis].
The major benefit of LCSSA is that it makes many other loop optimizations
simpler.
@ -370,37 +368,37 @@ simpler.
First of all, a simple observation is that if one needs to see all
the outside users, they can just iterate over all the (loop closing)
PHI nodes in the exit blocks (the alternative would be to
scan the def-use chain [#def-use-chain]_ of all instructions in the loop).
scan the def-use chain [^def-use-chain] of all instructions in the loop).
Then, consider for example
:ref:`simple-loop-unswitch <passes-simple-loop-unswitch>` ing the loop above.
{ref}`simple-loop-unswitch <passes-simple-loop-unswitch>` ing the loop above.
Because it is in LCSSA form, we know that any value defined inside of
the loop will be used either only inside the loop or in a loop closing
PHI node. In this case, the only loop closing PHI node is X4.
This means that we can just copy the loop and change the X4
accordingly, like so:
.. code-block:: C
c = ...;
if (c) {
for (...) {
if (true)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2);
}
} else {
for (...) {
if (false)
X1' = ...
else
X2' = ...
X3' = phi(X1', X2');
}
```c
c = ...;
if (c) {
for (...) {
if (true)
X1 = ...
else
X2 = ...
X3 = phi(X1, X2);
}
X4 = phi(X3, X3')
} else {
for (...) {
if (false)
X1' = ...
else
X2' = ...
X3' = phi(X1', X2');
}
}
X4 = phi(X3, X3')
```
Now, all uses of X4 will get the updated value (in general,
if a loop is in LCSSA form, in any loop transformation,
@ -409,7 +407,7 @@ to take effect). If we did not have Loop Closed SSA form, it means that X3 coul
possibly be used outside the loop. So, we would have to introduce the
X4 (which is the new X3) and replace all uses of X3 with that.
However, we should note that because LLVM keeps a def-use chain
[#def-use-chain]_ for each Value, we wouldn't need
[^def-use-chain] for each Value, we wouldn't need
to perform data-flow analysis to find and replace all the uses
(there is even a utility function, replaceAllUsesWith(),
that performs this transformation by iterating the def-use chain).
@ -419,21 +417,21 @@ of an induction variable is the same. Without this, you need to
distinguish the case when the variable is used outside of
the loop it is defined in, for example:
.. code-block:: C
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
k = i + j;
use(k); // use 1
}
use(k); // use 2
```c
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
k = i + j;
use(k); // use 1
}
use(k); // use 2
}
```
Looking from the outer loop with the normal SSA form, the first use of k
is not well-behaved, while the second one is an induction variable with
base 100 and step 1. Although, in practice, and in the LLVM context,
such cases can be handled effectively by SCEV. Scalar Evolution
(:ref:`scalar-evolution <passes-scalar-evolution>`) or SCEV, is a
({ref}`scalar-evolution <passes-scalar-evolution>`) or SCEV, is a
(analysis) pass that analyzes and categorizes the evolution of scalar
expressions in loops.
@ -441,13 +439,13 @@ In general, it's easier to use SCEV in loops that are in LCSSA form.
The evolution of a scalar (loop-variant) expression that
SCEV can analyze is, by definition, relative to a loop.
An expression is represented in LLVM by an
`llvm::Instruction <https://llvm.org/doxygen/classllvm_1_1Instruction.html>`_.
[llvm::Instruction](https://llvm.org/doxygen/classllvm_1_1Instruction.html).
If the expression is inside two (or more) loops (which can only
happen if the loops are nested, like in the example above) and you want
to get an analysis of its evolution (from SCEV),
you have to also specify relative to what Loop you want it.
Specifically, you have to use
`getSCEVAtScope() <https://llvm.org/doxygen/classllvm_1_1ScalarEvolution.html#a21d6ee82eed29080d911dbb548a8bb68>`_.
[getSCEVAtScope()](https://llvm.org/doxygen/classllvm_1_1ScalarEvolution.html#a21d6ee82eed29080d911dbb548a8bb68).
However, if all loops are in LCSSA form, each expression is actually
represented by two different llvm::Instructions. One inside the loop
@ -455,16 +453,14 @@ and one outside, which is the loop-closing PHI node and represents
the value of the expression after the last iteration (effectively,
we break each loop-variant expression into two expressions and so, every
expression is at most in one loop). You can now just use
`getSCEV() <https://llvm.org/doxygen/classllvm_1_1ScalarEvolution.html#a30bd18ac905eacf3601bc6a553a9ff49>`_.
[getSCEV()](https://llvm.org/doxygen/classllvm_1_1ScalarEvolution.html#a30bd18ac905eacf3601bc6a553a9ff49).
and which of these two llvm::Instructions you pass to it disambiguates
the context / scope / relative loop.
.. rubric:: Footnotes
.. [#lcssa-construction] To insert these loop-closing PHI nodes, one has to
[^lcssa-construction]: To insert these loop-closing PHI nodes, one has to
(re-)compute dominance frontiers (if the loop has multiple exits).
.. [#point-of-use-phis] Considering the point of use of a PHI entry value
[^point-of-use-phis]: Considering the point of use of a PHI entry value
to be in the respective predecessor is a convention across the whole LLVM.
The reason is mostly practical; for example it preserves the dominance
property of SSA. It is also just an overapproximation of the actual
@ -484,121 +480,122 @@ the context / scope / relative loop.
use the original value afterwards (in which case the two live ranges overlap,
although in LCSSA (the whole point is that) we never do that).
.. [#def-use-chain] A property of SSA is that there exists a def-use chain
[^def-use-chain]: A property of SSA is that there exists a def-use chain
for each definition, which is a list of all the uses of this definition.
LLVM implements this property by keeping a list of all the uses of a Value
in an internal data structure.
"More Canonical" Loops
======================
## "More Canonical" Loops
.. _loop-terminology-loop-rotate:
(loop-terminology-loop-rotate)=
Rotated Loops
-------------
### Rotated Loops
Loops are rotated by the LoopRotate (:ref:`loop-rotate <passes-loop-rotate>`)
Loops are rotated by the LoopRotate ({ref}`loop-rotate <passes-loop-rotate>`)
pass, which converts loops into do/while style loops and is
implemented in
`LoopRotation.h <https://llvm.org/doxygen/LoopRotation_8h_source.html>`_. Example:
[LoopRotation.h](https://llvm.org/doxygen/LoopRotation_8h_source.html). Example:
.. code-block:: C
void test(int n) {
for (int i = 0; i < n; i += 1)
// Loop body
}
```c
void test(int n) {
for (int i = 0; i < n; i += 1)
// Loop body
}
```
is transformed to:
.. code-block:: C
void test(int n) {
int i = 0;
do {
// Loop body
i += 1;
} while (i < n);
}
```c
void test(int n) {
int i = 0;
do {
// Loop body
i += 1;
} while (i < n);
}
```
**Warning**: This transformation is valid only if the compiler
can prove that the loop body will be executed at least once. Otherwise,
it has to insert a guard which will test it at runtime. In the example
above, that would be:
.. code-block:: C
void test(int n) {
int i = 0;
if (n > 0) {
do {
// Loop body
i += 1;
} while (i < n);
}
```c
void test(int n) {
int i = 0;
if (n > 0) {
do {
// Loop body
i += 1;
} while (i < n);
}
}
```
It's important to understand the effect of loop rotation
at the LLVM IR level. We follow with the previous examples
in LLVM IR while also providing a graphical representation
of the control-flow graphs (CFG). You can get the same graphical
results by utilizing the :ref:`view-cfg <passes-view-cfg>` pass.
results by utilizing the {ref}`view-cfg <passes-view-cfg>` pass.
The initial **for** loop could be translated to:
.. code-block:: none
```
define void @test(i32 %n) {
entry:
br label %for.header
define void @test(i32 %n) {
entry:
br label %for.header
for.header:
%i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
%cond = icmp slt i32 %i, %n
br i1 %cond, label %body, label %exit
for.header:
%i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
%cond = icmp slt i32 %i, %n
br i1 %cond, label %body, label %exit
body:
; Loop body
br label %latch
body:
; Loop body
br label %latch
latch:
%i.next = add nsw i32 %i, 1
br label %for.header
latch:
%i.next = add nsw i32 %i, 1
br label %for.header
exit:
ret void
}
exit:
ret void
}
```
.. image:: ./loop-terminology-initial-loop.png
:width: 400 px
```{image} ./loop-terminology-initial-loop.png
:width: 400 px
```
Before we explain how LoopRotate will actually
transform this loop, here's how we could convert
it (by hand) to a do-while style loop.
.. code-block:: none
```
define void @test(i32 %n) {
entry:
br label %body
define void @test(i32 %n) {
entry:
br label %body
body:
%i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
; Loop body
br label %latch
body:
%i = phi i32 [ 0, %entry ], [ %i.next, %latch ]
; Loop body
br label %latch
latch:
%i.next = add nsw i32 %i, 1
%cond = icmp slt i32 %i.next, %n
br i1 %cond, label %body, label %exit
latch:
%i.next = add nsw i32 %i, 1
%cond = icmp slt i32 %i.next, %n
br i1 %cond, label %body, label %exit
exit:
ret void
}
exit:
ret void
}
```
.. image:: ./loop-terminology-rotated-loop.png
:width: 400 px
```{image} ./loop-terminology-rotated-loop.png
:width: 400 px
```
Note two things:
@ -612,38 +609,40 @@ Note two things:
This is how LoopRotate transforms this loop:
.. code-block:: none
```
define void @test(i32 %n) {
entry:
%guard_cond = icmp slt i32 0, %n
br i1 %guard_cond, label %loop.preheader, label %exit
define void @test(i32 %n) {
entry:
%guard_cond = icmp slt i32 0, %n
br i1 %guard_cond, label %loop.preheader, label %exit
loop.preheader:
br label %body
loop.preheader:
br label %body
body:
%i2 = phi i32 [ 0, %loop.preheader ], [ %i.next, %latch ]
br label %latch
body:
%i2 = phi i32 [ 0, %loop.preheader ], [ %i.next, %latch ]
br label %latch
latch:
%i.next = add nsw i32 %i2, 1
%cond = icmp slt i32 %i.next, %n
br i1 %cond, label %body, label %loop.exit
latch:
%i.next = add nsw i32 %i2, 1
%cond = icmp slt i32 %i.next, %n
br i1 %cond, label %body, label %loop.exit
loop.exit:
br label %exit
loop.exit:
br label %exit
exit:
ret void
}
exit:
ret void
}
```
.. image:: ./loop-terminology-guarded-loop.png
:width: 500 px
```{image} ./loop-terminology-guarded-loop.png
:width: 500 px
```
The result is a little bit more complicated than we may expect
because LoopRotate ensures that the loop is in
:ref:`Loop Simplify Form <loop-terminology-loop-simplify>`
{ref}`Loop Simplify Form <loop-terminology-loop-simplify>`
after rotation.
In this case, it inserted the %loop.preheader basic block so
that the loop has a preheader and it introduced the %loop.exit
@ -658,24 +657,24 @@ invariant instructions, especially loads, into the preheader.
That could be done in non-rotated loops as well but with
some disadvantages. Let's illustrate them with an example:
.. code-block:: C
for (int i = 0; i < n; ++i) {
auto v = *p;
use(v);
}
```c
for (int i = 0; i < n; ++i) {
auto v = *p;
use(v);
}
```
We assume that loading from p is invariant and use(v) is some
statement that uses v.
If we wanted to execute the load only once we could move it
"out" of the loop body, resulting in this:
.. code-block:: C
auto v = *p;
for (int i = 0; i < n; ++i) {
use(v);
}
```c
auto v = *p;
for (int i = 0; i < n; ++i) {
use(v);
}
```
However, now, in the case that n <= 0, in the initial form,
the loop body would never execute, and so, the load would
@ -687,14 +686,14 @@ the initial semantics.
To avoid both of these problems, we can insert a guard:
.. code-block:: C
if (n > 0) { // loop guard
auto v = *p;
for (int i = 0; i < n; ++i) {
use(v);
}
```c
if (n > 0) { // loop guard
auto v = *p;
for (int i = 0; i < n; ++i) {
use(v);
}
}
```
This is certainly better but it could be improved slightly. Notice
that the check for whether n is bigger than 0 is executed twice (and
@ -703,16 +702,16 @@ and once in the first execution of the loop. To avoid that, we could
do an unconditional first execution and insert the loop condition
in the end. This effectively means transforming the loop into a do-while loop:
.. code-block:: C
if (0 < n) {
auto v = *p;
do {
use(v);
++i;
} while (i < n);
}
```c
if (0 < n) {
auto v = *p;
do {
use(v);
++i;
} while (i < n);
}
```
Note that LoopRotate does not generally do such
hoisting. Rather, it is an enabling transformation for other
passes like Loop-Invariant Code Motion (:ref:`-licm <passes-licm>`).
passes like Loop-Invariant Code Motion ({ref}`-licm <passes-licm>`).

File diff suppressed because it is too large Load diff

View file

@ -1,123 +1,120 @@
=========
MemorySSA
=========
# MemorySSA
.. contents::
:local:
```{contents}
:local:
```
Introduction
============
## Introduction
``MemorySSA`` is an analysis that allows us to cheaply reason about the
`MemorySSA` is an analysis that allows us to cheaply reason about the
interactions between various memory operations. Its goal is to replace
``MemoryDependenceAnalysis`` for most (if not all) use-cases. This is because,
unless you're very careful, use of ``MemoryDependenceAnalysis`` can easily
result in quadratic-time algorithms in LLVM. Additionally, ``MemorySSA`` doesn't
have as many arbitrary limits as ``MemoryDependenceAnalysis``, so you should get
better results, too. One common use of ``MemorySSA`` is to quickly find out
`MemoryDependenceAnalysis` for most (if not all) use-cases. This is because,
unless you're very careful, use of `MemoryDependenceAnalysis` can easily
result in quadratic-time algorithms in LLVM. Additionally, `MemorySSA` doesn't
have as many arbitrary limits as `MemoryDependenceAnalysis`, so you should get
better results, too. One common use of `MemorySSA` is to quickly find out
that something definitely cannot happen (for example, reason that a hoist
out of a loop can't happen).
At a high level, one of the goals of ``MemorySSA`` is to provide an SSA based
At a high level, one of the goals of `MemorySSA` is to provide an SSA based
form for memory, complete with def-use and use-def chains, which
enables users to quickly find may-def and may-uses of memory operations.
It can also be thought of as a way to cheaply give versions to the complete
state of memory, and associate memory operations with those versions.
This document goes over how ``MemorySSA`` is structured, and some basic
intuition on how ``MemorySSA`` works.
This document goes over how `MemorySSA` is structured, and some basic
intuition on how `MemorySSA` works.
A paper on MemorySSA (with notes about how it's implemented in GCC) `can be
found here <http://www.airs.com/dnovillo/Papers/mem-ssa.pdf>`_. Though, it's
A paper on MemorySSA (with notes about how it's implemented in GCC) [can be
found here](http://www.airs.com/dnovillo/Papers/mem-ssa.pdf). Though, it's
relatively out-of-date; the paper references multiple memory partitions, but GCC
eventually swapped to just using one, like we now have in LLVM. Like
GCC's, LLVM's MemorySSA is intraprocedural.
MemorySSA Structure
===================
## MemorySSA Structure
MemorySSA is a virtual IR. After it's built, ``MemorySSA`` will contain a
structure that maps ``Instruction``\ s to ``MemoryAccess``\ es, which are
``MemorySSA``'s parallel to LLVM ``Instruction``\ s.
MemorySSA is a virtual IR. After it's built, `MemorySSA` will contain a
structure that maps `Instruction`s to `MemoryAccess`es, which are
`MemorySSA`'s parallel to LLVM `Instruction`s.
Each ``MemoryAccess`` can be one of three types:
Each `MemoryAccess` can be one of three types:
- ``MemoryDef``
- ``MemoryPhi``
- ``MemoryUse``
- `MemoryDef`
- `MemoryPhi`
- `MemoryUse`
``MemoryDef``\ s are operations which may either modify memory, or which
introduce some kind of ordering constraints. Examples of ``MemoryDef``\ s
include ``store``\ s, function calls, ``load``\ s with ``acquire`` (or higher)
ordering, volatile operations, memory fences, etc. A ``MemoryDef``
`MemoryDef`s are operations which may either modify memory, or which
introduce some kind of ordering constraints. Examples of `MemoryDef`s
include `store`s, function calls, `load`s with `acquire` (or higher)
ordering, volatile operations, memory fences, etc. A `MemoryDef`
always introduces a new version of the entire memory and is linked with a single
``MemoryDef/MemoryPhi`` which is the version of memory that the new
`MemoryDef/MemoryPhi` which is the version of memory that the new
version is based on. This implies that there is a *single*
``Def`` chain that connects all the ``Def``\ s, either directly
`Def` chain that connects all the `Def`s, either directly
or indirectly. For example in:
.. code-block:: llvm
```llvm
b = MemoryDef(a)
c = MemoryDef(b)
d = MemoryDef(c)
``d`` is connected directly with ``c`` and indirectly with ``b``.
This means that ``d`` potentially clobbers (see below) ``c`` *or*
``b`` *or* both. This in turn implies that without the use of `The walker`_,
initially every ``MemoryDef`` clobbers every other ``MemoryDef``.
```
``MemoryPhi``\ s are ``PhiNode``\ s, but for memory operations. If at any
point we have two (or more) ``MemoryDef``\ s that could flow into a
``BasicBlock``, the block's top ``MemoryAccess`` will be a
``MemoryPhi``. As in LLVM IR, ``MemoryPhi``\ s don't correspond to any
concrete operation. As such, ``BasicBlock``\ s are mapped to ``MemoryPhi``\ s
inside ``MemorySSA``, whereas ``Instruction``\ s are mapped to ``MemoryUse``\ s
and ``MemoryDef``\ s.
`d` is connected directly with `c` and indirectly with `b`.
This means that `d` potentially clobbers (see below) `c` *or*
`b` *or* both. This in turn implies that without the use of [The walker](#the-walker),
initially every `MemoryDef` clobbers every other `MemoryDef`.
`MemoryPhi`s are `PhiNode`s, but for memory operations. If at any
point we have two (or more) `MemoryDef`s that could flow into a
`BasicBlock`, the block's top `MemoryAccess` will be a
`MemoryPhi`. As in LLVM IR, `MemoryPhi`s don't correspond to any
concrete operation. As such, `BasicBlock`s are mapped to `MemoryPhi`s
inside `MemorySSA`, whereas `Instruction`s are mapped to `MemoryUse`s
and `MemoryDef`s.
Note also that in SSA, Phi nodes merge must-reach definitions (that is,
definitions that *must* be new versions of variables). In MemorySSA, PHI nodes
merge may-reach definitions (that is, until disambiguated, the versions that
reach a phi node may or may not clobber a given variable).
``MemoryUse``\ s are operations which use but don't modify memory. An example of
a ``MemoryUse`` is a ``load``, or a ``readonly`` function call.
`MemoryUse`s are operations which use but don't modify memory. An example of
a `MemoryUse` is a `load`, or a `readonly` function call.
Every function that exists has a special ``MemoryDef`` called ``liveOnEntry``.
It dominates every ``MemoryAccess`` in the function that ``MemorySSA`` is being
Every function that exists has a special `MemoryDef` called `liveOnEntry`.
It dominates every `MemoryAccess` in the function that `MemorySSA` is being
run on, and implies that we've hit the top of the function. It's the only
``MemoryDef`` that maps to no ``Instruction`` in LLVM IR. Use of
``liveOnEntry`` implies that the memory being used is either undefined or
`MemoryDef` that maps to no `Instruction` in LLVM IR. Use of
`liveOnEntry` implies that the memory being used is either undefined or
defined before the function begins.
An example of all of this overlaid on LLVM IR (obtained by running ``opt
-passes='print<memoryssa>' -disable-output`` on an ``.ll`` file) is below. When
An example of all of this overlaid on LLVM IR (obtained by running `opt
-passes='print<memoryssa>' -disable-output` on an `.ll` file) is below. When
viewing this example, it may be helpful to view it in terms of clobbers.
The operands of a given ``MemoryAccess`` are all (potential) clobbers of said
``MemoryAccess``, and the value produced by a ``MemoryAccess`` can act as a clobber
for other ``MemoryAccess``\ es.
The operands of a given `MemoryAccess` are all (potential) clobbers of said
`MemoryAccess`, and the value produced by a `MemoryAccess` can act as a clobber
for other `MemoryAccess`es.
If a ``MemoryAccess`` is a *clobber* of another, it means that these two
``MemoryAccess``\ es may access the same memory. For example, ``x = MemoryDef(y)``
means that ``x`` potentially modifies memory that ``y`` modifies/constrains
If a `MemoryAccess` is a *clobber* of another, it means that these two
`MemoryAccess`es may access the same memory. For example, `x = MemoryDef(y)`
means that `x` potentially modifies memory that `y` modifies/constrains
(or has modified / constrained).
In the same manner, ``a = MemoryPhi({BB1,b},{BB2,c})`` means that
anyone that uses ``a`` is accessing memory potentially modified / constrained
by either ``b`` or ``c`` (or both). And finally, ``MemoryUse(x)`` means
that this use accesses memory that ``x`` has modified / constrained
(as an example, think that if ``x = MemoryDef(...)``
and ``MemoryUse(x)`` are in the same loop, the use can't
In the same manner, `a = MemoryPhi({BB1,b},{BB2,c})` means that
anyone that uses `a` is accessing memory potentially modified / constrained
by either `b` or `c` (or both). And finally, `MemoryUse(x)` means
that this use accesses memory that `x` has modified / constrained
(as an example, think that if `x = MemoryDef(...)`
and `MemoryUse(x)` are in the same loop, the use can't
be hoisted outside alone).
Another useful way of looking at it is in terms of memory versions.
In that view, operands of a given ``MemoryAccess`` are the version
In that view, operands of a given `MemoryAccess` are the version
of the entire memory before the operation, and if the access produces
a value (i.e. ``MemoryDef/MemoryPhi``),
a value (i.e. `MemoryDef/MemoryPhi`),
the value is the new version of the memory after the operation.
.. code-block:: llvm
```llvm
define void @foo() {
entry:
%p1 = alloca i8
@ -152,64 +149,63 @@ the value is the new version of the memory after the operation.
br label %while.cond
}
The ``MemorySSA`` IR is shown in comments that precede the instructions they map
to (if such an instruction exists). For example, ``1 = MemoryDef(liveOnEntry)``
is a ``MemoryAccess`` (specifically, a ``MemoryDef``), and it describes the LLVM
instruction ``store i8 0, ptr %p3``. Other places in ``MemorySSA`` refer to this
particular ``MemoryDef`` as ``1`` (much like how one can refer to ``load i8, ptr
%p1`` in LLVM with ``%1``). Again, ``MemoryPhi``\ s don't correspond to any LLVM
Instruction, so the line directly below a ``MemoryPhi`` isn't special.
```
The `MemorySSA` IR is shown in comments that precede the instructions they map
to (if such an instruction exists). For example, `1 = MemoryDef(liveOnEntry)`
is a `MemoryAccess` (specifically, a `MemoryDef`), and it describes the LLVM
instruction `store i8 0, ptr %p3`. Other places in `MemorySSA` refer to this
particular `MemoryDef` as `1` (much like how one can refer to `load i8, ptr
%p1` in LLVM with `%1`). Again, `MemoryPhi`s don't correspond to any LLVM
Instruction, so the line directly below a `MemoryPhi` isn't special.
Going from the top down:
- ``6 = MemoryPhi({entry,1},{if.end,4})`` notes that, when entering
``while.cond``, the reaching definition for it is either ``1`` or ``4``. This
``MemoryPhi`` is referred to in the textual IR by the number ``6``.
- ``2 = MemoryDef(6)`` notes that ``store i8 0, ptr %p1`` is a definition,
and its reaching definition before it is ``6``, or the ``MemoryPhi`` after
``while.cond``. (See the `Use and Def optimization`_ and `Precision`_
sections below for why this ``MemoryDef`` isn't linked to a separate,
disambiguated ``MemoryPhi``.)
- ``3 = MemoryDef(6)`` notes that ``store i8 0, ptr %p2`` is a definition; its
reaching definition is also ``6``.
- ``5 = MemoryPhi({if.then,2},{if.else,3})`` notes that the clobber before
this block could either be ``2`` or ``3``.
- ``MemoryUse(5)`` notes that ``load i8, ptr %p1`` is a use of memory, and that
it's clobbered by ``5``.
- ``4 = MemoryDef(5)`` notes that ``store i8 2, ptr %p2`` is a definition; its
reaching definition is ``5``.
- ``MemoryUse(1)`` notes that ``load i8, ptr %p3`` is just a user of memory,
and the last thing that could clobber this use is above ``while.cond`` (e.g.
the store to ``%p3``). In memory versioning parlance, it really only depends on
- `6 = MemoryPhi({entry,1},{if.end,4})` notes that, when entering
`while.cond`, the reaching definition for it is either `1` or `4`. This
`MemoryPhi` is referred to in the textual IR by the number `6`.
- `2 = MemoryDef(6)` notes that `store i8 0, ptr %p1` is a definition,
and its reaching definition before it is `6`, or the `MemoryPhi` after
`while.cond`. (See the [Use and Def optimization](#use-and-def-optimization) and
[Precision](#precision) sections below for why this `MemoryDef` isn't linked
to a separate, disambiguated `MemoryPhi`.)
- `3 = MemoryDef(6)` notes that `store i8 0, ptr %p2` is a definition; its
reaching definition is also `6`.
- `5 = MemoryPhi({if.then,2},{if.else,3})` notes that the clobber before
this block could either be `2` or `3`.
- `MemoryUse(5)` notes that `load i8, ptr %p1` is a use of memory, and that
it's clobbered by `5`.
- `4 = MemoryDef(5)` notes that `store i8 2, ptr %p2` is a definition; its
reaching definition is `5`.
- `MemoryUse(1)` notes that `load i8, ptr %p3` is just a user of memory,
and the last thing that could clobber this use is above `while.cond` (e.g.
the store to `%p3`). In memory versioning parlance, it really only depends on
the memory version 1, and is unaffected by the new memory versions generated since
then.
As an aside, ``MemoryAccess`` is a ``Value`` mostly for convenience; it's not
As an aside, `MemoryAccess` is a `Value` mostly for convenience; it's not
meant to interact with LLVM IR.
Design of MemorySSA
===================
## Design of MemorySSA
``MemorySSA`` is an analysis that can be built for any arbitrary function. When
`MemorySSA` is an analysis that can be built for any arbitrary function. When
it's built, it does a pass over the function's IR in order to build up its
mapping of ``MemoryAccess``\ es. You can then query ``MemorySSA`` for things
like the dominance relation between ``MemoryAccess``\ es, and get the
``MemoryAccess`` for any given ``Instruction`` .
mapping of `MemoryAccess`es. You can then query `MemorySSA` for things
like the dominance relation between `MemoryAccess`es, and get the
`MemoryAccess` for any given `Instruction` .
When ``MemorySSA`` is done building, it also hands you a ``MemorySSAWalker``
When `MemorySSA` is done building, it also hands you a `MemorySSAWalker`
that you can use (see below).
The walker
----------
### The walker
A structure that helps ``MemorySSA`` do its job is the ``MemorySSAWalker``, or
A structure that helps `MemorySSA` do its job is the `MemorySSAWalker`, or
the walker, for short. The goal of the walker is to provide answers to clobber
queries beyond what's represented directly by ``MemoryAccess``\ es. For example,
queries beyond what's represented directly by `MemoryAccess`es. For example,
given:
.. code-block:: llvm
```llvm
define void @foo() {
%a = alloca i8
%b = alloca i8
@ -220,80 +216,78 @@ given:
store i8 0, ptr %b
}
The store to ``%a`` is clearly not a clobber for the store to ``%b``. It would
be the walker's goal to figure this out, and return ``liveOnEntry`` when queried
for the clobber of ``MemoryAccess`` ``2``.
```
By default, ``MemorySSA`` provides a walker that can optimize ``MemoryDef``\ s
and ``MemoryUse``\ s by consulting whatever alias analysis stack you happen to
The store to `%a` is clearly not a clobber for the store to `%b`. It would
be the walker's goal to figure this out, and return `liveOnEntry` when queried
for the clobber of `MemoryAccess` `2`.
By default, `MemorySSA` provides a walker that can optimize `MemoryDef`s
and `MemoryUse`s by consulting whatever alias analysis stack you happen to
be using. Walkers were built to be flexible, though, so it's entirely reasonable
(and expected) to create more specialized walkers (e.g. one that specifically
queries ``GlobalsAA``, one that always stops at ``MemoryPhi`` nodes, etc).
queries `GlobalsAA`, one that always stops at `MemoryPhi` nodes, etc).
Default walker APIs
^^^^^^^^^^^^^^^^^^^
#### Default walker APIs
There are two main APIs used to retrieve the clobbering access using the walker:
- ``MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA);`` return the
clobbering memory access for ``MA``, caching all intermediate results
- `MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA);` return the
clobbering memory access for `MA`, caching all intermediate results
computed along the way as part of each access queried.
- ``MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc);``
returns the access clobbering memory location ``Loc``, starting at ``MA``.
- `MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc);`
returns the access clobbering memory location `Loc`, starting at `MA`.
Because this API does not request the clobbering access of a specific memory
access, there are no results that can be cached.
Locating clobbers yourself
^^^^^^^^^^^^^^^^^^^^^^^^^^
#### Locating clobbers yourself
If you choose to make your own walker, you can find the clobber for a
``MemoryAccess`` by walking every ``MemoryDef`` that dominates said
``MemoryAccess``. The structure of ``MemoryDef``\ s makes this relatively simple;
`MemoryAccess` by walking every `MemoryDef` that dominates said
`MemoryAccess`. The structure of `MemoryDef`s makes this relatively simple;
they ultimately form a linked list of every clobber that dominates the
``MemoryAccess`` that you're trying to optimize. In other words, the
``definingAccess`` of a ``MemoryDef`` is always the nearest dominating
``MemoryDef`` or ``MemoryPhi`` of said ``MemoryDef``.
`MemoryAccess` that you're trying to optimize. In other words, the
`definingAccess` of a `MemoryDef` is always the nearest dominating
`MemoryDef` or `MemoryPhi` of said `MemoryDef`.
Use and Def optimization
------------------------
### Use and Def optimization
``MemoryUse``\ s keep a single operand, which is their defining or optimized
`MemoryUse`s keep a single operand, which is their defining or optimized
access.
Traditionally ``MemorySSA`` optimized ``MemoryUse``\ s at build-time, up to a
Traditionally `MemorySSA` optimized `MemoryUse`s at build-time, up to a
given threshold.
Specifically, the operand of every ``MemoryUse`` was optimized to point to the
actual clobber of said ``MemoryUse``. This can be seen in the above example; the
second ``MemoryUse`` in ``if.end`` has an operand of ``1``, which is a
``MemoryDef`` from the entry block. This is done to make walking,
Specifically, the operand of every `MemoryUse` was optimized to point to the
actual clobber of said `MemoryUse`. This can be seen in the above example; the
second `MemoryUse` in `if.end` has an operand of `1`, which is a
`MemoryDef` from the entry block. This is done to make walking,
value numbering, etc, faster and easier.
As of `this revision <https://reviews.llvm.org/D121381>`_, the default was
As of [this revision](https://reviews.llvm.org/D121381), the default was
changed to not optimize uses at build time, in order to provide the option to
reduce compile-time if the walking is not necessary in a pass. Most users call
the new API ``ensureOptimizedUses()`` to keep the previous behavior and do a
one-time optimization of ``MemoryUse``\ s, if this was not done before.
New pass users are recommended to call ``ensureOptimizedUses()``.
the new API `ensureOptimizedUses()` to keep the previous behavior and do a
one-time optimization of `MemoryUse`s, if this was not done before.
New pass users are recommended to call `ensureOptimizedUses()`.
Initially it was not possible to optimize ``MemoryDef``\ s in the same way, as we
restricted ``MemorySSA`` to one operand per access.
This was changed and ``MemoryDef``\ s now keep two operands.
Initially it was not possible to optimize `MemoryDef`s in the same way, as we
restricted `MemorySSA` to one operand per access.
This was changed and `MemoryDef`s now keep two operands.
The first one, the defining access, is
always the previous ``MemoryDef`` or ``MemoryPhi`` in the same basic block, or
always the previous `MemoryDef` or `MemoryPhi` in the same basic block, or
the last one in a dominating predecessor if the current block doesn't have any
other accesses writing to memory. This is needed for walking Def chains.
The second operand is the optimized access, if there was a previous call on the
walker's ``getClobberingMemoryAccess(MA)``. This API will cache information
as part of ``MA``.
Optimizing all ``MemoryDef``\ s has quadratic time complexity and is not done
walker's `getClobberingMemoryAccess(MA)`. This API will cache information
as part of `MA`.
Optimizing all `MemoryDef`s has quadratic time complexity and is not done
by default.
A walk of the uses for any MemoryDef can find the accesses that were optimized
to it.
A code snippet for such a walk looks like this:
.. code-block:: c++
```c++
MemoryDef *Def; // find who's optimized or defining for this MemoryDef
for (auto &U : Def->uses()) {
MemoryAccess *MA = cast<MemoryAccess>(U.getUser());
@ -305,12 +299,13 @@ A code snippet for such a walk looks like this:
}
}
When ``MemoryUse``\ s are optimized, for a given store, you can find all loads
```
When `MemoryUse`s are optimized, for a given store, you can find all loads
clobbered by that store by walking the immediate and transitive uses of
the store.
.. code-block:: c++
```c++
checkUses(MemoryAccess *Def) { // Def can be a MemoryDef or a MemoryPhi.
for (auto &U : Def->uses()) {
MemoryAccess *MA = cast<MemoryAccess>(U.getUser());
@ -328,30 +323,29 @@ the store.
}
}
```
An example of similar traversals can be found in the DeadStoreElimination pass.
Invalidation and updating
-------------------------
### Invalidation and updating
Because ``MemorySSA`` keeps track of LLVM IR, it needs to be updated whenever
Because `MemorySSA` keeps track of LLVM IR, it needs to be updated whenever
the IR is updated. "Update", in this case, includes the addition, deletion, and
motion of ``Instructions``. The update API is being made on an as-needed basis.
If you'd like examples, ``GVNHoist`` and ``LICM`` are users of ``MemorySSA``\ s
motion of `Instructions`. The update API is being made on an as-needed basis.
If you'd like examples, `GVNHoist` and `LICM` are users of `MemorySSA`s
update API.
Note that adding new ``MemoryDef``\ s (by calling ``insertDef``) can be a
time-consuming update, if the new access triggers many ``MemoryPhi`` insertions and
renaming (optimization invalidation) of many ``MemoryAccesses``\ es.
Note that adding new `MemoryDef`s (by calling `insertDef`) can be a
time-consuming update, if the new access triggers many `MemoryPhi` insertions and
renaming (optimization invalidation) of many `MemoryAccesses`es.
Phi placement
^^^^^^^^^^^^^
#### Phi placement
``MemorySSA`` only places ``MemoryPhi``\ s where they're actually
`MemorySSA` only places `MemoryPhi`s where they're actually
needed. That is, it is a pruned SSA form, like LLVM's SSA form. For
example, consider:
.. code-block:: llvm
```llvm
define void @foo() {
entry:
%p1 = alloca i8
@ -381,27 +375,27 @@ example, consider:
br label %while.cond
}
Because we removed the stores from ``if.then`` and ``if.else``, a ``MemoryPhi``
for ``if.end`` would be pointless, so we don't place one. So, if you need to
place a ``MemoryDef`` in ``if.then`` or ``if.else``, you'll need to also create
a ``MemoryPhi`` for ``if.end``.
```
If it turns out that this is a large burden, we can just place ``MemoryPhi``\ s
Because we removed the stores from `if.then` and `if.else`, a `MemoryPhi`
for `if.end` would be pointless, so we don't place one. So, if you need to
place a `MemoryDef` in `if.then` or `if.else`, you'll need to also create
a `MemoryPhi` for `if.end`.
If it turns out that this is a large burden, we can just place `MemoryPhi`s
everywhere. Because we have Walkers that are capable of optimizing above said
phis, doing so shouldn't prohibit optimizations.
Non-Goals
---------
### Non-Goals
``MemorySSA`` is meant to reason about the relation between memory
`MemorySSA` is meant to reason about the relation between memory
operations, and enable quicker querying.
It isn't meant to be the single source of truth for all potential memory-related
optimizations. Specifically, care must be taken when trying to use ``MemorySSA``
optimizations. Specifically, care must be taken when trying to use `MemorySSA`
to reason about atomic or volatile operations, as in:
.. code-block:: llvm
```llvm
define i8 @foo(ptr %a) {
entry:
br i1 undef, label %if.then, label %if.end
@ -416,17 +410,17 @@ to reason about atomic or volatile operations, as in:
ret i8 %av
}
Going solely by ``MemorySSA``'s analysis, hoisting the ``load`` to ``entry`` may
```
Going solely by `MemorySSA`'s analysis, hoisting the `load` to `entry` may
seem legal. Because it's a volatile load, though, it's not.
Design tradeoffs
----------------
### Design tradeoffs
Precision
^^^^^^^^^
#### Precision
``MemorySSA`` in LLVM deliberately trades off precision for speed.
`MemorySSA` in LLVM deliberately trades off precision for speed.
Let us think about memory variables as if they were disjoint partitions of the
memory (that is, if you have one variable, as above, it represents the entire
memory, and if you have multiple variables, each one represents some
@ -462,31 +456,29 @@ have to query something to disambiguate further anyway.
As a result, LLVM partitions to one variable.
Precision in practice
^^^^^^^^^^^^^^^^^^^^^
#### Precision in practice
In practice, there are implementation details in LLVM that also affect the
results' precision provided by ``MemorySSA``. For example, AliasAnalysis has various
caps, or restrictions on looking through phis which can affect what ``MemorySSA``
results' precision provided by `MemorySSA`. For example, AliasAnalysis has various
caps, or restrictions on looking through phis which can affect what `MemorySSA`
can infer. Changes made by different passes may make MemorySSA either "overly
optimized" (it can provide a more accurate result than if it were recomputed
from scratch), or "under optimized" (it could infer more if it were recomputed).
This can lead to challenges to reproduced results in isolation with a single pass
when the result relies on the state acquired by ``MemorySSA`` due to being updated by
when the result relies on the state acquired by `MemorySSA` due to being updated by
multiple subsequent passes.
Passes that use and update ``MemorySSA`` should do so through the APIs provided by the
``MemorySSAUpdater``, or through calls on the Walker.
Direct optimizations to ``MemorySSA`` are not permitted.
Passes that use and update `MemorySSA` should do so through the APIs provided by the
`MemorySSAUpdater`, or through calls on the Walker.
Direct optimizations to `MemorySSA` are not permitted.
There is currently a single, narrowly scoped exception where DSE (DeadStoreElimination)
updates an optimized access of a store, after a traversal that guarantees the
optimization is correct. This is solely allowed due to the traversals and inferences
being beyond what ``MemorySSA`` does and them being "free" (i.e. DSE does them anyway).
being beyond what `MemorySSA` does and them being "free" (i.e. DSE does them anyway).
This exception is set under a flag ("-dse-optimize-memoryssa") and can be disabled to
help reproduce optimizations in isolation.
LLVM Developers Meeting presentations
-------------------------------------
### LLVM Developers Meeting presentations
- `2016 LLVM Developers' Meeting: G. Burgess - MemorySSA in Five Minutes <https://www.youtube.com/watch?v=bdxWmryoHak>`_.
- `2020 LLVM Developers' Meeting: S. Baziotis & S. Moll - Finding Your Way Around the LLVM Dependence Analysis Zoo <https://www.youtube.com/watch?v=1e5y6WDbXCQ>`_
- [2016 LLVM Developers' Meeting: G. Burgess - MemorySSA in Five Minutes](https://www.youtube.com/watch?v=bdxWmryoHak).
- [2020 LLVM Developers' Meeting: S. Baziotis & S. Moll - Finding Your Way Around the LLVM Dependence Analysis Zoo](https://www.youtube.com/watch?v=1e5y6WDbXCQ)

View file

@ -1,143 +1,139 @@
==========================
Using the New Pass Manager
==========================
# Using the New Pass Manager
.. contents::
:local:
```{contents}
:local:
```
Overview
========
## Overview
For an overview of the new pass manager, see the `blog post
<https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager/>`_.
For an overview of the new pass manager, see the [blog post].
Just Tell Me How To Run The Default Optimization Pipeline With The New Pass Manager
===================================================================================
[blog post]: https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager/
.. code-block:: c++
## Just Tell Me How To Run The Default Optimization Pipeline With The New Pass Manager
// Create the analysis managers.
// These must be declared in this order so that they are destroyed in the
// correct order due to inter-analysis-manager references.
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
```cpp
// Create the analysis managers.
// These must be declared in this order so that they are destroyed in the
// correct order due to inter-analysis-manager references.
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
// Create the new pass manager builder.
// Take a look at the PassBuilder constructor parameters for more
// customization, e.g. specifying a TargetMachine or various debugging
// options.
PassBuilder PB;
// Create the new pass manager builder.
// Take a look at the PassBuilder constructor parameters for more
// customization, e.g. specifying a TargetMachine or various debugging
// options.
PassBuilder PB;
// Register all the basic analyses with the managers.
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
// Register all the basic analyses with the managers.
PB.registerModuleAnalyses(MAM);
PB.registerCGSCCAnalyses(CGAM);
PB.registerFunctionAnalyses(FAM);
PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
// Create the pass manager.
// This one corresponds to a typical -O2 optimization pipeline.
ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2);
// Create the pass manager.
// This one corresponds to a typical -O2 optimization pipeline.
ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2);
// Optimize the IR!
MPM.run(MyModule, MAM);
// Optimize the IR!
MPM.run(MyModule, MAM);
```
The C API also supports most of this, see ``llvm-c/Transforms/PassBuilder.h``.
The C API also supports most of this, see `llvm-c/Transforms/PassBuilder.h`.
Adding Passes to a Pass Manager
===============================
## Adding Passes to a Pass Manager
For how to write a new PM pass, see :doc:`this page <WritingAnLLVMNewPMPass>`.
For how to write a new PM pass, see {doc}`this page <WritingAnLLVMNewPMPass>`.
To add a pass to a new PM pass manager, the important thing is to match the
pass type and the pass manager type. For example, a ``FunctionPassManager``
pass type and the pass manager type. For example, a `FunctionPassManager`
can only contain function passes:
.. code-block:: c++
FunctionPassManager FPM;
// InstSimplifyPass is a function pass
FPM.addPass(InstSimplifyPass());
```cpp
FunctionPassManager FPM;
// InstSimplifyPass is a function pass
FPM.addPass(InstSimplifyPass());
```
If you want to add a loop pass that runs on all loops in a function to a
``FunctionPassManager``, the loop pass must be wrapped in a function pass
`FunctionPassManager`, the loop pass must be wrapped in a function pass
adaptor that goes through all the loops in the function and runs the loop
pass on each one.
.. code-block:: c++
FunctionPassManager FPM;
// LoopRotatePass is a loop pass
FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
```cpp
FunctionPassManager FPM;
// LoopRotatePass is a loop pass
FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
```
The IR hierarchy in terms of the new PM is Module -> (CGSCC ->) Function ->
Loop, where going through a CGSCC is optional.
.. code-block:: c++
```cpp
FunctionPassManager FPM;
// loop -> function
FPM.addPass(createFunctionToLoopPassAdaptor(LoopFooPass()));
FunctionPassManager FPM;
// loop -> function
FPM.addPass(createFunctionToLoopPassAdaptor(LoopFooPass()));
CGSCCPassManager CGPM;
// loop -> function -> cgscc
CGPM.addPass(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass())));
// function -> cgscc
CGPM.addPass(createCGSCCToFunctionPassAdaptor(FunctionFooPass()));
CGSCCPassManager CGPM;
// loop -> function -> cgscc
CGPM.addPass(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass())));
// function -> cgscc
CGPM.addPass(createCGSCCToFunctionPassAdaptor(FunctionFooPass()));
ModulePassManager MPM;
// loop -> function -> module
MPM.addPass(createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass())));
// function -> module
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionFooPass()));
// loop -> function -> cgscc -> module
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass()))));
// function -> cgscc -> module
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(FunctionFooPass())));
ModulePassManager MPM;
// loop -> function -> module
MPM.addPass(createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass())));
// function -> module
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionFooPass()));
// loop -> function -> cgscc -> module
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor(LoopFooPass()))));
// function -> cgscc -> module
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(createCGSCCToFunctionPassAdaptor(FunctionFooPass())));
```
A pass manager of a specific IR unit is also a pass of that kind. For
example, a ``FunctionPassManager`` is a function pass, meaning it can be
added to a ``ModulePassManager``:
example, a `FunctionPassManager` is a function pass, meaning it can be
added to a `ModulePassManager`:
.. code-block:: c++
```cpp
ModulePassManager MPM;
ModulePassManager MPM;
FunctionPassManager FPM;
// InstSimplifyPass is a function pass
FPM.addPass(InstSimplifyPass());
FunctionPassManager FPM;
// InstSimplifyPass is a function pass
FPM.addPass(InstSimplifyPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
```
Generally you want to group CGSCC/function/loop passes together in a pass
manager, as opposed to adding adaptors for each pass to the containing upper
level pass manager. For example,
.. code-block:: c++
```cpp
ModulePassManager MPM;
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass1()));
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass2()));
MPM.run();
```
ModulePassManager MPM;
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass1()));
MPM.addPass(createModuleToFunctionPassAdaptor(FunctionPass2()));
MPM.run();
will run `FunctionPass1` on each function in a module, then run
`FunctionPass2` on each function in the module. In contrast,
will run ``FunctionPass1`` on each function in a module, then run
``FunctionPass2`` on each function in the module. In contrast,
```cpp
ModulePassManager MPM;
.. code-block:: c++
FunctionPassManager FPM;
FPM.addPass(FunctionPass1());
FPM.addPass(FunctionPass2());
ModulePassManager MPM;
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
```
FunctionPassManager FPM;
FPM.addPass(FunctionPass1());
FPM.addPass(FunctionPass2());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
will run ``FunctionPass1`` and ``FunctionPass2`` on the first function in a
will run `FunctionPass1` and `FunctionPass2` on the first function in a
module, then run both passes on the second function in the module, and so on.
This is better for cache locality around LLVM data structures. This similarly
applies for the other IR types, and in some cases can even affect the quality
@ -145,48 +141,46 @@ of optimization. For example, running all loop passes on a loop may cause a
later loop to be able to be optimized more than if each loop pass were run
separately.
Inserting Passes into Default Pipelines
=======================================
## Inserting Passes into Default Pipelines
Rather than manually adding passes to a pass manager, the typical way of
creating a pass manager is to use a ``PassBuilder`` and call something like
``PassBuilder::buildPerModuleDefaultPipeline()`` which creates a typical
creating a pass manager is to use a `PassBuilder` and call something like
`PassBuilder::buildPerModuleDefaultPipeline()` which creates a typical
pipeline for a given optimization level.
Sometimes either frontends or backends will want to inject passes into the
pipeline. For example, frontends may want to add instrumentation, and target
backends may want to add passes that lower custom intrinsics. For these
cases, ``PassBuilder`` exposes callbacks that allow injecting passes into
cases, `PassBuilder` exposes callbacks that allow injecting passes into
certain parts of the pipeline. For example,
.. code-block:: c++
```cpp
PassBuilder PB;
PB.registerPipelineStartEPCallback(
[&](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(FooPass());
});
```
PassBuilder PB;
PB.registerPipelineStartEPCallback(
[&](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
MPM.addPass(FooPass());
});
will add `FooPass` near the very beginning of the pipeline for pass
managers created by that `PassBuilder`. See the documentation for
`PassBuilder` for the various places that passes can be added.
will add ``FooPass`` near the very beginning of the pipeline for pass
managers created by that ``PassBuilder``. See the documentation for
``PassBuilder`` for the various places that passes can be added.
If a ``PassBuilder`` has a corresponding ``TargetMachine`` for a backend, it
will call ``TargetMachine::registerPassBuilderCallbacks()`` to allow the
If a `PassBuilder` has a corresponding `TargetMachine` for a backend, it
will call `TargetMachine::registerPassBuilderCallbacks()` to allow the
backend to inject passes into the pipeline.
Clang's ``BackendUtil.cpp`` shows examples of a frontend adding (mostly
Clang's `BackendUtil.cpp` shows examples of a frontend adding (mostly
sanitizer) passes to various parts of the pipeline.
``AMDGPUTargetMachine::registerPassBuilderCallbacks()`` is an example of a
`AMDGPUTargetMachine::registerPassBuilderCallbacks()` is an example of a
backend adding passes to various parts of the pipeline.
Pass plugins can also add passes into default pipelines. Different tools have
different ways of loading dynamic pass plugins. For example, ``opt
-load-pass-plugin=path/to/plugin.so`` loads a pass plugin into ``opt``. For
information on writing a pass plugin, see :doc:`WritingAnLLVMNewPMPass`.
different ways of loading dynamic pass plugins. For example, `opt
-load-pass-plugin=path/to/plugin.so` loads a pass plugin into `opt`. For
information on writing a pass plugin, see {doc}`WritingAnLLVMNewPMPass`.
Using Analyses
==============
## Using Analyses
LLVM provides many analyses that passes can use, such as a dominator tree.
Calculating these can be expensive, so the new pass manager has
@ -196,7 +190,7 @@ When a pass runs on some IR, it also receives an analysis manager which it can
query for analyses. Querying for an analysis will cause the manager to check if
it has already computed the result for the requested IR. If it already has and
the result is still valid, it will return that. Otherwise it will construct a
new result by calling the analysis's ``run()`` method, cache it, and return it.
new result by calling the analysis's `run()` method, cache it, and return it.
You can also ask the analysis manager to only return an analysis if it's
already cached.
@ -208,26 +202,26 @@ down the IR hierarchy. For example, an SCC pass may want to look at function
analyses for the functions inside the SCC. Or it may want to look at some
immutable global analysis. In these cases, the analysis manager can provide a
proxy to an outer or inner level analysis manager. For example, to get a
``FunctionAnalysisManager`` from a ``CGSCCAnalysisManager``, you can call
`FunctionAnalysisManager` from a `CGSCCAnalysisManager`, you can call
.. code-block:: c++
```cpp
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerCGSCCProxy>(InitialC, CG)
.getManager();
```
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerCGSCCProxy>(InitialC, CG)
.getManager();
and use ``FAM`` as a typical ``FunctionAnalysisManager`` that a function pass
and use `FAM` as a typical `FunctionAnalysisManager` that a function pass
would have access to. To get access to an outer level IR analysis, you can
call
.. code-block:: c++
const auto &MAMProxy =
AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
FooAnalysisResult *AR = MAMProxy.getCachedResult<FooAnalysis>(M);
```cpp
const auto &MAMProxy =
AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
FooAnalysisResult *AR = MAMProxy.getCachedResult<FooAnalysis>(M);
```
Asking for a cached and immutable outer level IR analysis works via
``getCachedResult()``, but getting direct access to an outer level IR analysis
`getCachedResult()`, but getting direct access to an outer level IR analysis
manager to compute an outer level IR analysis is not allowed. This is for a
couple reasons.
@ -265,7 +259,7 @@ make sure the function analyses that loop passes use are valid, they are
manually updated in the loop passes to ensure that invalidation is not
necessary. There is a set of common function analyses that loop passes and
analyses have access to which is passed into loop passes as a
``LoopStandardAnalysisResults`` parameter. Other mutable function analyses are
`LoopStandardAnalysisResults` parameter. Other mutable function analyses are
not accessible from loop passes.
As with any caching mechanism, we need some way to tell analysis managers
@ -286,55 +280,55 @@ valid and should be invalidated. If a pass wants to keep some specific
analysis up to date, such as when updating it would be faster than
invalidating and recalculating it, the analysis itself may have methods to
update it for specific transformations, or there may be helper updaters like
``DomTreeUpdater`` for a ``DominatorTree``. Otherwise to mark some analysis
as no longer valid, the pass can return a ``PreservedAnalyses`` with the
`DomTreeUpdater` for a `DominatorTree`. Otherwise to mark some analysis
as no longer valid, the pass can return a `PreservedAnalyses` with the
proper analyses invalidated.
.. code-block:: c++
```cpp
// We've made no transformations that can affect any analyses.
return PreservedAnalyses::all();
// We've made no transformations that can affect any analyses.
return PreservedAnalyses::all();
// We've made transformations and don't want to bother to update any analyses.
return PreservedAnalyses::none();
// We've made transformations and don't want to bother to update any analyses.
return PreservedAnalyses::none();
// We've specifically updated the dominator tree alongside any transformations, but other analysis results may be invalid.
PreservedAnalyses PA;
PA.preserve<DominatorAnalysis>();
return PA;
// We've specifically updated the dominator tree alongside any transformations, but other analysis results may be invalid.
PreservedAnalyses PA;
PA.preserve<DominatorAnalysis>();
return PA;
// We haven't made any control flow changes, any analyses that only care about the control flow are still valid.
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
```
// We haven't made any control flow changes, any analyses that only care about the control flow are still valid.
PreservedAnalyses PA;
PA.preserveSet<CFGAnalyses>();
return PA;
The pass manager will call the analysis manager's ``invalidate()`` method
with the pass's returned ``PreservedAnalyses``. This can be also done
The pass manager will call the analysis manager's `invalidate()` method
with the pass's returned `PreservedAnalyses`. This can be also done
manually within the pass:
.. code-block:: c++
```cpp
FooModulePass::run(Module& M, ModuleAnalysisManager& AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
FooModulePass::run(Module& M, ModuleAnalysisManager& AM) {
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
// Invalidate all analysis results for function F1.
FAM.invalidate(F1, PreservedAnalyses::none());
// Invalidate all analysis results for function F1.
FAM.invalidate(F1, PreservedAnalyses::none());
// Invalidate all analysis results across the entire module.
AM.invalidate(M, PreservedAnalyses::none());
// Invalidate all analysis results across the entire module.
AM.invalidate(M, PreservedAnalyses::none());
// Clear the entry in the analysis manager for function F2 if we've completely removed it from the module.
FAM.clear(F2);
// Clear the entry in the analysis manager for function F2 if we've completely removed it from the module.
FAM.clear(F2);
...
}
...
}
```
One thing to note when accessing inner level IR analyses is cached results for
deleted IR. If a function is deleted in a module pass, its address is still used
as the key for cached analyses. Take care in the pass to either clear the
results for that function or not use inner analyses at all.
``AM.invalidate(M, PreservedAnalyses::none());`` will invalidate the inner
`AM.invalidate(M, PreservedAnalyses::none());` will invalidate the inner
analysis manager proxy which will clear all cached analyses, conservatively
assuming that there are invalid addresses used as keys for cached analyses.
However, if you'd like to be more selective about which analyses are
@ -343,65 +337,64 @@ essentially saying that all deleted entries have been taken care of manually.
This should only be done with measurable compile time gains as it can be tricky
to make sure all the right analyses are invalidated.
Implementing Analysis Invalidation
==================================
## Implementing Analysis Invalidation
By default, an analysis is invalidated if ``PreservedAnalyses`` says that
By default, an analysis is invalidated if `PreservedAnalyses` says that
analyses on the IR unit it runs on are not preserved (see
``AnalysisResultModel::invalidate()``). An analysis can implement
``invalidate()`` to be more conservative when it comes to invalidation. For
`AnalysisResultModel::invalidate()`). An analysis can implement
`invalidate()` to be more conservative when it comes to invalidation. For
example,
.. code-block:: c++
```cpp
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
auto PAC = PA.getChecker<FooAnalysis>();
// the default would be:
// return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()
|| PAC.preservedSet<CFGAnalyses>());
}
```
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
auto PAC = PA.getChecker<FooAnalysis>();
// the default would be:
// return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>());
return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()
|| PAC.preservedSet<CFGAnalyses>());
}
says that if the ``PreservedAnalyses`` specifically preserves
``FooAnalysis``, or if ``PreservedAnalyses`` preserves all analyses (implicit
in ``PAC.preserved()``), or if ``PreservedAnalyses`` preserves all function
analyses, or ``PreservedAnalyses`` preserves all analyses that only care
about the CFG, the ``FooAnalysisResult`` should not be invalidated.
says that if the `PreservedAnalyses` specifically preserves
`FooAnalysis`, or if `PreservedAnalyses` preserves all analyses (implicit
in `PAC.preserved()`), or if `PreservedAnalyses` preserves all function
analyses, or `PreservedAnalyses` preserves all analyses that only care
about the CFG, the `FooAnalysisResult` should not be invalidated.
If an analysis is stateless and generally shouldn't be invalidated, use the
following:
.. code-block:: c++
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise, it's
// stateless and remains preserved.
auto PAC = PA.getChecker<FooAnalysis>();
return !PAC.preservedWhenStateless();
}
```cpp
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise, it's
// stateless and remains preserved.
auto PAC = PA.getChecker<FooAnalysis>();
return !PAC.preservedWhenStateless();
}
```
If an analysis depends on other analyses, those analyses also need to be
checked if they are invalidated:
.. code-block:: c++
```cpp
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv) {
auto PAC = PA.getChecker<FooAnalysis>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>())
return true;
bool FooAnalysisResult::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &Inv) {
auto PAC = PA.getChecker<FooAnalysis>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>())
return true;
// Check transitive dependencies.
return Inv.invalidate<BarAnalysis>(F, PA) ||
Inv.invalidate<BazAnalysis>(F, PA);
}
// Check transitive dependencies.
return Inv.invalidate<BarAnalysis>(F, PA) ||
Inv.invalidate<BazAnalysis>(F, PA);
}
```
Combining invalidation and analysis manager proxies results in some
complexity. For example, when we invalidate all analyses in a module pass,
we have to make sure that we also invalidate function analyses accessible via
any existing inner proxies. The inner proxy's ``invalidate()`` first checks
any existing inner proxies. The inner proxy's `invalidate()` first checks
if the proxy itself should be invalidated. If so, that means the proxy may
contain pointers to IR that is no longer valid, meaning that the inner proxy
needs to completely clear all relevant analysis results. Otherwise the proxy
@ -414,41 +407,40 @@ the outer analysis is invalidated, we need to make sure that dependent inner
analyses are also invalidated. This actually happens with alias analysis
results. Alias analysis is a function-level analysis, but there are
module-level implementations of specific types of alias analysis. Currently
``GlobalsAA`` is the only module-level alias analysis and it generally is not
`GlobalsAA` is the only module-level alias analysis and it generally is not
invalidated so this is not so much of a concern. See
``OuterAnalysisManagerProxy::Result::registerOuterAnalysisInvalidation()``
`OuterAnalysisManagerProxy::Result::registerOuterAnalysisInvalidation()`
for more details.
Invoking ``opt``
================
## Invoking `opt`
.. code-block:: shell
$ opt -passes='pass1,pass2' /tmp/a.ll -S
# -p is an alias for -passes
$ opt -p pass1,pass2 /tmp/a.ll -S
```console
$ opt -passes='pass1,pass2' /tmp/a.ll -S
# -p is an alias for -passes
$ opt -p pass1,pass2 /tmp/a.ll -S
```
The new PM typically requires explicit pass nesting. For example, to run a
function pass, then a module pass, we need to wrap the function pass in a module
adaptor:
.. code-block:: shell
```console
$ opt -passes='function(no-op-function),no-op-module' /tmp/a.ll -S
```
$ opt -passes='function(no-op-function),no-op-module' /tmp/a.ll -S
A more complete example, and ``-debug-pass-manager`` to show the execution
A more complete example, and `-debug-pass-manager` to show the execution
order:
.. code-block:: shell
$ opt -passes='no-op-module,cgscc(no-op-cgscc,function(no-op-function,loop(no-op-loop))),function(no-op-function,loop(no-op-loop))' /tmp/a.ll -S -debug-pass-manager
```console
$ opt -passes='no-op-module,cgscc(no-op-cgscc,function(no-op-function,loop(no-op-loop))),function(no-op-function,loop(no-op-loop))' /tmp/a.ll -S -debug-pass-manager
```
Improper nesting can lead to error messages such as
.. code-block:: shell
$ opt -passes='no-op-function,no-op-module' /tmp/a.ll -S
opt: unknown function pass 'no-op-module'
```console
$ opt -passes='no-op-function,no-op-module' /tmp/a.ll -S
opt: unknown function pass 'no-op-module'
```
The nesting is: module (-> cgscc) -> function -> loop, where the CGSCC nesting is optional.
@ -459,42 +451,41 @@ There are a couple of special cases for easier typing:
* For example, the following are equivalent
.. code-block:: shell
$ opt -passes='no-op-function,no-op-function' /tmp/a.ll -S
$ opt -passes='function(no-op-function,no-op-function)' /tmp/a.ll -S
```console
$ opt -passes='no-op-function,no-op-function' /tmp/a.ll -S
$ opt -passes='function(no-op-function,no-op-function)' /tmp/a.ll -S
```
* If there is an adaptor for a pass that lets it fit in the previous pass
manager, that is implicitly created
* For example, the following are equivalent
.. code-block:: shell
$ opt -passes='no-op-function,no-op-loop' /tmp/a.ll -S
$ opt -passes='no-op-function,loop(no-op-loop)' /tmp/a.ll -S
```console
$ opt -passes='no-op-function,no-op-loop' /tmp/a.ll -S
$ opt -passes='no-op-function,loop(no-op-loop)' /tmp/a.ll -S
```
For a list of available passes and analyses, including the IR unit (module,
CGSCC, function, loop) they operate on, run
.. code-block:: shell
```console
$ opt --print-passes
```
$ opt --print-passes
or take a look at `PassRegistry.def`.
or take a look at ``PassRegistry.def``.
To make sure an analysis named ``foo`` is available before a pass, add
``require<foo>`` to the pass pipeline. This adds a pass that simply requests
To make sure an analysis named `foo` is available before a pass, add
`require<foo>` to the pass pipeline. This adds a pass that simply requests
that the analysis is run. This pass is also subject to proper nesting. For
example, to make sure some function analysis is already computed for all
functions before a module pass:
.. code-block:: shell
```console
$ opt -passes='function(require<my-function-analysis>),my-module-pass' /tmp/a.ll -S
```
$ opt -passes='function(require<my-function-analysis>),my-module-pass' /tmp/a.ll -S
Status of the New and Legacy Pass Managers
==========================================
## Status of the New and Legacy Pass Managers
LLVM currently contains two pass managers, the legacy PM and the new PM. The
optimization pipeline (aka the middle-end) uses the new PM, whereas the backend
@ -505,14 +496,14 @@ deprecated and there are ongoing efforts to remove its usage.
Some IR passes are considered part of the backend codegen pipeline even if
they are LLVM IR passes (whereas all MIR passes are codegen passes). This
includes anything added via ``TargetPassConfig`` hooks, e.g.
``TargetPassConfig::addCodeGenPrepare()``.
includes anything added via `TargetPassConfig` hooks, e.g.
`TargetPassConfig::addCodeGenPrepare()`.
The ``TargetMachine::adjustPassManager()`` function that was used to extend a
The `TargetMachine::adjustPassManager()` function that was used to extend a
legacy PM with passes on a per target basis has been removed. It was mainly
used from opt, but since support for using the default pipelines has been
removed in opt the function isn't needed any longer. In the new PM such
adjustments are done by using ``TargetMachine::registerPassBuilderCallbacks()``.
adjustments are done by using `TargetMachine::registerPassBuilderCallbacks()`.
Currently there are efforts to make the codegen pipeline work with the new
PM.