L2Regenerator

abstract class L2Regenerator

This is used to transform and embed a called function's chunk's control flow graph into the calling function's chunk's control flow graph. Doing so:

  • eliminates the basic cost of the call and return,

  • passes parameters in and result out with moves that are easily eliminated,

  • allows stronger call-site types to narrow method lookups,

  • exposes primitive cancellation patterns like <x,y>[1] → x,

  • exposes L1 instruction cancellation, like avoiding creation of closures and label continuations,

  • allows nearly all conditional and loop control flow to be expressed as simple jumps,

  • exposes opportunities to operate on intermediate values in an unboxed form.

In addition, this class also gives the opportunity to postpone the transformation of certain virtualized L2Instructions like L2_VIRTUAL_CREATE_LABEL into a subgraph of real instructions, after they have been moved and duplicated as a unit through L2ControlFlowGraph.

Finally, it can be used for code-splitting, where a section of code is duplicated and specialized to take advantage of stronger type knowledge at a point where merging control flow paths would destroy that extra information.

Author

Mark van Gulik

Types

Link copied to clipboard

An AbstractOperandTransformer is an L2OperandDispatcher suitable for transforming operands for the enclosing L2Regenerator. Subclasses may choose different strategies for mapping the registers underlying the read and write operands.

Link copied to clipboard

An OperandRegisterTransformer is an L2OperandDispatcher suitable for copying operands for the enclosing L2Regenerator, when operand equivalency is via L2Register identity (i.e., when generatePhis is false).

Link copied to clipboard

An OperandSemanticTransformer is an L2OperandDispatcher suitable for copying operands for the enclosing L2Regenerator, when operand equivalency is via L2SemanticValues (i.e., when generatePhis is true).

Properties

Link copied to clipboard

The mapping from the L2BasicBlocks in the source graph to the generated L2BasicBlocks in the target graph, keyed by the set of required L2SplitConditions.

Link copied to clipboard

Answer whether this L2Generator is allowed to collapse unconditional jumps during code generation. This is usually allowed, but the code splitter disallows it to make the logic simpler.

Link copied to clipboard

An inverse mapping from source block to SpecialBlock. This is used to detect when we need to record a corresponding target block as a SpecialBlock.

Link copied to clipboard

The L2Generator on which to output the transformed L2 code.

Functions

Link copied to clipboard
fun basicProcessInstruction(sourceInstruction: L2Instruction)

Transform the instruction's operands, updating the isomorphism, and emit the same kind of instruction to the targetGenerator.

Link copied to clipboard
fun emitInstruction(operation: L2Operation, vararg operands: L2Operand)

Emit an L2Instruction into the L1Translator's current block. Use the given L2Operation and L2Operands to construct the instruction. The operands should have been transformed by this inliner already.

Force all postponed instructions to be generated now. Some of these may end up being considered dead code, and will be removed by a later pass.

Link copied to clipboard

During a control flow merge, the phi creation mechanism detected that the incoming edges all provided a particular L2SemanticValue for a RegisterKind, at least one source was a postponed instruction, and not all of the incoming edges had their values postponed by the same instruction.

Link copied to clipboard

A helper method for instruction postponement. Given an L2Regenerator and an L2Instruction from the old graph being regenerated, emit a translated version of that instruction. If the instruction uses values that are not yet available in registers due to postponement, first translate the instructions that produce those values.

Link copied to clipboard

Generate a number unique within the targetGenerator.

Link copied to clipboard
open fun processInstruction(sourceInstruction: L2Instruction)

Process the single instruction from the source graph, transforming it as needed. Subclasses should override this to accomplish postponed instruction rewriting, code splitting, and inlining. The typical result is to rewrite some translation of the instruction to the target graph.

Link copied to clipboard
fun processSourceGraph(oldGraph: L2ControlFlowGraph, interestingConditionsByOldBlock: Map<L2BasicBlock, Set<L2SplitCondition>>)

Given an original L2ControlFlowGraph, translate each L2BasicBlock (in topological order), translating each instruction within that block. Since the new graph has essentially the same shape as the original, we don't need to do any special synchronization at merge points. There's no way for a block of the original to be reached before one of its predecessors, and the translation of an instruction can't suddenly jump to a point in the target graph that corresponds with an earlier point in the source graph. Therefore, when we reach a block in the original, we can safely assume that its translation(s) in the target graph have already had their predecessors completely generated.

Link copied to clipboard
open fun <O : L2Operand> transformOperand(operand: O): O

Produce a transformed copy of the given L2Operand, strengthened to a suitable type. NOT thread-safe for multiple threads using the same inliner.