///|
// This worker is called only by the existing linear-interference path. Keep
// branch joins and conservative barriers on the unchanged old worker.
fn cl_add_linear_source_write_dest_read_interferences(
instrs : Array[@lib.Instruction],
actions : Array[CLAction],
effective : Array[Bool],
types : Array[@lib.ValType],
param_count : Int32,
interferences : CLBitMatrix,
candidate_visits~ : Array[Int32]? = None,
fallback_calls~ : Array[Int32]? = None,
) -> Unit {
for instr in instrs {
match instr {
@lib.Block(_, _)
| @lib.Loop(_, _)
| @lib.If(_, _, _)
| @lib.Try(_, _, _, _)
| @lib.TryTable(_, _, _)
| @lib.BrIf(_)
| @lib.BrTable(_, _) => {
match fallback_calls {
Some(calls) => calls[0] += 1
None => ()
}
cl_add_source_write_dest_read_interferences(
instrs,
actions,
effective,
types,
param_count,
interferences,
candidate_visits~,
)
return
}
_ => ()
}
}
let writers = Array::make(types.length(), false)
let mut saw_source_write = false
let mut has_later_read = false
for action_idx = 0; action_idx < actions.length(); action_idx = action_idx + 1 {
let action = actions[action_idx]
match action.kind {
CLActionKind::Get => {
ignore(writers[action.local_idx])
if saw_source_write {
has_later_read = true
}
}
CLActionKind::Set | CLActionKind::Tee =>
if cl_action_is_effective(effective, action_idx) {
writers[action.local_idx] = true
if action.local_idx >= param_count {
saw_source_write = true
}
}
}
}
// No effective body-local write precedes any read. No source/dest hazard
// can be added; retain the existing matrix and avoid compiling steps.
if !has_later_read {
return
}
let steps : Array[CLSourceHazardStep] = []
cl_compile_source_hazard_steps(instrs, effective, [0], steps, None)
let cleared_at = Array::make(types.length(), 0)
// Each effective non-parameter write increments this once across ALL rows,
// so tick <= effective action count <= actions.length(); no wrap is needed.
let mut tick = 0
for source in param_count.. {
if dest < 0 || dest >= types.length() {
continue
}
if cleared_at[dest] == row_done {
continue
}
let clear = if cleared_at[dest] > reset_at {
cleared_at[dest]
} else {
reset_at
}
if written_at > clear {
if dest != source {
if types[source] == types[dest] {
if !cl_bit_matrix_get(interferences, source, dest) {
cl_add_interference(interferences, source, dest)
}
}
}
cleared_at[dest] = row_done
}
}
Write(local, copied_dest) =>
if local == source {
tick += 1
written_at = tick
if copied_dest >= 0 &&
copied_dest < types.length() &&
cleared_at[copied_dest] != row_done {
cleared_at[copied_dest] = written_at
}
} else if local >= 0 &&
local < types.length() &&
cleared_at[local] != row_done {
cleared_at[local] = written_at
}
Reset => reset_at = tick
Branch(_, _) | Barrier =>
abort("linear hazard admission allowed a control step")
}
}
}
}