@@ -34,6 +34,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
34
34
use rustc_data_structures:: graph:: dominators:: DominatorFrontiers ;
35
35
use ykpack;
36
36
use ykpack:: LocalIndex as TirLocal ;
37
+ use rustc_data_structures:: fx:: FxHashSet ;
37
38
38
39
const SECTION_NAME : & ' static str = ".yk_tir" ;
39
40
const TMP_EXT : & ' static str = ".yk_tir.tmp" ;
@@ -53,6 +54,8 @@ struct ConvCx<'a, 'tcx, 'gcx> {
53
54
tcx : & ' a TyCtxt < ' a , ' tcx , ' gcx > ,
54
55
/// Maps TIR variables to their definition sites.
55
56
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 > > > ,
56
59
/// Monotonically increasing number used to give TIR variables a unique ID.
57
60
next_tir_var : Cell < TirLocal > ,
58
61
/// A mapping from MIR variables to TIR variables.
@@ -64,13 +67,15 @@ struct ConvCx<'a, 'tcx, 'gcx> {
64
67
impl < ' a , ' tcx , ' gcx > ConvCx < ' a , ' tcx , ' gcx > {
65
68
fn new ( tcx : & ' a TyCtxt < ' a , ' tcx , ' gcx > , mir : & Mir < ' tcx > ) -> Self {
66
69
let var_map = IndexVec :: new ( ) ;
70
+ let num_blks = mir. basic_blocks ( ) . len ( ) ;
67
71
68
72
Self {
69
73
tcx,
70
74
def_sites : RefCell :: new ( Vec :: new ( ) ) ,
75
+ block_defines : RefCell :: new ( IndexVec :: from_elem_n ( FxHashSet :: default ( ) , num_blks) ) ,
71
76
next_tir_var : Cell :: new ( 0 ) ,
72
77
var_map : RefCell :: new ( var_map) ,
73
- num_blks : mir . basic_blocks ( ) . len ( ) ,
78
+ num_blks : num_blks ,
74
79
}
75
80
}
76
81
@@ -101,8 +106,9 @@ impl<'a, 'tcx, 'gcx> ConvCx<'a, 'tcx, 'gcx> {
101
106
} )
102
107
}
103
108
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 ( ) )
106
112
}
107
113
108
114
/// Add `bb` as a definition site of the TIR variable `var`.
@@ -118,6 +124,9 @@ impl<'a, 'tcx, 'gcx> ConvCx<'a, 'tcx, 'gcx> {
118
124
BitSet :: new_empty ( self . num_blks ) ) ;
119
125
}
120
126
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) ;
121
130
}
122
131
}
123
132
@@ -186,7 +195,8 @@ fn do_generate_tir<'a, 'tcx, 'gcx>(
186
195
let mut pack = ( & ccx, def_id, tcx. optimized_mir ( * def_id) ) . to_pack ( ) ;
187
196
{
188
197
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) ;
190
200
}
191
201
192
202
// FIXME - rename variables with fresh SSA names.
@@ -213,27 +223,12 @@ fn do_generate_tir<'a, 'tcx, 'gcx>(
213
223
/// Algorithm reference:
214
224
/// Bottom of p406 of 'Modern Compiler Implementation in Java (2nd ed.)' by Andrew Appel.
215
225
fn 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 > > ) {
218
228
let doms = mir. dominators ( ) ;
219
229
let df = DominatorFrontiers :: new ( mir, & doms) ;
220
230
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 ( ) ;
237
232
238
233
let mut a_phi: Vec < BitSet < TirLocal > > = Vec :: with_capacity ( num_tir_blks) ;
239
234
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,
249
244
let a_u32 = a as u32 ;
250
245
if !a_phi[ y_usize] . contains ( a_u32) {
251
246
a_phi[ y_usize] . insert ( a_u32) ;
252
- if !a_orig[ y] . contains ( a_u32) {
247
+ if !a_orig[ y] . contains ( & a_u32) {
253
248
// The assertion in `tir_var()` has already checked the cast is safe.
254
249
insert_phi ( & mut blocks[ y_usize] , a as u32 , mir. predecessors_for ( y) . len ( ) ) ;
255
250
w. insert ( y) ;
0 commit comments