diff options
| author | 2025-10-10 22:34:17 +0200 | |
|---|---|---|
| committer | 2025-10-10 22:34:17 +0200 | |
| commit | 0fb2b5712cc98ea993f37bd86eeed89fddc5d6d9 (patch) | |
| tree | de9fce7ad0212b54c3de3a72dbe67038e8dd7936 /regalloc.c | |
| parent | 0cb0dd0d23386a6a6ff4e981bb633b9e34a87c65 (diff) | |
bugfixes
Diffstat (limited to 'regalloc.c')
| -rw-r--r-- | regalloc.c | 110 |
1 files changed, 55 insertions, 55 deletions
@@ -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 |