|
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
CFG
.
See:
Description
Class Summary | |
---|---|
AASR | This class replaces array element address calculations in a loop with simple additions. |
BasicBlockOps | Perform optimizations on each basic block. |
CP | Perform copy propagation optimization on a Scribble graph. |
DeadVarElimination | This class performs dead variable elimination. |
ExprMap | Map from an expression to another expression. |
GlobalVarReplacement | This class replaces references to global variables with references to local variables. |
Inlining | This class performs inlining. |
LICM | This transformation moves CFG nodes to the outer-most basic block in which they may be executed correctly. |
LoopPermute | This optimization permutes the loops of a routine based on cache order. |
LoopTrans | The base class for all loop transformation optimizations. |
Noopt | This class performs no optimization. |
Optimization | This class is the base class for all optimizations performed on the CFG. |
PRE | Perform the Partial Redundancy Elimination optimization. |
ScalarReplacement | This class replaces references to array elements with references to scalar variables. |
SCC | This class performs the sparse conditional constant propagation. |
SFIR | This class replaces references to fields of C structures with references to local variables. |
TreeHeight | Perform expression tree height reduction on a Scribble graph. |
URJ | This class performs unroll & jam. |
UselessCopy | This class removes useless copies from the CFG. |
ValNum | Global value numbering optimization. |
This package provides various optimizations that operate on the CFG
.
When an optimization considers performing some transformation, there are two questions that must be answered:
Because the interactions between optimizations can be very complex, some transformations may not appear to be benneficial but may enable an optimization that is very beneficial. One transformation may also inhibit a more beneficial transformation.
Most transformations result in an increase in register pressure. If the register pressure, for some sequence of generated instructions, becomes too great, register spilling results. Spilling a register may negate any benefit the transformation may otherwise have provided. If the register pressure becomes large enough, the transformed program may perform worse than the un-optimized program.
Answering question 2 optimally in any particular context is very difficult. Heuristics are usually used. Many of the Scale optimizations are written to assume that the answer to question two is always the same as the answer to question one; if it can be done, it will be done.
scale/score/trans
directory. This class must be derived
from the Optimization
class.
Note that the Inlining
optimization
is a special case because it is performed over all functions at the
same time. Therefore, it is not derived from the Optimization
class.
requiresSSA()
method
correctly. This method informs the compiler of the required condition
for the CFG in order for your optimization to be performed.
invalidSSAForm()
method.
Scale
class to add the
information needed to find and invoke your optimization.
optimizationLetter
field.
optimizationName
field in the same position as you added
your letter in the previous step.
optimizationClass
field in the same order.
cannedOpts
field. The elements of this array correspond
to the five optimization levels (i.e., -O0, -O1, -O2, -O3, -O4
).
SSA
form. SSA form provides variable liveness
information that is not available otherwise. However, some
optimizations (e.g., GlobalVarReplacement
, SFIR
) require
non-SSA form because they are not able to easily keep the SSA form
valid. Some optimizations don't care either way (e.g., TreeHeight
, BasicBlockOps
).
The SSA form of the CFG is valid if two conditions are met:
URJ
sometimes violates this rule.
PRE
violates
this rule.)
The requiresSSA()
specifies in what form the CFG is required.
invalidSSAForm()
method.
(1) Stack wl = WorkArea.getStack("xxx"); (2) Chord.nextVisit(); (3) wl.push(begin); (4) begin.setVisited(); (5) while (!wl.isEmpty()) { (6) Chord c = (Chord) wl.pop(); (7) c.pushOutCfgEdges(wl); (8) ... } (9) WorkArea.returnStack(wl);
Stack
to be used as a work
list. We use our own version of the stack implementation to avoid the
overhead of synchronization. We use the WorkArea
class to obtain previously used stacks
in order to avoid allocating new stacks and to avoid the allocations
required to grow the stack. A unique identification is supplied so
that if the code fails to return the stack (see (9)), it is possible
to determine what place in the compiler obtained it.
getBegin()
method can be used to obtain this CFG node.
pushOutCfgEdges()
.
pushChordWhenReady()
.
An important thing to remember about the above code example is that there is only one color that can be assigned to a CFG node. Thus, if the processing in step 8 must also span the CFG, the two spanning algorithms will collide. To overcome this problem, a different spanning algorithm can be used for one of them.
Stack wl = WorkArea.getStack("xxx"); HashSet done = WorkArea.getSet("xxx"); wl.push(begin); while (!wl.empty()) { Chord c = (Chord) wl.pop(); c.pushOutCfgEdges(wl, done); ... } WorkArea.returnStack(wl); WorkArea.returnSet(done);In this example a set of visited nodes is used in place of coloring each node.
dominators
. The compiler computes this
information the first time it is requested. (See getDomination()
.) If an
optimization changes the CFG by adding or deleting a CFG node, then
the optimization must either:
addDominatee()
, or
recomputeDominators()
.
dominance frontier
of a node. The
compiler computes this information the first time it is
requested. (See getDominanceFrontier()
.) If an optimization changes the CFG by
changing the dominance frontier of a CFG node, then the optimization
must tell the compiler that the dominance frontier information is no
longer valid by calling recomputeDominators()
.
getRefs()
.)
The References
class provides
various methods for accessing and updating this information. An
optimization can force the compiler to recompute this information as
well by calling the recomputeRefs()
method.
loop
in the CFG. The
compiler computes this information the first time it is requested. An
optimization that changes the loop structure of the CFG (e.g., loop
fusion, loop permutation} must inform the compiler that this
information is no longer valid by calling the recomputeLoops()
method.
PRE
doesn't do much. And, it's
expensive. It requires an additional constraint on the SSA
form that is only valid prior to the operation of
any other optimization. For that reason, Scale leaves SSA form and
re-enters it if PRE is used after some other optimization. PRE is not
under regression test.
Global value numbering
is much more effective.
Some optimizations don't seem to be effective on Fortran code.
The problem may be due to the fact that Fortran passes arguments by
reference. If an index variable is passed to a subroutine, it causes
some optimizations to skip that variable. Also, if the DO
loop is
controlled by variables passed in as an arguments, Scale may fail
to find important loop information.
|
|||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |