# HG changeset patch # User Petter T. # Date 1698423590 -7200 # Node ID 0abebb3f41e40460c73a9e2e566fffaf222722f2 # Parent c841a01aca556010ab58a166db77734614a70446 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 diff -r c841a01aca55 -r 0abebb3f41e4 libinterp/parse-tree/pt-bytecode-vm-internal.h --- 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 (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 (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) \ diff -r c841a01aca55 -r 0abebb3f41e4 libinterp/parse-tree/pt-bytecode-vm.cc --- 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 diff -r c841a01aca55 -r 0abebb3f41e4 libinterp/parse-tree/pt-bytecode-walk.cc --- 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 (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 (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); diff -r c841a01aca55 -r 0abebb3f41e4 libinterp/parse-tree/pt-bytecode.h --- 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