From 89f45a5c824c4d08bd66f68baf7f670ca8448bed Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 15 Mar 2017 15:38:47 -0700 Subject: [PATCH] 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. --- lib/cretonne/meta/gen_legalizer.py | 15 +++++++++++---- lib/cretonne/src/ir/dfg.rs | 31 +++++++++++++++++++----------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 85aa715996..95d16d3663 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -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( diff --git a/lib/cretonne/src/ir/dfg.rs b/lib/cretonne/src/ir/dfg.rs index 1b1ff418e8..5a70c92608 100644 --- a/lib/cretonne/src/ir/dfg.rs +++ b/lib/cretonne/src/ir/dfg.rs @@ -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 { + 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 { + 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`.