summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-08-02 07:34:54 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-08-02 07:34:54 +0900
commit188c150f44bd28ab0e4a91d58e6156952aef9904 (patch)
tree7eb83f78842b29f1cdac6fea38faffae974cae52 /mrbgems/mruby-compiler
parent1315e8751e70937e4cf43ba9225ea0cfaa67689d (diff)
downloadmruby-188c150f44bd28ab0e4a91d58e6156952aef9904.tar.gz
mruby-188c150f44bd28ab0e4a91d58e6156952aef9904.zip
codegen.c: constant folding binary operators, <<, >>, %, &, |, ^.
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c60
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);