@@ -80,25 +80,6 @@ enum AbstractValue {
8080}
8181
8282impl AbstractValue {
83- fn join ( self , other : AbstractValue ) -> AbstractValue {
84- match ( self , other) {
85- // Joining with `None` has no effect
86- ( AbstractValue :: None , p2) => p2,
87- ( p1, AbstractValue :: None ) => p1,
88- // Joining with `Many` produces `Many`
89- ( AbstractValue :: Many , _p2) => AbstractValue :: Many ,
90- ( _p1, AbstractValue :: Many ) => AbstractValue :: Many ,
91- // The only interesting case
92- ( AbstractValue :: One ( v1) , AbstractValue :: One ( v2) ) => {
93- if v1 == v2 {
94- AbstractValue :: One ( v1)
95- } else {
96- AbstractValue :: Many
97- }
98- }
99- }
100- }
101-
10283 fn is_one ( self ) -> bool {
10384 matches ! ( self , AbstractValue :: One ( _) )
10485 }
@@ -200,14 +181,12 @@ impl SolverState {
200181 }
201182
202183 fn get ( & self , actual : Value ) -> AbstractValue {
203- * self
204- . absvals
205- . get ( & actual)
184+ self . maybe_get ( actual)
206185 . unwrap_or_else ( || panic ! ( "SolverState::get: formal param {:?} is untracked?!" , actual) )
207186 }
208187
209- fn maybe_get ( & self , actual : Value ) -> Option < & AbstractValue > {
210- self . absvals . get ( & actual)
188+ fn maybe_get ( & self , actual : Value ) -> Option < AbstractValue > {
189+ self . absvals . get ( & actual) . copied ( )
211190 }
212191
213192 fn set ( & mut self , actual : Value , lp : AbstractValue ) {
@@ -292,30 +271,50 @@ pub fn do_remove_constant_phis(func: &mut Function, domtree: &mut DominatorTree)
292271 let src_summary = & summaries[ src] ;
293272 for edge in & src_summary. dests {
294273 assert ! ( edge. block != entry_block) ;
295- // By contrast, the dst block must have a summary. Phase 1
296- // will have only included an entry in `src_summary.dests` if
297- // that branch/jump carried at least one parameter. So the
298- // dst block does take parameters, so it must have a summary.
274+ // Phase 1 will have only saved an edge if that branch/jump
275+ // carried at least one parameter. Therefore the dst block does
276+ // take parameters, and it must have a summary.
299277 let dst_summary = & summaries[ edge. block ] ;
300278 let dst_formals = & dst_summary. formals ;
301279 assert_eq ! ( edge. args. len( ) , dst_formals. len( ) ) ;
302- for ( formal, actual) in dst_formals. iter ( ) . zip ( edge. args ) {
303- // Find the abstract value for `actual`. If it is a block
304- // formal parameter then the most recent abstract value is
305- // to be found in the solver state. If not, then it's a
306- // real value defining point (not a phi), in which case
307- // return it itself.
308- let actual_absval = match state. maybe_get ( * actual) {
309- Some ( pt) => * pt,
310- None => AbstractValue :: One ( * actual) ,
280+ for ( & formal, & actual) in dst_formals. iter ( ) . zip ( edge. args ) {
281+ // In case `actual` is itself defined by a block formal
282+ // parameter, look up our current abstract value for that
283+ // formal's definition.
284+ let replacement = match state. maybe_get ( actual) {
285+ // If `actual` isn't one of the formal parameters we're
286+ // considering, or we've already proven that there is no
287+ // one value we can substitute for it, then use `actual`
288+ // itself.
289+ None | Some ( AbstractValue :: Many ) => actual,
290+
291+ // Otherwise, the evidence we've found so far says
292+ // we can replace `actual` with some other value.
293+ // Assume that hypothesis is true and propagate the
294+ // replacement. We may later prove this false, but we'll
295+ // fix it on later fix-point iterations.
296+ Some ( AbstractValue :: One ( replacement) ) => replacement,
297+
298+ // Since we visit blocks in reverse post-order, we must
299+ // have visited at least one predecessor of the block
300+ // that defines this formal parameter, and gotten at
301+ // least one actual value for it.
302+ Some ( AbstractValue :: None ) => unreachable ! ( ) ,
311303 } ;
312304
313- // And `join` the new value with the old.
314- let formal_absval_old = state. get ( * formal) ;
315- let formal_absval_new = formal_absval_old. join ( actual_absval) ;
305+ // We have one value for this formal; join it with any
306+ // others we've found previously.
307+ let formal_absval_old = state. get ( formal) ;
308+ let formal_absval_new = match formal_absval_old {
309+ AbstractValue :: Many => AbstractValue :: Many ,
310+ // If the value is different, there are many values.
311+ AbstractValue :: One ( v) if v != replacement => AbstractValue :: Many ,
312+ // Otherwise no previous value or it was the same value.
313+ _ => AbstractValue :: One ( replacement) ,
314+ } ;
316315 if formal_absval_new != formal_absval_old {
317316 changed = true ;
318- state. set ( * formal, formal_absval_new) ;
317+ state. set ( formal, formal_absval_new) ;
319318 }
320319 }
321320 }
0 commit comments