mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-24 12:36:30 +00:00
Some documentation for LegalizeTypes.
llvm-svn: 59962
This commit is contained in:
parent
b316bd9e62
commit
d7f821e645
@ -50,6 +50,7 @@
|
||||
Process</a></li>
|
||||
<li><a href="#selectiondag_build">Initial SelectionDAG
|
||||
Construction</a></li>
|
||||
<li><a href="#selectiondag_legalize_types">SelectionDAG LegalizeTypes Phase</a></li>
|
||||
<li><a href="#selectiondag_legalize">SelectionDAG Legalize Phase</a></li>
|
||||
<li><a href="#selectiondag_optimize">SelectionDAG Optimization
|
||||
Phase: the DAG Combiner</a></li>
|
||||
@ -813,8 +814,9 @@ basic block function it would be the return node.</p>
|
||||
operations and supported types. On a 32-bit PowerPC, for example, a DAG with
|
||||
a value of type i1, i8, i16, or i64 would be illegal, as would a DAG that uses a
|
||||
SREM or UREM operation. The
|
||||
<a href="#selectiondag_legalize">legalize</a> phase is responsible for turning
|
||||
an illegal DAG into a legal DAG.</p>
|
||||
<a href="#selectinodag_legalize_types">legalize types</a> and
|
||||
<a href="#selectiondag_legalize">legalize operations</a> phases are
|
||||
responsible for turning an illegal DAG into a legal DAG.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -837,12 +839,18 @@ an illegal DAG into a legal DAG.</p>
|
||||
pairs) for targets that support these meta operations. This makes the
|
||||
resultant code more efficient and the <a href="#selectiondag_select">select
|
||||
instructions from DAG</a> phase (below) simpler.</li>
|
||||
<li><a href="#selectiondag_legalize">Legalize SelectionDAG</a> - This stage
|
||||
converts the illegal SelectionDAG to a legal SelectionDAG by eliminating
|
||||
unsupported operations and data types.</li>
|
||||
<li><a href="#selectiondag_optimize">Optimize SelectionDAG (#2)</a> - This
|
||||
second run of the SelectionDAG optimizes the newly legalized DAG to
|
||||
eliminate inefficiencies introduced by legalization.</li>
|
||||
<li><a href="#selectiondag_legalize_types">Legalize SelectionDAG Types</a> - This
|
||||
stage transforms SelectionDAG nodes to eliminate any types that are
|
||||
unsupported on the target.</li>
|
||||
<li><a href="#selectiondag_optimize">Optimize SelectionDAG</a> - The
|
||||
SelectionDAG optimizer is run to clean up redundancies exposed
|
||||
by type legalization.</li>
|
||||
<li><a href="#selectiondag_legalize">Legalize SelectionDAG Types</a> - This
|
||||
stage transforms SelectionDAG nodes to eliminate any types that are
|
||||
unsupported on the target.</li>
|
||||
<li><a href="#selectiondag_optimize">Optimize SelectionDAG</a> - The
|
||||
SelectionDAG optimizer is run to eliminate inefficiencies introduced
|
||||
by operation legalization.</li>
|
||||
<li><a href="#selectiondag_select">Select instructions from DAG</a> - Finally,
|
||||
the target instruction selector matches the DAG operations to target
|
||||
instructions. This process translates the target-independent input DAG into
|
||||
@ -876,7 +884,7 @@ add support for it).</p>
|
||||
<p>The <tt>-view-sunit-dags</tt> displays the Scheduler's dependency graph.
|
||||
This graph is based on the final SelectionDAG, with nodes that must be
|
||||
scheduled together bundled into a single scheduling-unit node, and with
|
||||
immediate operands and other nodes that aren't relevent for scheduling
|
||||
immediate operands and other nodes that aren't relevant for scheduling
|
||||
omitted.
|
||||
</p>
|
||||
|
||||
@ -901,6 +909,40 @@ returns, varargs, etc. For these features, the
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="selectiondag_legalize_types">SelectionDAG LegalizeTypes Phase</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The Legalize phase is in charge of converting a DAG to only use the types
|
||||
that are natively supported by the target.</p>
|
||||
|
||||
<p>There are two main ways of converting values of unsupported scalar types
|
||||
to values of supported types: converting small types to
|
||||
larger types ("promoting"), and breaking up large integer types
|
||||
into smaller ones ("expanding"). For example, a target might require
|
||||
that all f32 values are promoted to f64 and that all i1/i8/i16 values
|
||||
are promoted to i32. The same target might require that all i64 values
|
||||
be expanded into pairs of i32 values. These changes can insert sign and
|
||||
zero extensions as needed to make sure that the final code has the same
|
||||
behavior as the input.</p>
|
||||
|
||||
<p>There are two main ways of converting values of unsupported vector types
|
||||
to value of supported types: splitting vector types, multiple times if
|
||||
necessary, until a legal type is found, and extending vector types by
|
||||
adding elements to the end to round them out to legal types ("widening").
|
||||
If a vector gets split all the way down to single-element parts with
|
||||
no supported vector type being found, the elements are converted to
|
||||
scalars ("scalarizing").</p>
|
||||
|
||||
<p>A target implementation tells the legalizer which types are supported
|
||||
(and which register class to use for them) by calling the
|
||||
<tt>addRegisterClass</tt> method in its TargetLowering constructor.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="selectiondag_legalize">SelectionDAG Legalize Phase</a>
|
||||
@ -908,46 +950,28 @@ returns, varargs, etc. For these features, the
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The Legalize phase is in charge of converting a DAG to only use the types and
|
||||
operations that are natively supported by the target. This involves two major
|
||||
tasks:</p>
|
||||
<p>The Legalize phase is in charge of converting a DAG to only use the
|
||||
operations that are natively supported by the target.</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Convert values of unsupported types to values of supported types.</p>
|
||||
<p>There are two main ways of doing this: converting small types to
|
||||
larger types ("promoting"), and breaking up large integer types
|
||||
into smaller ones ("expanding"). For example, a target might require
|
||||
that all f32 values are promoted to f64 and that all i1/i8/i16 values
|
||||
are promoted to i32. The same target might require that all i64 values
|
||||
be expanded into i32 values. These changes can insert sign and zero
|
||||
extensions as needed to make sure that the final code has the same
|
||||
behavior as the input.</p>
|
||||
<p>A target implementation tells the legalizer which types are supported
|
||||
(and which register class to use for them) by calling the
|
||||
<tt>addRegisterClass</tt> method in its TargetLowering constructor.</p>
|
||||
</li>
|
||||
<p>Targets often have weird constraints, such as not supporting every
|
||||
operation on every supported datatype (e.g. X86 does not support byte
|
||||
conditional moves and PowerPC does not support sign-extending loads from
|
||||
a 16-bit memory location). Legalize takes care of this by open-coding
|
||||
another sequence of operations to emulate the operation ("expansion"), by
|
||||
promoting one type to a larger type that supports the operation
|
||||
("promotion"), or by using a target-specific hook to implement the
|
||||
legalization ("custom").</p>
|
||||
|
||||
<li><p>Eliminate operations that are not supported by the target.</p>
|
||||
<p>Targets often have weird constraints, such as not supporting every
|
||||
operation on every supported datatype (e.g. X86 does not support byte
|
||||
conditional moves and PowerPC does not support sign-extending loads from
|
||||
a 16-bit memory location). Legalize takes care of this by open-coding
|
||||
another sequence of operations to emulate the operation ("expansion"), by
|
||||
promoting one type to a larger type that supports the operation
|
||||
("promotion"), or by using a target-specific hook to implement the
|
||||
legalization ("custom").</p>
|
||||
<p>A target implementation tells the legalizer which operations are not
|
||||
supported (and which of the above three actions to take) by calling the
|
||||
<tt>setOperationAction</tt> method in its <tt>TargetLowering</tt>
|
||||
constructor.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>A target implementation tells the legalizer which operations are not
|
||||
supported (and which of the above three actions to take) by calling the
|
||||
<tt>setOperationAction</tt> method in its <tt>TargetLowering</tt>
|
||||
constructor.</p>
|
||||
|
||||
<p>Prior to the existance of the Legalize pass, we required that every target
|
||||
<p>Prior to the existence of the Legalize passes, we required that every target
|
||||
<a href="#selectiondag_optimize">selector</a> supported and handled every
|
||||
operator and type even if they are not natively supported. The introduction of
|
||||
the Legalize phase allows all of the cannonicalization patterns to be shared
|
||||
across targets, and makes it very easy to optimize the cannonicalized code
|
||||
the Legalize phases allows all of the canonicalization patterns to be shared
|
||||
across targets, and makes it very easy to optimize the canonicalized code
|
||||
because it is still in the form of a DAG.</p>
|
||||
|
||||
</div>
|
||||
@ -960,12 +984,12 @@ because it is still in the form of a DAG.</p>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The SelectionDAG optimization phase is run twice for code generation: once
|
||||
immediately after the DAG is built and once after legalization. The first run
|
||||
of the pass allows the initial code to be cleaned up (e.g. performing
|
||||
<p>The SelectionDAG optimization phase is run multiple times for code generation,
|
||||
immediately after the DAG is built and once after each legalization. The first
|
||||
run of the pass allows the initial code to be cleaned up (e.g. performing
|
||||
optimizations that depend on knowing that the operators have restricted type
|
||||
inputs). The second run of the pass cleans up the messy code generated by the
|
||||
Legalize pass, which allows Legalize to be very simple (it can focus on making
|
||||
inputs). Subsequent runs of the pass clean up the messy code generated by the
|
||||
Legalize passes, which allows Legalize to be very simple (it can focus on making
|
||||
code legal instead of focusing on generating <em>good</em> and legal code).</p>
|
||||
|
||||
<p>One important class of optimizations performed is optimizing inserted sign
|
||||
@ -1228,7 +1252,7 @@ values in the function.</p>
|
||||
<p><tt>PHI</tt> nodes need to be handled specially, because the calculation
|
||||
of the live variable information from a depth first traversal of the CFG of
|
||||
the function won't guarantee that a virtual register used by the <tt>PHI</tt>
|
||||
node is defined before it's used. When a <tt>PHI</tt> node is encounted, only
|
||||
node is defined before it's used. When a <tt>PHI</tt> node is encountered, only
|
||||
the definition is handled, because the uses will be handled in other basic
|
||||
blocks.</p>
|
||||
|
||||
@ -1722,7 +1746,7 @@ that people test.</p>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The folowing target-specific calling conventions are known to backend:</p>
|
||||
<p>The following target-specific calling conventions are known to backend:</p>
|
||||
|
||||
<ul>
|
||||
<li><b>x86_StdCall</b> - stdcall calling convention seen on Microsoft Windows
|
||||
@ -1829,7 +1853,7 @@ pointer is free to grow or shrink. A base pointer is also used if llvm-gcc is
|
||||
not passed the -fomit-frame-pointer flag. The stack pointer is always aligned to
|
||||
16 bytes, so that space allocated for altivec vectors will be properly
|
||||
aligned.</p>
|
||||
<p>An invocation frame is layed out as follows (low memory at top);</p>
|
||||
<p>An invocation frame is laid out as follows (low memory at top);</p>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
@ -1938,7 +1962,7 @@ passed in registers, with the space in the parameter area unused. However, if
|
||||
there are not enough registers or the callee is a thunk or vararg function,
|
||||
these register arguments can be spilled into the parameter area. Thus, the
|
||||
parameter area must be large enough to store all the parameters for the largest
|
||||
call sequence made by the caller. The size must also be mimimally large enough
|
||||
call sequence made by the caller. The size must also be minimally large enough
|
||||
to spill registers r3-r10. This allows callees blind to the call signature,
|
||||
such as thunks and vararg functions, enough space to cache the argument
|
||||
registers. Therefore, the parameter area is minimally 32 bytes (64 bytes in 64
|
||||
@ -1960,7 +1984,7 @@ shifted to top of stack, and the new space is available immediately below the
|
||||
linkage and parameter areas. The cost of shifting the linkage and parameter
|
||||
areas is minor since only the link value needs to be copied. The link value can
|
||||
be easily fetched by adding the original frame size to the base pointer. Note
|
||||
that allocations in the dynamic space need to observe 16 byte aligment.</p>
|
||||
that allocations in the dynamic space need to observe 16 byte alignment.</p>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
Loading…
Reference in New Issue
Block a user