aboutsummaryrefslogtreecommitdiffhomepage
path: root/regalloc.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-10-10 22:34:17 +0200
committerlemon <lsof@mailbox.org>2025-10-10 22:34:17 +0200
commit0fb2b5712cc98ea993f37bd86eeed89fddc5d6d9 (patch)
treede9fce7ad0212b54c3de3a72dbe67038e8dd7936 /regalloc.c
parent0cb0dd0d23386a6a6ff4e981bb633b9e34a87c65 (diff)
bugfixes
Diffstat (limited to 'regalloc.c')
-rw-r--r--regalloc.c110
1 files changed, 55 insertions, 55 deletions
diff --git a/regalloc.c b/regalloc.c
index a3731e3..8e9d4ff 100644
--- a/regalloc.c
+++ b/regalloc.c
@@ -439,77 +439,77 @@ intervaloverlap(struct interval *a, struct interval *b)
}
static void
-addrange0(struct interval *it, struct range new)
+intervalbegin(struct interval *it, ushort from)
{
- int dst = it->nrange;
-
- if (dst == 0) { Push: pushrange(it, new); return; }
- /* start from the end, find place by order */
- for (int i = dst - 1; i >= 0; --i) {
- struct range range = itrange(it, i);
-
- /* fully contained? */
- if (range.from <= new.from && new.to <= range.to)
- return;
- if (range.from > new.from)
- dst = i;
- }
- if (dst == it->nrange) goto Push;
- if (rangeoverlap(new, itrange(it, dst)) || rangeadj(new, itrange(it, dst))) {
- struct range old = itrange(it, dst),
- *merge = &itrange(it, dst);
- if (new.from < old.from) merge->from = new.from;
- if (new.to > old.to) merge->to = new.to;
+ if (!it->nrange) {
+ pushrange(it, (struct range){from,from});
} else {
- /* insert at dst */
- pushrange(it, new);
- for (int j = it->nrange-1; j > dst; --j)
- itrange(it, j) = itrange(it, j-1);
- itrange(it, dst) = new;
+ itrange(it, 0).from = from;
}
- /* more merges? */
- for (struct range *last = &itrange(it, it->nrange-2);
- it->nrange > 1 && (rangeoverlap(last[0], last[1]) || rangeadj(last[0], last[1]));
- --last)
- {
- if (last[1].from < last[0].from)
- last[0].from = last[1].from;
- if (last[1].to > last[0].to)
- last[0].to = last[1].to;
-
- if (--it->nrange == 2) {
- struct range *tmp = it->_dyn;
- memcpy(it->_inl, tmp, 2*sizeof*tmp);
- xbfree(it->_dyn);
- }
+}
+
+static bool
+intervaldef(struct intervals *intervals, int t, struct block *blk, int pos, int reghint)
+{
+ struct interval *it = &intervals->temps[t];
+ if (it->nrange) {
+ assert(itrange(it, 0).from <= pos);
+ itrange(it, 0).from = pos;
+ return 1;
}
+ return 0;
}
static void
-addrange(struct intervals *intervals, int t, struct range range, int reghint)
+addrange(struct intervals *intervals, int t, struct range new, int reghint)
{
struct interval *it = &intervals->temps[t];
+ struct range *fst;
+ int n;
+
if (!it->nrange) {
++intervals->count;
it->rhint = reghint;
it->fpr = kisflt(insrescls(instrtab[t]));
+ pushrange(it, new);
+ return;
}
- addrange0(it, range);
-}
-static bool
-intervaldef(struct intervals *intervals, int t, struct block *blk, int pos, int reghint)
-{
- struct interval *it = &intervals->temps[t];
- if (it->nrange) {
- if (itrange(it, 0).from <= pos) /* shorten */
- itrange(it, 0).from = pos;
- else
- addrange0(it, (struct range){pos, blk->inumstart + blk->ins.n+1});
- if (it->rhint < 0) it->rhint = reghint;
- return 1;
+ fst = &itrange(it, 0);
+ /* fully covered by first range? */
+ if (fst->from <= new.from && fst->to >= new.to) return;
+ /* overlaps with first range ? */
+ if (fst->from <= new.to && new.to < fst->to) {
+ fst->from = new.from;
+ } else {
+ /* put new range at the start */
+ pushrange(it, new);
+ memmove(&itrange(it, 1), &itrange(it, 0), sizeof(struct range) * (it->nrange - 1));
+ itrange(it, 0) = new;
+ }
+
+ /* new range might cover existing ranges (loop header lives),
+ * check and succesively merge */
+ fst = &itrange(it, 0);
+ n = 0;
+ for (int i = 1; i < it->nrange; ++i) {
+ struct range other = itrange(it, i);
+ if (fst->to >= other.from) {
+ fst->to = fst->to > other.to ? fst->to : other.to;
+ ++n;
+ } else break;
+ }
+
+ if (n > 0) {
+ for (int i = 1; i + n < it->nrange; ++i)
+ itrange(it, i) = itrange(it, i+n);
+ if (it->nrange > 2 && it->nrange - n <= 2) {
+ struct range *dyn = it->_dyn;
+ memcpy(it->_inl, dyn, (it->nrange - n) * sizeof *dyn);
+ xbfree(dyn);
+ }
+ it->nrange -= n;
}
- return 0;
}
static void