Use the term "EBB parameter" everywhere.
Add EBB parameter and EBB argument to the langref glossary to clarify the distinction between formal EBB parameter values and arguments passed to branches. - Replace "ebb_arg" with "ebb_param" in function names that deal with EBB parameters. - Rename the ValueDef variants to Result and Param. - A bunch of other small langref fixes. No functional changes intended.
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! Conventional SSA form is a subset of SSA form where any (transitively) phi-related values do
|
||||
//! not interfere. We construct CSSA by building virtual registers that are as large as possible
|
||||
//! and inserting copies where necessary such that all values passed to an EBB argument will belong
|
||||
//! to the same virtual register as the EBB argument value itself.
|
||||
//! and inserting copies where necessary such that all argument values passed to an EBB parameter
|
||||
//! will belong to the same virtual register as the EBB parameter value itself.
|
||||
|
||||
use cursor::{Cursor, EncCursor};
|
||||
use dbg::DisplayList;
|
||||
@@ -289,8 +289,8 @@ impl Coalescing {
|
||||
for &ebb in domtree.cfg_postorder() {
|
||||
let preds = cfg.get_predecessors(ebb);
|
||||
if !preds.is_empty() {
|
||||
for argnum in 0..context.func.dfg.num_ebb_args(ebb) {
|
||||
context.coalesce_ebb_arg(ebb, argnum, preds)
|
||||
for argnum in 0..context.func.dfg.num_ebb_params(ebb) {
|
||||
context.coalesce_ebb_param(ebb, argnum, preds)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,10 +298,10 @@ impl Coalescing {
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
/// Coalesce the `argnum`'th argument to `ebb`.
|
||||
fn coalesce_ebb_arg(&mut self, ebb: Ebb, argnum: usize, preds: &[BasicBlock]) {
|
||||
/// Coalesce the `argnum`'th parameter on `ebb`.
|
||||
fn coalesce_ebb_param(&mut self, ebb: Ebb, argnum: usize, preds: &[BasicBlock]) {
|
||||
self.split_values.clear();
|
||||
let mut succ_val = self.func.dfg.ebb_args(ebb)[argnum];
|
||||
let mut succ_val = self.func.dfg.ebb_params(ebb)[argnum];
|
||||
dbg!("Processing {}/{}: {}", ebb, argnum, succ_val);
|
||||
|
||||
// We want to merge the virtual register for `succ_val` with the virtual registers for
|
||||
@@ -421,7 +421,7 @@ impl<'a> Context<'a> {
|
||||
// Never coalesce incoming function arguments on the stack. These arguments are
|
||||
// pre-spilled, and the rest of the virtual register would be forced to spill to the
|
||||
// `incoming_arg` stack slot too.
|
||||
if let ValueDef::Arg(def_ebb, def_num) = self.func.dfg.value_def(pred_val) {
|
||||
if let ValueDef::Param(def_ebb, def_num) = self.func.dfg.value_def(pred_val) {
|
||||
if Some(def_ebb) == self.func.layout.entry_block() &&
|
||||
self.func.signature.argument_types[def_num]
|
||||
.location
|
||||
@@ -530,7 +530,7 @@ impl<'a> Context<'a> {
|
||||
/// Split the congruence class for the successor EBB value itself.
|
||||
fn split_succ(&mut self, ebb: Ebb, succ_val: Value) -> Value {
|
||||
let ty = self.func.dfg.value_type(succ_val);
|
||||
let new_val = self.func.dfg.replace_ebb_arg(succ_val, ty);
|
||||
let new_val = self.func.dfg.replace_ebb_param(succ_val, ty);
|
||||
|
||||
// Insert a copy instruction at the top of ebb.
|
||||
let mut pos = EncCursor::new(self.func, self.isa).at_first_inst(ebb);
|
||||
|
||||
@@ -409,7 +409,7 @@ impl<'a> Context<'a> {
|
||||
// If this is the first time we branch to `dest`, color its arguments to match the current
|
||||
// register state.
|
||||
if let Some(dest) = color_dest_args {
|
||||
self.color_ebb_arguments(inst, dest);
|
||||
self.color_ebb_params(inst, dest);
|
||||
}
|
||||
|
||||
// Apply the solution to the defs.
|
||||
@@ -556,7 +556,7 @@ impl<'a> Context<'a> {
|
||||
|
||||
// Now handle the EBB arguments.
|
||||
let br_args = self.cur.func.dfg.inst_variable_args(inst);
|
||||
let dest_args = self.cur.func.dfg.ebb_args(dest);
|
||||
let dest_args = self.cur.func.dfg.ebb_params(dest);
|
||||
assert_eq!(br_args.len(), dest_args.len());
|
||||
for (&dest_arg, &br_arg) in dest_args.iter().zip(br_args) {
|
||||
// The first time we encounter a branch to `dest`, we get to pick the location. The
|
||||
@@ -565,7 +565,7 @@ impl<'a> Context<'a> {
|
||||
ValueLoc::Unassigned => {
|
||||
// This is the first branch to `dest`, so we should color `dest_arg` instead of
|
||||
// `br_arg`. However, we don't know where `br_arg` will end up until
|
||||
// after `shuffle_inputs`. See `color_ebb_arguments` below.
|
||||
// after `shuffle_inputs`. See `color_ebb_params` below.
|
||||
//
|
||||
// It is possible for `dest_arg` to have no affinity, and then it should simply
|
||||
// be ignored.
|
||||
@@ -595,13 +595,13 @@ impl<'a> Context<'a> {
|
||||
false
|
||||
}
|
||||
|
||||
/// Knowing that we've never seen a branch to `dest` before, color its arguments to match our
|
||||
/// Knowing that we've never seen a branch to `dest` before, color its parameters to match our
|
||||
/// register state.
|
||||
///
|
||||
/// This function is only called when `program_ebb_arguments()` returned `true`.
|
||||
fn color_ebb_arguments(&mut self, inst: Inst, dest: Ebb) {
|
||||
fn color_ebb_params(&mut self, inst: Inst, dest: Ebb) {
|
||||
let br_args = self.cur.func.dfg.inst_variable_args(inst);
|
||||
let dest_args = self.cur.func.dfg.ebb_args(dest);
|
||||
let dest_args = self.cur.func.dfg.ebb_params(dest);
|
||||
assert_eq!(br_args.len(), dest_args.len());
|
||||
for (&dest_arg, &br_arg) in dest_args.iter().zip(br_args) {
|
||||
match self.cur.func.locations[dest_arg] {
|
||||
@@ -914,7 +914,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace all global values define by `inst` with local values that are then copied into the
|
||||
/// Replace all global values defined by `inst` with local values that are then copied into the
|
||||
/// global value:
|
||||
///
|
||||
/// v1 = foo
|
||||
@@ -938,7 +938,7 @@ impl<'a> Context<'a> {
|
||||
for lv in tracker.live_mut().iter_mut().rev() {
|
||||
// Keep going until we reach a value that is not defined by `inst`.
|
||||
if match self.cur.func.dfg.value_def(lv.value) {
|
||||
ValueDef::Res(i, _) => i != inst,
|
||||
ValueDef::Result(i, _) => i != inst,
|
||||
_ => true,
|
||||
}
|
||||
{
|
||||
|
||||
@@ -202,24 +202,22 @@ impl LiveValueTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// Now add all the live arguments to `ebb`.
|
||||
// Now add all the live parameters to `ebb`.
|
||||
let first_arg = self.live.values.len();
|
||||
for &value in dfg.ebb_args(ebb) {
|
||||
let lr = liveness.get(value).expect(
|
||||
"EBB argument value has no live range",
|
||||
);
|
||||
for &value in dfg.ebb_params(ebb) {
|
||||
let lr = &liveness[value];
|
||||
assert_eq!(lr.def(), ebb.into());
|
||||
match lr.def_local_end().into() {
|
||||
ExpandedProgramPoint::Inst(endpoint) => {
|
||||
self.live.push(value, endpoint, lr);
|
||||
}
|
||||
ExpandedProgramPoint::Ebb(local_ebb) => {
|
||||
// This is a dead EBB argument which is not even live into the first
|
||||
// This is a dead EBB parameter which is not even live into the first
|
||||
// instruction in the EBB.
|
||||
assert_eq!(
|
||||
local_ebb,
|
||||
ebb,
|
||||
"EBB argument live range ends at wrong EBB header"
|
||||
"EBB parameter live range ends at wrong EBB header"
|
||||
);
|
||||
// Give this value a fake endpoint that is the first instruction in the EBB.
|
||||
// We expect it to be removed by calling `drop_dead_args()`.
|
||||
|
||||
@@ -205,7 +205,7 @@ fn get_or_create<'a>(
|
||||
let def;
|
||||
let affinity;
|
||||
match func.dfg.value_def(value) {
|
||||
ValueDef::Res(inst, rnum) => {
|
||||
ValueDef::Result(inst, rnum) => {
|
||||
def = inst.into();
|
||||
// Initialize the affinity from the defining instruction's result constraints.
|
||||
// Don't do this for call return values which are always tied to a single register.
|
||||
@@ -221,14 +221,14 @@ fn get_or_create<'a>(
|
||||
})
|
||||
.unwrap_or_default();
|
||||
}
|
||||
ValueDef::Arg(ebb, num) => {
|
||||
ValueDef::Param(ebb, num) => {
|
||||
def = ebb.into();
|
||||
if func.layout.entry_block() == Some(ebb) {
|
||||
// The affinity for entry block arguments can be inferred from the function
|
||||
// The affinity for entry block parameters can be inferred from the function
|
||||
// signature.
|
||||
affinity = Affinity::abi(&func.signature.argument_types[num], isa);
|
||||
} else {
|
||||
// Don't apply any affinity to normal EBB arguments.
|
||||
// Don't apply any affinity to normal EBB parameters.
|
||||
// They could be in a register or on the stack.
|
||||
affinity = Default::default();
|
||||
}
|
||||
@@ -290,8 +290,8 @@ pub struct Liveness {
|
||||
/// It lives here to avoid repeated allocation of scratch memory.
|
||||
worklist: Vec<Ebb>,
|
||||
|
||||
/// Working space for the `propagate_ebb_arguments` algorithm.
|
||||
ebb_args: Vec<Value>,
|
||||
/// Working space for the `propagate_ebb_params` algorithm.
|
||||
ebb_params: Vec<Value>,
|
||||
}
|
||||
|
||||
impl Liveness {
|
||||
@@ -303,7 +303,7 @@ impl Liveness {
|
||||
Liveness {
|
||||
ranges: LiveRangeSet::new(),
|
||||
worklist: Vec::new(),
|
||||
ebb_args: Vec::new(),
|
||||
ebb_params: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,10 +378,10 @@ impl Liveness {
|
||||
// elimination pass if we visit a post-order of the dominator tree?
|
||||
// TODO: Resolve value aliases while we're visiting instructions?
|
||||
for ebb in func.layout.ebbs() {
|
||||
// Make sure we have created live ranges for dead EBB arguments.
|
||||
// TODO: If these arguments are really dead, we could remove them, except for the entry
|
||||
// block which must match the function signature.
|
||||
for &arg in func.dfg.ebb_args(ebb) {
|
||||
// Make sure we have created live ranges for dead EBB parameters.
|
||||
// TODO: If these parameters are really dead, we could remove them, except for the
|
||||
// entry block which must match the function signature.
|
||||
for &arg in func.dfg.ebb_params(ebb) {
|
||||
get_or_create(&mut self.ranges, arg, isa, func, &enc_info);
|
||||
}
|
||||
|
||||
@@ -431,28 +431,28 @@ impl Liveness {
|
||||
}
|
||||
}
|
||||
|
||||
self.propagate_ebb_arguments(func, cfg);
|
||||
self.propagate_ebb_params(func, cfg);
|
||||
}
|
||||
|
||||
/// Propagate affinities for EBB arguments.
|
||||
/// Propagate affinities for EBB parameters.
|
||||
///
|
||||
/// If an EBB argument value has an affinity, all predecessors must pass a value with an
|
||||
/// affinity.
|
||||
pub fn propagate_ebb_arguments(&mut self, func: &Function, cfg: &ControlFlowGraph) {
|
||||
assert!(self.ebb_args.is_empty());
|
||||
pub fn propagate_ebb_params(&mut self, func: &Function, cfg: &ControlFlowGraph) {
|
||||
assert!(self.ebb_params.is_empty());
|
||||
|
||||
for ebb in func.layout.ebbs() {
|
||||
for &arg in func.dfg.ebb_args(ebb) {
|
||||
for &arg in func.dfg.ebb_params(ebb) {
|
||||
let affinity = self.ranges.get(arg).unwrap().affinity;
|
||||
if affinity.is_none() {
|
||||
continue;
|
||||
}
|
||||
self.ebb_args.push(arg);
|
||||
self.ebb_params.push(arg);
|
||||
|
||||
// Now apply the affinity to all predecessors recursively.
|
||||
while let Some(succ_arg) = self.ebb_args.pop() {
|
||||
while let Some(succ_arg) = self.ebb_params.pop() {
|
||||
let (succ_ebb, num) = match func.dfg.value_def(succ_arg) {
|
||||
ValueDef::Arg(e, n) => (e, n),
|
||||
ValueDef::Param(e, n) => (e, n),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
@@ -461,7 +461,7 @@ impl Liveness {
|
||||
let pred_affinity = &mut self.ranges.get_mut(pred_arg).unwrap().affinity;
|
||||
if pred_affinity.is_none() {
|
||||
*pred_affinity = affinity;
|
||||
self.ebb_args.push(pred_arg);
|
||||
self.ebb_params.push(pred_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ impl<'a> Context<'a> {
|
||||
assert_eq!(liveins.len(), 0);
|
||||
self.visit_entry_args(ebb, args);
|
||||
} else {
|
||||
self.visit_ebb_args(ebb, args);
|
||||
self.visit_ebb_params(ebb, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,10 @@ impl<'a> Context<'a> {
|
||||
if arg.affinity.is_stack() {
|
||||
// An incoming register parameter was spilled. Replace the parameter value
|
||||
// with a temporary register value that is immediately spilled.
|
||||
let reg = self.cur.func.dfg.replace_ebb_arg(arg.value, abi.value_type);
|
||||
let reg = self.cur.func.dfg.replace_ebb_param(
|
||||
arg.value,
|
||||
abi.value_type,
|
||||
);
|
||||
let affinity = Affinity::abi(&abi, self.cur.isa);
|
||||
self.liveness.create_dead(reg, ebb, affinity);
|
||||
self.insert_spill(ebb, arg.value, reg);
|
||||
@@ -170,7 +173,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ebb_args(&mut self, ebb: Ebb, _args: &[LiveValue]) {
|
||||
fn visit_ebb_params(&mut self, ebb: Ebb, _args: &[LiveValue]) {
|
||||
self.cur.goto_first_inst(ebb);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user