]> granicus.if.org Git - php/commitdiff
Remove unused temporary variables
authorDmitry Stogov <dmitry@zend.com>
Tue, 5 Sep 2017 11:46:03 +0000 (14:46 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 5 Sep 2017 11:46:03 +0000 (14:46 +0300)
17 files changed:
ext/opcache/Optimizer/compact_vars.c
ext/opcache/tests/opt/dce_001.phpt
ext/opcache/tests/opt/dce_002.phpt
ext/opcache/tests/opt/dce_003.phpt
ext/opcache/tests/opt/dce_004.phpt
ext/opcache/tests/opt/dce_005.phpt
ext/opcache/tests/opt/sccp_001.phpt
ext/opcache/tests/opt/sccp_002.phpt
ext/opcache/tests/opt/sccp_003.phpt
ext/opcache/tests/opt/sccp_004.phpt
ext/opcache/tests/opt/sccp_005.phpt
ext/opcache/tests/opt/sccp_007.phpt
ext/opcache/tests/opt/sccp_009.phpt
ext/opcache/tests/opt/sccp_010.phpt
ext/opcache/tests/opt/sccp_011.phpt
ext/opcache/tests/opt/sccp_012.phpt
ext/opcache/tests/opt/sccp_016.phpt

index c5a9b79553d948eb933e7da7b0b40be679ff22e2..016fbfffbcafeb2eca948e95a6f10acbbd19073a 100644 (file)
 #include "Optimizer/zend_optimizer_internal.h"
 #include "zend_bitset.h"
 
-/* This pass removes all CVs that are completely unused. It does *not* merge any CVs.
+/* This pass removes all CVs and temporaries that are completely unused. It does *not* merge any CVs or TMPs.
  * This pass does not operate on SSA form anymore. */
 void zend_optimizer_compact_vars(zend_op_array *op_array) {
        int i;
 
        ALLOCA_FLAG(use_heap1);
        ALLOCA_FLAG(use_heap2);
-       uint32_t used_cvs_len = zend_bitset_len(op_array->last_var);
-       zend_bitset used_cvs = ZEND_BITSET_ALLOCA(used_cvs_len, use_heap1);
-       uint32_t *cv_map = do_alloca(op_array->last_var * sizeof(uint32_t), use_heap2);
-       uint32_t num_cvs, tmp_offset;
+       uint32_t used_vars_len = zend_bitset_len(op_array->last_var + op_array->T);
+       zend_bitset used_vars = ZEND_BITSET_ALLOCA(used_vars_len, use_heap1);
+       uint32_t *vars_map = do_alloca((op_array->last_var + op_array->T) * sizeof(uint32_t), use_heap2);
+       uint32_t num_cvs, num_tmps;
 
        /* Determine which CVs are used */
-       zend_bitset_clear(used_cvs, used_cvs_len);
+       zend_bitset_clear(used_vars, used_vars_len);
        for (i = 0; i < op_array->last; i++) {
                zend_op *opline = &op_array->opcodes[i];
-               if (opline->op1_type == IS_CV) {
-                       zend_bitset_incl(used_cvs, VAR_NUM(opline->op1.var));
+               if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       zend_bitset_incl(used_vars, VAR_NUM(opline->op1.var));
                }
-               if (opline->op2_type == IS_CV) {
-                       zend_bitset_incl(used_cvs, VAR_NUM(opline->op2.var));
+               if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       zend_bitset_incl(used_vars, VAR_NUM(opline->op2.var));
                }
-               if (opline->result_type == IS_CV) {
-                       zend_bitset_incl(used_cvs, VAR_NUM(opline->result.var));
+               if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       zend_bitset_incl(used_vars, VAR_NUM(opline->result.var));
+                       if (opline->opcode == ZEND_ROPE_INIT) {
+                               uint32_t num = ((opline->extended_value * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
+                               while (num > 1) {
+                                       num--;
+                                       zend_bitset_incl(used_vars, VAR_NUM(opline->result.var) + num);
+                               }
+                       }
                }
        }
 
        num_cvs = 0;
        for (i = 0; i < op_array->last_var; i++) {
-               if (zend_bitset_in(used_cvs, i)) {
-                       cv_map[i] = num_cvs++;
+               if (zend_bitset_in(used_vars, i)) {
+                       vars_map[i] = num_cvs++;
+               } else {
+                       vars_map[i] = (uint32_t) -1;
+               }
+       }
+
+       num_tmps = 0;
+       for (i = op_array->last_var; i < op_array->last_var + op_array->T; i++) {
+               if (zend_bitset_in(used_vars, i)) {
+                       vars_map[i] = num_cvs + num_tmps++;
                } else {
-                       cv_map[i] = (uint32_t) -1;
+                       vars_map[i] = (uint32_t) -1;
                }
        }
 
-       free_alloca(used_cvs, use_heap1);
-       if (num_cvs == op_array->last_var) {
-               free_alloca(cv_map, use_heap2);
+       free_alloca(used_vars, use_heap1);
+       if (num_cvs == op_array->last_var && num_tmps == op_array->T) {
+               free_alloca(vars_map, use_heap2);
                return;
        }
 
-       ZEND_ASSERT(num_cvs < op_array->last_var);
-       tmp_offset = op_array->last_var - num_cvs;
+       ZEND_ASSERT(num_cvs <= op_array->last_var);
+       ZEND_ASSERT(num_tmps <= op_array->T);
 
        /* Update CV and TMP references in opcodes */
        for (i = 0; i < op_array->last; i++) {
                zend_op *opline = &op_array->opcodes[i];
-               if (opline->op1_type == IS_CV) {
-                       opline->op1.var = NUM_VAR(cv_map[VAR_NUM(opline->op1.var)]);
-               } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
-                       opline->op1.var -= sizeof(zval) * tmp_offset;
+               if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       opline->op1.var = NUM_VAR(vars_map[VAR_NUM(opline->op1.var)]);
                }
-               if (opline->op2_type == IS_CV) {
-                       opline->op2.var = NUM_VAR(cv_map[VAR_NUM(opline->op2.var)]);
-               } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
-                       opline->op2.var -= sizeof(zval) * tmp_offset;
+               if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       opline->op2.var = NUM_VAR(vars_map[VAR_NUM(opline->op2.var)]);
                }
-               if (opline->result_type == IS_CV) {
-                       opline->result.var = NUM_VAR(cv_map[VAR_NUM(opline->result.var)]);
-               } else if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
-                       opline->result.var -= sizeof(zval) * tmp_offset;
+               if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+                       opline->result.var = NUM_VAR(vars_map[VAR_NUM(opline->result.var)]);
                }
        }
 
        /* Update TMP references in live ranges */
        if (op_array->live_range) {
                for (i = 0; i < op_array->last_live_range; i++) {
-                       op_array->live_range[i].var -= sizeof(zval) * tmp_offset;
+                       op_array->live_range[i].var =
+                               (op_array->live_range[i].var & ZEND_LIVE_MASK) |
+                               NUM_VAR(vars_map[VAR_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK)]);
                }
        }
 
        /* Update CV name table */
-       {
+       if (num_cvs != op_array->last_var) {
                zend_string **names = safe_emalloc(sizeof(zend_string *), num_cvs, 0);
                for (i = 0; i < op_array->last_var; i++) {
-                       if (cv_map[i] != (uint32_t) -1) {
-                               names[cv_map[i]] = op_array->vars[i];
+                       if (vars_map[i] != (uint32_t) -1) {
+                               names[vars_map[i]] = op_array->vars[i];
                        } else {
                                zend_string_release(op_array->vars[i]);
                        }
@@ -107,6 +119,7 @@ void zend_optimizer_compact_vars(zend_op_array *op_array) {
        }
 
        op_array->last_var = num_cvs;
+       op_array->T = num_tmps;
 
-       free_alloca(cv_map, use_heap2);
+       free_alloca(vars_map, use_heap2);
 }
index 97011f08038a5184c64a6367c932e3d9828719d8..e41afdafa16e3d03aa7487397143c7816d6e5acb 100644 (file)
@@ -21,7 +21,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %sdce_001.php:1-8
 L0:     RETURN int(1)
 
-foo: ; (lines=5, args=4, vars=4, tmps=3)
+foo: ; (lines=5, args=4, vars=4, tmps=0)
     ; (after optimizer)
     ; %sdce_001.php:2-6
 L0:     CV0($s1) = RECV 1
index 5fb9f47ee7c16717c7366aee62da1b34a2eb5732..6cb50a3f0baad5262d1a609c84b9565648e8f874 100644 (file)
@@ -24,7 +24,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %sdce_002.php:1-11
 L0:     RETURN int(1)
 
-foo: ; (lines=5, args=1, vars=2, tmps=1)
+foo: ; (lines=5, args=1, vars=2, tmps=0)
     ; (after optimizer)
     ; %sdce_002.php:2-9
 L0:     CV0($a) = RECV 1
index 815bf42d534b4f203264faadea5e44515285c046..651a8fea481912fad3e27f3b290ca595a92e0568 100644 (file)
@@ -20,7 +20,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %sdce_003.php:1-7
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=1, vars=1, tmps=1)
+foo: ; (lines=3, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %sdce_003.php:2-5
 L0:     CV0($a) = RECV 1
index 74eda804e77cf2096d1f379582b1313f56d841e9..3038028294ba0261e3e54cd54b49c94399bca412 100644 (file)
@@ -21,7 +21,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %sdce_004.php:1-8
 L0:     RETURN int(1)
 
-foo: ; (lines=4, args=2, vars=3, tmps=1)
+foo: ; (lines=4, args=2, vars=3, tmps=0)
     ; (after optimizer)
     ; %sdce_004.php:2-7
 L0:     CV0($x) = RECV 1
index cabd534ee4a8beb098b0d74a9c5811a21fe5bb58..5aa13b3c380807ac8ca82359c7bff601e841a075 100644 (file)
@@ -21,7 +21,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %sdce_005.php:1-8
 L0:     RETURN int(1)
 
-foo: ; (lines=2, args=1, vars=1, tmps=1)
+foo: ; (lines=2, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %sdce_005.php:4-7
 L0:     CV0($x) = RECV 1
index 70d2ddce07c997931c6408aea144e929afaf1c80..9e6292740543b6826b7aeb2f1dda79929c1fd6b7 100644 (file)
@@ -22,7 +22,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_001.php:1-9
 L0:     RETURN int(1)
 
-foo: ; (lines=1, args=0, vars=0, tmps=1)
+foo: ; (lines=1, args=0, vars=0, tmps=0)
     ; (after optimizer)
     ; %ssccp_001.php:2-7
 L0:     RETURN int(4)
index 3b9aae441eb7bfebc1e9195f4a6c6f7019a37b76..960888e1fdad8828310ae267017262ae70a77e45 100644 (file)
@@ -27,7 +27,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_002.php:1-14
 L0:     RETURN int(1)
 
-foo: ; (lines=4, args=1, vars=1, tmps=1)
+foo: ; (lines=4, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_002.php:2-12
 L0:     CV0($x) = RECV 1
index 84c1e5ae9718c05944b41dd26dc6c83ee9529108..63e225b4be224ec8a81dedf13e6614937b4876e4 100644 (file)
@@ -27,7 +27,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_003.php:1-14
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=0, vars=0, tmps=1)
+foo: ; (lines=3, args=0, vars=0, tmps=0)
     ; (after optimizer)
     ; %ssccp_003.php:2-12
 L0:     ECHO int(1)
index 7a59bfaa38d0dc513f013df3759ce1f3544c991f..e8a7593b65e66bcd0a1af99fa6096c2c7ed3c45e 100644 (file)
@@ -30,7 +30,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_004.php:1-17
 L0:     RETURN int(1)
 
-foo: ; (lines=4, args=1, vars=1, tmps=1)
+foo: ; (lines=4, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_004.php:2-15
 L0:     CV0($x) = RECV 1
index bb639f7ec7db298edc009b9acca888888eca2f0d..0ec6e04be54c0cb2835ecb44833a0739f1216e52 100644 (file)
@@ -20,7 +20,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_005.php:1-7
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=1, vars=1, tmps=1)
+foo: ; (lines=3, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_005.php:2-5
 L0:     CV0($x) = RECV 1
index 8aeda3201182a130989663a90ffda653792cd683..f9cb4132b10749b883a61f3ec3d7db0311a58be1 100644 (file)
@@ -24,7 +24,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_007.php:1-11
 L0:     RETURN int(1)
 
-foo: ; (lines=5, args=1, vars=1, tmps=1)
+foo: ; (lines=5, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_007.php:2-9
 L0:     CV0($x) = RECV 1
index 9da9a3bbc1ae112eec62ef224ee75c3255207976..78efe4581516acb4fb452c870bf9828ffffbbb76 100644 (file)
@@ -21,7 +21,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_009.php:1-8
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=1, vars=1, tmps=1)
+foo: ; (lines=3, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_009.php:2-6
 L0:     CV0($x) = RECV 1
index 7d0d5332162e3b4fbd9772562d6ff5532bfa15d5..7e91107f41dda88a9c352a5cba851b957f3fc2a1 100644 (file)
@@ -28,7 +28,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_010.php:1-15
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=0, vars=0, tmps=1)
+foo: ; (lines=3, args=0, vars=0, tmps=0)
     ; (after optimizer)
     ; %ssccp_010.php:2-13
 L0:     ECHO int(1)
index 49288deb43ffee63c5396248bed61d5e6cdcf0c2..e679d5f8b86ac9fa25229fac105bc47a84f3f887 100644 (file)
@@ -27,7 +27,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_011.php:1-14
 L0:     RETURN int(1)
 
-foo: ; (lines=5, args=1, vars=1, tmps=1)
+foo: ; (lines=5, args=1, vars=1, tmps=0)
     ; (after optimizer)
     ; %ssccp_011.php:2-12
 L0:     CV0($x) = RECV 1
index 41db449316cd815c0ebb6eb8c22d74b6d2f6a817..fb4ee3d897cefade013a2bbc641587298f74a152 100644 (file)
@@ -30,7 +30,7 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0)
     ; %ssccp_012.php:1-17
 L0:     RETURN int(1)
 
-foo: ; (lines=3, args=0, vars=0, tmps=1)
+foo: ; (lines=3, args=0, vars=0, tmps=0)
     ; (after optimizer)
     ; %ssccp_012.php:2-15
 L0:     ECHO int(1)
index 18562b019ba94f18b983698f73bf2b139a524389..d877e57a719f9cc5d33ab524e988deb22d72e1d2 100644 (file)
@@ -12,7 +12,7 @@ opcache.opt_debug_level=0x20000
 return isset($undef) || php_sapi_name() == php_sapi_name();
 ?>
 --EXPECTF--
-$_main: ; (lines=4, args=0, vars=1, tmps=3)
+$_main: ; (lines=4, args=0, vars=1, tmps=1)
     ; (after optimizer)
     ; %ssccp_016.php:1-4
 L0:     T1 = ISSET_ISEMPTY_CV (isset) CV0($undef)