88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- //! This is Move- Constant-Simplify propagation pass. This is a composition of three distinct
11+ //! This is Constant-Simplify propagation pass. This is a composition of three distinct
1212//! dataflow passes: alias-propagation, constant-propagation and terminator simplification.
1313//!
1414//! All these are very similar in their nature:
1515//!
16- //! | Constant | Move | Simplify |
17- //! |----------------|-----------|----------|---------- -|
18- //! | Lattice Domain | Lvalue | Lvalue | Lvalue |
19- //! | Lattice Value | Constant | Lvalue | Constant |
20- //! | Transfer | x = const | x = lval | x = const |
21- //! | Rewrite | x → const | x → lval | T(x) → T' |
22- //! | Bottom | {} | {} | {} |
23- //! | Join | intersect | intersec | intersect |
16+ //! | Constant | Simplify |
17+ //! |----------------|-----------|-----------|
18+ //! | Lattice Domain | Lvalue | Lvalue |
19+ //! | Lattice Value | Constant | Constant |
20+ //! | Transfer | x = const | x = const |
21+ //! | Rewrite | x → const | T(x) → T' |
22+ //! | Bottom | {} | {} |
23+ //! | Join | intersect | intersect |
2424//!
2525//! For all of them we will be using a lattice of `HashMap<Lvalue, Either<Lvalue, Constant, Top>>`.
2626
@@ -29,19 +29,20 @@ use rustc::middle::const_val::ConstVal;
2929use rustc:: mir:: repr:: * ;
3030use rustc:: mir:: tcx:: binop_ty;
3131use rustc:: mir:: transform:: { Pass , MirPass , MirSource } ;
32- use rustc:: mir:: visit:: { MutVisitor , LvalueContext } ;
32+ use rustc:: mir:: visit:: { MutVisitor } ;
3333use rustc:: ty:: TyCtxt ;
3434use rustc_const_eval:: { eval_const_binop, eval_const_unop, cast_const} ;
35+ use std:: collections:: hash_map:: Entry ;
3536
3637use super :: dataflow:: * ;
3738
38- pub struct McsPropagate ;
39+ pub struct CsPropagate ;
3940
40- impl Pass for McsPropagate { }
41+ impl Pass for CsPropagate { }
4142
42- impl < ' tcx > MirPass < ' tcx > for McsPropagate {
43+ impl < ' tcx > MirPass < ' tcx > for CsPropagate {
4344 fn run_pass < ' a > ( & mut self , tcx : TyCtxt < ' a , ' tcx , ' tcx > , _: MirSource , mir : & mut Mir < ' tcx > ) {
44- * mir = Dataflow :: forward ( mir, McsTransfer { tcx : tcx } ,
45+ * mir = Dataflow :: forward ( mir, CsTransfer { tcx : tcx } ,
4546 ConstRewrite { tcx : tcx } . and_then ( SimplifyRewrite ) ) ;
4647 }
4748}
@@ -53,18 +54,34 @@ enum Either<'tcx> {
5354 Top
5455}
5556
57+ impl < ' tcx > Lattice for Either < ' tcx > {
58+ fn bottom ( ) -> Self { unimplemented ! ( ) }
59+ fn join ( & mut self , other : Self ) -> bool {
60+ if !other. eq ( self ) {
61+ if Either :: Top . eq ( self ) {
62+ false
63+ } else {
64+ * self = Either :: Top ;
65+ true
66+ }
67+ } else {
68+ false
69+ }
70+ }
71+ }
72+
5673#[ derive( Debug , Clone ) ]
57- struct McsLattice < ' tcx > {
74+ struct CsLattice < ' tcx > {
5875 values : FnvHashMap < Lvalue < ' tcx > , Either < ' tcx > >
5976}
6077
61- impl < ' tcx > McsLattice < ' tcx > {
62- fn insert ( & mut self , key : & Lvalue < ' tcx > , val : Either < ' tcx > ) -> Option < Either < ' tcx > > {
78+ impl < ' tcx > CsLattice < ' tcx > {
79+ fn insert ( & mut self , key : & Lvalue < ' tcx > , val : Either < ' tcx > ) {
6380 // FIXME: HashMap has no way to insert stuff without cloning the key even if it exists
6481 // already.
6582 match * key {
6683 // Do not bother with statics – global state.
67- Lvalue :: Static ( _) => return None ,
84+ Lvalue :: Static ( _) => { }
6885 // I feel like this could be handled, but needs special care. For example in code like
6986 // this:
7087 //
@@ -74,11 +91,19 @@ impl<'tcx> McsLattice<'tcx> {
7491 // assert!(var.field);
7592 // ```
7693 //
77- // taking a reference to var should invalidate knowledge about all the projections of
78- // var and not just var itself. Currently we handle this by not keeping any knowledge
79- // about projections at all, but I think eventually we want to do so.
80- Lvalue :: Projection ( _) => return None ,
81- _ => self . values . insert ( key. clone ( ) , val)
94+ // taking a reference to var should invalidate knowledge about all the
95+ // projections of var and not just var itself. Currently we handle this by not
96+ // keeping any knowledge about projections at all, but I think eventually we
97+ // want to do so.
98+ Lvalue :: Projection ( _) => { } ,
99+ _ => match self . values . entry ( key. clone ( ) ) {
100+ Entry :: Vacant ( e) => {
101+ e. insert ( val) ;
102+ }
103+ Entry :: Occupied ( mut e) => {
104+ e. get_mut ( ) . join ( val) ;
105+ }
106+ }
82107 }
83108 }
84109 fn remove ( & mut self , key : & Lvalue < ' tcx > ) -> Option < Either < ' tcx > > {
@@ -89,8 +114,8 @@ impl<'tcx> McsLattice<'tcx> {
89114 }
90115}
91116
92- impl < ' tcx > Lattice for McsLattice < ' tcx > {
93- fn bottom ( ) -> Self { McsLattice { values : FnvHashMap ( ) } }
117+ impl < ' tcx > Lattice for CsLattice < ' tcx > {
118+ fn bottom ( ) -> Self { CsLattice { values : FnvHashMap ( ) } }
94119 fn join ( & mut self , mut other : Self ) -> bool {
95120 // Calculate inteersection this way:
96121 let mut changed = false ;
@@ -119,12 +144,12 @@ impl<'tcx> Lattice for McsLattice<'tcx> {
119144 }
120145}
121146
122- struct McsTransfer < ' a , ' tcx : ' a > {
123- tcx : TyCtxt < ' a , ' tcx , ' tcx >
147+ struct CsTransfer < ' a , ' tcx : ' a > {
148+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
124149}
125150
126- impl < ' a , ' tcx > Transfer < ' tcx > for McsTransfer < ' a , ' tcx > {
127- type Lattice = McsLattice < ' tcx > ;
151+ impl < ' a , ' tcx > Transfer < ' tcx > for CsTransfer < ' a , ' tcx > {
152+ type Lattice = CsLattice < ' tcx > ;
128153 type TerminatorReturn = Vec < Self :: Lattice > ;
129154
130155 fn stmt ( & self , s : & Statement < ' tcx > , mut lat : Self :: Lattice )
@@ -134,6 +159,7 @@ impl<'a, 'tcx> Transfer<'tcx> for McsTransfer<'a, 'tcx> {
134159 match * rval {
135160 Rvalue :: Use ( Operand :: Consume ( ref nlval) ) => {
136161 lat. insert ( lval, Either :: Lvalue ( nlval. clone ( ) ) ) ;
162+ // Consider moved.
137163 lat. remove ( nlval) ;
138164 } ,
139165 Rvalue :: Use ( Operand :: Constant ( ref cnst) ) => {
@@ -264,9 +290,8 @@ impl<'a, 'tcx> Transfer<'tcx> for McsTransfer<'a, 'tcx> {
264290struct ConstRewrite < ' a , ' tcx : ' a > {
265291 tcx : TyCtxt < ' a , ' tcx , ' tcx >
266292}
267-
268293impl < ' a , ' tcx , T > Rewrite < ' tcx , T > for ConstRewrite < ' a , ' tcx >
269- where T : Transfer < ' tcx , Lattice =McsLattice < ' tcx > >
294+ where T : Transfer < ' tcx , Lattice =CsLattice < ' tcx > >
270295{
271296 fn stmt ( & self , stmt : & Statement < ' tcx > , fact : & T :: Lattice ) -> StatementChange < ' tcx > {
272297 let mut stmt = stmt. clone ( ) ;
0 commit comments