///|
fn operand_program_point(
block : Int32,
instruction : Int32,
timing : OperandTiming,
) -> ProgramPoint {
let phase = match timing {
Early => 0
Late => 1
}
ProgramPoint(block, instruction * 2 + phase)
}
///|
fn[F : FunctionView] collect_function_liveness(
function : F,
ranges : LiveRangeSet,
) -> Array[Array[Int32]] {
let word_count = (function.value_count() + 63) / 64
let block_count = function.block_count()
let use_dense = block_count == 0 || word_count <= 262144 / block_count
let block_defs : Array[SparseVRegSet] = []
let live_in : Array[SparseVRegSet] = []
let successors : Array[Array[Int32]] = []
let block_ids : Array[Int32] = []
for block in 0.. {
function.block_successor_at(block, successor)
}),
)
}
propagate_live_sets(
function.block_count(),
build_dense_successor_edges(block_ids, successors),
block_defs,
live_in,
)
}
///|
fn[F : FunctionView] build_function_range_fragments(
ranges : LiveRangeSet,
function : F,
live_out : Array[Array[Int32]],
) -> Unit {
let block_ends = Array::make(function.block_count(), 0)
let open_ends = Array::make(function.value_count(), no_program_point())
let open_values : Array[Int32] = []
for block in 0.. 0 {
let edge_point = ProgramPoint(block, (instruction_count - 1) * 2)
for successor in 0.. 0 {
instruction_index = instruction_index - 1
let instruction = function.block_instruction_at(block, instruction_index)
let operands = function.instruction_operands(instruction)
for timing in [OperandTiming::Late, Early] {
for operand in operands {
if operand.timing == timing &&
(operand.role is Def || operand.role is UseDef) {
let point = operand_program_point(block, instruction_index, timing)
let end = open_ends[operand.vreg.id]
add_live_range_fragment(
ranges,
operand.vreg,
point,
if end.present {
end.point
} else {
point
},
)
open_ends[operand.vreg.id] = no_program_point()
}
}
for operand in operands {
if operand.timing == timing &&
(operand.role is Use || operand.role is UseDef) {
let point = operand_program_point(block, instruction_index, timing)
if !open_ends[operand.vreg.id].present {
open_values.push(operand.vreg.id)
open_ends[operand.vreg.id] = some_program_point(point)
}
}
}
}
}
for parameter_index in 0.. LiveRangeSet {
let block_order = Array::make(function.block_count(), 0)
for block in 0..