///|
fn operand_program_point(
block : Int,
instruction : Int,
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,
) -> DenseLiveSets {
let block_defs : Array[SparseVRegSet] = []
let live_in : Array[SparseVRegSet] = []
let successors : Array[Array[Int]] = []
let block_ids : Array[Int] = []
for block in 0.. Unit {
let open_ends : Array[ProgramPoint?] = Array::make(
function.value_count(),
None,
)
let open_values : Array[Int] = []
for block in 0.. 0 {
instruction_index = instruction_index - 1
let operands = function.instruction_operands(
instructions[instruction_index],
)
for timing in [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)
match open_ends[operand.vreg.id] {
Some(end) => {
add_live_range_fragment(ranges, operand.vreg, point, end)
open_ends[operand.vreg.id] = None
}
None =>
add_live_range_fragment(ranges, operand.vreg, point, 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] is None {
open_values.push(operand.vreg.id)
open_ends[operand.vreg.id] = Some(point)
}
}
}
}
}
for parameter in function.block_parameters(block) {
match open_ends[parameter.id] {
Some(end) => {
add_live_range_fragment(ranges, parameter, block_start, end)
open_ends[parameter.id] = None
}
None =>
add_live_range_fragment(ranges, parameter, block_start, block_start)
}
}
if block == 0 {
for parameter in function.entry_values() {
match open_ends[parameter.id] {
Some(end) => {
add_live_range_fragment(ranges, parameter, block_start, end)
open_ends[parameter.id] = None
}
None =>
add_live_range_fragment(ranges, parameter, block_start, block_start)
}
}
}
for value_id in open_values {
if open_ends[value_id] is Some(end) {
add_live_range_fragment(
ranges,
{ id: value_id, class: function.value_class(value_id) },
block_start,
end,
)
open_ends[value_id] = None
}
}
open_values.clear()
}
for range in ranges.ranges {
range.sort_ranges(ranges.block_order)
}
}
///|
fn[F : FunctionView] build_function_live_ranges(function : F) -> LiveRangeSet {
let block_order = Array::make(function.block_count(), 0)
for block in 0.. {
let by_point = lhs.compare_with_order(rhs, ranges.block_order)
if by_point != 0 {
by_point
} else {
a.vreg.id - b.vreg.id
}
}
(None, Some(_)) => 1
(Some(_), None) => -1
(None, None) => a.vreg.id - b.vreg.id
}
})
ranges
}