changeset 32443:0abebb3f41e4

Opcode for binary operations with literal Avoids the need for PUSH of constant in binary operations. * pt-bytecode-vm-internal.h: New macros * pt-bytecode-vm.cc: New opcodes * pt-bytecode-walk.cc: Emit new opcodes * pt-bytecode.h: New opcodes
author Petter T.
date Fri, 27 Oct 2023 18:19:50 +0200
parents c841a01aca55
children f5dee2d8173e
files libinterp/parse-tree/pt-bytecode-vm-internal.h libinterp/parse-tree/pt-bytecode-vm.cc libinterp/parse-tree/pt-bytecode-walk.cc libinterp/parse-tree/pt-bytecode.h
diffstat 4 files changed, 315 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-bytecode-vm-internal.h	Fri Oct 27 18:19:45 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode-vm-internal.h	Fri Oct 27 18:19:50 2023 +0200
@@ -121,6 +121,34 @@
   CATCH_BAD_ALLOC                                                                        \
 }                                                                                        \
 
+#define MAKE_BINOP_CST_SPECIALIZED(op_fn,jmp_target,op_target,target_type) \
+{                                                                              \
+  octave_value &cst = data [arg0];                                             \
+  octave_value &arg = TOP_OV ();                                               \
+  int lhs_is_cst = *ip++;                                                      \
+                                                                               \
+  int arg_type = arg.type_id ();                                               \
+  if (OCTAVE_UNLIKELY (arg_type != target_type))                               \
+    {                                                                          \
+      ip[-3] = static_cast<unsigned char> (INSTR::op_target);                  \
+      ip--;                                                                    \
+      goto jmp_target;                                                         \
+    }                                                                          \
+                                                                               \
+  try                                                                          \
+    {                                                                          \
+      octave_value ret =  lhs_is_cst ?                                         \
+        op_fn (cst.get_rep (), arg.get_rep ()) :                               \
+        op_fn (arg.get_rep (), cst.get_rep ());                                \
+      STACK_DESTROY (1);                                                       \
+      PUSH_OV (ret);                                                           \
+    }                                                                          \
+  CATCH_INTERRUPT_EXCEPTION                                                    \
+  CATCH_INDEX_EXCEPTION                                                        \
+  CATCH_EXECUTION_EXCEPTION                                                    \
+  CATCH_BAD_ALLOC                                                              \
+}                                                                              \
+
 #define MAKE_UNOP_SPECIALIZED(op_fn, jmp_target, op_target, target_type) \
 {                                                                                        \
   octave_value &ov = TOP_OV ();                                                          \
@@ -168,7 +196,40 @@
   CATCH_INDEX_EXCEPTION                                                                    \
   CATCH_EXECUTION_EXCEPTION                                                                \
   CATCH_BAD_ALLOC                                                                          \
-}                                                                                          \
+}
+
+#define MAKE_BINOP_CST_SELFMODIFYING(op, jmp_target, op_target) \
+{                                                                                             \
+  octave_value &cst = data [arg0];                                                            \
+  octave_value &arg = TOP_OV ();                                                              \
+  int lhs_is_cst = *ip++;                                                                     \
+                                                                                              \
+  int cst_type = cst.type_id ();                                                              \
+  int arg_type = arg.type_id ();                                                              \
+  if (OCTAVE_UNLIKELY (cst_type == arg_type && cst_type == m_scalar_typeid))                  \
+    {                                                                                         \
+      ip[-3] = static_cast<unsigned char> (INSTR::op_target);                                 \
+      ip--;                                                                                   \
+      goto jmp_target;                                                                        \
+    }                                                                                         \
+                                                                                              \
+  try                                                                                         \
+    {                                                                                         \
+      octave_value ans = lhs_is_cst ?                                                         \
+          binary_op (*m_ti,                                                                   \
+                      octave_value::op,                                                       \
+                      cst, arg)                                                               \
+        : binary_op (*m_ti,                                                                   \
+                      octave_value::op,                                                       \
+                      arg, cst);                                                              \
+      STACK_DESTROY (1);                                                                      \
+      PUSH_OV (std::move (ans));                                                              \
+    }                                                                                         \
+  CATCH_INTERRUPT_EXCEPTION                                                                   \
+  CATCH_INDEX_EXCEPTION                                                                       \
+  CATCH_EXECUTION_EXCEPTION                                                                   \
+  CATCH_BAD_ALLOC                                                                             \
+}
 
 #define CATCH_INDEX_EXCEPTION \
 catch (index_exception& ie)                              \
