]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
fix problem with shift opcodes on x86
authorAleksey Demakov <ademakov@gmail.com>
Sat, 9 Jul 2011 18:18:42 +0000 (01:18 +0700)
committerAleksey Demakov <ademakov@gmail.com>
Sat, 9 Jul 2011 18:18:42 +0000 (01:18 +0700)
ChangeLog
jit/jit-reg-alloc.c
jit/jit-rules-x86.c
jit/jit-rules-x86.ins

index 2d085f6dabe77c04b7a51c3a294c495a2d98eef3..783ec23b65ec6dc12752ef99e1468fcc1afd7bb9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-07-10  Aleksey Demakov  <ademakov@gmail.com>
+
+       * 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  <ademakov@gmail.com>
 
        * jit/jit-compile.c (compile_block): amend debug info
index b7eeafe84a68654cf44ea7c4288cc0131ee205cc..b6a8cdfc70cfa8a7a909b9e05cab21beb49e417f 100644 (file)
@@ -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, &regs->descs[2], &regs->descs[1]);
+               if(regs->ternary)
+               {
+                       check_duplicate_value(regs, &regs->descs[2], &regs->descs[0]);
+               }
+       }
+       if(regs->descs[1].value && regs->descs[1].reg >= 0)
+       {
+               if(regs->ternary)
+               {
+                       check_duplicate_value(regs, &regs->descs[1], &regs->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
index 244e42a67d34b39d7e0114f4472af3dc0cf6f7b4..eb9739e0fc4dec5287855bd5fdc760cd5ff29dc0 100644 (file)
@@ -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.
  */
index 7196198116372ae92816944915866dc4ebb0816f..326cbf9067482bdb2a3b047d51efed5e229643a8 100644 (file)
@@ -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