[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
- [PATCH 0/8] mips: Fill delay slots, Paul Cercueil, 2023/01/07
- [PATCH 1/8] mips: Optimize jit_eqr / jit_eqi, Paul Cercueil, 2023/01/07
- [PATCH 2/8] mips: Fill delay slots of JR opcodes in jit_jmpr,
Paul Cercueil <=
- [PATCH 3/8] mips: Fill delay slots of JALR opcodes in jit_callr, Paul Cercueil, 2023/01/07
- [PATCH 4/8] mips: Fill delay slots of J in jit_jmpi, Paul Cercueil, 2023/01/07
- [PATCH 5/8] mips: Fill delay slots in jit_beqr / jit_beqi, Paul Cercueil, 2023/01/07
- [PATCH 6/8] mips: Fill delay slots in jit_bner / jit_bnei, Paul Cercueil, 2023/01/07
- [PATCH 7/8] mips: Fill delay slots in jit_bgtr, jit_bgti, jit_bler, jit_blei, Paul Cercueil, 2023/01/07
- [PATCH 8/8] mips: Fill delay slots in jit_bger, jit_bgei, jit_bltr, jit_blti, Paul Cercueil, 2023/01/07