summaryrefslogtreecommitdiff
path: root/docs/Frontend/PerformanceTips.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/Frontend/PerformanceTips.rst')
-rw-r--r--docs/Frontend/PerformanceTips.rst227
1 files changed, 170 insertions, 57 deletions
diff --git a/docs/Frontend/PerformanceTips.rst b/docs/Frontend/PerformanceTips.rst
index 8d0abcd1c172c..142d262eb6573 100644
--- a/docs/Frontend/PerformanceTips.rst
+++ b/docs/Frontend/PerformanceTips.rst
@@ -11,12 +11,60 @@ Abstract
The intended audience of this document is developers of language frontends
targeting LLVM IR. This document is home to a collection of tips on how to
-generate IR that optimizes well. As with any optimizer, LLVM has its strengths
-and weaknesses. In some cases, surprisingly small changes in the source IR
-can have a large effect on the generated code.
+generate IR that optimizes well.
+
+IR Best Practices
+=================
+
+As with any optimizer, LLVM has its strengths and weaknesses. In some cases,
+surprisingly small changes in the source IR can have a large effect on the
+generated code.
+
+Beyond the specific items on the list below, it's worth noting that the most
+mature frontend for LLVM is Clang. As a result, the further your IR gets from what Clang might emit, the less likely it is to be effectively optimized. It
+can often be useful to write a quick C program with the semantics you're trying
+to model and see what decisions Clang's IRGen makes about what IR to emit.
+Studying Clang's CodeGen directory can also be a good source of ideas. Note
+that Clang and LLVM are explicitly version locked so you'll need to make sure
+you're using a Clang built from the same svn revision or release as the LLVM
+library you're using. As always, it's *strongly* recommended that you track
+tip of tree development, particularly during bring up of a new project.
+
+The Basics
+^^^^^^^^^^^
+
+#. Make sure that your Modules contain both a data layout specification and
+ target triple. Without these pieces, non of the target specific optimization
+ will be enabled. This can have a major effect on the generated code quality.
+
+#. For each function or global emitted, use the most private linkage type
+ possible (private, internal or linkonce_odr preferably). Doing so will
+ make LLVM's inter-procedural optimizations much more effective.
+
+#. Avoid high in-degree basic blocks (e.g. basic blocks with dozens or hundreds
+ of predecessors). Among other issues, the register allocator is known to
+ perform badly with confronted with such structures. The only exception to
+ this guidance is that a unified return block with high in-degree is fine.
+
+Use of allocas
+^^^^^^^^^^^^^^
+
+An alloca instruction can be used to represent a function scoped stack slot,
+but can also represent dynamic frame expansion. When representing function
+scoped variables or locations, placing alloca instructions at the beginning of
+the entry block should be preferred. In particular, place them before any
+call instructions. Call instructions might get inlined and replaced with
+multiple basic blocks. The end result is that a following alloca instruction
+would no longer be in the entry basic block afterward.
+
+The SROA (Scalar Replacement Of Aggregates) and Mem2Reg passes only attempt
+to eliminate alloca instructions that are in the entry basic block. Given
+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
-================================================
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
@@ -27,7 +75,7 @@ instruction supported by the targeted hardware are well supported. These can
be an effective way to represent collections of small packed fields.
Prefer zext over sext when legal
-==================================
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On some architectures (X86_64 is one), sign extension can involve an extra
instruction whereas zero extension can be folded into a load. LLVM will try to
@@ -39,7 +87,7 @@ Alternatively, you can :ref:`specify the range of the value using metadata
<range-metadata>` and LLVM can do the sext to zext conversion for you.
Zext GEP indices to machine register width
-============================================
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Internally, LLVM often promotes the width of GEP indices to machine register
width. When it does so, it will default to using sign extension (sext)
@@ -47,47 +95,37 @@ operations for safety. If your source language provides information about
the range of the index, you may wish to manually extend indices to machine
register width using a zext instruction.
-Other things to consider
-=========================
-
-#. Make sure that a DataLayout is provided (this will likely become required in
- the near future, but is certainly important for optimization).
+When to specify alignment
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+LLVM will always generate correct code if you don’t specify alignment, but may
+generate inefficient code. For example, if you are targeting MIPS (or older
+ARM ISAs) then the hardware does not handle unaligned loads and stores, and
+so you will enter a trap-and-emulate path if you do a load or store with
+lower-than-natural alignment. To avoid this, LLVM will emit a slower
+sequence of loads, shifts and masks (or load-right + load-left on MIPS) for
+all cases where the load / store does not have a sufficiently high alignment
+in the IR.
-#. Add nsw/nuw flags as appropriate. Reasoning about overflow is
- generally hard for an optimizer so providing these facts from the frontend
- can be very impactful.
+The alignment is used to guarantee the alignment on allocas and globals,
+though in most cases this is unnecessary (most targets have a sufficiently
+high default alignment that they’ll be fine). It is also used to provide a
+contract to the back end saying ‘either this load/store has this alignment, or
+it is undefined behavior’. This means that the back end is free to emit
+instructions that rely on that alignment (and mid-level optimizers are free to
+perform transforms that require that alignment). For x86, it doesn’t make
+much difference, as almost all instructions are alignment-independent. For
+MIPS, it can make a big difference.
-#. Use fast-math flags on floating point operations if legal. If you don't
- need strict IEEE floating point semantics, there are a number of additional
- optimizations that can be performed. This can be highly impactful for
- floating point intensive computations.
+Note that if your loads and stores are atomic, the backend will be unable to
+lower an under aligned access into a sequence of natively aligned accesses.
+As a result, alignment is mandatory for atomic loads and stores.
-#. Use inbounds on geps. This can help to disambiguate some aliasing queries.
-
-#. Add noalias/align/dereferenceable/nonnull to function arguments and return
- values as appropriate
-
-#. Mark functions as readnone/readonly or noreturn/nounwind when known. The
- optimizer will try to infer these flags, but may not always be able to.
- Manual annotations are particularly important for external functions that
- the optimizer can not analyze.
+Other Things to Consider
+^^^^^^^^^^^^^^^^^^^^^^^^
#. Use ptrtoint/inttoptr sparingly (they interfere with pointer aliasing
analysis), prefer GEPs
-#. Use the lifetime.start/lifetime.end and invariant.start/invariant.end
- intrinsics where possible. Common profitable uses are for stack like data
- structures (thus allowing dead store elimination) and for describing
- life times of allocas (thus allowing smaller stack sizes).
-
-#. Use pointer aliasing metadata, especially tbaa metadata, to communicate
- otherwise-non-deducible pointer aliasing facts
-
-#. Use the "most-private" possible linkage types for the functions being defined
- (private, internal or linkonce_odr preferably)
-
-#. Mark invariant locations using !invariant.load and TBAA's constant flags
-
#. Prefer globals over inttoptr of a constant address - this gives you
dereferencability information. In MCJIT, use getSymbolAddress to provide
actual address.
@@ -104,15 +142,6 @@ Other things to consider
desired. This is generally not required because the optimizer will convert
an invoke with an unreachable unwind destination to a call instruction.
-#. If you language uses range checks, consider using the IRCE pass. It is not
- currently part of the standard pass order.
-
-#. For languages with numerous rarely executed guard conditions (e.g. null
- checks, type checks, range checks) consider adding an extra execution or
- two of LoopUnswith and LICM to your pass order. The standard pass order,
- which is tuned for C and C++ applications, may not be sufficient to remove
- all dischargeable checks from loops.
-
#. Use profile metadata to indicate statically known cold paths, even if
dynamic profiling information is not available. This can make a large
difference in code placement and thus the performance of tight loops.
@@ -136,11 +165,6 @@ Other things to consider
improvement. Note that this is not always profitable and does involve a
potentially large increase in code size.
-#. Avoid high in-degree basic blocks (e.g. basic blocks with dozens or hundreds
- of predecessors). Among other issues, the register allocator is known to
- perform badly with confronted with such structures. The only exception to
- this guidance is that a unified return block with high in-degree is fine.
-
#. When checking a value against a constant, emit the check using a consistent
comparison type. The GVN pass *will* optimize redundant equalities even if
the type of comparison is inverted, but GVN only runs late in the pipeline.
@@ -164,10 +188,99 @@ Other things to consider
time and optimization effectiveness. The former is fixable with enough
effort, but the later is fairly fundamental to their designed purpose.
-p.s. If you want to help improve this document, patches expanding any of the
-above items into standalone sections of their own with a more complete
-discussion would be very welcome.
+Describing Language Specific Properties
+=======================================
+
+When translating a source language to LLVM, finding ways to express concepts
+and guarantees available in your source language which are not natively
+provided by LLVM IR will greatly improve LLVM's ability to optimize your code.
+As an example, C/C++'s ability to mark every add as "no signed wrap (nsw)" goes
+a long way to assisting the optimizer in reasoning about loop induction
+variables and thus generating more optimal code for loops.
+
+The LLVM LangRef includes a number of mechanisms for annotating the IR with
+additional semantic information. It is *strongly* recommended that you become
+highly familiar with this document. The list below is intended to highlight a
+couple of items of particular interest, but is by no means exhaustive.
+
+Restricted Operation Semantics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#. Add nsw/nuw flags as appropriate. Reasoning about overflow is
+ generally hard for an optimizer so providing these facts from the frontend
+ can be very impactful.
+
+#. Use fast-math flags on floating point operations if legal. If you don't
+ need strict IEEE floating point semantics, there are a number of additional
+ optimizations that can be performed. This can be highly impactful for
+ floating point intensive computations.
+
+Describing Aliasing Properties
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+#. Add noalias/align/dereferenceable/nonnull to function arguments and return
+ values as appropriate
+
+#. Use pointer aliasing metadata, especially tbaa metadata, to communicate
+ otherwise-non-deducible pointer aliasing facts
+
+#. Use inbounds on geps. This can help to disambiguate some aliasing queries.
+
+
+Modeling Memory Effects
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+#. Mark functions as readnone/readonly/argmemonly or noreturn/nounwind when
+ known. The optimizer will try to infer these flags, but may not always be
+ able to. Manual annotations are particularly important for external
+ functions that the optimizer can not analyze.
+
+#. Use the lifetime.start/lifetime.end and invariant.start/invariant.end
+ intrinsics where possible. Common profitable uses are for stack like data
+ structures (thus allowing dead store elimination) and for describing
+ life times of allocas (thus allowing smaller stack sizes).
+
+#. Mark invariant locations using !invariant.load and TBAA's constant flags
+
+Pass Ordering
+^^^^^^^^^^^^^
+
+One of the most common mistakes made by new language frontend projects is to
+use the existing -O2 or -O3 pass pipelines as is. These pass pipelines make a
+good starting point for an optimizing compiler for any language, but they have
+been carefully tuned for C and C++, not your target language. You will almost
+certainly need to use a custom pass order to achieve optimal performance. A
+couple specific suggestions:
+
+#. For languages with numerous rarely executed guard conditions (e.g. null
+ checks, type checks, range checks) consider adding an extra execution or
+ two of LoopUnswith and LICM to your pass order. The standard pass order,
+ which is tuned for C and C++ applications, may not be sufficient to remove
+ all dischargeable checks from loops.
+
+#. If you language uses range checks, consider using the IRCE pass. It is not
+ currently part of the standard pass order.
+
+#. A useful sanity check to run is to run your optimized IR back through the
+ -O2 pipeline again. If you see noticeable improvement in the resulting IR,
+ you likely need to adjust your pass order.
+
+
+I Still Can't Find What I'm Looking For
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you didn't find what you were looking for above, consider proposing an piece
+of metadata which provides the optimization hint you need. Such extensions are
+relatively common and are generally well received by the community. You will
+need to ensure that your proposal is sufficiently general so that it benefits
+others if you wish to contribute it upstream.
+
+You should also consider describing the problem you're facing on `llvm-dev
+<http://lists.llvm.org/mailman/listinfo/llvm-dev>`_ and asking for advice.
+It's entirely possible someone has encountered your problem before and can
+give good advice. If there are multiple interested parties, that also
+increases the chances that a metadata extension would be well received by the
+community as a whole.
Adding to this document
=======================