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.
|
// Internal table storage for extended values.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
enum ValueData {
|
enum ValueData {
|
||||||
// Value is defined by an instruction, but it is not the first result.
|
// Value is defined by an instruction, but it is not the first result.
|
||||||
Inst {
|
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.
|
/// 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> {
|
pub fn next_ebb_arg(&self, arg: Value) -> Option<Value> {
|
||||||
if let ExpandedValue::Table(index) = arg.expand() {
|
if let ExpandedValue::Table(index) = arg.expand() {
|
||||||
@@ -886,6 +947,36 @@ mod tests {
|
|||||||
assert_eq!(dfg.ebb_args(ebb).collect::<Vec<_>>(), [take2, arg3, take1]);
|
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]
|
#[test]
|
||||||
fn aliases() {
|
fn aliases() {
|
||||||
use ir::InstBuilder;
|
use ir::InstBuilder;
|
||||||
|
|||||||
Reference in New Issue
Block a user