diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-13 19:20:56 +0200 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-13 19:25:59 +0200 |
commit | 57f6b41047e95374701ee276248f0f8615168450 (patch) | |
tree | 919a47249b2442dab31ae236f1f9f858651e5357 /src/ejit.c | |
parent | ba9145b0b7af2a82c62f8dfa28807958af5d0c8d (diff) | |
download | ejit-57f6b41047e95374701ee276248f0f8615168450.tar.gz ejit-57f6b41047e95374701ee276248f0f8615168450.zip |
improve register allocation
+ Still linear, but orders regs by some kind of priority
+ Use all registers available, not just callee-save
Diffstat (limited to 'src/ejit.c')
-rw-r--r-- | src/ejit.c | 75 |
1 files changed, 65 insertions, 10 deletions
@@ -6,20 +6,48 @@ #include "common.h" -static size_t max(size_t a, size_t b) +static struct gpr_stat zero_gpr_stat() { - return a > b ? a : b; + return (struct gpr_stat){ + .r = EJIT_GPR(0), + .prio = 0, + .rno = 0 + }; +} + +static struct fpr_stat zero_fpr_stat() +{ + return (struct fpr_stat){ + .f = EJIT_FPR(0), + .prio = 0, + .fno = 0 + }; } static void update_gpr(struct ejit_func *f, struct ejit_gpr r0) { - /* +1 because we want to look at count, not index */ - f->gpr = max(f->gpr, r0.r + 1); + while (gpr_stats_len(&f->gpr) <= r0.r) + gpr_stats_append(&f->gpr, zero_gpr_stat()); + + struct gpr_stat *gpr = gpr_stats_at(&f->gpr, r0.r); + /* presumably first time we see this gpr */ + /** @todo are branches faster than a memory write? */ + if (gpr->prio == 0) + gpr->r = r0; + + gpr->prio += f->prio; } static void update_fpr(struct ejit_func *f, struct ejit_fpr f0) { - f->fpr = max(f->fpr, f0.f + 1); + while (fpr_stats_len(&f->fpr) <= f0.f) + fpr_stats_append(&f->fpr, zero_fpr_stat()); + + struct fpr_stat *fpr = fpr_stats_at(&f->fpr, f0.f); + if (fpr->prio == 0) + fpr->f = f0; + + fpr->prio += f->prio; } static void update_64(struct ejit_func *f, int64_t o) @@ -288,11 +316,12 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, f->insns = insns_create(); f->labels = labels_create(); + f->gpr = gpr_stats_create(); + f->fpr = fpr_stats_create(); f->arena = NULL; f->direct_call = NULL; f->size = 0; - f->gpr = 0; - f->fpr = 0; + f->prio = 1; f->use_64 = false; for (size_t i = 0; i < argc; ++i) { @@ -318,7 +347,11 @@ struct ejit_func *ejit_create_func(enum ejit_type rtype, size_t argc, void ejit_compile_func(struct ejit_func *f) { - ejit_select_compile_func(f, f->gpr, f->fpr, f->use_64, true); + ejit_select_compile_func(f, + gpr_stats_len(&f->gpr), + fpr_stats_len(&f->fpr), + f->use_64, + true); } void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, @@ -328,8 +361,8 @@ void ejit_select_compile_func(struct ejit_func *f, size_t gpr, size_t fpr, emit_insn_o(f, END); /* user can get some sanity checking done by passing these explicitly */ - assert(gpr >= f->gpr); - assert(fpr >= f->fpr); + assert(gpr >= gpr_stats_len(&f->gpr)); + assert(fpr >= fpr_stats_len(&f->fpr)); assert(!f->use_64 || (use_64 == f->use_64)); /* try to jit compile if possible */ @@ -364,6 +397,8 @@ void ejit_destroy_func(struct ejit_func *f) insns_destroy(&f->insns); labels_destroy(&f->labels); + gpr_stats_destroy(&f->gpr); + fpr_stats_destroy(&f->fpr); free(f); } @@ -1570,3 +1605,23 @@ double ejit_run_func_f(struct ejit_func *f, size_t argc, destroy_interp_state(state); return r; } + +size_t ejit_get_prio(struct ejit_func *s) +{ + return s->prio; +} + +void ejit_set_prio(struct ejit_func *s, size_t prio) +{ + s->prio = prio; +} + +void ejit_inc_prio(struct ejit_func *s, size_t prio) +{ + s->prio += prio; +} + +void ejit_dec_prio(struct ejit_func *s, size_t prio) +{ + s->prio -= prio; +} |