Optimise out redundant uOPs, where the output register is never read.

This commit is contained in:
SarahW 2019-02-10 12:32:25 +00:00
commit 3f2d9ecf87
4 changed files with 200 additions and 57 deletions

View file

@ -21,6 +21,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
int jump_target_at_end = -1;
int c;
codegen_reg_mark_as_required();
codegen_reg_process_dead_list(ir);
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
block_pos = 0;
codegen_backend_prologue(block);
@ -45,6 +47,9 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
}
}
if ((uop->type & UOP_MASK) == UOP_INVALID)
continue;
if (uop->type & UOP_TYPE_PARAMS_REGS)
{
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);

View file

@ -312,6 +312,8 @@
#define UOP_MAX 0xc6
#define UOP_INVALID 0xff
#define UOP_MASK 0xffff
typedef struct uop_t
@ -338,7 +340,7 @@ typedef struct ir_data_t
int wr_pos;
} ir_data_t;
static inline uop_t *uop_alloc(ir_data_t *ir)
static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type)
{
uop_t *uop;
@ -353,7 +355,10 @@ static inline uop_t *uop_alloc(ir_data_t *ir)
uop->src_reg_c = invalid_ir_reg;
uop->jump_list_next = -1;
if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))
codegen_reg_mark_as_required();
return uop;
}
@ -366,7 +371,7 @@ static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
@ -375,7 +380,7 @@ static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -385,7 +390,7 @@ static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg
static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -393,7 +398,7 @@ static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int ar
static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
@ -404,86 +409,86 @@ static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->p = p;
}
static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -494,7 +499,7 @@ static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -504,7 +509,7 @@ static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int sr
static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -514,7 +519,7 @@ static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_re
static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -525,7 +530,7 @@ static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int sr
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->imm_data = imm;
@ -533,7 +538,7 @@ static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
@ -541,7 +546,7 @@ static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
@ -550,7 +555,7 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -559,7 +564,7 @@ static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int
static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
@ -569,7 +574,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p)
{
uop_t *uop = uop_alloc(ir);
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);

View file

