From 2a17b87219134d204c6e94051961d812a6bea95f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 13 Apr 2023 20:56:49 +0300 Subject: [PATCH] LSRA optimization --- ir_private.h | 17 +++++++-- ir_ra.c | 103 ++++++++++++++++++++++++++------------------------- 2 files changed, 65 insertions(+), 55 deletions(-) diff --git a/ir_private.h b/ir_private.h index f4d92d8..a6c098c 100644 --- a/ir_private.h +++ b/ir_private.h @@ -1043,6 +1043,8 @@ int ir_gen_dessa_moves(ir_ctx *ctx, uint32_t b, emit_copy_t emit_copy); #if defined(IR_REGSET_64BIT) +typedef enum _ir_reg ir_reg; + /*** Register Sets ***/ #if IR_REGSET_64BIT typedef uint64_t ir_regset; @@ -1100,13 +1102,21 @@ typedef uint32_t ir_regset; # define IR_REGSET_LAST(set) ((ir_reg)(ir_nlz(set)^31)) #endif +IR_ALWAYS_INLINE ir_reg ir_regset_pop_first(ir_regset *set) +{ + ir_reg reg; + + IR_ASSERT(!IR_REGSET_IS_EMPTY(*set)); + reg = IR_REGSET_FIRST(*set); + *set = (*set) & ((*set) - 1); + return reg; +} + #define IR_REGSET_FOREACH(set, reg) \ do { \ ir_regset _tmp = (set); \ while (!IR_REGSET_IS_EMPTY(_tmp)) { \ - ir_reg _reg = IR_REGSET_FIRST(_tmp); \ - IR_REGSET_EXCL(_tmp, _reg); \ - reg = _reg; \ + reg = ir_regset_pop_first(&_tmp); #define IR_REGSET_FOREACH_END() \ } \ @@ -1152,7 +1162,6 @@ IR_ALWAYS_INLINE int8_t ir_get_alocated_reg(const ir_ctx *ctx, ir_ref ref, int o #define IR_RULE_MASK 0xff -typedef enum _ir_reg ir_reg; typedef struct _ir_target_constraints ir_target_constraints; #define IR_TMP_REG(_num, _type, _start, _end) \ diff --git a/ir_ra.c b/ir_ra.c index 34dfb9c..36ce33f 100644 --- a/ir_ra.c +++ b/ir_ra.c @@ -1936,7 +1936,7 @@ static void ir_merge_to_unhandled(ir_live_interval **unhandled, ir_live_interval ival->list_next = *prev; *prev = ival; prev = &ival->list_next; - ival = ival->next; + ival = ival->next; } } #if IR_DEBUG @@ -2015,19 +2015,14 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l reg = other->reg; IR_ASSERT(reg >= 0); if (reg >= IR_REG_SCRATCH) { - ir_regset regset; - if (reg == IR_REG_SCRATCH) { - regset = IR_REGSET_INTERSECTION(available, IR_REGSET_SCRATCH); + available = IR_REGSET_DIFFERENCE(available, IR_REGSET_SCRATCH); } else { IR_ASSERT(reg == IR_REG_ALL); - regset = available; + available = IR_REGSET_EMPTY; } - IR_REGSET_FOREACH(regset, reg) { - freeUntilPos[reg] = 0; - } IR_REGSET_FOREACH_END(); - } else if (IR_REGSET_IN(available, reg)) { - freeUntilPos[reg] = 0; + } else { + IR_REGSET_EXCL(available, reg); } other = other->list_next; } @@ -2038,31 +2033,33 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l * but it is still necessary after coalescing and splitting */ other = inactive; + pos = ival->end; while (other) { /* freeUntilPos[it.reg] = next intersection of it with current */ - reg = other->reg; - IR_ASSERT(reg >= 0); - if (reg >= IR_REG_SCRATCH) { + if (other->current_range->start < pos) { next = ir_ivals_overlap(&ival->range, other->current_range); if (next) { - ir_regset regset; + reg = other->reg; + IR_ASSERT(reg >= 0); + if (reg >= IR_REG_SCRATCH) { + ir_regset regset; - if (reg == IR_REG_SCRATCH) { - regset = IR_REGSET_INTERSECTION(available, IR_REGSET_SCRATCH); - } else { - IR_ASSERT(reg == IR_REG_ALL); - regset = available; - } - IR_REGSET_FOREACH(regset, reg) { + if (reg == IR_REG_SCRATCH) { + regset = IR_REGSET_INTERSECTION(available, IR_REGSET_SCRATCH); + } else { + IR_ASSERT(reg == IR_REG_ALL); + regset = available; + } + IR_REGSET_FOREACH(regset, reg) { + if (next < freeUntilPos[reg]) { + freeUntilPos[reg] = next; + } + } IR_REGSET_FOREACH_END(); + } else if (IR_REGSET_IN(available, reg)) { if (next < freeUntilPos[reg]) { freeUntilPos[reg] = next; } - } IR_REGSET_FOREACH_END(); - } - } else if (IR_REGSET_IN(available, reg)) { - next = ir_ivals_overlap(&ival->range, other->current_range); - if (next && next < freeUntilPos[reg]) { - freeUntilPos[reg] = next; + } } } other = other->list_next; @@ -2102,9 +2099,8 @@ static ir_reg ir_try_allocate_free_reg(ir_ctx *ctx, ir_live_interval *ival, ir_l pos = freeUntilPos[i]; reg = i; } else if (freeUntilPos[i] == pos - && (reg == IR_REG_NONE - || (!IR_REGSET_IN(IR_REGSET_SCRATCH, reg) - && IR_REGSET_IN(IR_REGSET_SCRATCH, i)))) { + && !IR_REGSET_IN(IR_REGSET_SCRATCH, reg) + && IR_REGSET_IN(IR_REGSET_SCRATCH, i)) { /* prefer caller-saved registers to avoid save/restore in prologue/epilogue */ pos = freeUntilPos[i]; reg = i; @@ -2699,21 +2695,24 @@ static int ir_linear_scan(ir_ctx *ctx) while (other) { ir_live_range *r = other->current_range; - if (r && r->end <= position) { + IR_ASSERT(r); + if (r->end <= position) { do { r = r->next; } while (r && r->end <= position); + if (!r) { + /* move i from active to handled */ + other = other->list_next; + if (prev) { + prev->list_next = other; + } else { + active = other; + } + continue; + } other->current_range = r; } - /* if (ir_ival_end(other) <= position) {*/ - if (!r) { - /* move i from active to handled */ - if (prev) { - prev->list_next = other->list_next; - } else { - active = other->list_next; - } - } else if (position < r->start) { + if (position < r->start) { /* move i from active to inactive */ if (prev) { prev->list_next = other->list_next; @@ -2734,22 +2733,24 @@ static int ir_linear_scan(ir_ctx *ctx) while (other) { ir_live_range *r = other->current_range; - if (r && r->end <= position) { + IR_ASSERT(r); + if (r->end <= position) { do { r = r->next; } while (r && r->end <= position); + if (!r) { + /* move i from inactive to handled */ + other = other->list_next; + if (prev) { + prev->list_next = other; + } else { + inactive = other; + } + continue; + } other->current_range = r; } - /* if (ir_ival_end(other) <= position) {*/ - if (!r) { - /* move i from inactive to handled */ - if (prev) { - prev->list_next = other->list_next; - } else { - inactive = other->list_next; - } - /* } else if (ir_ival_covers(other, position)) {*/ - } else if (position >= r->start) { + if (position >= r->start) { /* move i from active to inactive */ if (prev) { prev->list_next = other->list_next;