@@ -1386,6 +1386,7 @@ pub struct Interval {
13861386 pub ranges : Vec < LiveRange > ,
13871387 pub id : VRegId ,
13881388 pub state : State ,
1389+ pub assigned : Option < Allocation > ,
13891390}
13901391
13911392impl Interval {
@@ -1395,6 +1396,7 @@ impl Interval {
13951396 ranges : vec ! [ ] ,
13961397 id : i,
13971398 state : State :: Unhandled ,
1399+ assigned : None ,
13981400 }
13991401 }
14001402
@@ -2149,25 +2151,25 @@ impl Assembler
21492151
21502152 let mut free_registers: BTreeSet < usize > = ( 0 ..num_registers) . collect ( ) ;
21512153 let mut active: Vec < Interval > = Vec :: new ( ) ; // sorted by increasing end point
2152- let mut assignment: Vec < Option < Allocation > > = vec ! [ None ; intervals. len( ) ] ;
21532154 let mut num_stack_slots: usize = 0 ;
21542155
2155- // Collect vreg indices that have valid ranges, sorted by start point
2156- let mut sorted_intervals: Vec < Interval > = intervals. iter ( )
2156+ let mut handled: Vec < Interval > = Vec :: new ( ) ;
2157+ let num_intervals = intervals. len ( ) ;
2158+
2159+ let mut sorted_intervals: Vec < Interval > = intervals. into_iter ( )
21572160 . filter ( |i| i. has_bounds ( ) )
2158- . cloned ( )
21592161 . collect ( ) ;
21602162 sorted_intervals. sort_by_key ( |i| i. start ( ) ) ;
21612163
21622164 let mut unhandled: VecDeque < Interval > = sorted_intervals. into ( ) ;
21632165
2164- while let Some ( interval) = unhandled. pop_front ( ) {
2165- // Expire old intervals
2166- active . retain ( |active_interval| {
2167- if active_interval . end ( ) > interval. start ( ) {
2168- true
2166+ while let Some ( mut interval) = unhandled. pop_front ( ) {
2167+ // Expire old intervals.
2168+ for it in std :: mem :: take ( & mut active ) {
2169+ if it . end ( ) > interval. start ( ) {
2170+ active . push ( it ) ;
21692171 } else {
2170- if let Some ( allocation) = assignment [ active_interval . id ] {
2172+ if let Some ( allocation) = it . assigned {
21712173 if let Some ( reg) = allocation. alloc_pool_index ( num_registers) {
21722174 let was_not_there_before = free_registers. insert ( reg) ;
21732175 assert ! (
@@ -2188,14 +2190,14 @@ impl Assembler
21882190 ) ;
21892191 }
21902192 }
2191- false
2193+ handled . push ( it ) ;
21922194 }
2193- } ) ;
2195+ }
21942196
21952197 let preferred_reg = preferred_registers[ interval. id ] ;
21962198 let preferred_taken = preferred_reg. is_some_and ( |reg| {
21972199 active. iter ( ) . any ( |active_interval| {
2198- assignment [ active_interval. id ]
2200+ active_interval. assigned
21992201 . and_then ( |alloc| alloc. assigned_reg ( ) )
22002202 . is_some_and ( |active_reg| active_reg. reg_no == reg. reg_no )
22012203 } )
@@ -2204,13 +2206,13 @@ impl Assembler
22042206 if let Some ( preferred_reg) = preferred_reg. filter ( |_| !preferred_taken) {
22052207 if let Some ( reg_idx) = Allocation :: Fixed ( preferred_reg) . alloc_pool_index ( num_registers) {
22062208 if free_registers. remove ( & reg_idx) {
2207- assignment [ interval. id ] = Some ( Allocation :: Fixed ( preferred_reg) ) ;
2209+ interval. assigned = Some ( Allocation :: Fixed ( preferred_reg) ) ;
22082210 let insert_idx = active. partition_point ( |i| i. end ( ) < interval. end ( ) ) ;
22092211 active. insert ( insert_idx, interval) ;
22102212 continue ;
22112213 }
22122214 } else {
2213- assignment [ interval. id ] = Some ( Allocation :: Fixed ( preferred_reg) ) ;
2215+ interval. assigned = Some ( Allocation :: Fixed ( preferred_reg) ) ;
22142216 let insert_idx = active. partition_point ( |i| i. end ( ) < interval. end ( ) ) ;
22152217 active. insert ( insert_idx, interval) ;
22162218 continue ;
@@ -2226,36 +2228,43 @@ impl Assembler
22262228 // can be mutated below.
22272229 let spill = active. iter ( ) . rev ( )
22282230 . find ( |active_interval| {
2229- matches ! ( assignment [ active_interval. id ] , Some ( Allocation :: Reg ( _) ) )
2231+ matches ! ( active_interval. assigned , Some ( Allocation :: Reg ( _) ) )
22302232 } )
22312233 . map ( |active_interval| ( active_interval. id , active_interval. end ( ) ) ) ;
22322234 let slot = Allocation :: Stack ( num_stack_slots) ;
22332235 num_stack_slots += 1 ;
22342236
22352237 if let Some ( ( spill_id, _) ) = spill. filter ( |& ( _, spill_end) | spill_end > interval. end ( ) ) {
22362238 // Spill the last active interval; give its register to current
2237- assignment[ interval. id ] = assignment[ spill_id] ;
2238- assignment[ spill_id] = Some ( slot) ;
22392239 let spill_idx = active. iter ( ) . position ( |active_interval| active_interval. id == spill_id) . unwrap ( ) ;
2240- active. remove ( spill_idx) ;
2240+ let mut spilled = active. remove ( spill_idx) ;
2241+ interval. assigned = spilled. assigned ;
2242+ spilled. assigned = Some ( slot) ;
2243+ handled. push ( spilled) ;
22412244 // Insert current into sorted active
22422245 let insert_idx = active. partition_point ( |i| i. end ( ) < interval. end ( ) ) ;
22432246 active. insert ( insert_idx, interval) ;
22442247 } else {
22452248 // Spill the current interval
2246- assignment[ interval. id ] = Some ( slot) ;
2249+ interval. assigned = Some ( slot) ;
2250+ handled. push ( interval) ;
22472251 }
22482252 } else {
22492253 // Allocate lowest free register
22502254 let reg = * free_registers. iter ( ) . min ( ) . unwrap ( ) ;
22512255 free_registers. remove ( & reg) ;
2252- assignment [ interval. id ] = Some ( Allocation :: Reg ( reg) ) ;
2256+ interval. assigned = Some ( Allocation :: Reg ( reg) ) ;
22532257 // Insert into sorted active
22542258 let insert_idx = active. partition_point ( |i| i. end ( ) < interval. end ( ) ) ;
22552259 active. insert ( insert_idx, interval) ;
22562260 }
22572261 }
22582262
2263+ let mut assignment: Vec < Option < Allocation > > = vec ! [ None ; num_intervals] ;
2264+ for it in active. into_iter ( ) . chain ( handled) {
2265+ assignment[ it. id ] = it. assigned ;
2266+ }
2267+
22592268 ( assignment, num_stack_slots)
22602269 }
22612270
0 commit comments