--- a/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Oct 27 18:19:45 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Oct 27 18:19:50 2023 +0200
@@ -330,6 +330,29 @@
           CASE_START (POP_N_INTS)     PCHAR () CASE_END ()
           CASE_START (DUP_MOVE)       PCHAR () CASE_END ()
 
+          CASE_START (MUL_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (MUL_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+          CASE_START (DIV_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (DIV_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+          CASE_START (ADD_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (ADD_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+          CASE_START (SUB_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (SUB_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+          CASE_START (LE_CST)         PCHAR () PCHAR () CASE_END ()
+          CASE_START (LE_CST_DBL)     PCHAR () PCHAR () CASE_END ()
+          CASE_START (LE_EQ_CST)      PCHAR () PCHAR () CASE_END ()
+          CASE_START (LE_EQ_CST_DBL)  PCHAR () PCHAR () CASE_END ()
+          CASE_START (GR_CST)         PCHAR () PCHAR () CASE_END ()
+          CASE_START (GR_CST_DBL)     PCHAR () PCHAR () CASE_END ()
+          CASE_START (GR_EQ_CST)      PCHAR () PCHAR () CASE_END ()
+          CASE_START (GR_EQ_CST_DBL)  PCHAR () PCHAR () CASE_END ()
+          CASE_START (EQ_CST)         PCHAR () PCHAR () CASE_END ()
+          CASE_START (EQ_CST_DBL)     PCHAR () PCHAR () CASE_END ()
+          CASE_START (NEQ_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (NEQ_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+          CASE_START (POW_CST)        PCHAR () PCHAR () CASE_END ()
+          CASE_START (POW_CST_DBL)    PCHAR () PCHAR () CASE_END ()
+
           CASE_START (ASSIGN)                     PSLOT() CASE_END ()
           CASE_START (BIND_ANS)                   PSLOT() CASE_END ()
           CASE_START (INCR_ID_PREFIX)             PSLOT() CASE_END ()
@@ -990,6 +1013,28 @@
       &&enter_nested_frame,
       &&install_function,
       &&dup_move,
+      &&mul_cst_dbl,
+      &&mul_cst,
+      &&add_cst_dbl,
+      &&add_cst,
+      &&div_cst_dbl,
+      &&div_cst,
+      &&sub_cst_dbl,
+      &&sub_cst,
+      &&le_cst_dbl,
+      &&le_cst,
+      &&le_eq_cst_dbl,
+      &&le_eq_cst,
+      &&gr_cst_dbl,
+      &&gr_cst,
+      &&gr_eq_cst_dbl,
+      &&gr_eq_cst,
+      &&eq_cst_dbl,
+      &&eq_cst,
+      &&neq_cst_dbl,
+      &&neq_cst,
+      &&pow_cst_dbl,
+      &&pow_cst,
     };
 
   if (OCTAVE_UNLIKELY (m_profiler_enabled))
@@ -6340,7 +6385,6 @@
   }
   DISPATCH_1BYTEOP ();
 
-
   install_function:
   {
     int slot = arg0;
@@ -6363,6 +6407,74 @@
       ov = octave_value {};
   }
   DISPATCH ();
+
+  mul_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_mul, mul_cst_dbl, MUL_CST_DBL);
+  DISPATCH ();
+  mul_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_mul, mul_cst, MUL_CST, m_scalar_typeid);
+  DISPATCH ();
+  add_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_add, add_cst_dbl, ADD_CST_DBL);
+  DISPATCH ();
+  add_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_add, add_cst, ADD_CST, m_scalar_typeid);
+  DISPATCH ();
+  div_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_div, div_cst_dbl, DIV_CST_DBL);
+  DISPATCH ();
+  div_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_div, div_cst, DIV_CST, m_scalar_typeid);
+  DISPATCH ();
+  sub_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_sub, sub_cst_dbl, SUB_CST_DBL);
+  DISPATCH ();
+  sub_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_sub, sub_cst, SUB_CST, m_scalar_typeid);
+  DISPATCH ();
+  le_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_lt, le_cst_dbl, LE_CST_DBL);
+  DISPATCH ();
+  le_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_le, le_cst, LE_CST, m_scalar_typeid);
+  DISPATCH ();
+  le_eq_cst:
+  MAKE_BINOP_CST_SELFMODIFYING (binary_op::op_le, le_eq_cst_dbl, LE_EQ_CST_DBL);
+  DISPATCH ();
+  le_eq_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_le_eq, le_eq_cst, LE_EQ_CST, m_scalar_typeid);
+  DISPATCH ();
+  gr_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_gr, gr_cst, GR_CST, m_scalar_typeid)
+  DISPATCH ();
+  gr_cst:
+  MAKE_BINOP_CST_SELFMODIFYING(binary_op::op_gt, gr_cst_dbl, GR_CST_DBL)
+  DISPATCH();
+  gr_eq_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_gr_eq, gr_eq_cst, GR_EQ_CST, m_scalar_typeid)
+  DISPATCH();
+  gr_eq_cst:
+  MAKE_BINOP_CST_SELFMODIFYING(binary_op::op_ge, gr_eq_cst_dbl, GR_EQ_CST_DBL)
+  DISPATCH();
+  eq_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED(m_fn_dbl_eq, eq_cst, EQ_CST, m_scalar_typeid)
+  DISPATCH();
+  eq_cst:
+  MAKE_BINOP_CST_SELFMODIFYING(binary_op::op_eq, eq_cst_dbl, EQ_CST_DBL)
+  DISPATCH();
+  neq_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED(m_fn_dbl_neq, neq_cst, NEQ_CST, m_scalar_typeid)
+  DISPATCH();
+  neq_cst:
+  MAKE_BINOP_CST_SELFMODIFYING(binary_op::op_ne, neq_cst_dbl, NEQ_CST_DBL)
+  DISPATCH();
+  pow_cst_dbl:
+  MAKE_BINOP_CST_SPECIALIZED (m_fn_dbl_pow, pow_cst, POW_CST, m_scalar_typeid)
+  DISPATCH();
+  pow_cst:
+  MAKE_BINOP_CST_SELFMODIFYING(binary_op::op_pow, pow_cst_dbl, POW_CST_DBL)
+  DISPATCH();
+
 }
 
 octave_value
