Keep EBB arguments in a ValueList.

This is the first step of the value list refactoring which will replace
linked lists of values with value lists.

- Keep a ValueList in the EbbData struct containing all the EBB
  arguments.
- Change dfg.ebb_args() to return a slice instead of an iterator.

This leaves us in a temporary hybrid state where we maintain both a
linked list and a ValueList vector of the EBB arguments.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-11 11:36:50 -07:00
parent 1c890f317d
commit ccba325b6c
6 changed files with 40 additions and 48 deletions

View File

@@ -222,6 +222,11 @@ impl<T: EntityRef> ListPool<T> {
}
impl<T: EntityRef> EntityList<T> {
/// Create a new empty list.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if the list has a length of 0.
pub fn is_empty(&self) -> bool {
// 0 is a magic value for the empty list. Any list in the pool array must have a positive

View File

@@ -1,6 +1,6 @@
//! Data flow graph tracking Instructions, Values, and EBBs.
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueListPool};
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueListPool};
use ir::entities::ExpandedValue;
use ir::instructions::{Opcode, InstructionData, CallInfo};
use ir::extfunc::ExtFuncData;
@@ -687,17 +687,7 @@ impl DataFlowGraph {
/// Get the number of arguments on `ebb`.
pub fn num_ebb_args(&self, ebb: Ebb) -> usize {
match self.ebbs[ebb].last_arg.expand() {
None => 0,
Some(last_arg) => {
if let ExpandedValue::Table(idx) = last_arg.expand() {
if let ValueData::Arg { num, .. } = self.extended_values[idx] {
return num as usize + 1;
}
}
panic!("inconsistent value table entry for EBB argument");
}
}
self.ebbs[ebb].args.len(&self.value_lists)
}
/// Append an argument with type `ty` to `ebb`.
@@ -712,12 +702,9 @@ impl DataFlowGraph {
val
}
/// Iterate through the arguments to an EBB.
pub fn ebb_args(&self, ebb: Ebb) -> Values {
Values {
dfg: self,
cur: self.ebbs[ebb].first_arg.into(),
}
/// Get the arguments to an EBB.
pub fn ebb_args(&self, ebb: Ebb) -> &[Value] {
self.ebbs[ebb].args.as_slice(&self.value_lists)
}
/// Replace an EBB argument with a new value of type `ty`.
@@ -752,6 +739,8 @@ impl DataFlowGraph {
old_data);
};
self.ebbs[ebb].args.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
// Now fix up the linked lists.
if self.ebbs[ebb].last_arg.expand() == Some(old_arg) {
self.ebbs[ebb].last_arg = new_arg.into();
@@ -804,6 +793,7 @@ impl DataFlowGraph {
let first = self.ebbs[ebb].first_arg.into();
self.ebbs[ebb].first_arg = None.into();
self.ebbs[ebb].last_arg = None.into();
self.ebbs[ebb].args.clear(&mut self.value_lists);
first
}
@@ -815,6 +805,7 @@ impl DataFlowGraph {
///
/// In almost all cases, you should be using `append_ebb_arg()` instead of this method.
pub fn attach_ebb_arg(&mut self, ebb: Ebb, arg: Value) {
self.ebbs[ebb].args.push(arg, &mut self.value_lists);
let arg_num = match self.ebbs[ebb].last_arg.map(|v| v.expand()) {
// If last_argument is `None`, we're adding the first EBB argument.
None => {
@@ -861,6 +852,9 @@ impl DataFlowGraph {
// match the function arguments.
#[derive(Clone)]
struct EbbData {
// List of arguments to this EBB.
args: ValueList,
// First argument to this EBB, or `None` if the block has no arguments.
//
// The arguments are all `ValueData::Argument` entries that form a linked list from `first_arg`
@@ -874,6 +868,7 @@ struct EbbData {
impl EbbData {
fn new() -> EbbData {
EbbData {
args: ValueList::new(),
first_arg: None.into(),
last_arg: None.into(),
}
@@ -966,28 +961,20 @@ mod tests {
let ebb = dfg.make_ebb();
assert_eq!(ebb.to_string(), "ebb0");
assert_eq!(dfg.num_ebb_args(ebb), 0);
assert_eq!(dfg.ebb_args(ebb).next(), None);
assert_eq!(dfg.ebb_args(ebb), &[]);
assert_eq!(dfg.detach_ebb_args(ebb), None);
assert_eq!(dfg.num_ebb_args(ebb), 0);
assert_eq!(dfg.ebb_args(ebb).next(), None);
assert_eq!(dfg.ebb_args(ebb), &[]);
let arg1 = dfg.append_ebb_arg(ebb, types::F32);
assert_eq!(arg1.to_string(), "vx0");
assert_eq!(dfg.num_ebb_args(ebb), 1);
{
let mut args1 = dfg.ebb_args(ebb);
assert_eq!(args1.next(), Some(arg1));
assert_eq!(args1.next(), None);
}
assert_eq!(dfg.ebb_args(ebb), &[arg1]);
let arg2 = dfg.append_ebb_arg(ebb, types::I16);
assert_eq!(arg2.to_string(), "vx1");
assert_eq!(dfg.num_ebb_args(ebb), 2);
{
let mut args2 = dfg.ebb_args(ebb);
assert_eq!(args2.next(), Some(arg1));
assert_eq!(args2.next(), Some(arg2));
assert_eq!(args2.next(), None);
}
assert_eq!(dfg.ebb_args(ebb), &[arg1, arg2]);
assert_eq!(dfg.value_def(arg1), ValueDef::Arg(ebb, 0));
assert_eq!(dfg.value_def(arg2), ValueDef::Arg(ebb, 1));
@@ -997,7 +984,7 @@ mod tests {
// Swap the two EBB arguments.
let take1 = dfg.detach_ebb_args(ebb).unwrap();
assert_eq!(dfg.num_ebb_args(ebb), 0);
assert_eq!(dfg.ebb_args(ebb).next(), None);
assert_eq!(dfg.ebb_args(ebb), &[]);
let take2 = dfg.next_ebb_arg(take1).unwrap();
assert_eq!(take1, arg1);
assert_eq!(take2, arg2);
@@ -1005,7 +992,7 @@ mod tests {
dfg.attach_ebb_arg(ebb, take2);
let arg3 = dfg.append_ebb_arg(ebb, types::I32);
dfg.attach_ebb_arg(ebb, take1);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [take2, arg3, take1]);
assert_eq!(dfg.ebb_args(ebb), &[take2, arg3, take1]);
}
#[test]
@@ -1018,24 +1005,24 @@ mod tests {
let new1 = dfg.replace_ebb_arg(arg1, types::I64);
assert_eq!(dfg.value_type(arg1), types::F32);
assert_eq!(dfg.value_type(new1), types::I64);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [new1]);
assert_eq!(dfg.ebb_args(ebb), &[new1]);
dfg.attach_ebb_arg(ebb, arg1);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [new1, arg1]);
assert_eq!(dfg.ebb_args(ebb), &[new1, arg1]);
let new2 = dfg.replace_ebb_arg(arg1, types::I8);
assert_eq!(dfg.value_type(arg1), types::F32);
assert_eq!(dfg.value_type(new2), types::I8);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [new1, new2]);
assert_eq!(dfg.ebb_args(ebb), &[new1, new2]);
dfg.attach_ebb_arg(ebb, arg1);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [new1, new2, arg1]);
assert_eq!(dfg.ebb_args(ebb), &[new1, new2, arg1]);
let new3 = dfg.replace_ebb_arg(new2, types::I16);
assert_eq!(dfg.value_type(new1), types::I64);
assert_eq!(dfg.value_type(new2), types::I8);
assert_eq!(dfg.value_type(new3), types::I16);
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [new1, new3, arg1]);
assert_eq!(dfg.ebb_args(ebb), &[new1, new3, arg1]);
}
#[test]

View File

@@ -182,7 +182,7 @@ impl LiveValueTracker {
// Now add all the live arguments to `ebb`.
let first_arg = self.live.values.len();
for value in dfg.ebb_args(ebb) {
for &value in dfg.ebb_args(ebb) {
let lr = liveness
.get(value)
.expect("EBB argument value has no live range");

View File

@@ -151,7 +151,7 @@ impl<'a> Verifier<'a> {
}
// Arguments belong to the correct ebb.
for arg in self.func.dfg.ebb_args(ebb) {
for &arg in self.func.dfg.ebb_args(ebb) {
match self.func.dfg.value_def(arg) {
ValueDef::Arg(arg_ebb, _) => {
if ebb != arg_ebb {
@@ -405,7 +405,7 @@ impl<'a> Verifier<'a> {
return err!(ebb, "entry block arguments must match function signature");
}
for (i, arg) in self.func.dfg.ebb_args(ebb).enumerate() {
for (i, &arg) in self.func.dfg.ebb_args(ebb).iter().enumerate() {
let arg_type = self.func.dfg.value_type(arg);
if arg_type != expected_types[i].value_type {
return err!(ebb,
@@ -510,7 +510,8 @@ impl<'a> Verifier<'a> {
let iter = self.func
.dfg
.ebb_args(ebb)
.map(|v| self.func.dfg.value_type(v));
.iter()
.map(|&v| self.func.dfg.value_type(v));
self.typecheck_variable_args_iterator(inst, iter)?;
}
BranchInfo::Table(table) => {

View File

@@ -95,7 +95,7 @@ pub fn write_ebb_header(w: &mut Write, func: &Function, ebb: Ebb) -> Result {
write!(w, " ")?;
}
let mut args = func.dfg.ebb_args(ebb);
let mut args = func.dfg.ebb_args(ebb).iter().cloned();
match args.next() {
None => return writeln!(w, "{}:", ebb),
Some(arg) => {

View File

@@ -1895,13 +1895,12 @@ mod tests {
let mut ebbs = func.layout.ebbs();
let ebb0 = ebbs.next().unwrap();
assert_eq!(func.dfg.ebb_args(ebb0).next(), None);
assert_eq!(func.dfg.ebb_args(ebb0), &[]);
let ebb4 = ebbs.next().unwrap();
let mut ebb4_args = func.dfg.ebb_args(ebb4);
let arg0 = ebb4_args.next().unwrap();
assert_eq!(func.dfg.value_type(arg0), types::I32);
assert_eq!(ebb4_args.next(), None);
let ebb4_args = func.dfg.ebb_args(ebb4);
assert_eq!(ebb4_args.len(), 1);
assert_eq!(func.dfg.value_type(ebb4_args[0]), types::I32);
}
#[test]