[GC] Document the recently added PlaceSafepoints and RewriteGCForStatepoints passes
llvm-svn: 230420
This commit is contained in:
parent
74dc7ea2e9
commit
c88d732822
|
@ -111,8 +111,8 @@ garbage collected objects.
|
||||||
collected values, transforming the IR to expose a pointer giving the
|
collected values, transforming the IR to expose a pointer giving the
|
||||||
base object for every such live pointer, and inserting all the
|
base object for every such live pointer, and inserting all the
|
||||||
intrinsics correctly is explicitly out of scope for this document.
|
intrinsics correctly is explicitly out of scope for this document.
|
||||||
The recommended approach is described in the section of Late
|
The recommended approach is to use the :ref:`utility passes
|
||||||
Safepoint Placement below.
|
<statepoint-utilities>` described below.
|
||||||
|
|
||||||
This abstract function call is concretely represented by a sequence of
|
This abstract function call is concretely represented by a sequence of
|
||||||
intrinsic calls known as a 'statepoint sequence'.
|
intrinsic calls known as a 'statepoint sequence'.
|
||||||
|
@ -151,7 +151,7 @@ When lowered, this example would generate the following x86 assembly::
|
||||||
|
|
||||||
Each of the potentially relocated values has been spilled to the
|
Each of the potentially relocated values has been spilled to the
|
||||||
stack, and a record of that location has been recorded to the
|
stack, and a record of that location has been recorded to the
|
||||||
:ref:`Stack Map section <stackmap-section>`. If the garbage collector
|
:ref: `Stack Map section <stackmap-section>`. If the garbage collector
|
||||||
needs to update any of these pointers during the call, it knows
|
needs to update any of these pointers during the call, it knows
|
||||||
exactly what to change.
|
exactly what to change.
|
||||||
|
|
||||||
|
@ -393,6 +393,93 @@ key relocation invariant, but this is ongoing work on developing such
|
||||||
a verifier. Please ask on llvmdev if you're interested in
|
a verifier. Please ask on llvmdev if you're interested in
|
||||||
experimenting with the current version.
|
experimenting with the current version.
|
||||||
|
|
||||||
|
.. _statepoint-utilities:
|
||||||
|
|
||||||
|
Utility Passes for Safepoint Insertion
|
||||||
|
======================================
|
||||||
|
|
||||||
|
.. _RewriteStatepointsForGC:
|
||||||
|
|
||||||
|
RewriteStatepointsForGC
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The pass RewriteStatepointsForGC transforms a functions IR by replacing a
|
||||||
|
``gc.statepoint`` (with an optional ``gc.result``) with a full relocation
|
||||||
|
sequence, including all required ``gc.relocates``. To function, the pass
|
||||||
|
requires that the GC strategy specified for the function be able to reliably
|
||||||
|
distinguish between GC references and non-GC references in IR it is given.
|
||||||
|
|
||||||
|
As an example, given this code:
|
||||||
|
|
||||||
|
.. code-block:: llvm
|
||||||
|
|
||||||
|
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||||
|
gc "statepoint-example" {
|
||||||
|
call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
|
||||||
|
ret i8 addrspace(1)* %obj
|
||||||
|
}
|
||||||
|
|
||||||
|
The pass would produce this IR:
|
||||||
|
|
||||||
|
.. code-block:: llvm
|
||||||
|
|
||||||
|
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||||
|
gc "statepoint-example" {
|
||||||
|
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
|
||||||
|
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
|
||||||
|
ret i8 addrspace(1)* %obj.relocated
|
||||||
|
}
|
||||||
|
|
||||||
|
In the above examples, the addrspace(1) marker on the pointers is the mechanism
|
||||||
|
that the ``statepoint-example`` GC strategy uses to distinguish references from
|
||||||
|
non references. Address space 1 is not globally reserved for this purpose.
|
||||||
|
|
||||||
|
This pass can be used an utility function by a language frontend that doesn't
|
||||||
|
want to manually reason about liveness, base pointers, or relocation when
|
||||||
|
constructing IR. As currently implemented, RewriteStatepointsForGC must be
|
||||||
|
run after SSA construction (i.e. mem2ref).
|
||||||
|
|
||||||
|
|
||||||
|
In practice, RewriteStatepointsForGC can be run much later in the pass
|
||||||
|
pipeline, after most optimization is already done. This helps to improve
|
||||||
|
the quality of the generated code when compiled with garbage collection support.
|
||||||
|
In the long run, this is the intended usage model. At this time, a few details
|
||||||
|
have yet to be worked out about the semantic model required to guarantee this
|
||||||
|
is always correct. As such, please use with caution and report bugs.
|
||||||
|
|
||||||
|
.. _PlaceSafepoints:
|
||||||
|
|
||||||
|
PlaceSafepoints
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The pass PlaceSafepoints transforms a function's IR by replacing any call or
|
||||||
|
invoke instructions with appropriate ``gc.statepoint`` and ``gc.result`` pairs,
|
||||||
|
and inserting safepoint polls sufficient to ensure running code checks for a
|
||||||
|
safepoint request on a timely manner. This pass is expected to be run before
|
||||||
|
RewriteStatepointsForGC and thus does not produce full relocation sequences.
|
||||||
|
|
||||||
|
At the moment, PlaceSafepoints can insert safepoint polls at method entry and
|
||||||
|
loop backedges locations. Extending this to work with return polls would be
|
||||||
|
straight forward if desired.
|
||||||
|
|
||||||
|
PlaceSafepoints includes a number of optimizations to avoid placing safepoint
|
||||||
|
polls at particular sites unless needed to ensure timely execution of a poll
|
||||||
|
under normal conditions. PlaceSafepoints does not attempt to ensure timely
|
||||||
|
execution of a poll under worst case conditions such as heavy system paging.
|
||||||
|
|
||||||
|
The implementation of a safepoint poll action is specified by looking up a
|
||||||
|
function of the name ``gc.safepoint_poll`` in the containing Module. The body
|
||||||
|
of this function is inserted at each poll site desired. While calls or invokes
|
||||||
|
inside this method are transformed to a ``gc.statepoints``, recursive poll
|
||||||
|
insertion is not performed.
|
||||||
|
|
||||||
|
If you are scheduling the RewriteStatepointsForGC pass late in the pass order,
|
||||||
|
you should probably schedule this pass immediately before it. The exception
|
||||||
|
would be if you need to preserve abstract frame information (e.g. for
|
||||||
|
deoptimization or introspection) at safepoints. In that case, ask on the
|
||||||
|
llvmdev mailing list for suggestions.
|
||||||
|
|
||||||
|
|
||||||
Bugs and Enhancements
|
Bugs and Enhancements
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue