@@ -5,8 +5,10 @@ use crate::{
55 AllocationKind , Block , FxHashMap , Inst , InstPosition , Operand , OperandConstraint , OperandKind ,
66 OperandPos , PReg , PRegSet , RegClass , SpillSlot , VReg ,
77} ;
8- use alloc:: vec:: Vec ;
8+ use alloc:: format;
9+ use alloc:: { vec, vec:: Vec } ;
910use core:: convert:: TryInto ;
11+ use core:: fmt;
1012use core:: iter:: FromIterator ;
1113use core:: ops:: { Index , IndexMut } ;
1214
@@ -194,8 +196,6 @@ impl<T> IndexMut<OperandPos> for PartedByOperandPos<T> {
194196 }
195197}
196198
197- use core:: fmt;
198-
199199impl < T : fmt:: Display > fmt:: Display for PartedByOperandPos < T > {
200200 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
201201 write ! ( f, "{{ early: {}, late: {} }}" , self . items[ 0 ] , self . items[ 1 ] )
@@ -243,7 +243,6 @@ pub struct Env<'a, F: Function> {
243243
244244impl < ' a , F : Function > Env < ' a , F > {
245245 fn new ( func : & ' a F , env : & ' a MachineEnv ) -> Self {
246- use alloc:: vec;
247246 let mut regs = [
248247 env. preferred_regs_by_class [ RegClass :: Int as usize ] . clone ( ) ,
249248 env. preferred_regs_by_class [ RegClass :: Float as usize ] . clone ( ) ,
@@ -327,47 +326,43 @@ impl<'a, F: Function> Env<'a, F> {
327326 self . edits . scratch_regs = self . edits . dedicated_scratch_regs . clone ( ) ;
328327 }
329328
330- fn alloc_scratch_reg ( & mut self , inst : Inst , class : RegClass ) -> Result < ( ) , RegAllocError > {
331- use OperandPos :: { Early , Late } ;
332- let reg = self . get_scratch_reg (
333- inst,
334- class,
335- self . available_pregs [ Late ] & self . available_pregs [ Early ] ,
336- ) ?;
337- self . edits . scratch_regs [ class] = Some ( reg) ;
338- self . available_pregs [ OperandPos :: Early ] . remove ( reg) ;
339- self . available_pregs [ OperandPos :: Late ] . remove ( reg) ;
340- Ok ( ( ) )
341- }
342-
343- fn get_scratch_reg_for_reload (
329+ fn alloc_scratch_reg (
344330 & mut self ,
345331 inst : Inst ,
346332 class : RegClass ,
347- avail_regs : PRegSet ,
348- ) -> Result < PReg , RegAllocError > {
349- let Some ( preg) = self . lrus [ class] . last ( avail_regs) else {
350- return Err ( RegAllocError :: TooManyLiveRegs ) ;
351- } ;
352- if self . vreg_in_preg [ preg. index ( ) ] != VReg :: invalid ( ) {
353- self . evict_vreg_in_preg_before_inst ( inst, preg) ;
333+ pos : InstPosition ,
334+ ) -> Result < ( ) , RegAllocError > {
335+ let avail_regs =
336+ self . available_pregs [ OperandPos :: Late ] & self . available_pregs [ OperandPos :: Early ] ;
337+ if let Some ( preg) = self . lrus [ class] . last ( avail_regs) {
338+ if self . vreg_in_preg [ preg. index ( ) ] != VReg :: invalid ( ) {
339+ self . evict_vreg_in_preg ( inst, preg, pos) ?;
340+ }
341+ self . edits . scratch_regs [ class] = Some ( preg) ;
342+ self . available_pregs [ OperandPos :: Early ] . remove ( preg) ;
343+ self . available_pregs [ OperandPos :: Late ] . remove ( preg) ;
344+ Ok ( ( ) )
345+ } else {
346+ Err ( RegAllocError :: TooManyLiveRegs )
354347 }
355- Ok ( preg)
356348 }
357349
358- fn get_scratch_reg (
350+ fn add_move (
359351 & mut self ,
360352 inst : Inst ,
353+ from : Allocation ,
354+ to : Allocation ,
361355 class : RegClass ,
362- avail_regs : PRegSet ,
363- ) -> Result < PReg , RegAllocError > {
364- let Some ( preg ) = self . lrus [ class ] . last ( avail_regs ) else {
365- return Err ( RegAllocError :: TooManyLiveRegs ) ;
366- } ;
367- if self . vreg_in_preg [ preg . index ( ) ] != VReg :: invalid ( ) {
368- self . evict_vreg_in_preg ( inst, preg ) ;
356+ pos : InstPosition ,
357+ ) -> Result < ( ) , RegAllocError > {
358+ if self . edits . is_stack ( from )
359+ && self . edits . is_stack ( to )
360+ && self . edits . scratch_regs [ class ] . is_none ( )
361+ {
362+ self . alloc_scratch_reg ( inst, class , pos ) ? ;
369363 }
370- Ok ( preg)
364+ self . edits . add_move ( inst, from, to, class, pos) ;
365+ Ok ( ( ) )
371366 }
372367
373368 fn reserve_reg_for_fixed_operand (
@@ -461,7 +456,12 @@ impl<'a, F: Function> Env<'a, F> {
461456 }
462457 }
463458
464- fn base_evict_vreg_in_preg ( & mut self , inst : Inst , preg : PReg , pos : InstPosition ) {
459+ fn evict_vreg_in_preg (
460+ & mut self ,
461+ inst : Inst ,
462+ preg : PReg ,
463+ pos : InstPosition ,
464+ ) -> Result < ( ) , RegAllocError > {
465465 trace ! ( "Removing the vreg in preg {} for eviction" , preg) ;
466466 let evicted_vreg = self . vreg_in_preg [ preg. index ( ) ] ;
467467 trace ! ( "The removed vreg: {}" , evicted_vreg) ;
@@ -472,21 +472,13 @@ impl<'a, F: Function> Env<'a, F> {
472472 let slot = self . vreg_spillslots [ evicted_vreg. vreg ( ) ] ;
473473 self . vreg_allocs [ evicted_vreg. vreg ( ) ] = Allocation :: stack ( slot) ;
474474 trace ! ( "Move reason: eviction" ) ;
475- self . edits . add_move (
475+ self . add_move (
476476 inst,
477477 self . vreg_allocs [ evicted_vreg. vreg ( ) ] ,
478478 Allocation :: reg ( preg) ,
479479 evicted_vreg. class ( ) ,
480480 pos,
481- ) ;
482- }
483-
484- fn evict_vreg_in_preg_before_inst ( & mut self , inst : Inst , preg : PReg ) {
485- self . base_evict_vreg_in_preg ( inst, preg, InstPosition :: Before )
486- }
487-
488- fn evict_vreg_in_preg ( & mut self , inst : Inst , preg : PReg ) {
489- self . base_evict_vreg_in_preg ( inst, preg, InstPosition :: After )
481+ )
490482 }
491483
492484 fn freealloc ( & mut self , vreg : VReg ) {
@@ -542,7 +534,7 @@ impl<'a, F: Function> Env<'a, F> {
542534 return Err ( RegAllocError :: TooManyLiveRegs ) ;
543535 } ;
544536 if self . vreg_in_preg [ preg. index ( ) ] != VReg :: invalid ( ) {
545- self . evict_vreg_in_preg ( inst, preg) ;
537+ self . evict_vreg_in_preg ( inst, preg, InstPosition :: After ) ? ;
546538 }
547539 trace ! ( "The allocated register for vreg {}: {}" , op. vreg( ) , preg) ;
548540 self . lrus [ op. class ( ) ] . poke ( preg) ;
@@ -639,23 +631,9 @@ impl<'a, F: Function> Env<'a, F> {
639631 // used (in `prev_alloc`, that is).
640632 else {
641633 trace ! ( "Move reason: Prev allocation doesn't meet constraints" ) ;
642- if self . edits . is_stack ( new_alloc)
643- && self . edits . is_stack ( curr_alloc)
644- && self . edits . scratch_regs [ op. class ( ) ] . is_none ( )
645- {
646- self . alloc_scratch_reg ( inst, op. class ( ) ) ?;
647- }
648634 if op. kind ( ) == OperandKind :: Def {
649635 trace ! ( "Adding edit from {new_alloc:?} to {curr_alloc:?} after inst {inst:?} for {op}" ) ;
650- self . edits . add_move (
651- inst,
652- new_alloc,
653- curr_alloc,
654- op. class ( ) ,
655- InstPosition :: After ,
656- ) ;
657- // No need to set vreg_in_preg because it will be set during
658- // `freealloc` if needed.
636+ self . add_move ( inst, new_alloc, curr_alloc, op. class ( ) , InstPosition :: After ) ?;
659637 }
660638 // Edits for use operands are added later to avoid inserting
661639 // edits out of order.
@@ -729,7 +707,6 @@ impl<'a, F: Function> Env<'a, F> {
729707 /// this function places branch arguments in the spillslots
730708 /// expected by the destination blocks.
731709 fn process_branch ( & mut self , block : Block , inst : Inst ) -> Result < ( ) , RegAllocError > {
732- use OperandPos :: * ;
733710 trace ! ( "Processing branch instruction {inst:?} in block {block:?}" ) ;
734711
735712 let mut int_parallel_moves = ParallelMoves :: new ( ) ;
@@ -758,25 +735,13 @@ impl<'a, F: Function> Env<'a, F> {
758735 self . live_vregs . insert ( * vreg) ;
759736 self . vreg_to_live_inst_range [ vreg. vreg ( ) ] . 1 = ProgPoint :: before ( inst) ;
760737 } else if curr_alloc != vreg_spill {
761- if self . edits . is_stack ( curr_alloc)
762- && self . edits . scratch_regs [ vreg. class ( ) ] . is_none ( )
763- {
764- let reg = self . get_scratch_reg_for_reload (
765- inst,
766- vreg. class ( ) ,
767- self . available_pregs [ Early ] & self . available_pregs [ Late ] ,
768- ) ?;
769- self . edits . scratch_regs [ vreg. class ( ) ] = Some ( reg) ;
770- self . available_pregs [ OperandPos :: Early ] . remove ( reg) ;
771- self . available_pregs [ OperandPos :: Late ] . remove ( reg) ;
772- }
773- self . edits . add_move (
738+ self . add_move (
774739 inst,
775740 vreg_spill,
776741 curr_alloc,
777742 vreg. class ( ) ,
778743 InstPosition :: Before ,
779- ) ;
744+ ) ? ;
780745 }
781746 self . vreg_allocs [ vreg. vreg ( ) ] = vreg_spill;
782747 let parallel_moves = match vreg. class ( ) {
@@ -796,7 +761,8 @@ impl<'a, F: Function> Env<'a, F> {
796761 let resolved_vec = vec_parallel_moves. resolve ( ) ;
797762 let mut scratch_regs = self . edits . scratch_regs . clone ( ) ;
798763 let mut num_spillslots = self . stack . num_spillslots ;
799- let mut avail_regs = self . available_pregs [ Early ] & self . available_pregs [ Late ] ;
764+ let mut avail_regs =
765+ self . available_pregs [ OperandPos :: Early ] & self . available_pregs [ OperandPos :: Late ] ;
800766
801767 trace ! ( "Resolving parallel moves" ) ;
802768 for ( resolved, class) in [
@@ -886,12 +852,7 @@ impl<'a, F: Function> Env<'a, F> {
886852 "Evicting {} from fixed register {preg}" ,
887853 self . vreg_in_preg[ preg. index( ) ]
888854 ) ;
889- if self . fixed_stack_slots . contains ( preg)
890- && self . edits . scratch_regs [ preg. class ( ) ] . is_none ( )
891- {
892- self . alloc_scratch_reg ( inst, preg. class ( ) ) ?;
893- }
894- self . evict_vreg_in_preg ( inst, preg) ;
855+ self . evict_vreg_in_preg ( inst, preg, InstPosition :: After ) ?;
895856 self . vreg_in_preg [ preg. index ( ) ] = VReg :: invalid ( ) ;
896857 }
897858 }
@@ -902,12 +863,7 @@ impl<'a, F: Function> Env<'a, F> {
902863 "Evicting {} from clobber {preg}" ,
903864 self . vreg_in_preg[ preg. index( ) ]
904865 ) ;
905- if self . fixed_stack_slots . contains ( preg)
906- && self . edits . scratch_regs [ preg. class ( ) ] . is_none ( )
907- {
908- self . alloc_scratch_reg ( inst, preg. class ( ) ) ?;
909- }
910- self . evict_vreg_in_preg ( inst, preg) ;
866+ self . evict_vreg_in_preg ( inst, preg, InstPosition :: After ) ?;
911867 self . vreg_in_preg [ preg. index ( ) ] = VReg :: invalid ( ) ;
912868 }
913869 }
@@ -926,24 +882,9 @@ impl<'a, F: Function> Env<'a, F> {
926882 if slot. is_valid ( ) {
927883 self . vreg_to_live_inst_range [ op. vreg ( ) . vreg ( ) ] . 2 = Allocation :: stack ( slot) ;
928884 let curr_alloc = self . vreg_allocs [ op. vreg ( ) . vreg ( ) ] ;
929- let vreg_slot = self . vreg_spillslots [ op. vreg ( ) . vreg ( ) ] ;
930- let ( is_stack_to_stack, src_and_dest_are_same) =
931- if let Some ( curr_alloc) = curr_alloc. as_stack ( ) {
932- ( true , curr_alloc == vreg_slot)
933- } else {
934- ( self . edits . is_stack ( curr_alloc) , false )
935- } ;
936- if !src_and_dest_are_same {
937- if is_stack_to_stack && self . edits . scratch_regs [ op. class ( ) ] . is_none ( ) {
938- self . alloc_scratch_reg ( inst, op. class ( ) ) ?;
939- } ;
940- self . edits . add_move (
941- inst,
942- self . vreg_allocs [ op. vreg ( ) . vreg ( ) ] ,
943- Allocation :: stack ( self . vreg_spillslots [ op. vreg ( ) . vreg ( ) ] ) ,
944- op. class ( ) ,
945- InstPosition :: After ,
946- ) ;
885+ let new_alloc = Allocation :: stack ( self . vreg_spillslots [ op. vreg ( ) . vreg ( ) ] ) ;
886+ if curr_alloc != new_alloc {
887+ self . add_move ( inst, curr_alloc, new_alloc, op. class ( ) , InstPosition :: After ) ?;
947888 }
948889 }
949890 self . vreg_to_live_inst_range [ op. vreg ( ) . vreg ( ) ] . 0 = ProgPoint :: after ( inst) ;
@@ -970,17 +911,17 @@ impl<'a, F: Function> Env<'a, F> {
970911 if op. as_fixed_nonallocatable ( ) . is_some ( ) {
971912 continue ;
972913 }
973- if self . vreg_allocs [ op. vreg ( ) . vreg ( ) ] != self . allocs [ ( inst . index ( ) , op_idx ) ] {
974- let curr_alloc = self . vreg_allocs [ op . vreg ( ) . vreg ( ) ] ;
975- let new_alloc = self . allocs [ ( inst . index ( ) , op_idx ) ] ;
914+ let curr_alloc = self . vreg_allocs [ op. vreg ( ) . vreg ( ) ] ;
915+ let new_alloc = self . allocs [ ( inst . index ( ) , op_idx ) ] ;
916+ if curr_alloc != new_alloc {
976917 trace ! ( "Adding edit from {curr_alloc:?} to {new_alloc:?} before inst {inst:?} for {op}" ) ;
977- self . edits . add_move (
918+ self . add_move (
978919 inst,
979920 curr_alloc,
980921 new_alloc,
981922 op. class ( ) ,
982923 InstPosition :: Before ,
983- ) ;
924+ ) ? ;
984925 }
985926 }
986927 if self . func . is_branch ( inst) {
@@ -1059,21 +1000,13 @@ impl<'a, F: Function> Env<'a, F> {
10591000 "Move reason: reload {} at begin - move from its spillslot" ,
10601001 vreg
10611002 ) ;
1062- if self . edits . is_stack ( prev_alloc) && self . edits . scratch_regs [ vreg. class ( ) ] . is_none ( ) {
1063- let reg = self . get_scratch_reg_for_reload (
1064- first_inst,
1065- vreg. class ( ) ,
1066- avail_regs_for_scratch,
1067- ) ?;
1068- self . edits . scratch_regs [ vreg. class ( ) ] = Some ( reg) ;
1069- }
1070- self . edits . add_move (
1003+ self . add_move (
10711004 self . func . block_insns ( block) . first ( ) ,
10721005 slot,
10731006 prev_alloc,
10741007 vreg. class ( ) ,
10751008 InstPosition :: Before ,
1076- ) ;
1009+ ) ? ;
10771010 }
10781011 for vreg in self . live_vregs . iter ( ) {
10791012 trace ! ( "Processing {}" , vreg) ;
@@ -1149,7 +1082,6 @@ impl<'a, F: Function> Env<'a, F> {
11491082 }
11501083
11511084 fn log_post_reload_at_begin_state ( & self , block : Block ) {
1152- use alloc:: format;
11531085 trace ! ( "" ) ;
11541086 trace ! ( "State after instruction reload_at_begin of {:?}" , block) ;
11551087 let mut map = FxHashMap :: default ( ) ;
@@ -1172,7 +1104,6 @@ impl<'a, F: Function> Env<'a, F> {
11721104 }
11731105
11741106 fn log_post_inst_processing_state ( & self , inst : Inst ) {
1175- use alloc:: format;
11761107 trace ! ( "" ) ;
11771108 trace ! ( "State after instruction {:?}" , inst) ;
11781109 let mut map = FxHashMap :: default ( ) ;
@@ -1266,7 +1197,6 @@ fn log_function<F: Function>(func: &F) {
12661197
12671198fn log_output < ' a , F : Function > ( env : & Env < ' a , F > ) {
12681199 trace ! ( "Done!" ) ;
1269- use alloc:: format;
12701200 let mut v = Vec :: new ( ) ;
12711201 for i in 0 ..env. func . num_vregs ( ) {
12721202 if env. vreg_spillslots [ i] . is_valid ( ) {
0 commit comments