Skip to content

Commit 1f08342

Browse files
authored
Allow merging bundles that have a fixed-reg def (#155)
The previous check was overly conservative: we only need to reject bundles that have multiple uses in the same instruction. This can only happen with an early use and a late def, so we round the start of each range containing a fixed def up to the start of its instruction to detect overlaps.
1 parent bf1423b commit 1f08342

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

src/ion/merge.rs

Lines changed: 21 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()

0 commit comments

Comments
 (0)