@ -4,8 +4,10 @@
#include "codegen_ir_defs.h"
#include "codegen_reg.h"
uint16_t reg_dead_list = 0;
uint8_t reg_last_version[IREG_COUNT];
uint8_t reg_version_refcount[IREG_COUNT][256];
reg_version_t reg_version[IREG_COUNT][256];
ir_reg_t invalid_ir_reg = {IREG_INVALID};
@ -175,6 +177,19 @@ struct
[IREG_temp1d] = {REG_DOUBLE, (void *)48, REG_FP, REG_VOLATILE},
};
void codegen_reg_mark_as_required()
{
int reg;
for (reg = 0; reg < IREG_COUNT; reg++)
{
int last_version = reg_last_version[reg];
if (last_version > 0 && ireg_data[reg].is_volatile == REG_PERMANENT)
reg_version[reg][last_version].flags |= REG_FLAGS_REQUIRED;
}
}
static int reg_is_native_size(ir_reg_t ir_reg)
{
int native_size = ireg_data[IREG_GET_REG(ir_reg.reg)].native_size;
@ -220,7 +235,7 @@ void codegen_reg_reset()
for (c = 0; c < IREG_COUNT; c++)
{
reg_last_version[c] = 0;
reg_version_refcount[c][0] = 0;
reg_version[c][0].refcount = 0;
}
for (c = 0; c < CODEGEN_HOST_REGS; c++)
{
@ -232,6 +247,8 @@ void codegen_reg_reset()
host_fp_reg_set.regs[c] = invalid_ir_reg;
host_fp_reg_set.dirty[c] = 0;
}
reg_dead_list = 0;
}
static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
@ -239,9 +256,9 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID);
}
static inline int ir_get_get_refcount(ir_reg_t ir_reg)
static inline int ir_get_refcount(ir_reg_t ir_reg)
{
return reg_version_refcount[IREG_GET_REG(ir_reg.reg)][ir_reg.version];
return reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version].refcount;
}
static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg)
@ -342,7 +359,7 @@ 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] &&
if (!reg_version[ir_reg][reg_set->regs[c].version].refcount &&
ireg_data[ir_reg].is_volatile)
return;
@ -463,10 +480,30 @@ static void alloc_dest_reg(ir_reg_t ir_reg, int dest_reference)
{
if (IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (reg_set->regs[c].version == ir_reg.version || (reg_set->regs[c].version == (ir_reg.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference))
if (reg_set->regs[c].version == ir_reg.version)
{
reg_set->locked |= (1 << c);
}
else
{
/*The immediate prior version may have been
optimised out, so search backwards to find the
last valid version*/
int prev_version = ir_reg.version-1;
// pclog("prev_version search from %i\n", prev_version);
while (prev_version >= 0)
{
reg_version_t *regv = &reg_version[IREG_GET_REG(reg_set->regs[c].reg)][prev_version];
if (!(regv->flags & REG_FLAGS_DEAD) && regv->refcount == dest_reference)
{
reg_set->locked |= (1 << c);
return;
}
prev_version--;
}
fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, ir_reg.version, dest_reference);
}
return;
}
}
@ -513,7 +550,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version)
break;
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version])
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version <= ir_reg.version)
{
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount++;
break;
}
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount)
fatal("codegen_reg_alloc_read_reg - version mismatch!\n");
}
@ -522,7 +565,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
/*No unused registers. Search for an unlocked register with no pending reads*/
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(reg_set->locked & (1 << c)) && !ir_get_get_refcount(reg_set->regs[c]))
if (!(reg_set->locked & (1 << c)) && IREG_GET_REG(reg_set->regs[c].reg) != IREG_INVALID && !ir_get_refcount(reg_set->regs[c]))
break;
}
if (c == reg_set->nr_regs)
@ -548,13 +591,13 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
// else
// 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] == (uint8_t)-1)
reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount--;
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount == (uint8_t)-1)
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
if (host_reg_idx)
*host_reg_idx = c;
// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c);
// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], reg_set->regs[c].reg,reg_set->regs[c].version, c);
return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
}
@ -570,11 +613,11 @@ 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]++;
reg_version[IREG_GET_REG(ir_reg.reg)][ir_reg.version - 1].refcount++;
codegen_reg_alloc_read_reg(block, parent_reg, &c);
if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version != ir_reg.version-1)
if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version > ir_reg.version-1)
fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c,
reg_set->regs[c].reg,reg_set->regs[c].version,
ir_reg.reg,ir_reg.version);
@ -591,9 +634,9 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (reg_set->regs[c].version == ir_reg.version-1)
if (reg_set->regs[c].version <= ir_reg.version-1)
{
if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] != 0)
if (reg_version[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version].refcount != 0)
fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n");
break;
}
@ -682,3 +725,49 @@ void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block)
reg_set->dirty[c] = 0;
}
}
/*Process dead register list, and optimise out register versions and uOPs where
possible*/
void codegen_reg_process_dead_list(ir_data_t *ir)
{
while (reg_dead_list)
{
int version = reg_dead_list & 0xff;
int reg = reg_dead_list >> 8;
reg_version_t *regv = &reg_version[reg][version];
uop_t *uop = &ir->uops[regv->parent_uop];
/*Barrier uOPs should be preserved*/
if (!(uop->type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER)))
{
// pclog(" codegen_process_dead_list: reg=%i version=%i uop=%i\n", reg, version, regv->parent_uop);
uop->type = UOP_INVALID;
/*Adjust refcounts on source registers. If these drop to
zero then those registers can be considered for removal*/
if (uop->src_reg_a.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_a.reg)][uop->src_reg_a.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_a.reg), uop->src_reg_a.version);
}
if (uop->src_reg_b.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_b.reg)][uop->src_reg_b.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_b.reg), uop->src_reg_b.version);
}
if (uop->src_reg_c.reg != IREG_INVALID)
{
reg_version_t *src_regv = &reg_version[IREG_GET_REG(uop->src_reg_c.reg)][uop->src_reg_c.version];
src_regv->refcount--;
if (!src_regv->refcount)
add_to_dead_list(src_regv, IREG_GET_REG(uop->src_reg_c.reg), uop->src_reg_c.version);
}
regv->flags |= REG_FLAGS_DEAD;
}
reg_dead_list = regv->next;
}
}

