diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-08-02 07:34:54 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-08-02 07:34:54 +0900 |
| commit | 188c150f44bd28ab0e4a91d58e6156952aef9904 (patch) | |
| tree | 7eb83f78842b29f1cdac6fea38faffae974cae52 /mrbgems/mruby-compiler/core/codegen.c | |
| parent | 1315e8751e70937e4cf43ba9225ea0cfaa67689d (diff) | |
| download | mruby-188c150f44bd28ab0e4a91d58e6156952aef9904.tar.gz mruby-188c150f44bd28ab0e4a91d58e6156952aef9904.zip | |
codegen.c: constant folding binary operators, <<, >>, %, &, |, ^.
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 7d0b51740..4c1fa257c 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -798,6 +798,63 @@ gen_muldiv(codegen_scope *s, uint8_t op, uint16_t dst) } } +static mrb_bool +gen_binop(codegen_scope *s, mrb_sym op, uint16_t dst) +{ + if (no_peephole(s)) return FALSE; + else { + struct mrb_insn_data data = mrb_last_insn(s); + mrb_int n, n0; + if (addr_pc(s, data.addr) == s->lastlabel || !get_int_operand(s, &data, &n)) { + /* not integer immediate */ + return FALSE; + } + struct mrb_insn_data data0 = mrb_decode_insn(mrb_prev_pc(s, data.addr)); + if (!get_int_operand(s, &data0, &n0)) { + return FALSE; + } + if (op == MRB_OPSYM_2(s->mrb, lshift)) { + if (n < 0) { + if (-63 > n || -n >= sizeof(mrb_int)*8) return FALSE; + n = n0 >> (-n); + } + else { + if (n >= sizeof(mrb_int)*8-1) return FALSE; + n = n0 << n; + } + } + else if (op == MRB_OPSYM_2(s->mrb, rshift)) { + if (n < 0) { + if (-63 > n || -n > sizeof(mrb_int)*8-1) return FALSE; + n = n0 << (-n); + } + else { + if (n >= sizeof(mrb_int)*8-1) return FALSE; + n = n0 >> n; + } + } + else if (op == MRB_OPSYM_2(s->mrb, mod)) { + if (n0 < 0 || n < 0) return FALSE; + n = n0 % n; + } + else if (op == MRB_OPSYM_2(s->mrb, and)) { + n = n0 & n; + } + else if (op == MRB_OPSYM_2(s->mrb, or)) { + n = n0 | n; + } + else if (op == MRB_OPSYM_2(s->mrb, xor)) { + n = n0 ^ n; + } + else { + return FALSE; + } + s->pc = addr_pc(s, data0.addr); + gen_int(s, dst, n); + return TRUE; + } +} + static uint32_t dispatch(codegen_scope *s, uint32_t pos0) { @@ -1551,6 +1608,9 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe) sym == MRB_OPSYM_2(s->mrb, neg))) { gen_uniop(s, sym, cursp()); } + else if (!noop && n == 1 && gen_binop(s, sym, cursp())) { + /* constant folding succeeded */ + } else { int idx = new_sym(s, sym); |
