lightning
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/8] mips: Fill delay slots of JR opcodes in jit_jmpr


From: Paul Cercueil
Subject: [PATCH 2/8] mips: Fill delay slots of JR opcodes in jit_jmpr
Date: Sat, 7 Jan 2023 20:35:44 +0000

When we know that the last generated opcode is not the target of a jump,
and that it does not write the register used by the JR opcode, we can
swap it with the JR opcode, so that it now becomes the delay slot of the
JR opcode.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 lib/jit_mips-cpu.c | 101 ++++++++++++++++++++++++++++++++++++++++++---
 lib/jit_mips.c     |   6 ++-
 2 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/lib/jit_mips-cpu.c b/lib/jit_mips-cpu.c
index d73535a..5fd3007 100644
--- a/lib/jit_mips-cpu.c
+++ b/lib/jit_mips-cpu.c
@@ -52,6 +52,7 @@ typedef union {
     struct {   jit_uint32_t _:16;      jit_uint32_t b : 16; } is;
     struct {   jit_uint32_t _: 6;      jit_uint32_t b : 26; } ii;
 #endif
+    jit_uint32_t                       _op;
     int                                        op;
 } jit_instr_t;
 #if defined(_MIPS_ARCH_MIPS32R2) || defined(_MIPS_ARCH_MIPS64R2)
@@ -712,8 +713,8 @@ static jit_word_t 
_bgti_u(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
 static jit_word_t _bner(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
 #define bnei(i0,r0,i1)                 _bnei(_jit,i0,r0,i1)
 static jit_word_t _bnei(jit_state_t*,jit_word_t,jit_int32_t,jit_word_t);
-#  define jmpr(r0)                     _jmpr(_jit,r0)
-static void _jmpr(jit_state_t*,jit_int32_t);
+#  define jmpr(r0,no_flag)             _jmpr(_jit,r0,no_flag)
+static void _jmpr(jit_state_t*,jit_int32_t,jit_bool_t);
 #  define jmpi(i0)                     _jmpi(_jit,i0)
 static jit_word_t _jmpi(jit_state_t*,jit_word_t);
 #  define boaddr(i0,r0,r1)             _boaddr(_jit,i0,r0,r1)
@@ -777,6 +778,81 @@ static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
 #endif
 
 #if CODE
+static jit_bool_t has_delay_slot(jit_instr_t instr)
+{
+    switch (instr.hc.b) {
+       case MIPS_SPECIAL:
+               switch (instr.tc.b) {
+               case MIPS_JR:
+               case MIPS_JALR:
+                       return 1;
+               default:
+                       return 0;
+               }
+       case MIPS_J:                    case MIPS_JAL:
+       case MIPS_BLEZ:                 case MIPS_BLEZL:
+       case MIPS_BEQ:                  case MIPS_BEQL:
+       case MIPS_BGTZ:                 case MIPS_BGTZL:
+       case MIPS_BNE:                  case MIPS_BNEL:
+       case MIPS_REGIMM:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static jit_bool_t op_writes_register(jit_instr_t instr, jit_int32_t r0)
+{
+    if (r0 == _ZERO_REGNO)
+       return 0;
+
+    switch (instr.hc.b) {
+    case MIPS_SPECIAL:
+        switch (instr.tc.b) {
+        case MIPS_JR:
+        case MIPS_SYSCALL:
+        case MIPS_BREAK:
+        case MIPS_MULT:
+        case MIPS_MULTU:
+        case MIPS_DIV:
+        case MIPS_DIVU:
+        case MIPS_MTHI:
+        case MIPS_MTLO:
+            return 0;
+        default:
+            return r0 == instr.rd.b;
+        }
+    case MIPS_ADDI:
+    case MIPS_ADDIU:
+    case MIPS_SLTI:
+    case MIPS_SLTIU:
+    case MIPS_ANDI:
+    case MIPS_ORI:
+    case MIPS_XORI:
+    case MIPS_LUI:
+    case MIPS_LB:
+    case MIPS_LH:
+    case MIPS_LWL:
+    case MIPS_LW:
+    case MIPS_LBU:
+    case MIPS_LHU:
+    case MIPS_LWR:
+        return r0 == instr.rt.b;
+    case MIPS_JAL:
+        return r0 == 31;
+    case MIPS_REGIMM:
+        switch (instr.rt.b) {
+        case MIPS_BLTZAL:   case MIPS_BLTZALL:
+        case MIPS_BGEZAL:   case MIPS_BGEZALL:
+            return r0 == 31;
+        default:
+            return 0;
+        }
+    default:
+        return 0;
+    }
+}
+
 static void
 _hrrrit(jit_state_t *_jit,jit_int32_t hc,
        jit_int32_t rs, jit_int32_t rt, jit_int32_t rd,
@@ -2441,10 +2517,23 @@ _bnei(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, 
jit_word_t i1)
 }
 
 static void
-_jmpr(jit_state_t *_jit, jit_int32_t r0)
+_jmpr(jit_state_t *_jit, jit_int32_t r0, jit_bool_t no_flag)
 {
-    JR(r0);
-    NOP(1);
+    jit_int32_t                prev, offset;
+
+    offset = ((jit_word_t)_jit->pc.ui - (jit_word_t)_jit->code.ptr) / 
sizeof(jit_instr_t);
+
+    if (no_flag
+        && (offset < 2 || !has_delay_slot((jit_instr_t)*(_jit->pc.ui - 2)))
+        && !op_writes_register((jit_instr_t)*(_jit->pc.ui - 1), r0)) {
+        prev = *--_jit->pc.ui;
+
+        JR(r0);
+        ii(prev);
+    } else {
+        JR(r0);
+        NOP(1);
+    }
 }
 
 static jit_word_t
@@ -2461,7 +2550,7 @@ _jmpi(jit_state_t *_jit, jit_word_t i0)
     else {
        reg = jit_get_reg(jit_class_gpr|jit_class_nospill);
        movi_p(rn(reg), i0);
-       jmpr(rn(reg));
+       jmpr(rn(reg), 0);
        jit_unget_reg(reg);
     }
 
diff --git a/lib/jit_mips.c b/lib/jit_mips.c
index df18fbb..847bf15 100644
--- a/lib/jit_mips.c
+++ b/lib/jit_mips.c
@@ -1176,6 +1176,8 @@ _emit_code(jit_state_t *_jit)
     jit_word_t          word;
     jit_int32_t                 value;
     jit_int32_t                 offset;
+    jit_bool_t       no_flag = 0;      /* Set if previous instruction is
+                                        * *not* a jump target. */
     struct {
        jit_node_t      *node;
        jit_word_t       word;
@@ -1686,7 +1688,7 @@ _emit_code(jit_state_t *_jit)
                case_brr(bunord, _d);
                case_brf(bunord, _d, 64);
            case jit_code_jmpr:
-               jmpr(rn(node->u.w));
+               jmpr(rn(node->u.w), no_flag);
                break;
            case jit_code_jmpi:
                if (node->flag & jit_flag_node) {
@@ -1894,6 +1896,8 @@ _emit_code(jit_state_t *_jit)
        assert(_jitc->synth == 0);
        /* update register live state */
        jit_reglive(node);
+
+        no_flag = !(node->flag & jit_flag_patch);
     }
 #undef case_brf
 #undef case_brw
-- 
2.39.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]