Add a DataFlowGraph::replace_ebb_arg() method.
This is needed for rewriting EBB arguments with legalized types.
This commit is contained in:
@@ -261,7 +261,7 @@ pub enum ValueDef {
|
||||
}
|
||||
|
||||
// Internal table storage for extended values.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
enum ValueData {
|
||||
// Value is defined by an instruction, but it is not the first result.
|
||||
Inst {
|
||||
@@ -663,6 +663,67 @@ impl DataFlowGraph {
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace an EBB argument with a new value of type `ty`.
|
||||
///
|
||||
/// The `old_value` must be an attached EBB argument. It is removed from its place in the list
|
||||
/// of arguments and replaced by a new value of type `new_type`. The new value gets the same
|
||||
/// position in the list, and other arguments are not disturbed.
|
||||
///
|
||||
/// The old value is left detached, so it should probably be changed into something else.
|
||||
///
|
||||
/// Returns the new value.
|
||||
pub fn replace_ebb_arg(&mut self, old_arg: Value, new_type: Type) -> Value {
|
||||
let old_data = if let ExpandedValue::Table(index) = old_arg.expand() {
|
||||
self.extended_values[index].clone()
|
||||
} else {
|
||||
panic!("old_arg: {} must be an EBB argument", old_arg);
|
||||
};
|
||||
|
||||
// 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 {
|
||||
(ebb,
|
||||
num,
|
||||
self.make_value(ValueData::Arg {
|
||||
ty: new_type,
|
||||
num: num,
|
||||
ebb: ebb,
|
||||
next: next,
|
||||
}))
|
||||
} else {
|
||||
panic!("old_arg: {} must be an EBB argument: {:?}",
|
||||
old_arg,
|
||||
old_data);
|
||||
};
|
||||
|
||||
// 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 mut arg = self.ebbs[ebb].first_arg.expect("EBB has no arguments");
|
||||
for _ in 1..num {
|
||||
arg = self.next_ebb_arg(arg).expect("Too few EBB arguments");
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
/// Given a value that is known to be an EBB argument, return the next EBB argument.
|
||||
pub fn next_ebb_arg(&self, arg: Value) -> Option<Value> {
|
||||
if let ExpandedValue::Table(index) = arg.expand() {
|
||||
@@ -886,6 +947,36 @@ mod tests {
|
||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [take2, arg3, take1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_ebb_arguments() {
|
||||
let mut dfg = DataFlowGraph::new();
|
||||
|
||||
let ebb = dfg.make_ebb();
|
||||
let arg1 = dfg.append_ebb_arg(ebb, types::F32);
|
||||
|
||||
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]);
|
||||
|
||||
dfg.attach_ebb_arg(ebb, arg1);
|
||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [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]);
|
||||
|
||||
dfg.attach_ebb_arg(ebb, arg1);
|
||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [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]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aliases() {
|
||||
use ir::InstBuilder;
|
||||
|
||||
Reference in New Issue
Block a user