From: Aleksey Demakov Date: Sat, 9 Jul 2011 18:18:42 +0000 (+0700) Subject: fix problem with shift opcodes on x86 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=d9951a093ab203d9ca9c97d5e99443182f806596;p=francis%2Flibjit.git fix problem with shift opcodes on x86 --- diff --git a/ChangeLog b/ChangeLog index 2d085f6..783ec23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-07-10 Aleksey Demakov + + * jit/jit-reg-alloc.c (choose_output_register, _jit_regs_assign): + fix handling of explicitely assigned registers. + + * jit/jit-rules-x86.c (shift_reg): remove function. + * jit/jit-rules-x86.ins (JIT_OP_ISHL, JIT_OP_ISHR, JIT_OP_ISHR_UN): + rewrite rules with explicit assignment to "ecx" register, don't use + shift_reg() function. + 2011-07-02 Aleksey Demakov * jit/jit-compile.c (compile_block): amend debug info diff --git a/jit/jit-reg-alloc.c b/jit/jit-reg-alloc.c index b7eeafe..b6a8cdf 100644 --- a/jit/jit-reg-alloc.c +++ b/jit/jit-reg-alloc.c @@ -1135,6 +1135,8 @@ static void choose_output_register(jit_gencode_t gen, _jit_regs_t *regs) { _jit_regclass_t *regclass; + int assigned_inreg1, assigned_inreg2; + int suitable_inreg1, suitable_inreg2; int reg_index, reg, other_reg; int use_cost; int suitable_reg, suitable_other_reg; @@ -1147,6 +1149,32 @@ choose_output_register(jit_gencode_t gen, _jit_regs_t *regs) regclass = regs->descs[0].regclass; + assigned_inreg1 = suitable_inreg1 = -1; + if(regs->descs[1].value) + { + if(regs->descs[1].reg >= 0) + { + assigned_inreg1 = suitable_inreg1 = regs->descs[1].reg; + } + else if (regs->descs[1].value->in_register) + { + suitable_inreg1 = regs->descs[1].value->reg; + } + } + + assigned_inreg2 = suitable_inreg2 = -1; + if(regs->descs[2].value) + { + if(regs->descs[2].reg >= 0) + { + assigned_inreg2 = suitable_inreg2 = regs->descs[2].reg; + } + else if (regs->descs[2].value->in_register) + { + suitable_inreg2 = regs->descs[2].value->reg; + } + } + suitable_reg = -1; suitable_other_reg = -1; suitable_cost = COST_TOO_MUCH; @@ -1228,32 +1256,26 @@ choose_output_register(jit_gencode_t gen, _jit_regs_t *regs) } if(regs->free_dest) { - if(regs->descs[0].early_clobber) + if(regs->descs[0].early_clobber + && (reg == suitable_inreg1 || reg == suitable_inreg2)) { - if(regs->descs[1].value - && regs->descs[1].value->in_register - && regs->descs[1].value->reg == reg) - { - continue; - } - if(regs->descs[2].value - && regs->descs[2].value->in_register - && regs->descs[2].value->reg == reg) - { - continue; - } + continue; } use_cost = 0; } - else if(regs->descs[1].value - && regs->descs[1].value->in_register - && regs->descs[1].value->reg == reg) + else if(reg == assigned_inreg1) + { + use_cost = 0; + } + else if(reg == assigned_inreg2) + { + continue; + } + else if(reg == suitable_inreg1) { use_cost = 0; } - else if(regs->descs[2].value - && regs->descs[2].value->in_register - && regs->descs[2].value->reg == reg) + else if(reg == suitable_inreg2) { if(regs->commutative) { @@ -2831,7 +2853,7 @@ _jit_regs_spill_all(jit_gencode_t gen) } #ifdef JIT_REG_DEBUG - printf("leave _jit_regs_spill_all\n"); + printf("leave _jit_regs_spill_all\n\n"); #endif } @@ -3343,16 +3365,30 @@ _jit_regs_assign(jit_gencode_t gen, _jit_regs_t *regs) printf("_jit_regs_assign()\n"); #endif - /* For binary or unary ops with explicitely assigned registers - the output always goes to the same register as the first input - value unless this is a three-address instruction. */ - if(!regs->ternary && !regs->free_dest - && regs->descs[0].value && regs->descs[0].reg < 0 - && regs->descs[1].value && regs->descs[1].reg >= 0) + /* Check explicitely assigned registers */ + if(regs->descs[2].value && regs->descs[2].reg >= 0) { - set_regdesc_register(gen, regs, 0, - regs->descs[1].reg, - regs->descs[1].other_reg); + check_duplicate_value(regs, ®s->descs[2], ®s->descs[1]); + if(regs->ternary) + { + check_duplicate_value(regs, ®s->descs[2], ®s->descs[0]); + } + } + if(regs->descs[1].value && regs->descs[1].reg >= 0) + { + if(regs->ternary) + { + check_duplicate_value(regs, ®s->descs[1], ®s->descs[0]); + } + else if(!regs->free_dest && regs->descs[0].value && regs->descs[0].reg < 0) + { + /* For binary or unary ops with explicitely assigned registers + the output always goes to the same register as the first input + value unless this is a three-address instruction. */ + set_regdesc_register(gen, regs, 0, + regs->descs[1].reg, + regs->descs[1].other_reg); + } } #if JIT_REG_STACK diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index 244e42a..eb9739e 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -1152,34 +1152,6 @@ void _jit_gen_fix_value(jit_value_t value) } } -/* - * Shift the contents of a register. - */ -static unsigned char *shift_reg(unsigned char *inst, int opc, int reg, int reg2) -{ - if(reg2 == X86_ECX) - { - /* The shift value is already in ECX */ - x86_shift_reg(inst, opc, reg); - } - else if(reg == X86_ECX) - { - /* The value to be shifted is in ECX, so swap the order */ - x86_xchg_reg_reg(inst, reg, reg2, 4); - x86_shift_reg(inst, opc, reg2); - x86_mov_reg_reg(inst, reg, reg2, 4); - } - else - { - /* Save ECX, perform the shift, and then restore ECX */ - x86_push_reg(inst, X86_ECX); - x86_mov_reg_reg(inst, X86_ECX, reg2, 4); - x86_shift_reg(inst, opc, reg); - x86_pop_reg(inst, X86_ECX); - } - return inst; -} - /* * Set a register value based on a condition code. */ diff --git a/jit/jit-rules-x86.ins b/jit/jit-rules-x86.ins index 7196198..326cbf9 100644 --- a/jit/jit-rules-x86.ins +++ b/jit/jit-rules-x86.ins @@ -1077,24 +1077,24 @@ JIT_OP_ISHL: [reg, imm] -> { x86_shift_reg_imm(inst, X86_SHL, $1, ($2 & 0x1F)); } - [reg, reg] -> { - inst = shift_reg(inst, X86_SHL, $1, $2); + [reg, reg("ecx")] -> { + x86_shift_reg(inst, X86_SHL, $1); } JIT_OP_ISHR: [reg, imm] -> { x86_shift_reg_imm(inst, X86_SAR, $1, ($2 & 0x1F)); } - [reg, reg] -> { - inst = shift_reg(inst, X86_SAR, $1, $2); + [reg, reg("ecx")] -> { + x86_shift_reg(inst, X86_SAR, $1); } JIT_OP_ISHR_UN: [reg, imm] -> { x86_shift_reg_imm(inst, X86_SHR, $1, ($2 & 0x1F)); } - [reg, reg] -> { - inst = shift_reg(inst, X86_SHR, $1, $2); + [reg, reg("ecx")] -> { + x86_shift_reg(inst, X86_SHR, $1); } JIT_OP_LAND: commutative