Skip to content

Commit 6ba8cab

Browse files
authored
Propagate the cached fixed-def flag when merging bundles (#161)
* Propagate the cached fixed-def flag when merging bundles This was missed in #155, and previously wasn't an issue since such bundles were never merged. * Revert "Revert "Allow merging bundles that have a fixed-reg def (#155)" (#160)" This reverts commit 783ba47.
1 parent bcaaf39 commit 6ba8cab

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

src/ion/merge.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
1515
use super::{Env, LiveBundleIndex, SpillSet, SpillSlotIndex, VRegIndex};
1616
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,
1819
};
1920
use alloc::format;
2021
use smallvec::smallvec;
@@ -58,6 +59,21 @@ impl<'a, F: Function> Env<'a, F> {
5859
}
5960
}
6061

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+
6177
// Check for overlap in LiveRanges and for conflicting
6278
// requirements.
6379
let ranges_from = &self.bundles[from].ranges[..];
@@ -76,9 +92,11 @@ impl<'a, F: Function> Env<'a, F> {
7692
return false;
7793
}
7894

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 {
8096
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+
{
82100
idx_from += 1;
83101
} else {
84102
// Overlap -- cannot merge.
@@ -91,15 +109,6 @@ impl<'a, F: Function> Env<'a, F> {
91109
}
92110
}
93111

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-
103112
// Check for a requirements conflict.
104113
if self.bundles[from].cached_stack()
105114
|| self.bundles[from].cached_fixed()
@@ -152,6 +161,9 @@ impl<'a, F: Function> Env<'a, F> {
152161
if self.bundles[from].cached_fixed() {
153162
self.bundles[to].set_cached_fixed();
154163
}
164+
if self.bundles[from].cached_fixed_def() {
165+
self.bundles[to].set_cached_fixed_def();
166+
}
155167

156168
return true;
157169
}
@@ -218,6 +230,9 @@ impl<'a, F: Function> Env<'a, F> {
218230
if self.bundles[from].cached_fixed() {
219231
self.bundles[to].set_cached_fixed();
220232
}
233+
if self.bundles[from].cached_fixed_def() {
234+
self.bundles[to].set_cached_fixed_def();
235+
}
221236

222237
true
223238
}

0 commit comments

Comments
 (0)