Improved DFG API (#95)
* Improved DFG API with swap_remove_ebb_args and append_inst_arg * Implemented EntityList::swap_remove And used it for dfg::swap_remove_ebb_arg
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
dacc4003a3
commit
731278aad8
@@ -416,7 +416,7 @@ impl<T: EntityRef> EntityList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the element at position `index` from the list.
|
/// Removes the element at position `index` from the list. Potentially linear complexity.
|
||||||
pub fn remove(&mut self, index: usize, pool: &mut ListPool<T>) {
|
pub fn remove(&mut self, index: usize, pool: &mut ListPool<T>) {
|
||||||
let len;
|
let len;
|
||||||
{
|
{
|
||||||
@@ -448,6 +448,22 @@ impl<T: EntityRef> EntityList<T> {
|
|||||||
pool.data[block] = T::new(len - 1);
|
pool.data[block] = T::new(len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes the element at `index` in constant time by switching it with the last element of
|
||||||
|
/// the list.
|
||||||
|
pub fn swap_remove(&mut self, index: usize, pool: &mut ListPool<T>) {
|
||||||
|
let len = self.len(pool);
|
||||||
|
assert!(index < len);
|
||||||
|
if index == len - 1 {
|
||||||
|
self.remove(index, pool);
|
||||||
|
} else {
|
||||||
|
{
|
||||||
|
let seq = self.as_mut_slice(pool);
|
||||||
|
seq.swap(index, len - 1);
|
||||||
|
}
|
||||||
|
self.remove(len - 1, pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Grow the list by inserting `count` elements at `index`.
|
/// Grow the list by inserting `count` elements at `index`.
|
||||||
///
|
///
|
||||||
/// The new elements are not initialized, they will contain whatever happened to be in memory.
|
/// The new elements are not initialized, they will contain whatever happened to be in memory.
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ fn resolve_aliases(values: &EntityMap<Value, ValueData>, value: Value) -> Value
|
|||||||
///
|
///
|
||||||
/// Values are either EBB arguments or instruction results.
|
/// Values are either EBB arguments or instruction results.
|
||||||
impl DataFlowGraph {
|
impl DataFlowGraph {
|
||||||
// Allocate an extended value entry.
|
/// Allocate an extended value entry.
|
||||||
fn make_value(&mut self, data: ValueData) -> Value {
|
fn make_value(&mut self, data: ValueData) -> Value {
|
||||||
self.values.push(data)
|
self.values.push(data)
|
||||||
}
|
}
|
||||||
@@ -562,6 +562,17 @@ impl DataFlowGraph {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Append a new value argument to an instruction.
|
||||||
|
///
|
||||||
|
/// Panics if the instruction doesn't support arguments.
|
||||||
|
pub fn append_inst_arg(&mut self, inst: Inst, new_arg: Value) {
|
||||||
|
let mut branch_values = self.insts[inst]
|
||||||
|
.take_value_list()
|
||||||
|
.expect("the instruction doesn't have value arguments");
|
||||||
|
branch_values.push(new_arg, &mut self.value_lists);
|
||||||
|
self.insts[inst].put_value_list(branch_values)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the first result of an instruction.
|
/// Get the first result of an instruction.
|
||||||
///
|
///
|
||||||
/// This function panics if the instruction doesn't have any result.
|
/// This function panics if the instruction doesn't have any result.
|
||||||
@@ -682,6 +693,35 @@ impl DataFlowGraph {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes `val` from `ebb`'s argument by swapping it with the last argument of `ebb`.
|
||||||
|
/// Returns the position of `val` before removal.
|
||||||
|
///
|
||||||
|
/// *Important*: to ensure O(1) deletion, this method swaps the removed argument with the
|
||||||
|
/// last `Ebb` argument. This can disrupt all the branch instructions jumping to this
|
||||||
|
/// `Ebb` for which you have to change the jump argument order if necessary.
|
||||||
|
///
|
||||||
|
/// Panics if `val` is not an `Ebb` argument. Returns `true` if `Ebb` arguments have been
|
||||||
|
/// swapped.
|
||||||
|
pub fn swap_remove_ebb_arg(&mut self, val: Value) -> usize {
|
||||||
|
let (ebb, num) = if let ValueData::Arg { num, ebb, .. } = self.values[val] {
|
||||||
|
(ebb, num)
|
||||||
|
} else {
|
||||||
|
panic!("{} must be an EBB argument", val);
|
||||||
|
};
|
||||||
|
self.ebbs[ebb]
|
||||||
|
.args
|
||||||
|
.swap_remove(num as usize, &mut self.value_lists);
|
||||||
|
if let Some(last_arg_val) = self.ebbs[ebb].args.get(num as usize, &self.value_lists) {
|
||||||
|
// We update the position of the old last arg.
|
||||||
|
if let ValueData::Arg { num: ref mut old_num, .. } = self.values[last_arg_val] {
|
||||||
|
*old_num = num;
|
||||||
|
} else {
|
||||||
|
panic!("{} should be an Ebb argument but is not", last_arg_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
num as usize
|
||||||
|
}
|
||||||
|
|
||||||
/// Append an existing argument value to `ebb`.
|
/// Append an existing argument value to `ebb`.
|
||||||
///
|
///
|
||||||
/// The appended value can't already be attached to something else.
|
/// The appended value can't already be attached to something else.
|
||||||
@@ -899,6 +939,30 @@ mod tests {
|
|||||||
assert_eq!(dfg.ebb_args(ebb), &[new1, new3, arg1]);
|
assert_eq!(dfg.ebb_args(ebb), &[new1, new3, arg1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn swap_remove_ebb_arguments() {
|
||||||
|
let mut dfg = DataFlowGraph::new();
|
||||||
|
|
||||||
|
let ebb = dfg.make_ebb();
|
||||||
|
let arg1 = dfg.append_ebb_arg(ebb, types::F32);
|
||||||
|
let arg2 = dfg.append_ebb_arg(ebb, types::F32);
|
||||||
|
let arg3 = dfg.append_ebb_arg(ebb, types::F32);
|
||||||
|
assert_eq!(dfg.ebb_args(ebb), &[arg1, arg2, arg3]);
|
||||||
|
|
||||||
|
dfg.swap_remove_ebb_arg(arg1);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg1), false);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg2), true);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg3), true);
|
||||||
|
assert_eq!(dfg.ebb_args(ebb), &[arg3, arg2]);
|
||||||
|
dfg.swap_remove_ebb_arg(arg2);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg2), false);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg3), true);
|
||||||
|
assert_eq!(dfg.ebb_args(ebb), &[arg3]);
|
||||||
|
dfg.swap_remove_ebb_arg(arg3);
|
||||||
|
assert_eq!(dfg.value_is_attached(arg3), false);
|
||||||
|
assert_eq!(dfg.ebb_args(ebb), &[]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aliases() {
|
fn aliases() {
|
||||||
use ir::InstBuilder;
|
use ir::InstBuilder;
|
||||||
|
|||||||
Reference in New Issue
Block a user