///|
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] compute_function_live_sets(function : F) -> DenseLiveSets {
let use_defs : Array[LiveSetUseDef] = []
let definitions : Array[ProgramPoint?] = Array::make(
function.value_count(),
None,
)
let uses : Array[Array[ProgramPoint]] = []
for _ in 0.. Unit {
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.get(operand.vreg.id) {
Some(end) => {
add_live_range_fragment(ranges, operand.vreg, point, end)
open_ends.remove(operand.vreg.id)
}
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.get(operand.vreg.id) is None {
open_ends[operand.vreg.id] = point
}
}
}
}
}
for parameter in function.block_parameters(block) {
match open_ends.get(parameter.id) {
Some(end) => {
add_live_range_fragment(ranges, parameter, block_start, end)
open_ends.remove(parameter.id)
}
None =>
add_live_range_fragment(ranges, parameter, block_start, block_start)
}
}
if block == 0 {
for parameter in function.entry_values() {
match open_ends.get(parameter.id) {
Some(end) => {
add_live_range_fragment(ranges, parameter, block_start, end)
open_ends.remove(parameter.id)
}
None =>
add_live_range_fragment(ranges, parameter, block_start, block_start)
}
}
}
for value_id, end in open_ends {
add_live_range_fragment(
ranges,
{ id: value_id, class: function.value_class(value_id) },
block_start,
end,
)
}
}
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
}