View file

@ -272,7 +272,36 @@ static inline int ireg_seg_limit_high(x86seg *seg)
}
extern uint8_t reg_last_version[IREG_COUNT];
extern uint8_t reg_version_refcount[IREG_COUNT][256];
/*This version of the register must be calculated, regardless of whether it is
apparently required or not. Do not optimise out.*/
#define REG_FLAGS_REQUIRED (1 << 0)
/*This register and the parent uOP have been optimised out.*/
#define REG_FLAGS_DEAD (1 << 1)
typedef struct
{
/*Refcount of pending reads on this register version*/
uint8_t refcount;
/*Flags*/
uint8_t flags;
/*uOP that generated this register version*/
uint16_t parent_uop;
/*Pointer to next register version in dead register list*/
uint16_t next;
} reg_version_t;
extern reg_version_t reg_version[IREG_COUNT][256];
/*Head of dead register list; a list of register versions that are not used and
can be optimised out*/
extern uint16_t reg_dead_list;
static inline void add_to_dead_list(reg_version_t *regv, int reg, int version)
{
regv->next = reg_dead_list;
reg_dead_list = version | (reg << 8);
}
typedef struct
{
@ -289,37 +318,50 @@ typedef uint16_t ir_host_reg_t;
static inline ir_reg_t codegen_reg_read(int reg)
{
ir_reg_t ireg;
reg_version_t *version;
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_read - IREG_INVALID\n");
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)];
reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]++;
if (!reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version])
version = &reg_version[IREG_GET_REG(ireg.reg)][ireg.version];
version->flags = 0;
version->refcount++;
if (!version->refcount)
fatal("codegen_reg_read - refcount overflow\n");
else if (reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version] > REG_VERSION_MAX)
else if (version->refcount > REG_VERSION_MAX)
CPU_BLOCK_END();
// pclog("codegen_reg_read: %i %i %i\n", reg & IREG_REG_MASK, ireg.version, reg_version_refcount[IREG_GET_REG(ireg.reg)][ireg.version]);
return ireg;
}
static inline ir_reg_t codegen_reg_write(int reg)
static inline ir_reg_t codegen_reg_write(int reg, int uop_nr)
{
ir_reg_t ireg;
int last_version = reg_last_version[IREG_GET_REG(reg)];
reg_version_t *version;
if (IREG_GET_REG(reg) == IREG_INVALID)
fatal("codegen_reg_write - IREG_INVALID\n");
ireg.reg = reg;
ireg.version = reg_last_version[IREG_GET_REG(reg)] + 1;
ireg.version = last_version + 1;
if (IREG_GET_REG(reg) > IREG_EBX && last_version && !reg_version[IREG_GET_REG(reg)][last_version].refcount &&
!(reg_version[IREG_GET_REG(reg)][last_version].flags & REG_FLAGS_REQUIRED))
add_to_dead_list(&reg_version[IREG_GET_REG(reg)][last_version], IREG_GET_REG(reg), last_version);
reg_last_version[IREG_GET_REG(reg)]++;
if (!reg_last_version[IREG_GET_REG(reg)])
fatal("codegen_reg_write - version overflow\n");
else if (reg_last_version[IREG_GET_REG(reg)] > REG_VERSION_MAX)
CPU_BLOCK_END();
reg_version_refcount[IREG_GET_REG(reg)][ireg.version] = 0;
version = &reg_version[IREG_GET_REG(reg)][ireg.version];
version->refcount = 0;
version->flags = 0;
version->parent_uop = uop_nr;
// pclog("codegen_reg_write: %i\n", reg & IREG_REG_MASK);
return ireg;
}
@ -337,4 +379,6 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx);
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg);
void codegen_reg_mark_as_required();
void codegen_reg_process_dead_list(struct ir_data_t *ir);
#endif