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:
@@ -90,10 +90,17 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
for d in node.defs[1:]:
|
for d in node.defs[1:]:
|
||||||
fmt.line('let src_{};'.format(d))
|
fmt.line('let src_{};'.format(d))
|
||||||
with fmt.indented('{', '}'):
|
with fmt.indented('{', '}'):
|
||||||
fmt.line('let mut vals = dfg.detach_secondary_results(inst);')
|
fmt.line(
|
||||||
for d in node.defs[1:]:
|
'src_{} = dfg.detach_secondary_results(inst).unwrap();'
|
||||||
fmt.line('src_{} = vals.next().unwrap();'.format(d))
|
.format(node.defs[1]))
|
||||||
fmt.line('assert_eq!(vals.next(), None);')
|
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:]:
|
for d in node.defs[1:]:
|
||||||
if d.has_free_typevar():
|
if d.has_free_typevar():
|
||||||
fmt.line(
|
fmt.line(
|
||||||
|
|||||||
@@ -430,19 +430,29 @@ impl DataFlowGraph {
|
|||||||
ReplaceBuilder::new(self, inst)
|
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`,
|
/// 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.
|
/// 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
|
/// Use this method to detach secondary values before using `replace(inst)` to provide an
|
||||||
/// alternate instruction for computing the primary result value.
|
/// alternate instruction for computing the primary result value.
|
||||||
pub fn detach_secondary_results(&mut self, inst: Inst) -> Values {
|
pub fn detach_secondary_results(&mut self, inst: Inst) -> Option<Value> {
|
||||||
let second_result = self[inst].second_result_mut().and_then(|r| r.take());
|
self[inst].second_result_mut().and_then(|r| r.take())
|
||||||
Values {
|
}
|
||||||
dfg: self,
|
|
||||||
cur: second_result,
|
/// 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.
|
/// Get the first result of an instruction.
|
||||||
@@ -811,9 +821,8 @@ mod tests {
|
|||||||
|
|
||||||
// Detach the 'c' value from `iadd`.
|
// Detach the 'c' value from `iadd`.
|
||||||
{
|
{
|
||||||
let mut vals = dfg.detach_secondary_results(iadd);
|
assert_eq!(dfg.detach_secondary_results(iadd), Some(c));
|
||||||
assert_eq!(vals.next(), Some(c));
|
assert_eq!(dfg.next_secondary_result(c), None);
|
||||||
assert_eq!(vals.next(), None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace `iadd_cout` with a normal `iadd` and an `icmp`.
|
// Replace `iadd_cout` with a normal `iadd` and an `icmp`.
|
||||||
|
|||||||
Reference in New Issue
Block a user