Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions llvm/docs/Frontend/PerformanceTips.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,36 @@ SSA is the canonical form expected by much of the optimizer; if allocas can
not be eliminated by Mem2Reg or SROA, the optimizer is likely to be less
effective than it could be.

Avoid loads and stores of large aggregate type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Avoid creating values of aggregate type
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Avoid creating values of :ref:`aggregate types <t_aggregate>` (i.e. structs and
arrays). In particular, avoid loading and storing them, or manipulating them
with insertvalue and extractvalue instructions. Instead, only load and store
individual fields of the aggregate.

There are some exceptions to this rule:

* It is fine to use values of aggregate type in global variable initializers.
* It is fine to return structs, if this is done to represent the return of
multiple values in registers.
* It is fine to work with structs returned by LLVM intrinsics, such as the
``with.overflow`` family of intrinsics.
* It is fine to use aggregate *types* without creating values. For example,
they are commonly used in ``getelementptr`` instructions or attributes like
``sret``.

Avoid loads and stores of non-byte-sized types
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "non-byte-sized" a standard term? I first thought it means "types of a size that is not exactly one byte". But I'm also not super familiar with standard LLVM terminology.

The text inside this section makes it clear enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a pretty common term. In the backend we use isByteSized, in the middle-end typeSizeEqualsStoreSize to query these.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Avoid loading or storing non-byte-sized types like ``i1``. Instead,
appropriately extend them to the next byte-sized type.

LLVM currently does not optimize well loads and stores of large :ref:`aggregate
types <t_aggregate>` (i.e. structs and arrays). As an alternative, consider
loading individual fields from memory.
For example, when working with boolean values, store them by zero-extending
``i1`` to ``i8`` and load them by loading ``i8`` and truncating to ``i1``.

Aggregates that are smaller than the largest (performant) load or store
instruction supported by the targeted hardware are well supported. These can
be an effective way to represent collections of small packed fields.
If you do use loads/stores on non-byte-sized types, make sure that you *always*
use those types. For example, do not first store ``i8`` and then load ``i1``.

Prefer zext over sext when legal
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down