guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 02/02: Fuse comparisons and branches in JIT


From: Andy Wingo
Subject: [Guile-commits] 02/02: Fuse comparisons and branches in JIT
Date: Sat, 25 Aug 2018 10:25:00 -0400 (EDT)

wingo pushed a commit to branch lightning
in repository guile.

commit 18dfe48fc46ec488b1f6a1c51b53feebb6b40b22
Author: Andy Wingo <address@hidden>
Date:   Sat Aug 25 16:20:49 2018 +0200

    Fuse comparisons and branches in JIT
    
    * libguile/jit.c (emit_load_compare_result)
      (emit_store_compare_result): Remove these.
      (emit_branch_if_frame_locals_count_not_eq): New helper.
      (fuse_conditional_branch): New helper.
    * libguile/jit.c (compile_u64_numerically_equal)
      (compile_u64_less, compile_s64_less, compile_f64_numerically_equal)
      (compile_f64_less, compile_numerically_equal, compile_less)
      (compile_check_arguments, compile_check_positional_arguments):
      (compile_immediate_tag_equals, compile_heap_tag_equals)
      (compile_eq, compile_heap_numbers_equal)
      (compile_s64_imm_numerically_equal, compile_u64_imm_less)
      (compile_imm_u64_less, compile_s64_imm_less, compile_imm_s64_less):
      Fuse conditional branches, to avoid going through compare-result.
      (compile_jl, compile_je, compile_jnl, compile_jne, compile_jge)
      (compile_jnge): Abort, since they shouldn't be reachable.
---
 libguile/jit.c | 703 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 475 insertions(+), 228 deletions(-)

diff --git a/libguile/jit.c b/libguile/jit.c
index ac923e3..0ab31cc 100644
--- a/libguile/jit.c
+++ b/libguile/jit.c
@@ -191,7 +191,6 @@ DEFINE_THREAD_OFFSET (block_asyncs);
 DEFINE_THREAD_VP_OFFSET (fp);
 DEFINE_THREAD_VP_OFFSET (sp);
 DEFINE_THREAD_VP_OFFSET (ip);
-DEFINE_THREAD_VP_OFFSET (compare_result);
 DEFINE_THREAD_VP_OFFSET (sp_min_since_gc);
 DEFINE_THREAD_VP_OFFSET (stack_limit);
 DEFINE_THREAD_VP_OFFSET (trace_level);
@@ -334,18 +333,6 @@ emit_store_current_ip (scm_jit_state *j, jit_gpr_t t)
 }
 
 static void
