Don't write back temporary registers if they won't be read again.
This commit is contained in:
parent
ac886c420f
commit
178c9d5c15
1 changed files with 101 additions and 85 deletions
|
|
@ -45,109 +45,120 @@ enum
|
|||
REG_FP
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/*Register may be accessed outside of code block, and must be written
|
||||
back before any control transfers*/
|
||||
REG_PERMANENT = 0,
|
||||
/*Register will not be accessed outside of code block, and does not need
|
||||
to be written back if there are no readers remaining*/
|
||||
REG_VOLATILE = 1
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
int native_size;
|
||||
void *p;
|
||||
int type;
|
||||
int is_volatile;
|
||||
} ireg_data[IREG_COUNT] =
|
||||
{
|
||||
[IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER},
|
||||
[IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER},
|
||||
[IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER},
|
||||
[IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER},
|
||||
[IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER},
|
||||
[IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER},
|
||||
[IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER},
|
||||
[IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER},
|
||||
[IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER},
|
||||
[IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER},
|
||||
[IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER},
|
||||
[IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER},
|
||||
[IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER},
|
||||
[IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER},
|
||||
[IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER},
|
||||
[IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER},
|
||||
[IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER},
|
||||
[IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER},
|
||||
[IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ssegsx] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER},
|
||||
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER},
|
||||
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER},
|
||||
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER},
|
||||
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER},
|
||||
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER},
|
||||
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER},
|
||||
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER},
|
||||
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER},
|
||||
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER},
|
||||
[IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER},
|
||||
[IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER},
|
||||
[IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER},
|
||||
[IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER},
|
||||
[IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER},
|
||||
[IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER},
|
||||
[IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
|
||||
[IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP, REG_PERMANENT},
|
||||
|
||||
[IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
|
||||
[IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_ST0_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST1_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST2_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST3_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST4_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST5_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST6_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_ST7_i64] = {REG_FPU_ST_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
|
||||
[IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP},
|
||||
[IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP},
|
||||
[IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP},
|
||||
[IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP},
|
||||
[IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP},
|
||||
[IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP},
|
||||
[IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP},
|
||||
[IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP},
|
||||
[IREG_MM0x] = {REG_QWORD, &cpu_state.MM[0], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM1x] = {REG_QWORD, &cpu_state.MM[1], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM2x] = {REG_QWORD, &cpu_state.MM[2], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM3x] = {REG_QWORD, &cpu_state.MM[3], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM4x] = {REG_QWORD, &cpu_state.MM[4], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM5x] = {REG_QWORD, &cpu_state.MM[5], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM6x] = {REG_QWORD, &cpu_state.MM[6], REG_FP, REG_PERMANENT},
|
||||
[IREG_MM7x] = {REG_QWORD, &cpu_state.MM[7], REG_FP, REG_PERMANENT},
|
||||
|
||||
[IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER},
|
||||
[IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER},
|
||||
[IREG_NPXCx] = {REG_WORD, &cpu_state.npxc, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_NPXSx] = {REG_WORD, &cpu_state.npxs, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER},
|
||||
[IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER},
|
||||
[IREG_flagsx] = {REG_WORD, &cpu_state.flags, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_eflagsx] = {REG_WORD, &cpu_state.eflags, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
/*Temporary registers are stored on the stack, and are not guaranteed to
|
||||
be preserved across uOPs. They will not be written back if they will
|
||||
not be read again.*/
|
||||
[IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER},
|
||||
[IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER},
|
||||
[IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER},
|
||||
[IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER},
|
||||
[IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER, REG_VOLATILE},
|
||||
[IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER, REG_VOLATILE},
|
||||
[IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER, REG_VOLATILE},
|
||||
[IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER, REG_VOLATILE},
|
||||
|
||||
[IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP},
|
||||
[IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP},
|
||||
[IREG_temp0d] = {REG_DOUBLE, (void *)40, REG_FP, REG_VOLATILE},
|
||||
[IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE},
|
||||
};
|
||||
|
||||
static int reg_is_native_size(ir_reg_t ir_reg)
|
||||
|
|
@ -317,6 +328,10 @@ static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, i
|
|||
int ir_reg = IREG_GET_REG(reg_set->regs[c].reg);
|
||||
void *p = ireg_data[ir_reg].p;
|
||||
|
||||
if (!reg_version_refcount[ir_reg][reg_set->regs[c].version] &&
|
||||
ireg_data[ir_reg].is_volatile)
|
||||
return;
|
||||
|
||||
switch (ireg_data[ir_reg].native_size)
|
||||
{
|
||||
case REG_BYTE:
|
||||
|
|
@ -520,7 +535,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
|
|||
// pclog(" already loaded %i\n", c);
|
||||
|
||||
reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]--;
|
||||
if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] < 0)
|
||||
if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == (uint8_t)-1)
|
||||
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
|
||||
|
||||
if (host_reg_idx)
|
||||
|
|
@ -541,6 +556,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
|
|||
|
||||
parent_reg.reg = IREG_GET_REG(ir_reg.reg) | IREG_SIZE_L;
|
||||
parent_reg.version = ir_reg.version - 1;
|
||||
reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1]++;
|
||||
|
||||
codegen_reg_alloc_read_reg(block, parent_reg, &c);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue