@@ -121,50 +121,46 @@ impl BlockRegAllocator {
121121 None
122122 }
123123
124- fn allocate_and_spill ( & mut self , any_reg : u16 , used_regs : & [ BlockRegSet ] , allowed_regs : RegReserve ) -> Option < Reg > {
125- let mut greatest_distance = 0 ;
126- let mut greatest_distance_reg = 0 ;
124+ fn allocate_and_spill ( & mut self , any_reg : u16 , live_ranges : & [ BlockRegSet ] , used_regs : & [ BlockRegSet ] , allowed_regs : RegReserve ) -> Option < Reg > {
127125 for ( i, mapped_reg) in self . stored_mapping_reverse . iter ( ) . enumerate ( ) {
126+ let reg = Reg :: from ( i as u8 ) ;
127+
128+ if mapped_reg. is_none ( ) && allowed_regs. is_reserved ( reg) && !live_ranges[ 1 ] . contains ( BlockReg :: Fixed ( reg) ) && !used_regs[ 0 ] . contains ( BlockReg :: Fixed ( reg) ) {
129+ self . set_stored_mapping ( any_reg, reg) ;
130+ return Some ( reg) ;
131+ }
132+ }
133+
134+ for ( i, mapped_reg) in self . stored_mapping_reverse . iter ( ) . enumerate ( ) {
135+ let reg = Reg :: from ( i as u8 ) ;
136+
128137 if let & Some ( mapped_reg) = mapped_reg {
129- let reg = Reg :: from ( i as u8 ) ;
130- if allowed_regs. is_reserved ( reg) && !used_regs[ 0 ] . contains ( BlockReg :: Any ( mapped_reg) ) {
131- for i in 1 ..used_regs. len ( ) {
132- if used_regs[ i] . contains ( BlockReg :: Any ( mapped_reg) ) || used_regs[ i] . contains ( BlockReg :: Fixed ( reg) ) {
133- if i > greatest_distance {
134- greatest_distance = i;
135- greatest_distance_reg = mapped_reg;
136- }
137- break ;
138- }
139- }
138+ if allowed_regs. is_reserved ( reg) && !used_regs[ 0 ] . contains ( BlockReg :: Any ( mapped_reg) ) && !live_ranges[ 1 ] . contains ( BlockReg :: Any ( mapped_reg) ) {
139+ self . swap_stored_mapping ( any_reg, mapped_reg) ;
140+ return Some ( reg) ;
140141 }
141142 }
142143 }
143144
144- if greatest_distance != 0 {
145- let reg = self . stored_mapping [ greatest_distance_reg as usize ] ;
146- self . spilled += BlockReg :: Any ( greatest_distance_reg) ;
147- self . gen_pre_handle_spilled_inst ( greatest_distance_reg, reg, BlockTransferOp :: Write ) ;
148- self . swap_stored_mapping ( any_reg, greatest_distance_reg) ;
149- return Some ( reg) ;
145+ for ( i, mapped_reg) in self . stored_mapping_reverse . iter ( ) . enumerate ( ) {
146+ let reg = Reg :: from ( i as u8 ) ;
147+
148+ if let & Some ( mapped_reg) = mapped_reg {
149+ if allowed_regs. is_reserved ( reg) && !used_regs[ 0 ] . contains ( BlockReg :: Any ( mapped_reg) ) {
150+ self . spilled += BlockReg :: Any ( mapped_reg) ;
151+ self . gen_pre_handle_spilled_inst ( mapped_reg, reg, BlockTransferOp :: Write ) ;
152+ self . swap_stored_mapping ( any_reg, mapped_reg) ;
153+ return Some ( reg) ;
154+ }
155+ }
150156 }
151157
152158 None
153159 }
154160
155161 fn allocate_local ( & mut self , any_reg : u16 , live_ranges : & [ BlockRegSet ] , used_regs : & [ BlockRegSet ] ) -> Reg {
156- let mut live_ranges_until_expiration = BlockRegSet :: new ( ) ;
157- let mut used_fixed_until_expiration = used_regs[ 0 ] . get_fixed ( ) ;
158- for i in 1 ..live_ranges. len ( ) {
159- if !live_ranges[ i] . contains ( BlockReg :: Any ( any_reg) ) {
160- break ;
161- }
162- live_ranges_until_expiration += live_ranges[ i] ;
163- used_fixed_until_expiration += used_regs[ i] . get_fixed ( ) ;
164- }
165-
166162 for reg in SCRATCH_REGS {
167- if !used_fixed_until_expiration . is_reserved ( reg ) && self . stored_mapping_reverse [ reg as usize ] . is_none ( ) && !live_ranges[ 1 ] . contains ( BlockReg :: Fixed ( reg) ) {
163+ if self . stored_mapping_reverse [ reg as usize ] . is_none ( ) && !live_ranges[ 1 ] . contains ( BlockReg :: Fixed ( reg) ) {
168164 self . set_stored_mapping ( any_reg, reg) ;
169165 return reg;
170166 }
@@ -174,22 +170,7 @@ impl BlockRegAllocator {
174170 return reg;
175171 }
176172
177- for ( i, mapped_reg) in self . stored_mapping_reverse . iter ( ) . enumerate ( ) {
178- if let & Some ( mapped_reg) = mapped_reg {
179- let reg = Reg :: from ( i as u8 ) ;
180- if !used_regs[ 0 ] . contains ( BlockReg :: Any ( mapped_reg) )
181- && !live_ranges_until_expiration. contains ( BlockReg :: Any ( mapped_reg) )
182- && !live_ranges_until_expiration. contains ( BlockReg :: Fixed ( reg) )
183- {
184- self . spilled += BlockReg :: Any ( mapped_reg) ;
185- self . gen_pre_handle_spilled_inst ( mapped_reg, reg, BlockTransferOp :: Write ) ;
186- self . swap_stored_mapping ( any_reg, mapped_reg) ;
187- return reg;
188- }
189- }
190- }
191-
192- if let Some ( reg) = self . allocate_and_spill ( any_reg, used_regs, SCRATCH_REGS + ALLOCATION_REGS ) {
173+ if let Some ( reg) = self . allocate_and_spill ( any_reg, live_ranges, used_regs, SCRATCH_REGS + ALLOCATION_REGS ) {
193174 return reg;
194175 }
195176
@@ -201,7 +182,11 @@ impl BlockRegAllocator {
201182 return reg;
202183 }
203184
204- if let Some ( reg) = self . allocate_and_spill ( any_reg, used_regs, ALLOCATION_REGS ) {
185+ if let Some ( reg) = self . allocate_and_spill ( any_reg, live_ranges, used_regs, ALLOCATION_REGS ) {
186+ return reg;
187+ }
188+
189+ if let Some ( reg) = self . allocate_and_spill ( any_reg, live_ranges, used_regs, SCRATCH_REGS ) {
205190 return reg;
206191 }
207192
@@ -350,11 +335,17 @@ impl BlockRegAllocator {
350335
351336 if DEBUG && unsafe { BLOCK_LOG } {
352337 println ! ( "inputs: {inputs:?}, outputs: {outputs:?}" ) ;
338+ println ! ( "used regs {:?}" , used_regs[ 0 ] ) ;
353339 }
354340
355341 self . relocate_guest_regs ( inputs. get_guests ( ) . get_gp_regs ( ) , live_ranges, & inputs, used_regs, true ) ;
356342 self . relocate_guest_regs ( outputs. get_guests ( ) . get_gp_regs ( ) , live_ranges, & inputs, used_regs, false ) ;
357343
344+ if DEBUG && unsafe { BLOCK_LOG } {
345+ println ! ( "pre mapping {:?}" , self . stored_mapping_reverse) ;
346+ println ! ( "pre spilled {:?}" , self . spilled) ;
347+ }
348+
358349 for any_input_reg in inputs. iter_any ( ) {
359350 let reg = self . get_input_reg ( any_input_reg, live_ranges, used_regs) ;
360351 inst. replace_input_regs ( BlockReg :: Any ( any_input_reg) , BlockReg :: Fixed ( reg) ) ;
@@ -370,6 +361,11 @@ impl BlockRegAllocator {
370361 inst. replace_output_regs ( BlockReg :: Any ( any_output_reg) , BlockReg :: Fixed ( reg) ) ;
371362 self . dirty_regs += reg;
372363 }
364+
365+ if DEBUG && unsafe { BLOCK_LOG } {
366+ println ! ( "after mapping {:?}" , self . stored_mapping_reverse) ;
367+ println ! ( "after spilled {:?}" , self . spilled) ;
368+ }
373369 }
374370
375371 pub fn ensure_global_mappings ( & mut self , output_regs : BlockRegSet ) {
@@ -439,7 +435,7 @@ impl BlockRegAllocator {
439435 self . spilled -= BlockReg :: Any ( output_reg) ;
440436 self . gen_pre_handle_spilled_inst ( output_reg, desired_reg_mapping, BlockTransferOp :: Read ) ;
441437 } else {
442- panic ! ( "required output reg must already have a value" ) ;
438+ panic ! ( "required output reg {output_reg:?} must already have a value" ) ;
443439 }
444440 self . set_stored_mapping ( output_reg, desired_reg_mapping) ;
445441 }
0 commit comments