Add a dfg::replace_result() method.

This is analogous to replace_ebb_arg(). It replaces an instruction
result value with a new value, leaving the old value in a detached
state.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-05 15:07:48 -07:00
parent de0f0e5f0a
commit 402cb8e1f6

View File

@@ -10,6 +10,7 @@ use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueList, ValueLis
use write::write_operands;
use std::fmt;
use std::iter;
use std::mem;
use std::ops::{Index, IndexMut};
use std::u16;
@@ -509,6 +510,36 @@ impl DataFlowGraph {
};
}
/// Replace an instruction result with a new value of type `new_type`.
///
/// The `old_value` must be an attached instruction result.
///
/// The old value is left detached, so it should probably be changed into something else.
///
/// Returns the new value.
pub fn replace_result(&mut self, old_value: Value, new_type: Type) -> Value {
let (num, inst) = match self.values[old_value] {
ValueData::Inst { num, inst, .. } => (num, inst),
_ => panic!("{} is not an instruction result value", old_value),
};
let new_value = self.make_value(ValueData::Inst {
ty: new_type,
num,
inst,
});
let num = num as usize;
let attached = mem::replace(self.results[inst]
.get_mut(num, &mut self.value_lists)
.expect("Replacing detached result"),
new_value);
assert_eq!(attached,
old_value,
"{} wasn't detached from {}",
old_value,
self.display_inst(inst));
new_value
}
/// Append a new instruction result value to `inst`.
pub fn append_result(&mut self, inst: Inst, ty: Type) -> Value {
let res = self.values.next_key();
@@ -767,6 +798,15 @@ mod tests {
assert_eq!(dfg.value_def(val), ValueDef::Res(inst, 0));
assert_eq!(dfg.value_type(val), types::I32);
// Replacing results.
assert!(dfg.value_is_attached(val));
let v2 = dfg.replace_result(val, types::F64);
assert!(!dfg.value_is_attached(val));
assert!(dfg.value_is_attached(v2));
assert_eq!(dfg.inst_results(inst), &[v2]);
assert_eq!(dfg.value_def(v2), ValueDef::Res(inst, 0));
assert_eq!(dfg.value_type(v2), types::F64);
}
#[test]