Don't return a Values iterator from detach_secondary_results().

Instead, just return the first of the detached values, and provide a
next_secondary_result() method for traversing the list.

This is equivalent to how detach_ebb_args() works, and it allows the
data flow graph to be modified while traversing the list of results.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-15 15:38:47 -07:00
parent 765c866971
commit 89f45a5c82
2 changed files with 31 additions and 15 deletions

View File

@@ -90,10 +90,17 @@ def unwrap_inst(iref, node, fmt):
for d in node.defs[1:]:
fmt.line('let src_{};'.format(d))
with fmt.indented('{', '}'):
fmt.line('let mut vals = dfg.detach_secondary_results(inst);')
for d in node.defs[1:]:
fmt.line('src_{} = vals.next().unwrap();'.format(d))
fmt.line('assert_eq!(vals.next(), None);')
fmt.line(
'src_{} = dfg.detach_secondary_results(inst).unwrap();'
.format(node.defs[1]))
for i in range(2, len(node.defs)):
fmt.line(
'src_{} = dfg.next_secondary_result(src_{})'
'.unwrap();'
.format(node.defs[i], node.defs[i - 1]))
fmt.line(
'assert_eq!(dfg.next_secondary_result(src_{}), None);'
.format(node.defs[-1]))
for d in node.defs[1:]:
if d.has_free_typevar():
fmt.line(

View File

@@ -430,19 +430,29 @@ impl DataFlowGraph {
ReplaceBuilder::new(self, inst)
}
/// Detach secondary instruction results, and return them as an iterator.
/// Detach secondary instruction results, and return the first of them.
///
/// If `inst` produces two or more results, detach these secondary result values from `inst`,
/// and return an iterator that will enumerate them. The first result value cannot be detached.
/// If `inst` produces two or more results, detach these secondary result values from `inst`.
/// The first result value cannot be detached.
/// The full list of secondary results can be traversed with `next_secondary_result()`.
///
/// Use this method to detach secondary values before using `replace(inst)` to provide an
/// alternate instruction for computing the primary result value.
pub fn detach_secondary_results(&mut self, inst: Inst) -> Values {
let second_result = self[inst].second_result_mut().and_then(|r| r.take());
Values {
dfg: self,
cur: second_result,
pub fn detach_secondary_results(&mut self, inst: Inst) -> Option<Value> {
self[inst].second_result_mut().and_then(|r| r.take())
}
/// Get the next secondary result after `value`.
///
/// Use this function to traverse the full list of instruction results returned from
/// `detach_secondary_results()`.
pub fn next_secondary_result(&self, value: Value) -> Option<Value> {
if let ExpandedValue::Table(index) = value.expand() {
if let ValueData::Inst { next, .. } = self.extended_values[index] {
return next.into();
}
}
panic!("{} is not a secondary result value", value);
}
/// Get the first result of an instruction.
@@ -811,9 +821,8 @@ mod tests {
// Detach the 'c' value from `iadd`.
{
let mut vals = dfg.detach_secondary_results(iadd);
assert_eq!(vals.next(), Some(c));
assert_eq!(vals.next(), None);
assert_eq!(dfg.detach_secondary_results(iadd), Some(c));
assert_eq!(dfg.next_secondary_result(c), None);
}
// Replace `iadd_cout` with a normal `iadd` and an `icmp`.