1414
1515use super :: { Env , LiveBundleIndex , SpillSet , SpillSlotIndex , VRegIndex } ;
1616use crate :: {
17- ion:: data_structures:: { BlockparamOut , CodeRange } ,
18- Function , Inst , OperandConstraint , OperandKind , PReg , ProgPoint ,
17+ ion:: data_structures:: BlockparamOut , Function , Inst , OperandConstraint , OperandKind , PReg ,
1918} ;
2019use alloc:: format;
2120use smallvec:: smallvec;
@@ -59,21 +58,6 @@ impl<'a, F: Function> Env<'a, F> {
5958 }
6059 }
6160
62- // If a bundle has a fixed-reg def then we need to be careful to not
63- // extend the bundle to include another use in the same instruction.
64- // This could result in a minimal bundle that is impossible to split.
65- //
66- // This can only happen with an early use and a late def, so we round
67- // the start of each range containing a fixed def up to the start of
68- // its instruction to detect overlaps.
69- let adjust_range_start = |bundle_idx, range : CodeRange | {
70- if self . bundles [ bundle_idx] . cached_fixed_def ( ) {
71- ProgPoint :: before ( range. from . inst ( ) )
72- } else {
73- range. from
74- }
75- } ;
76-
7761 // Check for overlap in LiveRanges and for conflicting
7862 // requirements.
7963 let ranges_from = & self . bundles [ from] . ranges [ ..] ;
@@ -92,11 +76,9 @@ impl<'a, F: Function> Env<'a, F> {
9276 return false ;
9377 }
9478
95- if adjust_range_start ( from , ranges_from[ idx_from] . range ) >= ranges_to[ idx_to] . range . to {
79+ if ranges_from[ idx_from] . range . from >= ranges_to[ idx_to] . range . to {
9680 idx_to += 1 ;
97- } else if adjust_range_start ( to, ranges_to[ idx_to] . range )
98- >= ranges_from[ idx_from] . range . to
99- {
81+ } else if ranges_to[ idx_to] . range . from >= ranges_from[ idx_from] . range . to {
10082 idx_from += 1 ;
10183 } else {
10284 // Overlap -- cannot merge.
@@ -109,6 +91,15 @@ impl<'a, F: Function> Env<'a, F> {
10991 }
11092 }
11193
94+ // Avoid merging if either side has a fixed-reg def: this can
95+ // result in an impossible-to-solve allocation problem if
96+ // there is a fixed-reg use in the same reg on the same
97+ // instruction.
98+ if self . bundles [ from] . cached_fixed_def ( ) || self . bundles [ to] . cached_fixed_def ( ) {
99+ trace ! ( " -> one bundle has a fixed def; aborting merge" ) ;
100+ return false ;
101+ }
102+
112103 // Check for a requirements conflict.
113104 if self . bundles [ from] . cached_stack ( )
114105 || self . bundles [ from] . cached_fixed ( )
0 commit comments