aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-04-11 11:45:48 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-04-11 11:45:48 +0300
commit8ce25e04620d4173748a7d7dd310351bac90eacc (patch)
tree01f8aa649eb92ee1c1fc2560468c374c493e3840 /src
parent52d8eda04d1e2e33bf4c09713d83360453cec435 (diff)
downloadqbt-8ce25e04620d4173748a7d7dd310351bac90eacc.tar.gz
qbt-8ce25e04620d4173748a7d7dd310351bac90eacc.zip
formatting
Diffstat (limited to 'src')
-rw-r--r--src/abi.c4
-rw-r--r--src/asm.c20
-rw-r--r--src/correct.c12
-rw-r--r--src/regalloc.c144
4 files changed, 102 insertions, 78 deletions
diff --git a/src/abi.c b/src/abi.c
index 76d3e74..a91743c 100644
--- a/src/abi.c
+++ b/src/abi.c
@@ -44,13 +44,13 @@ static struct insn rewrite_arg(struct insn n)
if (n.in[0].class == TMP || n.in[0].class == REG) {
n = insn_create(MOVE, I27, nth_ar(nth_arg), n.in[0],
- noclass(), 0);
+ noclass(), 0);
set_insn_flags(&n, CALL_SETUP);
return n;
}
else if (n.in[0].class == IMM || n.in[0].class == REF) {
n = insn_create(COPY, I27, nth_ar(nth_arg), n.in[0],
- noclass(), 0);
+ noclass(), 0);
set_insn_flags(&n, CALL_SETUP);
return n;
}
diff --git a/src/asm.c b/src/asm.c
index 0491a0f..65d0eb8 100644
--- a/src/asm.c
+++ b/src/asm.c
@@ -234,7 +234,7 @@ static void output_save(struct insn n, FILE *o, struct fn *f)
assert(r.class == REG);
int64_t i = n.in[1].v;
fprintf(o, "st w %s, -%zi(fp)\n",
- rname(r), call_save_fploc(f, i));
+ rname(r), call_save_fploc(f, i));
}
static void output_restore(struct insn n, FILE *o, struct fn *f)
@@ -243,7 +243,7 @@ static void output_restore(struct insn n, FILE *o, struct fn *f)
assert(r.class == REG);
int64_t i = n.in[1].v;
fprintf(o, "ld w %s, -%zi(fp)\n",
- rname(r), call_save_fploc(f, i));
+ rname(r), call_save_fploc(f, i));
}
static void output_store(struct insn n, FILE *o)
@@ -262,7 +262,7 @@ static void output_store(struct insn n, FILE *o)
int64_t off = offset.v;
fprintf(o, "st %c %s, %lli(%s)\n",
- width, rname(t), (long long int)off, rname(b));
+ width, rname(t), (long long int)off, rname(b));
}
static void output_load(struct insn n, FILE *o)
@@ -281,7 +281,7 @@ static void output_load(struct insn n, FILE *o)
int64_t off = offset.v;
fprintf(o, "ld %c %s, %lli(%s)\n",
- width, rname(t), (long long int)off, rname(b));
+ width, rname(t), (long long int)off, rname(b));
}
static void output_lt(struct insn i, FILE *o)
@@ -289,10 +289,10 @@ static void output_lt(struct insn i, FILE *o)
assert(i.type == LT);
if (i.in[1].class == IMM)
fprintf(o, "slti %s, %s, %lli\n",
- rname(i.out), rname(i.in[0]), (long long)i.in[1].v);
+ rname(i.out), rname(i.in[0]), (long long)i.in[1].v);
else
fprintf(o, "slt %s, %s, %s\n",
- rname(i.out), rname(i.in[0]), rname(i.in[1]));
+ rname(i.out), rname(i.in[0]), rname(i.in[1]));
}
static void output_insn(struct insn n, FILE *o, struct fn *f)
@@ -336,22 +336,22 @@ static void output_bne(struct blk *b, struct fn *f, FILE *o)
{
assert(b->s2);
fprintf(o, "bne %s, %s, .%s.%lli\n",
- rname(b->cmp[0]), rname(b->cmp[1]),
- f->name, (long long)b->s2->id);
+ rname(b->cmp[0]), rname(b->cmp[1]),
+ f->name, (long long)b->s2->id);
}
static void output_bnz(struct blk *b, struct fn *f, FILE *o)
{
assert(b->s2);
fprintf(o, "bne %s, x0, .%s.%lli\n",
- rname(b->cmp[0]), f->name, (long long)b->s2->id);
+ rname(b->cmp[0]), f->name, (long long)b->s2->id);
}
static void output_bez(struct blk *b, struct fn *f, FILE *o)
{
assert(b->s2);
fprintf(o, "beq %s, x0, .%s.%lli\n",
- rname(b->cmp[0]), f->name, (long long)b->s2->id);
+ rname(b->cmp[0]), f->name, (long long)b->s2->id);
}
static void output_ret(struct fn *f, FILE *o)
diff --git a/src/correct.c b/src/correct.c
index 9191ff9..5db40dd 100644
--- a/src/correct.c
+++ b/src/correct.c
@@ -1,6 +1,7 @@
#include <qbt/opt.h>
-static size_t spill_ref(struct blk *b, size_t ii, struct insn i, size_t idx, size_t ri)
+static size_t spill_ref(struct blk *b, size_t ii, struct insn i, size_t idx,
+ size_t ri)
{
struct val tmp = tmp_val(ri++);
struct insn new = insn_create(ADDR, I27, tmp, i.in[idx], noclass(), 0);
@@ -10,7 +11,8 @@ static size_t spill_ref(struct blk *b, size_t ii, struct insn i, size_t idx, siz
return ri;
}
-static size_t spill_imm(struct blk *b, size_t ii, struct insn i, size_t idx, size_t ri)
+static size_t spill_imm(struct blk *b, size_t ii, struct insn i, size_t idx,
+ size_t ri)
{
struct val tmp = tmp_val(ri++);
struct insn new = insn_create(COPY, I27, tmp, i.in[idx], noclass(), 0);
@@ -37,7 +39,8 @@ static size_t correct_arith(struct blk *b, size_t ii, struct insn i, size_t ri)
return ri;
}
-static size_t correct_positional_arith(struct blk *b, size_t ii, struct insn i, size_t ri)
+static size_t correct_positional_arith(struct blk *b, size_t ii, struct insn i,
+ size_t ri)
{
if (i.in[0].class == IMM)
return spill_imm(b, ii, i, 0, ri);
@@ -56,7 +59,8 @@ static size_t correct_branch(struct blk *b, size_t ii, struct insn i, size_t ri)
return ri;
}
-static size_t correct_relations(struct blk *b, size_t ii, struct insn i, size_t ri)
+static size_t correct_relations(struct blk *b, size_t ii, struct insn i,
+ size_t ri)
{
if (i.in[0].class == IMM)
return spill_imm(b, ii, i, 0, ri);
diff --git a/src/regalloc.c b/src/regalloc.c
index f5157fe..8c42eab 100644
--- a/src/regalloc.c
+++ b/src/regalloc.c
@@ -11,7 +11,7 @@
* free to make sure function calls in loops etc. don't have to shuffle
* registers around as much. The preferred order can probably be bikeshedded to death,
* eventually would be kind of cool to add some heuristic for which category
- * might be best suited for a specific location.
+ * might be best suited for a specific location.
* One possible one would be that callee-save should be preferred if the
* lifetime overlaps a function call? */
static const int64_t tr_map[] = {
@@ -112,7 +112,8 @@ static void add_use(struct vec *lifetimes, struct val v, size_t i)
}
static void collect_lifetimes(struct blk *b, struct vec *hints,
- struct vec *lifetimes, struct vec *rmap, struct vec *calls)
+ struct vec *lifetimes, struct vec *rmap,
+ struct vec *calls)
{
foreach_blk_param(pi, b->params) {
struct val v = blk_param_at(b->params, pi);
@@ -146,6 +147,9 @@ static void collect_lifetimes(struct blk *b, struct vec *hints,
}
/* collect calls, to be used later */
+ /* could and probably should mark currently alive registers as
+ * 'stored' or something to avoid having to spill a million
+ * temporaries */
if (i.type == CALL)
vec_append(calls, &pos);
@@ -158,6 +162,8 @@ static void collect_lifetimes(struct blk *b, struct vec *hints,
if (b->cmp[1].class == TMP)
add_use(lifetimes, b->cmp[1], pos);
+ /* might also be a good idea to add equivalency chains, i.e. map block
+ * args to block params */
foreach_blk_param(pi, b->args1) {
struct val v = blk_param_at(b->args1, pi);
add_use(lifetimes, v, pos);
@@ -169,17 +175,20 @@ static void collect_lifetimes(struct blk *b, struct vec *hints,
}
}
-static void build_active_between(struct vec *active, struct vec *lifetimes, size_t start, size_t end)
+static void build_active_between(struct vec *active, struct vec *lifetimes,
+ size_t start, size_t end)
{
foreach_lifetime(li, *lifetimes) {
struct lifetime l = lifetime_at(*lifetimes, li);
if (l.used == 0)
continue;
- if (l.end < start)
+ /* start == end still counts as dead and we're free to reuse the
+ * reg */
+ if (l.end <= start)
continue;
- if (l.start > end)
+ if (l.start >= end)
continue;
vec_append(active, &l);
@@ -241,37 +250,37 @@ static size_t highest_sreg(struct val f)
{
assert(f.class == REG);
switch (f.r) {
- case RS0: return 1;
- case RS1: return 2;
- case RS2: return 3;
- case RS3: return 4;
- case RS4: return 5;
- case RS5: return 6;
- case RS6: return 7;
- case RS7: return 8;
- case RS8: return 9;
- case RS9: return 10;
- case RS10: return 11;
- case RS11: return 12;
- case RS12: return 13;
- case RS13: return 14;
- case RS14: return 15;
- case RS15: return 16;
- case RS16: return 17;
- case RS17: return 18;
- case RS18: return 19;
- case RS19: return 20;
- case RS20: return 21;
- case RS21: return 22;
- case RS22: return 23;
- case RS23: return 24;
+ case RS0: return 1;
+ case RS1: return 2;
+ case RS2: return 3;
+ case RS3: return 4;
+ case RS4: return 5;
+ case RS5: return 6;
+ case RS6: return 7;
+ case RS7: return 8;
+ case RS8: return 9;
+ case RS9: return 10;
+ case RS10: return 11;
+ case RS11: return 12;
+ case RS12: return 13;
+ case RS13: return 14;
+ case RS14: return 15;
+ case RS15: return 16;
+ case RS16: return 17;
+ case RS17: return 18;
+ case RS18: return 19;
+ case RS19: return 20;
+ case RS20: return 21;
+ case RS21: return 22;
+ case RS22: return 23;
+ case RS23: return 24;
}
return 0;
}
static size_t build_rmap(struct vec *hints, struct vec *lifetimes,
- struct vec *rmap)
+ struct vec *rmap)
{
size_t max_callee_save = 0;
struct vec active = vec_create(sizeof(struct lifetime));
@@ -358,36 +367,37 @@ static bool callee_save(struct val r)
{
assert(r.class == REG);
switch (r.r) {
- case RS0: return true;
- case RS1: return true;
- case RS2: return true;
- case RS3: return true;
- case RS4: return true;
- case RS5: return true;
- case RS6: return true;
- case RS7: return true;
- case RS8: return true;
- case RS9: return true;
- case RS10: return true;
- case RS11: return true;
- case RS12: return true;
- case RS13: return true;
- case RS14: return true;
- case RS15: return true;
- case RS16: return true;
- case RS17: return true;
- case RS18: return true;
- case RS19: return true;
- case RS20: return true;
- case RS21: return true;
- case RS22: return true;
- case RS23: return true;
+ case RS0: return true;
+ case RS1: return true;
+ case RS2: return true;
+ case RS3: return true;
+ case RS4: return true;
+ case RS5: return true;
+ case RS6: return true;
+ case RS7: return true;
+ case RS8: return true;
+ case RS9: return true;
+ case RS10: return true;
+ case RS11: return true;
+ case RS12: return true;
+ case RS13: return true;
+ case RS14: return true;
+ case RS15: return true;
+ case RS16: return true;
+ case RS17: return true;
+ case RS18: return true;
+ case RS19: return true;
+ case RS20: return true;
+ case RS21: return true;
+ case RS22: return true;
+ case RS23: return true;
}
return false;
}
-static void insn_insert_before_call(struct blk *b, struct insn save, ssize_t pos)
+static void insn_insert_before_call(struct blk *b, struct insn save,
+ ssize_t pos)
{
assert((insn_at(b->insns, pos)).type == CALL);
struct insn setup;
@@ -402,7 +412,8 @@ static void insn_insert_before_call(struct blk *b, struct insn save, ssize_t pos
insn_insert(b, save, pos + 1);
}
-static void insn_insert_after_call(struct blk *b, struct insn restore, size_t pos)
+static void insn_insert_after_call(struct blk *b, struct insn restore,
+ size_t pos)
{
assert((insn_at(b->insns, pos)).type == CALL);
size_t max = vec_len(&b->insns);
@@ -419,7 +430,8 @@ static void insn_insert_after_call(struct blk *b, struct insn restore, size_t po
insn_insert(b, restore, pos);
}
-static size_t do_call_saves(struct blk *b, struct vec *lifetimes, struct vec *rmap, struct vec *calls)
+static size_t do_call_saves(struct blk *b, struct vec *lifetimes,
+ struct vec *rmap, struct vec *calls)
{
size_t offset = 0;
size_t max_counter = 0;
@@ -447,8 +459,9 @@ static size_t do_call_saves(struct blk *b, struct vec *lifetimes, struct vec *rm
continue;
struct insn save = insn_create(SAVE, NOTYPE,
- noclass(), r,
- imm_val(counter, I27), 0);
+ noclass(), r,
+ imm_val(counter, I27),
+ 0);
insn_insert_before_call(b, save, call_pos + offset - 1);
offset++;
@@ -467,8 +480,9 @@ static size_t do_call_saves(struct blk *b, struct vec *lifetimes, struct vec *rm
/* hmm, restore should maybe put r as its output to be
* more consistent... */
struct insn restore = insn_create(RESTORE, NOTYPE,
- noclass(), r,
- imm_val(counter, I27), 0);
+ noclass(), r,
+ imm_val(counter, I27),
+ 0);
insn_insert_after_call(b, restore, call_pos - 1);
counter++;
@@ -505,7 +519,13 @@ void regalloc(struct fn *f)
size_t max_callee_save = build_rmap(&hints, &lifetimes, &rmap);
do_rewrites(b, &rmap);
- size_t max_call_save = do_call_saves(b, &lifetimes, &rmap, &calls);
+ size_t max_call_save = do_call_saves(b, &lifetimes, &rmap,
+ &calls);
+ /* hints should probably propagate registers as far as possible,
+ * right now I'm thinking that we should update block
+ * args/params and we can stop updating when the hints don't
+ * change. Unsure how efficient this would be, I guess we'll
+ * find out :) */
/** @todo forward_hints(b, &hints, &rmap) */
if (vec_len(&calls) != 0)
f->has_calls = true;