mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
vm: add OP_ADDILV/OP_SUBILV for local variable increment
fuse MOVE+ADDI+MOVE and MOVE+SUBI+MOVE patterns into single instructions. ADDILV/SUBILV add/subtract an immediate to a local variable in-place. BBB format: a=local, b=working space for method call, c=immediate. saves 5 bytes per instance (9->4 bytes), 40 occurrences in stdlib. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,8 @@ OPCODE(ADD, B) /* R[a] = R[a]+R[a+1] */
|
||||
OPCODE(ADDI, BB) /* R[a] = R[a]+mrb_int(b) */
|
||||
OPCODE(SUB, B) /* R[a] = R[a]-R[a+1] */
|
||||
OPCODE(SUBI, BB) /* R[a] = R[a]-mrb_int(b) */
|
||||
OPCODE(ADDILV, BBB) /* R[a] = R[a]+mrb_int(c); R[b],R[b+1] for method call */
|
||||
OPCODE(SUBILV, BBB) /* R[a] = R[a]-mrb_int(c); R[b],R[b+1] for method call */
|
||||
OPCODE(MUL, B) /* R[a] = R[a]*R[a+1] */
|
||||
OPCODE(DIV, B) /* R[a] = R[a]/R[a+1] */
|
||||
OPCODE(EQ, B) /* R[a] = R[a]==R[a+1] */
|
||||
|
||||
@@ -996,17 +996,22 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
|
||||
if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) break;
|
||||
if (addr_pc(s, data0.addr) != s->lastlabel) {
|
||||
/* constant folding */
|
||||
data0 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
|
||||
struct mrb_insn_data data1 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
|
||||
mrb_int n;
|
||||
if (data0.a == dst && get_int_operand(s, &data0, &n)) {
|
||||
if (data1.a == dst && get_int_operand(s, &data1, &n)) {
|
||||
if ((data.insn == OP_ADDI && !mrb_int_add_overflow(n, data.b, &n)) ||
|
||||
(data.insn == OP_SUBI && !mrb_int_sub_overflow(n, data.b, &n))) {
|
||||
s->pc = addr_pc(s, data0.addr);
|
||||
s->pc = addr_pc(s, data1.addr);
|
||||
gen_int(s, dst, n);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ADDILV/SUBILV fusion: MOVE temp local; ADDI temp imm; MOVE local temp */
|
||||
/* -> ADDILV local temp imm (temp is working space for method fallback) */
|
||||
s->pc = addr_pc(s, data0.addr);
|
||||
genop_3(s, data.insn == OP_ADDI ? OP_ADDILV : OP_SUBILV, dst, data.a, data.b);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -444,6 +444,14 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out)
|
||||
fprintf(out, "SUBI\t\tR%d\t%d", a, b);
|
||||
print_lv_a(mrb, irep, a, out);
|
||||
break;
|
||||
CASE(OP_ADDILV, BBB):
|
||||
fprintf(out, "ADDILV\tR%d\tR%d\t%d", a, b, c);
|
||||
print_lv_a(mrb, irep, a, out);
|
||||
break;
|
||||
CASE(OP_SUBILV, BBB):
|
||||
fprintf(out, "SUBILV\tR%d\tR%d\t%d", a, b, c);
|
||||
print_lv_a(mrb, irep, a, out);
|
||||
break;
|
||||
CASE(OP_MUL, B):
|
||||
fprintf(out, "MUL\t\tR%d\t(R%d)\n", a, a+1);
|
||||
break;
|
||||
|
||||
@@ -2937,6 +2937,51 @@ RETRY_TRY_BLOCK:
|
||||
OP_MATHI(sub);
|
||||
}
|
||||
|
||||
#ifdef MRB_NO_FLOAT
|
||||
#define OP_MATHILV_CASE_FLOAT(op_name) (void)0
|
||||
#else
|
||||
#define OP_MATHILV_CASE_FLOAT(op_name) \
|
||||
case MRB_TT_FLOAT: \
|
||||
{ \
|
||||
mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name c; \
|
||||
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
||||
} \
|
||||
break
|
||||
#endif
|
||||
#define OP_MATHILV(op_name) \
|
||||
/* a=local, b=working space, c=immediate */ \
|
||||
switch (mrb_type(regs[a])) { \
|
||||
case MRB_TT_INTEGER: \
|
||||
{ \
|
||||
mrb_int x = mrb_integer(regs[a]), y = (mrb_int)c, z; \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) { \
|
||||
OP_MATH_OVERFLOW_INT(op_name,x,y); \
|
||||
} \
|
||||
else { \
|
||||
SET_INT_VALUE(mrb,regs[a], z); \
|
||||
} \
|
||||
} \
|
||||
break; \
|
||||
OP_MATHILV_CASE_FLOAT(op_name); \
|
||||
default: \
|
||||
{ \
|
||||
mrb_value arg = mrb_int_value(mrb, c); \
|
||||
mrb_sym mid = MRB_OPSYM(op_name); \
|
||||
regs[a] = mrb_funcall_argv(mrb, regs[a], mid, 1, &arg); \
|
||||
mrb_gc_arena_restore(mrb, ai); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
NEXT
|
||||
|
||||
CASE(OP_ADDILV, BBB) {
|
||||
OP_MATHILV(add);
|
||||
}
|
||||
|
||||
CASE(OP_SUBILV, BBB) {
|
||||
OP_MATHILV(sub);
|
||||
}
|
||||
|
||||
#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
|
||||
|
||||
#ifdef MRB_NO_FLOAT
|
||||
|
||||
Reference in New Issue
Block a user