14
14
15
15
use super :: { Env , LiveBundleIndex , SpillSet , SpillSlotIndex , VRegIndex } ;
16
16
use crate :: {
17
- ion:: data_structures:: BlockparamOut , Function , Inst , OperandConstraint , OperandKind , PReg ,
17
+ ion:: data_structures:: { BlockparamOut , CodeRange } ,
18
+ Function , Inst , OperandConstraint , OperandKind , PReg , ProgPoint ,
18
19
} ;
19
20
use alloc:: format;
20
21
use smallvec:: smallvec;
@@ -58,6 +59,21 @@ impl<'a, F: Function> Env<'a, F> {
58
59
}
59
60
}
60
61
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
+
61
77
// Check for overlap in LiveRanges and for conflicting
62
78
// requirements.
63
79
let ranges_from = & self . bundles [ from] . ranges [ ..] ;
@@ -76,9 +92,11 @@ impl<'a, F: Function> Env<'a, F> {
76
92
return false ;
77
93
}
78
94
79
- if ranges_from[ idx_from] . range . from >= ranges_to[ idx_to] . range . to {
95
+ if adjust_range_start ( from , ranges_from[ idx_from] . range ) >= ranges_to[ idx_to] . range . to {
80
96
idx_to += 1 ;
81
- } else if ranges_to[ idx_to] . range . from >= ranges_from[ idx_from] . range . to {
97
+ } else if adjust_range_start ( to, ranges_to[ idx_to] . range )
98
+ >= ranges_from[ idx_from] . range . to
99
+ {
82
100
idx_from += 1 ;
83
101
} else {
84
102
// Overlap -- cannot merge.
@@ -91,15 +109,6 @@ impl<'a, F: Function> Env<'a, F> {
91
109
}
92
110
}
93
111
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
-
103
112
// Check for a requirements conflict.
104
113
if self . bundles [ from] . cached_stack ( )
105
114
|| self . bundles [ from] . cached_fixed ( )
@@ -152,6 +161,9 @@ impl<'a, F: Function> Env<'a, F> {
152
161
if self . bundles [ from] . cached_fixed ( ) {
153
162
self . bundles [ to] . set_cached_fixed ( ) ;
154
163
}
164
+ if self . bundles [ from] . cached_fixed_def ( ) {
165
+ self . bundles [ to] . set_cached_fixed_def ( ) ;
166
+ }
155
167
156
168
return true ;
157
169
}
@@ -218,6 +230,9 @@ impl<'a, F: Function> Env<'a, F> {
218
230
if self . bundles [ from] . cached_fixed ( ) {
219
231
self . bundles [ to] . set_cached_fixed ( ) ;
220
232
}
233
+ if self . bundles [ from] . cached_fixed_def ( ) {
234
+ self . bundles [ to] . set_cached_fixed_def ( ) ;
235
+ }
221
236
222
237
true
223
238
}
0 commit comments