diff options
author | Nicolas Williams <nico@cryptonector.com> | 2014-08-09 20:27:08 -0500 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2014-08-09 20:27:08 -0500 |
commit | f87521183f5c499b3c58e016c5936ade14819fd3 (patch) | |
tree | e98607208d323cc91189f9e23ab9451420fe68e5 /compile.c | |
parent | 8a561120c41969439f786ee133d7d699ee8edd1b (diff) |
Fold constant arrays
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 62 |
1 files changed, 62 insertions, 0 deletions
@@ -499,8 +499,70 @@ block gen_both(block a, block b) { return c; } +block gen_const_array(block expr) { + /* + * An expr of all constant elements looks like this: + * + * 0009 FORK 0027 + * 0011 FORK 0023 + * 0013 FORK 0019 + * 0015 LOADK 1 + * 0017 JUMP 0021 + * 0019 LOADK 2 + * 0021 JUMP 0025 + * 0023 LOADK 3 + * 0025 JUMP 0029 + * 0027 LOADK 4 + * + * That's: N-1 commas for N elements, N LOADKs, and a JUMP between + * every LOADK. The sequence ends in a LOADK. Any deviation and it's + * not a list of constants. + * + * Here we check for this pattern almost exactly. We don't check that + * the targets of the FORK and JUMP instructions are in the right + * sequence. + */ + int all_const = 1; + int commas = 0; + int normal = 1; + jv a = jv_array(); + for (inst *i = expr.first; i; i = i->next) { + if (i->op == FORK) { + commas++; + if (i->imm.target == NULL || i->imm.target->op != JUMP || + jv_array_length(jv_copy(a)) > 0) { + normal = 0; + break; + } + } else if (all_const && i->op == LOADK) { + if (i->next != NULL && i->next->op != JUMP) { + normal = 0; + break; + } + a = jv_array_append(a, jv_copy(i->imm.constant)); + } else if (i->op != JUMP || i->imm.target == NULL || + i->imm.target->op != LOADK) { + all_const = 0; + } + } + + if (all_const && normal && + (expr.last == NULL || expr.last->op == LOADK) && + jv_array_length(jv_copy(a)) == commas + 1) { + block_free(expr); + return gen_const(a); + } + + jv_free(a); + block b = {0,0}; + return b; +} block gen_collect(block expr) { + block const_array = gen_const_array(expr); + if (const_array.first != NULL) + return const_array; + block array_var = gen_op_var_fresh(STOREV, "collect"); block c = BLOCK(gen_op_simple(DUP), gen_const(jv_array()), array_var); |