Stop maintaining a linked list of EBB arguments.
Now that we have a value list of the arguments, we can get rid of: - The first_arg and last_arg members in EbbData, - The next member in the ValueData::Arg variant.
This commit is contained in:
@@ -295,7 +295,8 @@ impl<T: EntityRef> EntityList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Appends an element to the back of the list.
|
/// Appends an element to the back of the list.
|
||||||
pub fn push(&mut self, element: T, pool: &mut ListPool<T>) {
|
/// Returns the index where the element was inserted.
|
||||||
|
pub fn push(&mut self, element: T, pool: &mut ListPool<T>) -> usize {
|
||||||
let idx = self.index as usize;
|
let idx = self.index as usize;
|
||||||
match pool.len_of(self) {
|
match pool.len_of(self) {
|
||||||
None => {
|
None => {
|
||||||
@@ -305,6 +306,7 @@ impl<T: EntityRef> EntityList<T> {
|
|||||||
pool.data[block] = T::new(1);
|
pool.data[block] = T::new(1);
|
||||||
pool.data[block + 1] = element;
|
pool.data[block + 1] = element;
|
||||||
self.index = (block + 1) as u32;
|
self.index = (block + 1) as u32;
|
||||||
|
0
|
||||||
}
|
}
|
||||||
Some(len) => {
|
Some(len) => {
|
||||||
// Do we need to reallocate?
|
// Do we need to reallocate?
|
||||||
@@ -320,6 +322,7 @@ impl<T: EntityRef> EntityList<T> {
|
|||||||
}
|
}
|
||||||
pool.data[block + new_len] = element;
|
pool.data[block + new_len] = element;
|
||||||
pool.data[block] = T::new(new_len);
|
pool.data[block] = T::new(new_len);
|
||||||
|
len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,14 +519,14 @@ mod tests {
|
|||||||
let i3 = Inst::new(3);
|
let i3 = Inst::new(3);
|
||||||
let i4 = Inst::new(4);
|
let i4 = Inst::new(4);
|
||||||
|
|
||||||
list.push(i1, pool);
|
assert_eq!(list.push(i1, pool), 0);
|
||||||
assert_eq!(list.len(pool), 1);
|
assert_eq!(list.len(pool), 1);
|
||||||
assert!(!list.is_empty());
|
assert!(!list.is_empty());
|
||||||
assert_eq!(list.as_slice(pool), &[i1]);
|
assert_eq!(list.as_slice(pool), &[i1]);
|
||||||
assert_eq!(list.get(0, pool), Some(i1));
|
assert_eq!(list.get(0, pool), Some(i1));
|
||||||
assert_eq!(list.get(1, pool), None);
|
assert_eq!(list.get(1, pool), None);
|
||||||
|
|
||||||
list.push(i2, pool);
|
assert_eq!(list.push(i2, pool), 1);
|
||||||
assert_eq!(list.len(pool), 2);
|
assert_eq!(list.len(pool), 2);
|
||||||
assert!(!list.is_empty());
|
assert!(!list.is_empty());
|
||||||
assert_eq!(list.as_slice(pool), &[i1, i2]);
|
assert_eq!(list.as_slice(pool), &[i1, i2]);
|
||||||
@@ -531,7 +534,7 @@ mod tests {
|
|||||||
assert_eq!(list.get(1, pool), Some(i2));
|
assert_eq!(list.get(1, pool), Some(i2));
|
||||||
assert_eq!(list.get(2, pool), None);
|
assert_eq!(list.get(2, pool), None);
|
||||||
|
|
||||||
list.push(i3, pool);
|
assert_eq!(list.push(i3, pool), 2);
|
||||||
assert_eq!(list.len(pool), 3);
|
assert_eq!(list.len(pool), 3);
|
||||||
assert!(!list.is_empty());
|
assert!(!list.is_empty());
|
||||||
assert_eq!(list.as_slice(pool), &[i1, i2, i3]);
|
assert_eq!(list.as_slice(pool), &[i1, i2, i3]);
|
||||||
@@ -541,7 +544,7 @@ mod tests {
|
|||||||
assert_eq!(list.get(3, pool), None);
|
assert_eq!(list.get(3, pool), None);
|
||||||
|
|
||||||
// This triggers a reallocation.
|
// This triggers a reallocation.
|
||||||
list.push(i4, pool);
|
assert_eq!(list.push(i4, pool), 3);
|
||||||
assert_eq!(list.len(pool), 4);
|
assert_eq!(list.len(pool), 4);
|
||||||
assert!(!list.is_empty());
|
assert!(!list.is_empty());
|
||||||
assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4]);
|
assert_eq!(list.as_slice(pool), &[i1, i2, i3, i4]);
|
||||||
|
|||||||
@@ -276,7 +276,6 @@ enum ValueData {
|
|||||||
ty: Type,
|
ty: Type,
|
||||||
num: u16, // Argument number, starting from 0.
|
num: u16, // Argument number, starting from 0.
|
||||||
ebb: Ebb,
|
ebb: Ebb,
|
||||||
next: PackedOption<Value>, // Next argument to `ebb`.
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Value is an alias of another value.
|
// Value is an alias of another value.
|
||||||
@@ -308,7 +307,9 @@ impl<'a> Iterator for Values<'a> {
|
|||||||
ExpandedValue::Table(index) => {
|
ExpandedValue::Table(index) => {
|
||||||
match self.dfg.extended_values[index] {
|
match self.dfg.extended_values[index] {
|
||||||
ValueData::Inst { next, .. } => next.into(),
|
ValueData::Inst { next, .. } => next.into(),
|
||||||
ValueData::Arg { next, .. } => next.into(),
|
ValueData::Arg { .. } => {
|
||||||
|
panic!("EBB argument {} appeared in value list", prev)
|
||||||
|
}
|
||||||
ValueData::Alias { .. } => {
|
ValueData::Alias { .. } => {
|
||||||
panic!("Alias value {} appeared in value list", prev)
|
panic!("Alias value {} appeared in value list", prev)
|
||||||
}
|
}
|
||||||
@@ -696,7 +697,6 @@ impl DataFlowGraph {
|
|||||||
ty: ty,
|
ty: ty,
|
||||||
ebb: ebb,
|
ebb: ebb,
|
||||||
num: 0,
|
num: 0,
|
||||||
next: None.into(),
|
|
||||||
});
|
});
|
||||||
self.attach_ebb_arg(ebb, val);
|
self.attach_ebb_arg(ebb, val);
|
||||||
val
|
val
|
||||||
@@ -724,46 +724,20 @@ impl DataFlowGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create new value identical to the old one except for the type.
|
// Create new value identical to the old one except for the type.
|
||||||
let (ebb, num, new_arg) = if let ValueData::Arg { num, ebb, next, .. } = old_data {
|
let (ebb, num) = if let ValueData::Arg { num, ebb, .. } = old_data {
|
||||||
(ebb,
|
(ebb, num)
|
||||||
num,
|
|
||||||
self.make_value(ValueData::Arg {
|
|
||||||
ty: new_type,
|
|
||||||
num: num,
|
|
||||||
ebb: ebb,
|
|
||||||
next: next,
|
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
panic!("old_arg: {} must be an EBB argument: {:?}",
|
panic!("old_arg: {} must be an EBB argument: {:?}",
|
||||||
old_arg,
|
old_arg,
|
||||||
old_data);
|
old_data);
|
||||||
};
|
};
|
||||||
|
let new_arg = self.make_value(ValueData::Arg {
|
||||||
|
ty: new_type,
|
||||||
|
num: num,
|
||||||
|
ebb: ebb,
|
||||||
|
});
|
||||||
|
|
||||||
self.ebbs[ebb].args.as_mut_slice(&mut self.value_lists)[num as usize] = new_arg;
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.ebbs[ebb].first_arg.expand() == Some(old_arg) {
|
|
||||||
assert_eq!(num, 0);
|
|
||||||
self.ebbs[ebb].first_arg = new_arg.into();
|
|
||||||
} else {
|
|
||||||
// We need to find the num-1 argument value and change its next link.
|
|
||||||
let arg = self.ebbs[ebb].args.as_slice(&self.value_lists)[(num - 1) as usize];
|
|
||||||
if let ExpandedValue::Table(index) = arg.expand() {
|
|
||||||
if let ValueData::Arg { ref mut next, .. } = self.extended_values[index] {
|
|
||||||
assert_eq!(next.expand(), Some(old_arg));
|
|
||||||
*next = new_arg.into();
|
|
||||||
} else {
|
|
||||||
panic!("{} is not an EBB argument", arg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("{} is not an EBB argument", arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new_arg
|
new_arg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -773,8 +747,6 @@ impl DataFlowGraph {
|
|||||||
/// is to put them back on the same EBB with `attach_ebb_arg()` or change them into aliases
|
/// is to put them back on the same EBB with `attach_ebb_arg()` or change them into aliases
|
||||||
/// with `change_to_alias()`.
|
/// with `change_to_alias()`.
|
||||||
pub fn detach_ebb_args(&mut self, ebb: Ebb) -> ValueList {
|
pub fn detach_ebb_args(&mut self, ebb: Ebb) -> ValueList {
|
||||||
self.ebbs[ebb].first_arg = None.into();
|
|
||||||
self.ebbs[ebb].last_arg = None.into();
|
|
||||||
self.ebbs[ebb].args.take()
|
self.ebbs[ebb].args.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,38 +758,14 @@ impl DataFlowGraph {
|
|||||||
///
|
///
|
||||||
/// In almost all cases, you should be using `append_ebb_arg()` instead of this method.
|
/// 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) {
|
pub fn attach_ebb_arg(&mut self, ebb: Ebb, arg: Value) {
|
||||||
self.ebbs[ebb].args.push(arg, &mut self.value_lists);
|
let arg_num = self.ebbs[ebb].args.push(arg, &mut self.value_lists);
|
||||||
let arg_num = match self.ebbs[ebb].last_arg.map(|v| v.expand()) {
|
assert!(arg_num <= u16::MAX as usize, "Too many arguments to EBB");
|
||||||
// If last_argument is `None`, we're adding the first EBB argument.
|
|
||||||
None => {
|
|
||||||
self.ebbs[ebb].first_arg = arg.into();
|
|
||||||
0
|
|
||||||
}
|
|
||||||
// Append to the linked list of arguments.
|
|
||||||
Some(ExpandedValue::Table(idx)) => {
|
|
||||||
if let ValueData::Arg { ref mut next, num, .. } = self.extended_values[idx] {
|
|
||||||
*next = arg.into();
|
|
||||||
assert!(num < u16::MAX, "Too many arguments to EBB");
|
|
||||||
num + 1
|
|
||||||
} else {
|
|
||||||
panic!("inconsistent value table entry for EBB argument");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("inconsistent value table entry for EBB argument"),
|
|
||||||
};
|
|
||||||
self.ebbs[ebb].last_arg = arg.into();
|
|
||||||
|
|
||||||
// Now update `arg` itself.
|
// Now update `arg` itself.
|
||||||
let arg_ebb = ebb;
|
let arg_ebb = ebb;
|
||||||
if let ExpandedValue::Table(idx) = arg.expand() {
|
if let ExpandedValue::Table(idx) = arg.expand() {
|
||||||
if let ValueData::Arg {
|
if let ValueData::Arg { ref mut num, ebb, .. } = self.extended_values[idx] {
|
||||||
ref mut num,
|
*num = arg_num as u16;
|
||||||
ebb,
|
|
||||||
ref mut next,
|
|
||||||
..
|
|
||||||
} = self.extended_values[idx] {
|
|
||||||
*num = arg_num;
|
|
||||||
*next = None.into();
|
|
||||||
assert_eq!(arg_ebb, ebb, "{} should already belong to EBB", arg);
|
assert_eq!(arg_ebb, ebb, "{} should already belong to EBB", arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -835,24 +783,11 @@ impl DataFlowGraph {
|
|||||||
struct EbbData {
|
struct EbbData {
|
||||||
// List of arguments to this EBB.
|
// List of arguments to this EBB.
|
||||||
args: ValueList,
|
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`
|
|
||||||
// to `last_arg`.
|
|
||||||
first_arg: PackedOption<Value>,
|
|
||||||
|
|
||||||
// Last argument to this EBB, or `None` if the block has no arguments.
|
|
||||||
last_arg: PackedOption<Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EbbData {
|
impl EbbData {
|
||||||
fn new() -> EbbData {
|
fn new() -> EbbData {
|
||||||
EbbData {
|
EbbData { args: ValueList::new() }
|
||||||
args: ValueList::new(),
|
|
||||||
first_arg: None.into(),
|
|
||||||
last_arg: None.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user