L2Optimizer

class L2Optimizer

An L2Optimizer optimizes its L2ControlFlowGraph. This is a control graph. The vertices are L2BasicBlocks, which are connected via their successor and predecessor lists.

Author

Mark van Gulik

Parameters

generator

An L2Generator used for splicing in short sequences of new code as part of optimization.

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
fun adjustEdgesLeadingToJumps()

Any control flow edges that land on jumps should be redirected to the ultimate target of the jump, taking into account chains of jumps.

Link copied to clipboard
fun check(flags: Collection<KClass<out L2ControlFlowGraph.StateFlag>>)

Assert that each of the specified StateFlags has been set in the controlFlowGraph.

Link copied to clipboard
fun checkNot(flags: Collection<KClass<out L2ControlFlowGraph.StateFlag>>)

Assert that each of the specified StateFlags has been cleared in the controlFlowGraph.

Link copied to clipboard
fun clear(flags: Collection<KClass<out L2ControlFlowGraph.StateFlag>>)

Clear each of the specified StateFlags from the controlFlowGraph.

Link copied to clipboard
fun coalesceNoninterferingMoves()

For each L2_MOVE instruction, if the register groups associated with the source and destination registers don't have an interference edge between them then merge the groups together. The resulting merged group should have interferences with each group that the either the source register's group or the destination register's group had interferences with.

Link copied to clipboard
fun computeColors()

Assign final coloring to each register based on the interference graph and coalescing map.

Link copied to clipboard
fun computeInterferenceGraph()

Determine which pairs of registers have to be simultaneously live and potentially holding distinct values.

Link copied to clipboard
fun computeLivenessAtEachEdge()

Determine which registers are live-in for each block. We distinguish between always-live-in, where all future paths from the start of a block lead to a use of the register, and sometimes-live-in, where at least one future path from the start of the block leads to a use of the register.

Link copied to clipboard
fun insertPhiMoves()

For every phi operation, insert a move at the end of the block that leads to it. Because of our version of edge splitting, that block always contains just a jump. The CFG will no longer be in SSA form, because the phi variables will have multiple defining instructions (the moves).

Link copied to clipboard
fun optimize(interpreter: Interpreter)

Optimize the graph of instructions.

Link copied to clipboard
fun orderBlocks()

Re-order the blocks to minimize the number of pointless jumps. When we start generating JVM code, this should also try to make one of the paths from conditional branches come after the branch, otherwise an extra jump instruction has to be generated.

Link copied to clipboard
fun postOptimizationCleanup()

Remove information from the L2ControlFlowGraph that will no longer be needed. Note that during subsequent inlining of this chunk at a call site, the type information will be reconstructed without too much cost.

Link copied to clipboard
fun postponeConditionallyUsedValues()

Regenerate the edge-split SSA graph, postponing emission of side-effectless instructions until just before they're needed.

Link copied to clipboard
fun removeDeadCode(dataCouplingMode: DataCouplingMode, generatePhis: Boolean = true)

Remove all unreachable blocks and all instructions that don't either have a side-effect or produce a value ultimately used by an instruction that has a side-effect.

Link copied to clipboard
fun removeSameColorMoves()

Eliminate any L2_MOVEs between registers of the same color. The graph must have been colored already, and is not expected to be in SSA form, and is certainly not after this, since removed moves are the SSA definition points for their target registers.

Link copied to clipboard
fun removeUnreachableBlocks(): Boolean

Find the L2BasicBlock that are actually reachable recursively from the blocks marked as L2BasicBlock.isIrremovable.

Link copied to clipboard
fun replaceConstantRegisters()

Replace constant-valued registers with fresh registers that have no definitions. The JVM code generator will recognize that these are constants, and produce code to produce them on the JVM stack by reading the constants pool or via special instructions for int/double constants.

Link copied to clipboard
fun replacePlaceholderInstructions()

Find any remaining occurrences of L2_VIRTUAL_CREATE_LABEL, or any other L2Instruction using an L2Operation that says it L2Operation.isPlaceholder. This happens in a fresh control flow graph, as part of the injected behavior of an L2Regenerator.

Link copied to clipboard
fun replaceRegistersByColor()

Create a new register for every (i.e., color) of an existing register, then transform every instruction of this control flow graph to use the new registers. The new registers have a L2Register.uniqueValue that's the same as its finalIndex.

Link copied to clipboard
fun set(flags: Collection<KClass<out L2ControlFlowGraph.StateFlag>>)

Set each of the specified StateFlags in the controlFlowGraph.

Link copied to clipboard
open override fun toString(): String
Link copied to clipboard
fun transformToEdgeSplitSSA()

For every edge leading from a multiple-out block to a multiple-in block, split it by inserting a new block along it. Note that we do this regardless of whether the target block has any phi functions.

Properties

Link copied to clipboard
val blocks: MutableList<L2BasicBlock>

The mutable list of blocks taken from the controlFlowGraph.

Link copied to clipboard
val generator: L2Generator

An L2Generator used for splicing short sequences of code as part of optimization.