[Quipu-dev] quipu/quipu: Improve optimization of branches

Back to archive index

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);
 }
 




More information about the Quipu-dev mailing list
Back to archive index