1212
1313//! Bundle merging.
1414
15- use super :: { Env , LiveBundleIndex , SpillSet , SpillSlotIndex , VRegIndex } ;
16- use crate :: {
17- ion:: {
18- data_structures:: { BlockparamOut , CodeRange } ,
19- LiveRangeList ,
20- } ,
21- Function , Inst , OperandConstraint , OperandKind , PReg , ProgPoint ,
15+ use crate :: ion:: data_structures:: {
16+ BlockparamOut , CodeRange , Env , LiveBundleIndex , LiveRangeList , SpillSet , SpillSlotIndex ,
17+ VRegIndex ,
2218} ;
19+ use crate :: { Function , Inst , OperandConstraint , OperandKind , PReg , ProgPoint } ;
2320use alloc:: format;
2421
2522impl < ' a , F : Function > Env < ' a , F > {
23+ fn merge_bundle_properties ( & mut self , from : LiveBundleIndex , to : LiveBundleIndex ) {
24+ if self . bundles [ from] . cached_fixed ( ) {
25+ self . bundles [ to] . set_cached_fixed ( ) ;
26+ }
27+ if self . bundles [ from] . cached_fixed_def ( ) {
28+ self . bundles [ to] . set_cached_fixed_def ( ) ;
29+ }
30+ if self . bundles [ from] . cached_stack ( ) {
31+ self . bundles [ to] . set_cached_stack ( ) ;
32+ }
33+ if let Some ( theirs) = self . bundles [ from] . limit {
34+ match self . bundles [ to] . limit {
35+ Some ( ours) => self . bundles [ to] . limit = Some ( ours. min ( theirs) ) ,
36+ None => self . bundles [ to] . limit = Some ( theirs) ,
37+ }
38+ }
39+ }
40+
2641 pub fn merge_bundles ( & mut self , from : LiveBundleIndex , to : LiveBundleIndex ) -> bool {
2742 if from == to {
2843 // Merge bundle into self -- trivial merge.
@@ -114,8 +129,10 @@ impl<'a, F: Function> Env<'a, F> {
114129 // Check for a requirements conflict.
115130 if self . bundles [ from] . cached_stack ( )
116131 || self . bundles [ from] . cached_fixed ( )
132+ || self . bundles [ from] . limit . is_some ( )
117133 || self . bundles [ to] . cached_stack ( )
118134 || self . bundles [ to] . cached_fixed ( )
135+ || self . bundles [ to] . limit . is_some ( )
119136 {
120137 if self . merge_bundle_requirements ( from, to) . is_err ( ) {
121138 trace ! ( " -> conflicting requirements; aborting merge" ) ;
@@ -157,17 +174,7 @@ impl<'a, F: Function> Env<'a, F> {
157174 }
158175 }
159176 self . bundles [ to] . ranges = list;
160-
161- if self . bundles [ from] . cached_stack ( ) {
162- self . bundles [ to] . set_cached_stack ( ) ;
163- }
164- if self . bundles [ from] . cached_fixed ( ) {
165- self . bundles [ to] . set_cached_fixed ( ) ;
166- }
167- if self . bundles [ from] . cached_fixed_def ( ) {
168- self . bundles [ to] . set_cached_fixed_def ( ) ;
169- }
170-
177+ self . merge_bundle_properties ( from, to) ;
171178 return true ;
172179 }
173180
@@ -243,15 +250,7 @@ impl<'a, F: Function> Env<'a, F> {
243250 * to_range = to_range. join ( from_range) ;
244251 }
245252
246- if self . bundles [ from] . cached_stack ( ) {
247- self . bundles [ to] . set_cached_stack ( ) ;
248- }
249- if self . bundles [ from] . cached_fixed ( ) {
250- self . bundles [ to] . set_cached_fixed ( ) ;
251- }
252- if self . bundles [ from] . cached_fixed_def ( ) {
253- self . bundles [ to] . set_cached_fixed_def ( ) ;
254- }
253+ self . merge_bundle_properties ( from, to) ;
255254
256255 true
257256 }
@@ -283,16 +282,25 @@ impl<'a, F: Function> Env<'a, F> {
283282 let mut fixed = false ;
284283 let mut fixed_def = false ;
285284 let mut stack = false ;
285+ let mut limit: Option < usize > = None ;
286286 for entry in & self . bundles [ bundle] . ranges {
287287 for u in & self . ranges [ entry. index ] . uses {
288- if let OperandConstraint :: FixedReg ( _) = u. operand . constraint ( ) {
289- fixed = true ;
290- if u. operand . kind ( ) == OperandKind :: Def {
291- fixed_def = true ;
288+ use OperandConstraint :: * ;
289+ match u. operand . constraint ( ) {
290+ FixedReg ( _) => {
291+ fixed = true ;
292+ if u. operand . kind ( ) == OperandKind :: Def {
293+ fixed_def = true ;
294+ }
295+ }
296+ Stack => stack = true ,
297+ Limit ( current) => match limit {
298+ Some ( prev) => limit = Some ( prev. min ( current) ) ,
299+ None => limit = Some ( current) ,
300+ } ,
301+ Any | Reg | Reuse ( _) => {
302+ continue ;
292303 }
293- }
294- if let OperandConstraint :: Stack = u. operand . constraint ( ) {
295- stack = true ;
296304 }
297305 if fixed && stack && fixed_def {
298306 break ;
@@ -308,6 +316,7 @@ impl<'a, F: Function> Env<'a, F> {
308316 if stack {
309317 self . bundles [ bundle] . set_cached_stack ( ) ;
310318 }
319+ self . bundles [ bundle] . limit = limit;
311320
312321 // Create a spillslot for this bundle.
313322 let reg = self . vreg ( vreg) ;
0 commit comments