summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-08-09 11:25:04 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-08-11 10:48:18 +0900
commitb1b9b157f85fe371db706e0c11024681d84e4aba (patch)
treeaf652bb95da9231b44887d1336604f694fae030e
parent52eb2af7d05c9fe9aa1447c83ae2520bcc3966c6 (diff)
downloadmruby-b1b9b157f85fe371db706e0c11024681d84e4aba.tar.gz
mruby-b1b9b157f85fe371db706e0c11024681d84e4aba.zip
codegen.c: more peephole optimization.
`a=10; a+=1` to generate: ``` 1 000 OP_LOADI R1 11 ; R1:a ``` instead of: ``` 1 000 OP_LOADI R1 10 ; R1:a 1 003 OP_MOVE R2 R1 ; R1:a 1 006 OP_ADDI R2 1 1 009 OP_MOVE R1 R2 ; R1:a ```
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index a3a73fafa..b49db0e31 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -575,6 +575,9 @@ genjmp2(codegen_scope *s, mrb_code i, uint16_t a, uint32_t pc, int val)
#define genjmp2_0(s,i,a,val) genjmp2(s,i,a,JMPLINK_START,val)
+static mrb_bool get_int_operand(codegen_scope *s, struct mrb_insn_data *data, mrb_int *ns);
+static void gen_int(codegen_scope *s, uint16_t dst, mrb_int i);
+
static void
gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
{
@@ -622,6 +625,24 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
genop_2SS(s, data.insn, dst, i);
}
break;
+ case OP_ADDI: case OP_SUBI:
+ if (nopeep || addr_pc(s, data.addr) == s->lastlabel || data.a != src || data.a < s->nlocals) goto normal;
+ struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr));
+ if (data0.insn != OP_MOVE || data0.a != data.a || data0.b != dst) goto normal;
+ s->pc = addr_pc(s, data0.addr);
+ /* constant folding */
+ data0 = mrb_decode_insn(mrb_prev_pc(s, data0.addr));
+ mrb_int n;
+ if (data0.a == dst && get_int_operand(s, &data0, &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);
+ gen_int(s, dst, n);
+ break;
+ }
+ }
+ genop_2(s, data.insn, dst, data.b);
+ break;
default:
goto normal;
}
@@ -726,8 +747,6 @@ get_int_operand(codegen_scope *s, struct mrb_insn_data *data, mrb_int *n)
}
}
-static void gen_int(codegen_scope *s, uint16_t dst, mrb_int i);
-
static void
gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
{