@@ -34,6 +34,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
3434use rustc_data_structures:: graph:: dominators:: DominatorFrontiers ;
3535use ykpack;
3636use ykpack:: LocalIndex as TirLocal ;
37+ use rustc_data_structures:: fx:: FxHashSet ;
3738
3839const SECTION_NAME : & ' static str = ".yk_tir" ;
3940const TMP_EXT : & ' static str = ".yk_tir.tmp" ;
@@ -53,6 +54,8 @@ struct ConvCx<'a, 'tcx, 'gcx> {
5354 tcx : & ' a TyCtxt < ' a , ' tcx , ' gcx > ,
5455 /// Maps TIR variables to their definition sites.
5556 def_sites : RefCell < Vec < BitSet < BasicBlock > > > ,
57+ /// Maps each block to the variable it defines. This is what Appel calls `A_{orig}`.
58+ block_defines : RefCell < IndexVec < BasicBlock , FxHashSet < TirLocal > > > ,
5659 /// Monotonically increasing number used to give TIR variables a unique ID.
5760 next_tir_var : Cell < TirLocal > ,
5861 /// A mapping from MIR variables to TIR variables.
@@ -64,13 +67,15 @@ struct ConvCx<'a, 'tcx, 'gcx> {
6467impl < ' a , ' tcx , ' gcx > ConvCx < ' a , ' tcx , ' gcx > {
6568 fn new ( tcx : & ' a TyCtxt < ' a , ' tcx , ' gcx > , mir : & Mir < ' tcx > ) -> Self {
6669 let var_map = IndexVec :: new ( ) ;
70+ let num_blks = mir. basic_blocks ( ) . len ( ) ;
6771
6872 Self {
6973 tcx,
7074 def_sites : RefCell :: new ( Vec :: new ( ) ) ,
75+ block_defines : RefCell :: new ( IndexVec :: from_elem_n ( FxHashSet :: default ( ) , num_blks) ) ,
7176 next_tir_var : Cell :: new ( 0 ) ,
7277 var_map : RefCell :: new ( var_map) ,
73- num_blks : mir . basic_blocks ( ) . len ( ) ,
78+ num_blks : num_blks ,
7479 }
7580 }
7681
@@ -101,8 +106,9 @@ impl<'a, 'tcx, 'gcx> ConvCx<'a, 'tcx, 'gcx> {
101106 } )
102107 }
103108
104- fn def_sites ( self ) -> Vec < BitSet < BasicBlock > > {
105- self . def_sites . into_inner ( )
109+ /// Finalise the conversion context, returning the definition sites and block defines mappings.
110+ fn done ( self ) -> ( Vec < BitSet < BasicBlock > > , IndexVec < BasicBlock , FxHashSet < TirLocal > > ) {
111+ ( self . def_sites . into_inner ( ) , self . block_defines . into_inner ( ) )
106112 }
107113
108114 /// Add `bb` as a definition site of the TIR variable `var`.
@@ -118,6 +124,9 @@ impl<'a, 'tcx, 'gcx> ConvCx<'a, 'tcx, 'gcx> {
118124 BitSet :: new_empty ( self . num_blks ) ) ;
119125 }
120126 sites[ var_usize] . insert ( bb) ;
127+
128+ // Also push into the inverse mapping (blocks to defined vars).
129+ self . block_defines . borrow_mut ( ) [ bb] . insert ( var) ;
121130 }
122131}
123132
@@ -186,7 +195,8 @@ fn do_generate_tir<'a, 'tcx, 'gcx>(
186195 let mut pack = ( & ccx, def_id, tcx. optimized_mir ( * def_id) ) . to_pack ( ) ;
187196 {
188197 let ykpack:: Pack :: Mir ( ykpack:: Mir { ref mut blocks, ..} ) = pack;
189- insert_phis ( blocks, mir, ccx. def_sites ( ) ) ;
198+ let ( def_sites, block_defines) = ccx. done ( ) ;
199+ insert_phis ( blocks, mir, def_sites, block_defines) ;
190200 }
191201
192202 // FIXME - rename variables with fresh SSA names.
@@ -213,27 +223,12 @@ fn do_generate_tir<'a, 'tcx, 'gcx>(
213223/// Algorithm reference:
214224/// Bottom of p406 of 'Modern Compiler Implementation in Java (2nd ed.)' by Andrew Appel.
215225fn insert_phis ( blocks : & mut Vec < ykpack:: BasicBlock > , mir : & Mir ,
216- mut def_sites : Vec < BitSet < BasicBlock > > )
217- {
226+ mut def_sites : Vec < BitSet < BasicBlock > > ,
227+ a_orig : IndexVec < BasicBlock , FxHashSet < TirLocal > > ) {
218228 let doms = mir. dominators ( ) ;
219229 let df = DominatorFrontiers :: new ( mir, & doms) ;
220230 let num_tir_vars = def_sites. len ( ) ;
221-
222- // We first need a mapping from block to the variables it defines. Appel calls this
223- // `A_{orig}`. We can derive this from our definition sites.
224- let ( a_orig, num_tir_blks) = {
225- let num_tir_blks = blocks. len ( ) ;
226-
227- let mut a_orig: IndexVec < BasicBlock , BitSet < TirLocal > > =
228- IndexVec :: from_elem_n ( BitSet :: new_empty ( num_tir_vars) , num_tir_blks) ;
229- for ( a, def_blks) in def_sites. iter ( ) . enumerate ( ) {
230- for bb in def_blks. iter ( ) {
231- // `def_sites` is guaranteed to have at most `u32::max_value()` items.
232- a_orig[ bb] . insert ( a as u32 ) ;
233- }
234- }
235- ( a_orig, num_tir_blks)
236- } ;
231+ let num_tir_blks = a_orig. len ( ) ;
237232
238233 let mut a_phi: Vec < BitSet < TirLocal > > = Vec :: with_capacity ( num_tir_blks) ;
239234 a_phi. resize ( num_tir_blks, BitSet :: new_empty ( num_tir_vars) ) ;
@@ -249,7 +244,7 @@ fn insert_phis(blocks: &mut Vec<ykpack::BasicBlock>, mir: &Mir,
249244 let a_u32 = a as u32 ;
250245 if !a_phi[ y_usize] . contains ( a_u32) {
251246 a_phi[ y_usize] . insert ( a_u32) ;
252- if !a_orig[ y] . contains ( a_u32) {
247+ if !a_orig[ y] . contains ( & a_u32) {
253248 // The assertion in `tir_var()` has already checked the cast is safe.
254249 insert_phi ( & mut blocks[ y_usize] , a as u32 , mir. predecessors_for ( y) . len ( ) ) ;
255250 w. insert ( y) ;
0 commit comments