]> The Tcpdump Group git mirrors - libpcap/commitdiff
There are a bunch of optimizations we can only do in blocks that end
authorguy <guy>
Mon, 8 Nov 2004 09:03:37 +0000 (09:03 +0000)
committerguy <guy>
Mon, 8 Nov 2004 09:03:37 +0000 (09:03 +0000)
with jeq #x and that don't have a subsequent block that uses the value
the block leaves in the A register; make sure we only do them if the
last operation is a jeq with a constant operand and if nothing uses this
block's A register value.  (Some were being done with jeq x, and some
were done regardless of the branch that terminated the block and
regardless of whether the block's A register value is being used.)

optimize.c

index ae2f9d6530ebfa94cfb18a51acba1aac676cf562..1ae7e523f121268bce8aa71402c137c3b6859c02 100644 (file)
@@ -22,7 +22,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.78 2004-11-07 22:43:01 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.79 2004-11-08 09:03:37 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -755,16 +755,27 @@ opt_peep(b)
                }
        }
        /*
-        * If we have a subtract to do a comparison, and the X register
-        * is a known constant, we can merge this value into the
-        * comparison.
+        * If the comparison at the end of a block is an equality
+        * comparison against a constant, and nobody uses the value
+        * we leave in the A register at the end of a block, and
+        * the operation preceding the comparison is an arithmetic
+        * operation, we can sometime optimize it away.
         */
-       if (BPF_OP(b->s.code) == BPF_JEQ) {
-               if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
-                   !ATOMELEM(b->out_use, A_ATOM)) {
+       if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
+           !ATOMELEM(b->out_use, A_ATOM)) {
+               /*
+                * We can optimize away certain subtractions of the
+                * X register.
+                */
+               if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
                        val = b->val[X_ATOM];
                        if (vmap[val].is_const) {
                                /*
+                                * If we have a subtract to do a comparison,
+                                * and the X register is a known constant,
+                                * we can merge this value into the
+                                * comparison:
+                                *
                                 * sub x  ->    nop
                                 * jeq #y       jeq #(x+y)
                                 */
@@ -773,37 +784,45 @@ opt_peep(b)
                                done = 0;
                        } else if (b->s.k == 0) {
                                /*
-                                * sub #x  ->   nop
-                                * jeq #0       jeq #x
+                                * If the X register isn't a constant,
+                                * and the comparison in the test is
+                                * against 0, we can compare with the
+                                * X register, instead:
+                                *
+                                * sub x  ->    nop
+                                * jeq #0       jeq x
                                 */
                                last->s.code = NOP;
-                               b->s.code = BPF_CLASS(b->s.code) |
-                                       BPF_OP(b->s.code) | BPF_X;
+                               b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
                                done = 0;
                        }
                }
                /*
-                * Likewise, a constant subtract can be simplified.
+                * Likewise, a constant subtract can be simplified:
+                *
+                * sub #x ->    nop
+                * jeq #y ->    jeq #(x+y)
                 */
-               else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
-                        !ATOMELEM(b->out_use, A_ATOM)) {
-
+               else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
                        last->s.code = NOP;
                        b->s.k += last->s.k;
                        done = 0;
                }
-       }
-       /*
-        * and #k       nop
-        * jeq #0  ->   jset #k
-        */
-       if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
-           !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) {
-               b->s.k = last->s.k;
-               b->s.code = BPF_JMP|BPF_K|BPF_JSET;
-               last->s.code = NOP;
-               done = 0;
-               opt_not(b);
+               /*
+                * And, similarly, a constant AND can be simplified
+                * if we're testing against 0, i.e.:
+                *
+                * and #k       nop
+                * jeq #0  ->   jset #k
+                */
+               else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+                   b->s.k == 0) {
+                       b->s.k = last->s.k;
+                       b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+                       last->s.code = NOP;
+                       done = 0;
+                       opt_not(b);
+               }
        }
        /*
         * jset #0        ->   never