--- a/libinterp/parse-tree/pt-bytecode-walk.cc	Fri Oct 27 18:19:45 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode-walk.cc	Fri Oct 27 18:19:50 2023 +0200
@@ -2012,12 +2012,40 @@
   CHECK_NONNULL (op1);
   CHECK_NONNULL (op2);
 
-  if (op1->is_constant () && op2->is_constant () && DATA_SIZE () < 255)
+  bool op1_is_cst = op1->is_constant ();
+  bool op2_is_cst = op2->is_constant ();
+  int n_cst = op1_is_cst + op2_is_cst;
+  int cst_offset = -1;
+
+  if (op1_is_cst && op2_is_cst && DATA_SIZE () < 255)
     {
       // If both rhs and lhs are constants we want to emit a super op-code
       // aslong as the WIDE op is not going to be used (<255)
       emit_load_2_cst (op1, op2);
     }
+  else if (n_cst == 1 &&
+           (expr.op_type () <= octave_value::binary_op::op_ne && expr.op_type () >= octave_value::binary_op::op_add) &&
+           DATA_SIZE () < 255 && expr.op_type () != octave_value::binary_op::op_ldiv)
+    {
+      if (op1_is_cst)
+        {
+          tree_constant *tree_cst = static_cast<tree_constant *> (op1);
+          octave_value ov_cst = tree_cst->value ();
+          cst_offset = DATA_SIZE ();
+          PUSH_DATA (ov_cst);
+
+          op2->accept (*this);
+        }
+      else
+        {
+          tree_constant *tree_cst = static_cast<tree_constant *> (op2);
+          octave_value ov_cst = tree_cst->value ();
+          cst_offset = DATA_SIZE ();
+          PUSH_DATA (ov_cst);
+
+          op1->accept (*this);
+        }
+    }
   else
     {
       op1->accept (*this);
@@ -2029,37 +2057,115 @@
   switch (expr.op_type ())
     {
     case octave_value::binary_op::op_mul:
-      PUSH_CODE (INSTR::MUL);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::MUL);
+      else
+        {
+          PUSH_CODE (INSTR::MUL_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
+      break;
       break;
     case octave_value::binary_op::op_div:
-      PUSH_CODE (INSTR::DIV);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::DIV);
+      else
+        {
+          PUSH_CODE (INSTR::DIV_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_add:
-      PUSH_CODE (INSTR::ADD);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::ADD);
+      else
+        {
+          PUSH_CODE (INSTR::ADD_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_sub:
-      PUSH_CODE (INSTR::SUB);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::SUB);
+      else
+        {
+          PUSH_CODE (INSTR::SUB_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_lt:
-      PUSH_CODE (INSTR::LE);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::LE);
+      else
+        {
+          PUSH_CODE (INSTR::LE_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_le:
-      PUSH_CODE (INSTR::LE_EQ);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::LE_EQ);
+      else
+        {
+          PUSH_CODE (INSTR::LE_EQ_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_gt:
-      PUSH_CODE (INSTR::GR);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::GR);
+      else
+        {
+          PUSH_CODE (INSTR::GR_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_ge:
-      PUSH_CODE (INSTR::GR_EQ);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::GR_EQ);
+      else
+        {
+          PUSH_CODE (INSTR::GR_EQ_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_eq:
-      PUSH_CODE (INSTR::EQ);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::EQ);
+      else
+        {
+          PUSH_CODE (INSTR::EQ_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_ne:
-      PUSH_CODE (INSTR::NEQ);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::NEQ);
+      else
+        {
+          PUSH_CODE (INSTR::NEQ_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_pow:
-      PUSH_CODE (INSTR::POW);
+      if (cst_offset == -1)
+        PUSH_CODE (INSTR::POW);
+      else
+        {
+          PUSH_CODE (INSTR::POW_CST);
+          PUSH_CODE (cst_offset);
+          PUSH_CODE (op1_is_cst);
+        }
       break;
     case octave_value::binary_op::op_ldiv:
       PUSH_CODE (INSTR::LDIV);
--- a/libinterp/parse-tree/pt-bytecode.h	Fri Oct 27 18:19:45 2023 +0200
+++ b/libinterp/parse-tree/pt-bytecode.h	Fri Oct 27 18:19:50 2023 +0200
@@ -194,6 +194,28 @@
   ENTER_NESTED_FRAME,
   INSTALL_FUNCTION,
   DUP_MOVE,
+  MUL_CST_DBL,
+  MUL_CST,
+  ADD_CST_DBL,
+  ADD_CST,
+  DIV_CST_DBL,
+  DIV_CST,
+  SUB_CST_DBL,
+  SUB_CST,
+  LE_CST_DBL,
+  LE_CST,
+  LE_EQ_CST_DBL,
+  LE_EQ_CST,
+  GR_CST_DBL,
+  GR_CST,
+  GR_EQ_CST_DBL,
+  GR_EQ_CST,
+  EQ_CST_DBL,
+  EQ_CST,
+  NEQ_CST_DBL,
+  NEQ_CST,
+  POW_CST_DBL,
+  POW_CST,
 };
 
 enum class unwind_entry_type