Skip to content

Commit 9cee25a

Browse files
committed
Enhance register allocation with usage-based spill
Building on the VReg abstraction, this commit adds intelligent spill decisions based on variable usage patterns and context. - Track variable lifetime with first_use, last_use, and use_count - Add loop_depth field for identifying loop-resident variables - Transform spill cost from simple distance to multi-factor heuristic: * Loop variables: +200 cost per nesting level * Usage frequency: +5 cost per use * Live range length: +20 for long ranges * Constants: -50 (prefer spilling for rematerialization)
1 parent df4d771 commit 9cee25a

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

src/defs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ struct var {
374374
int vreg_id; /* Virtual register ID */
375375
int phys_reg; /* Physical register assignment (-1 if unassigned) */
376376
int vreg_flags; /* VReg flags */
377+
int first_use; /* First instruction index where variable is used */
378+
int last_use; /* Last instruction index where variable is used */
379+
int loop_depth; /* Nesting depth if variable is in a loop */
380+
int use_count; /* Number of times variable is used */
377381
};
378382

379383
typedef struct {

src/parser.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ var_t *require_var(block_t *blk)
6464
var_list->elements[var_list->size++] = var;
6565
var->consumed = -1;
6666
var->phys_reg = -1;
67+
var->first_use = -1;
68+
var->last_use = -1;
69+
var->loop_depth = 0;
70+
var->use_count = 0;
6771
var->base = var;
6872
var->type = TY_int;
6973
return var;

src/reg-alloc.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ bool check_live_out(basic_block_t *bb, var_t *var)
5454
return false;
5555
}
5656

57+
void track_var_use(var_t *var, int insn_idx)
58+
{
59+
if (!var)
60+
return;
61+
62+
var->use_count++;
63+
64+
if (var->first_use < 0)
65+
var->first_use = insn_idx;
66+
67+
var->last_use = insn_idx;
68+
}
69+
5770
void refresh(basic_block_t *bb, insn_t *insn)
5871
{
5972
for (int i = 0; i < REG_CNT; i++) {
@@ -95,16 +108,33 @@ ph2_ir_t *bb_add_ph2_ir(basic_block_t *bb, opcode_t op)
95108

96109
int calculate_spill_cost(var_t *var, basic_block_t *bb, int current_idx)
97110
{
111+
int cost = 0;
112+
98113
if (check_live_out(bb, var))
99-
return 1000;
114+
cost += 1000;
100115

101116
if (var->consumed > current_idx) {
102117
int distance = var->consumed - current_idx;
103118
if (distance < 10)
104-
return 100 - distance * 10;
119+
cost += 100 - distance * 10;
120+
}
121+
122+
if (var->use_count > 0)
123+
cost += var->use_count * 5;
124+
125+
if (var->loop_depth > 0)
126+
cost += var->loop_depth * 200;
127+
128+
if (var->is_const)
129+
cost -= 50;
130+
131+
if (var->first_use >= 0 && var->last_use >= 0) {
132+
int range_length = var->last_use - var->first_use;
133+
if (range_length > 100)
134+
cost += 20;
105135
}
106136

107-
return 0;
137+
return cost;
108138
}
109139

110140
int find_best_spill(basic_block_t *bb,
@@ -490,6 +520,7 @@ void reg_alloc(void)
490520

491521
switch (insn->opcode) {
492522
case OP_unwound_phi:
523+
track_var_use(insn->rs1, insn->idx);
493524
src0 = prepare_operand(bb, insn->rs1, -1);
494525

495526
if (!insn->rd->offset) {
@@ -583,6 +614,7 @@ void reg_alloc(void)
583614
if (insn->rd->consumed == -1)
584615
break;
585616

617+
track_var_use(insn->rs1, insn->idx);
586618
src0 = find_in_regs(insn->rs1);
587619

588620
/* If operand is loaded from stack, clear the original slot
@@ -727,6 +759,8 @@ void reg_alloc(void)
727759
case OP_bit_and:
728760
case OP_bit_or:
729761
case OP_bit_xor:
762+
track_var_use(insn->rs1, insn->idx);
763+
track_var_use(insn->rs2, insn->idx);
730764
src0 = prepare_operand(bb, insn->rs1, -1);
731765
src1 = prepare_operand(bb, insn->rs2, src0);
732766
dest = prepare_dest(bb, insn->rd, src0, src1);

0 commit comments

Comments
 (0)