-emit_load_compare_result (scm_jit_state *j, jit_gpr_t dst)
-{
-  jit_ldxi_uc (dst, THREAD, thread_offset_compare_result);
-}
-
-static void
-emit_store_compare_result (scm_jit_state *j, jit_gpr_t src)
-{
-  jit_stxi_c (thread_offset_compare_result, THREAD, src);
-}
-
-static void
 emit_reset_frame (scm_jit_state *j, jit_gpr_t fp, uint32_t nlocals)
 {
   emit_subtract_stack_slots (j, SP, fp, nlocals);
@@ -799,6 +786,14 @@ emit_branch_if_frame_locals_count_eq (scm_jit_state *j, 
jit_gpr_t fp,
 }
 
 static jit_node_t*
+emit_branch_if_frame_locals_count_not_eq (scm_jit_state *j, jit_gpr_t fp,
+                                          jit_gpr_t t, uint32_t nlocals)
+{
+  jit_subr (t, fp, SP);
+  return jit_bnei (t, nlocals * sizeof (union scm_vm_stack_element));
+}
+
+static jit_node_t*
 emit_branch_if_frame_locals_count_greater_than (scm_jit_state *j, jit_gpr_t fp,
                                                 jit_gpr_t t, uint32_t nlocals)
 {
@@ -2433,59 +2428,115 @@ compile_return_from_interrupt (scm_jit_state *j)
   emit_exit (j);
 }
 
+static enum scm_opcode
+fuse_conditional_branch (scm_jit_state *j, uint32_t **target)
+{
+  uint8_t next = j->next_ip[0] & 0xff;
+
+  switch (next)
+    {
+    case scm_op_jl:
+    case scm_op_je:
+    case scm_op_jnl:
+    case scm_op_jne:
+    case scm_op_jge:
+    case scm_op_jnge:
+      *target = j->next_ip + (((int32_t) j->next_ip[0]) >> 8);
+      j->next_ip += op_lengths[next];
+      return next;
+    default:
+      abort ();
+    }
+}
+
 static void
 compile_u64_numerically_equal (scm_jit_state *j, uint16_t a, uint16_t b)
 {
+  uint32_t *target;
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
   emit_sp_ref_u64 (j, T0, a);
   emit_sp_ref_u64 (j, T1, b);
-  k = jit_bner (T0, T1);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_beqr (T0, T1);
+      break;
+    case scm_op_jne:
+      k = jit_bner (T0, T1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
-  jit_node_t *k1, *k2, *k3;
+  jit_node_t *k1, *k2;
   emit_sp_ref_u64 (j, T0, T1, a);
   emit_sp_ref_u64 (j, T2, T3, b);
-  k1 = jit_bner (T0, T2);
-  k2 = jit_bner (T1, T3);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  k3 = jit_jmpi ();
-  jit_patch (k1);
-  jit_patch (k2);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k1 = jit_bner (T0, T2);
+      k2 = jit_beqr (T1, T3);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    case scm_op_jne:
+      k1 = jit_bner (T0, T2);
+      k2 = jit_bner (T1, T3);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
 compile_u64_less (scm_jit_state *j, uint16_t a, uint16_t b)
 {
+  uint32_t *target;
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
   emit_sp_ref_u64 (j, T0, a);
   emit_sp_ref_u64 (j, T1, b);
-  k = jit_bger_u (T0, T1);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_bltr_u (T0, T1);
+      break;
+    case scm_op_jnl:
+      k = jit_bger_u (T0, T1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
-  jit_node_t *k1, *k2, *less, *k3;
+  jit_node_t *k1, *k2, *k3;
   emit_sp_ref_u64 (j, T0, T1, a);
   emit_sp_ref_u64 (j, T2, T3, b);
-  less = jit_bltr_u (T1, T3);
-  k1 = jit_bner (T1, T3);
-  k2 = jit_bger_u (T0, T2);
-  jit_patch (less);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  k3 = jit_jmpi ();
-  jit_patch (k1);
-  jit_patch (k2);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k3);
+  k1 = jit_bltr_u (T1, T3);
+  k2 = jit_bner (T1, T3);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k3 = jit_bltr_u (T0, T2);
+      jit_patch (k2);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    case scm_op_jnl:
+      k3 = jit_bger_u (T0, T2);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
@@ -2497,152 +2548,216 @@ compile_s64_numerically_equal (scm_jit_state *j, 
uint16_t a, uint16_t b)
 static void
 compile_s64_less (scm_jit_state *j, uint16_t a, uint16_t b)
 {
+  uint32_t *target;
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  emit_sp_ref_u64 (j, T0, a);
-  emit_sp_ref_u64 (j, T1, b);
-  k = jit_bger (T0, T1);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k);
+  emit_sp_ref_s64 (j, T0, a);
+  emit_sp_ref_s64 (j, T1, b);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_bltr (T0, T1);
+      break;
+    case scm_op_jnl:
+      k = jit_bger (T0, T1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
-  jit_node_t *k1, *k2, *less, *k3;
-  emit_sp_ref_u64 (j, T0, T1, a);
-  emit_sp_ref_u64 (j, T2, T3, b);
-  less = jit_bltr (T1, T3);
-  k1 = jit_bner (T1, T3);
-  k2 = jit_bger (T0, T2);
-  jit_patch (less);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  k3 = jit_jmpi ();
-  jit_patch (k1);
-  jit_patch (k2);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k3);
+  jit_node_t *k1, *k2, *k3;
+  emit_sp_ref_s64 (j, T0, T1, a);
+  emit_sp_ref_s64 (j, T2, T3, b);
+  k1 = jit_bltr (T1, T3);
+  k2 = jit_bner (T1, T3);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k3 = jit_bltr (T0, T2);
+      jit_patch (k2);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    case scm_op_jnl:
+      k3 = jit_bger (T0, T2);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
 compile_f64_numerically_equal (scm_jit_state *j, uint16_t a, uint16_t b)
 {
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
+  uint32_t *target;
+
   emit_sp_ref_f64 (j, JIT_F0, a);
   emit_sp_ref_f64 (j, JIT_F1, b);
-  k = jit_beqr_d (JIT_F0, JIT_F1);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_beqr_d (JIT_F0, JIT_F1);
+      break;
+    case scm_op_jne:
+      k = jit_bner_d (JIT_F0, JIT_F1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_f64_less (scm_jit_state *j, uint16_t a, uint16_t b)
 {
-  jit_node_t *less, *ge, *k1, *k2;
+  jit_node_t *k;
+  uint32_t *target;
+
   emit_sp_ref_f64 (j, JIT_F0, a);
   emit_sp_ref_f64 (j, JIT_F1, b);
-  less = jit_bltr_d (JIT_F0, JIT_F1);
-  ge = jit_bger_d (JIT_F0, JIT_F1);
-  jit_movi (T2, SCM_F_COMPARE_INVALID);
-  k1 = jit_jmpi ();
-  jit_patch (ge);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  k2 = jit_jmpi ();
-  jit_patch (less);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k1);
-  jit_patch (k2);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_bltr_d (JIT_F0, JIT_F1);
+      break;
+    case scm_op_jnl:
+      k = jit_bunger_d (JIT_F0, JIT_F1);
+      break;
+    case scm_op_jge:
+      k = jit_bger_d (JIT_F0, JIT_F1);
+      break;
+    case scm_op_jnge:
+      k = jit_bunltr_d (JIT_F0, JIT_F1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_numerically_equal (scm_jit_state *j, uint16_t a, uint16_t b)
 {
   jit_node_t *k;
+  uint32_t *target;
+
   emit_store_current_ip (j, T0);
   emit_sp_ref_scm (j, T0, a);
   emit_sp_ref_scm (j, T1, b);
   emit_call_r_r (j, scm_vm_intrinsics.numerically_equal_p, T0, T1);
   jit_retval (T0);
   emit_reload_sp (j);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  k = jit_bnei (T0, 0);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_bnei (T0, 0);
+      break;
+    case scm_op_jne:
+      k = jit_beqi (T0, 0);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_less (scm_jit_state *j, uint16_t a, uint16_t b)
 {
+  jit_node_t *k;
+  uint32_t *target;
+
   emit_store_current_ip (j, T0);
   emit_sp_ref_scm (j, T0, a);
   emit_sp_ref_scm (j, T1, b);
   emit_call_r_r (j, scm_vm_intrinsics.less_p, T0, T1);
-  jit_retval (T2);
+  jit_retval (T0);
   emit_reload_sp (j);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_beqi (T0, SCM_F_COMPARE_LESS_THAN);
+      break;
+    case scm_op_jnl:
+      k = jit_bnei (T0, SCM_F_COMPARE_LESS_THAN);
+      break;
+    case scm_op_jge:
+      k = jit_beqi (T0, SCM_F_COMPARE_NONE);
+      break;
+    case scm_op_jnge:
+      k = jit_bnei (T0, SCM_F_COMPARE_NONE);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_check_arguments (scm_jit_state *j, uint32_t expected)
 {
-  jit_node_t *eq;
-  jit_gpr_t fp = T0, t = T1, res = T2;
+  jit_node_t *k;
+  uint32_t *target;
+  jit_gpr_t fp = T0, t = T1;
   
   emit_load_fp (j, fp);
-  jit_movi (res, SCM_F_COMPARE_EQUAL);
-  eq = emit_branch_if_frame_locals_count_eq (j, fp, t, expected);
-  if (expected > 0)
+  switch (fuse_conditional_branch (j, &target))
     {
-      jit_node_t *k2, *ge;
-      ge = emit_branch_if_frame_locals_count_greater_than (j, fp, t, 
expected-1);
-      jit_movi (res, SCM_F_COMPARE_LESS_THAN);
-      k2 = jit_jmpi ();
-      jit_patch (ge);
-      jit_movi (res, SCM_F_COMPARE_NONE);
-      jit_patch (k2);
+    case scm_op_jne:
+      k = emit_branch_if_frame_locals_count_not_eq (j, fp, t, expected);
+      break;
+    case scm_op_jl:
+      k = emit_branch_if_frame_locals_count_less_than (j, fp, t, expected);
+      break;
+    case scm_op_jge:
+      if (expected == 0)
+        k = jit_jmpi (); /* Shouldn't happen.  */
+      else
+        k = emit_branch_if_frame_locals_count_greater_than (j, fp, t, expected 
- 1);
+      break;
+    default:
+      abort ();
     }
-  else
-    jit_movi (res, SCM_F_COMPARE_NONE);
-  jit_patch (eq);
-  emit_store_compare_result (j, T2);
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_check_positional_arguments (scm_jit_state *j, uint32_t nreq, uint32_t 
expected)
 {
-  jit_node_t *k, *head, *lt, *eq, *done1, *done2;
-  jit_gpr_t walk = T0, npos = T1, obj = T2, t = T3, res = T0;
+  uint32_t *target;
+  jit_node_t *lt, *ge, *head;
+  jit_gpr_t walk = T0, min = T1, obj = T2, t = T3;
+
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jge:
+      /* Break to target if npos >= expected.  */
+      break;
+    default:
+      abort ();
+    }
 
   emit_load_fp (j, walk);
-  if (nreq == 0) abort ();
-  emit_subtract_stack_slots (j, walk, walk, nreq-1);
-  jit_movi (npos, nreq - 1);
+  emit_subtract_stack_slots (j, min, walk, expected);
+  emit_subtract_stack_slots (j, walk, walk, nreq);
   
   head = jit_label ();
-  jit_addi (npos, npos, 1);
   emit_subtract_stack_slots (j, walk, walk, 1);
-  k = jit_beqr (walk, SP);
+  lt = jit_bltr (walk, SP);
+  /* npos >= expected if walk <= min.  */
+  ge = jit_bler (walk, min);
   jit_ldr (obj, walk);
   jit_patch_at (emit_branch_if_immediate (j, obj), head);
   jit_patch_at (emit_branch_if_heap_object_not_tc7 (j, obj, t, 
scm_tc7_keyword),
                 head);
-  jit_patch (k);
-
-  lt = jit_blti (npos, expected);
-  eq = jit_beqi (npos, expected);
-  jit_movi (res, SCM_F_COMPARE_NONE);
-  done1 = jit_jmpi ();
   jit_patch (lt);
-  jit_movi (res, SCM_F_COMPARE_LESS_THAN);
-  done2 = jit_jmpi ();
-  jit_patch (eq);
-  jit_movi (res, SCM_F_COMPARE_EQUAL);
-  jit_patch (done1);
-  jit_patch (done2);
-  jit_stxi (thread_offset_compare_result, THREAD, res);
+  add_inter_instruction_patch (j, ge, target);
 }
 
 static void
@@ -2650,13 +2765,22 @@ compile_immediate_tag_equals (scm_jit_state *j, 
uint32_t a, uint16_t mask,
                               uint16_t expected)
 {
   jit_node_t *k;
+  uint32_t *target;
+
   emit_sp_ref_scm (j, T0, a);
   jit_andi (T0, T0, mask);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  k = jit_beqi (T0, expected);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_beqi (T0, expected);
+      break;
+    case scm_op_jne:
+      k = jit_bnei (T0, expected);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
@@ -2664,25 +2788,43 @@ compile_heap_tag_equals (scm_jit_state *j, uint32_t obj,
                          uint16_t mask, uint16_t expected)
 {
   jit_node_t *k;
+  uint32_t *target;
+
   emit_sp_ref_scm (j, T0, obj);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  k = emit_branch_if_heap_object_has_tc (j, T0, T0, mask, expected);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = emit_branch_if_heap_object_has_tc (j, T0, T0, mask, expected);
+      break;
+    case scm_op_jne:
+      k = emit_branch_if_heap_object_not_tc (j, T0, T0, mask, expected);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
 compile_eq (scm_jit_state *j, uint16_t a, uint16_t b)
 {
   jit_node_t *k;
+  uint32_t *target;
+
   emit_sp_ref_scm (j, T0, a);
   emit_sp_ref_scm (j, T1, b);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  k = jit_beqi (T0, T1);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_beqi (T0, T1);
+      break;
+    case scm_op_jne:
+      k = jit_bnei (T0, T1);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
@@ -2696,72 +2838,63 @@ compile_j (scm_jit_state *j, const uint32_t *vcode)
 static void
 compile_jl (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_beqi (T0, SCM_F_COMPARE_LESS_THAN);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_je (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_beqi (T0, SCM_F_COMPARE_EQUAL);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_jnl (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_bnei (T0, SCM_F_COMPARE_LESS_THAN);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_jne (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_bnei (T0, SCM_F_COMPARE_EQUAL);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_jge (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_beqi (T0, SCM_F_COMPARE_NONE);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_jnge (scm_jit_state *j, const uint32_t *vcode)
 {
-  jit_node_t *jmp;
-  emit_load_compare_result (j, T0);
-  jmp = jit_bnei (T0, SCM_F_COMPARE_NONE);
-  add_inter_instruction_patch (j, jmp, vcode);
+  abort (); /* All tests should fuse their following branches.  */
 }
 
 static void
 compile_heap_numbers_equal (scm_jit_state *j, uint16_t a, uint16_t b)
 {
   jit_node_t *k;
+  uint32_t *target;
+
   emit_store_current_ip (j, T0);
   emit_sp_ref_scm (j, T0, a);
   emit_sp_ref_scm (j, T1, b);
   emit_call_r_r (j, scm_vm_intrinsics.heap_numbers_equal_p, T0, T1);
   jit_retval (T0);
   emit_reload_sp (j);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  k = jit_bnei (T0, 0);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  jit_patch (k);
-  emit_store_compare_result (j, T2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_bnei (T0, 0);
+      break;
+    case scm_op_jne:
+      k = jit_beqi (T0, 0);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 }
 
 static void
@@ -2871,22 +3004,44 @@ compile_s64_imm_numerically_equal (scm_jit_state *j, 
uint16_t a, int16_t b)
 {
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  emit_sp_ref_u64 (j, T0, a);
-  k = jit_bnei (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  jit_patch (k);
+  uint32_t *target;
+
+  emit_sp_ref_s64 (j, T0, a);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k = jit_beqi (T0, b);
+      break;
+    case scm_op_jne:
+      k = jit_bnei (T0, b);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
   jit_node_t *k1, *k2;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  emit_sp_ref_u64 (j, T0, T1, a);
-  k1 = jit_bnei (T0, b);
-  k2 = jit_bnei (T1, b < 0 ? -1 : 0);
-  jit_movi (T2, SCM_F_COMPARE_EQUAL);
-  jit_patch (k1);
-  jit_patch (k2);
+  uint32_t *target;
+
+  emit_sp_ref_s64 (j, T0, T1, a);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_je:
+      k1 = jit_bnei (T0, b);
+      k2 = jit_beqi (T1, b < 0 ? -1 : 0);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    case scm_op_jne:
+      k1 = jit_bnei (T0, b);
+      k2 = jit_bnei (T1, b < 0 ? -1 : 0);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
@@ -2894,22 +3049,44 @@ compile_u64_imm_less (scm_jit_state *j, uint16_t a, 
uint16_t b)
 {
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  uint32_t *target;
+
   emit_sp_ref_u64 (j, T0, a);
-  k = jit_bgei_u (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_blti_u (T0, b);
+      break;
+    case scm_op_jnl:
+      k = jit_bgei_u (T0, b);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
   jit_node_t *k1, *k2;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  uint32_t *target;
+
   emit_sp_ref_u64 (j, T0, T1, a);
-  k1 = jit_bgei_u (T0, b);
-  k2 = jit_bnei (T1, 0);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k1);
-  jit_patch (k2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k1 = jit_bnei (T1, 0);
+      k2 = jit_blti_u (T0, b);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    case scm_op_jnl:
+      k1 = jit_bgti (T1, 0);
+      k2 = jit_bgei_u (T0, b);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
@@ -2917,22 +3094,44 @@ compile_imm_u64_less (scm_jit_state *j, uint16_t a, 
uint16_t b)
 {
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
+  uint32_t *target;
+
   emit_sp_ref_u64 (j, T0, a);
-  k = jit_bgti_u (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_bgti_u (T0, b);
+      break;
+    case scm_op_jnl:
+      k = jit_blei_u (T0, b);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
   jit_node_t *k1, *k2;
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
+  uint32_t *target;
+
   emit_sp_ref_u64 (j, T0, T1, a);
-  k1 = jit_bnei (T1, 0);
-  k2 = jit_bgti_u (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k1);
-  jit_patch (k2);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k1 = jit_bnei (T1, 0);
+      k2 = jit_bgti_u (T0, b);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    case scm_op_jnl:
+      k1 = jit_bnei (T1, 0);
+      k2 = jit_blei_u (T0, b);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
@@ -2940,25 +3139,49 @@ compile_s64_imm_less (scm_jit_state *j, uint16_t a, 
int16_t b)
 {
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  uint32_t *target;
+
   emit_sp_ref_s64 (j, T0, a);
-  k = jit_bgei (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_blti (T0, b);
+      break;
+    case scm_op_jnl:
+      k = jit_bgei (T0, b);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
   jit_node_t *k1, *k2, *k3;
   int32_t sign = b < 0 ? -1 : 0;
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
+  uint32_t *target;
+
   emit_sp_ref_s64 (j, T0, T1, a);
-  k1 = jit_blti (T1, sign);
-  k2 = jit_bnei (T1, sign);
-  k3 = jit_blti (T0, b);
-  jit_patch (k2);
-  jit_movi (T2, SCM_F_COMPARE_NONE);
-  jit_patch (k1);
-  jit_patch (k3);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k1 = jit_blti (T1, sign);
+      k2 = jit_bnei (T1, sign);
+      k3 = jit_blti (T0, b);
+      jit_patch (k2);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    case scm_op_jnl:
+      k1 = jit_bgti (T1, sign);
+      k2 = jit_bnei (T1, sign);
+      k3 = jit_bgei (T0, b);
+      jit_patch (k2);
+      add_inter_instruction_patch (j, k1, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void
@@ -2966,25 +3189,49 @@ compile_imm_s64_less (scm_jit_state *j, uint16_t a, 
int16_t b)
 {
 #if SIZEOF_UINTPTR_T >= 8
   jit_node_t *k;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  uint32_t *target;
+
   emit_sp_ref_s64 (j, T0, a);
-  k = jit_blei (T0, b);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k = jit_bgti (T0, b);
+      break;
+    case scm_op_jnl:
+      k = jit_blei (T0, b);
+      break;
+    default:
+      abort ();
+    }
+  add_inter_instruction_patch (j, k, target);
 #else
   jit_node_t *k1, *k2, *k3;
   int32_t sign = b < 0 ? -1 : 0;
-  jit_movi (T2, SCM_F_COMPARE_NONE);
+  uint32_t *target;
+
   emit_sp_ref_s64 (j, T0, T1, a);
-  k1 = jit_blti (T1, sign);
-  k2 = jit_bnei (T1, sign);
-  k3 = jit_blei (T0, b);
-  jit_patch (k2);
-  jit_movi (T2, SCM_F_COMPARE_LESS_THAN);
-  jit_patch (k1);
-  jit_patch (k3);
+  switch (fuse_conditional_branch (j, &target))
+    {
+    case scm_op_jl:
+      k1 = jit_blti (T1, sign);
+      k2 = jit_bnei (T1, sign);
+      k3 = jit_bgti (T0, b);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    case scm_op_jnl:
+      k1 = jit_bgti (T1, sign);
+      k2 = jit_bnei (T1, sign);
+      k3 = jit_blei (T0, b);
+      jit_patch (k1);
+      add_inter_instruction_patch (j, k2, target);
+      add_inter_instruction_patch (j, k3, target);
+      break;
+    default:
+      abort ();
+    }
 #endif
-  emit_store_compare_result (j, T2);
 }
 
 static void



reply via email to

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