scmno****@osdn*****
scmno****@osdn*****
Tue Jun 26 04:55:31 JST 2018
changeset b09334915327 in quipu/quipu details: http://hg.osdn.jp/view/quipu/quipu?cmd=changeset;node=b09334915327 user: Agustina Arzille <avarz****@riseu*****> date: Mon Jun 25 16:55:22 2018 -0300 description: Improve optimization of branches diffstat: compiler.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 66 insertions(+), 15 deletions(-) diffs (191 lines): diff -r 280a5b1d438f -r b09334915327 compiler.cpp --- a/compiler.cpp Mon Jun 25 04:07:47 2018 +0000 +++ b/compiler.cpp Mon Jun 25 16:55:22 2018 -0300 @@ -85,6 +85,22 @@ int acc = 0; }; + class whl_handler + { + public: + bc_emitter& bc; + + whl_handler (bc_emitter& ebc, whl_block *wp) : bc (ebc) + { + this->bc.push_whl (wp); + } + + ~whl_handler () + { + this->bc.pop_whl (); + } + }; + typedef sorted_list<xcmp_call> ctable_t; interpreter *interp; @@ -346,6 +362,9 @@ return; } } + else if (inst == OPX_(RET) && !cv.empty () && cv.back () == inst) + // Redundant 'ret'. + return; if (inst == OPX_(POP) && cv.size () >= 2) { @@ -361,9 +380,10 @@ { if (ix >= 4 && cv[ix - 2] == OPX_(LABEL) && cv[cv.size () - 2] == cv[ix - 2] && - cv[ix - 4] == OPX_(JMP) && cv[ix - 3] == cv[ix + 2]) + bcode_get(as_int (cv[ix - 4]))->branch_p () && + cv[ix - 3] == cv[ix + 2]) { /* Common pattern: - * jmp L1 + * branch L1 * ... * jmp L2 * L1: loadnil @@ -375,7 +395,7 @@ * the label L1 to point forward and avoid the redundant * loadnil+pop instruction: * - * jmp L1 + * branch L1 * ... * pop * L1: ... @@ -544,7 +564,8 @@ for (sorted_list<>::iterator it (fixup); it.valid (); ) { - if (ip[it.key () - 1] != OP_JMP && ip[it.key () - 1] != OP_JMPL) + int opc = ip[it.key () - 1]; + if (opc != OP_JMP && opc != OP_JMPL) { it.adv (); continue; @@ -553,7 +574,7 @@ const int sz = label_size (large); int next = it.key () + sz; - if (ip[it.key () - 1] == ip[next]) + if (opc == ip[next]) { // 2 jumps in a row - Delete the second one. fixup.erase (it.runp->next); remove_jmp (bvp, fixup, next, sz + 1, large); @@ -581,6 +602,30 @@ } } +static void +optimize_jmps (bvector *bvp, sorted_list<>& fixup, bool large) +{ + condense_jmps (bvp, fixup, large); + simplify_jmps (bvp, fixup, large); + + bool pass = false; + + for (sorted_list<>::iterator it (fixup); it.valid (); it.adv ()) + { + int idx = it.key () + label_get (large, bvp->data + it.key ()); + if (bvp->data[idx] == OP_LOADNIL && bvp->data[idx + 1] == OP_POP) + { + remove_jmp (bvp, fixup, idx, 1, large); + label_put (large, bvp->data + it.key (), + label_get (large, bvp->data + it.key ()) + 1); + pass = true; + } + } + + if (pass) + simplify_jmps (bvp, fixup, large); +} + object bc_emitter::encode () { auto& cv = this->code; @@ -637,8 +682,7 @@ this->bytecode->nbytes = this->bc_len; // Minimize the amount of jumps needed. - condense_jmps (this->bytecode, fixup_lbl, large); - simplify_jmps (this->bytecode, fixup_lbl, large); + optimize_jmps (this->bytecode, fixup_lbl, large); // Finally, register the bytecode and return. this->bytecode->full |= FLAGS_CONST; @@ -833,6 +877,12 @@ EVR_NONE = 0xff }; +static inline bool +evr_nlexit_p (int r) +{ + return (r == EVR_IRET || r == EVR_BRK || r == EVR_CONT); +} + int bc_emitter::compile_atom (object env, bool tail, object expr, bool quoted) { @@ -939,7 +989,7 @@ int r = this->compile_cond (env, false, tst) & ~EVR_SE; - if (qp_unlikely (r == EVR_IRET)) + if (qp_unlikely (evr_nlexit_p (r))) return (r); else if (qp_unlikely (r == EVR_ATOM)) return (this->compile_in (env, tail, then)); @@ -951,7 +1001,7 @@ this->emit (OPX_(BRN), intobj (el)); r = this->compile_in (env, tail, then); - if (r == EVR_IRET || r == EVR_BRK || r == EVR_CONT) + if (evr_nlexit_p (r)) ; else if (tail) this->emit (OPX_(RET)); @@ -971,9 +1021,9 @@ int bc_emitter::compile_while (object env, object cond, object body) { whl_block blk; + whl_handler (*this, &blk); size_t pos = this->code.size (); - this->push_whl (&blk); this->mark_label (blk.top_lbl); int r = this->compile_cond (env, false, cond) & ~EVR_SE; @@ -982,11 +1032,11 @@ this->emit (OPX_(LOADNIL)); return (EVR_NIL); } - else if (r == EVR_IRET) + else if (evr_nlexit_p (r)) return (r); else if (r == EVR_ATOM) { - this->compile_in (env, false, body); + r = this->compile_in (env, false, body); this->emit (OPX_(POP)); } else @@ -994,12 +1044,13 @@ this->code.insert (this->code.begin () + pos, OPX_(LOADT)); this->emit (OPX_(BRN), intobj (blk.end_lbl)); this->emit (OPX_(POP)); - this->compile_in (env, false, body); + r = this->compile_in (env, false, body); } - this->emit (OPX_(IRTJMP), intobj (blk.top_lbl)); + if (!evr_nlexit_p (r)) + this->emit (OPX_(IRTJMP), intobj (blk.top_lbl)); + this->mark_label (blk.end_lbl); - this->pop_whl (); return (EVR_NONE); }