]> granicus.if.org Git - php/commitdiff
Apply local optimizatons to extended bacic block (this allows some optimizarions...
authorDmitry Stogov <dmitry@zend.com>
Wed, 9 Dec 2015 22:17:35 +0000 (01:17 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 9 Dec 2015 22:17:35 +0000 (01:17 +0300)
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/zend_cfg.h
ext/opcache/Optimizer/zend_dump.c

index 8c0bc91762eb79cb815e1090077f220a577373dc..cddfb8bdfcf8a9d576e19ad29cf4f651fb89a2ce 100644 (file)
@@ -127,8 +127,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
        /* remove leading NOPs */
        strip_leading_nops(op_array, block);
 
-       /* we track data dependencies only insight a single basic block */
-       memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
        opline = op_array->opcodes + block->start;
        end = op_array->opcodes + block->end + 1;
        while (opline < end) {
@@ -324,9 +322,17 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
                }
 #endif
 
+                       case ZEND_FETCH_LIST:
+                               if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+                                       /* LIST variable will be deleted later by FREE */
+                                       Tsource[VAR_NUM(opline->op1.var)] = NULL;
+                               }
+                               break;
+
                        case ZEND_CASE:
                                if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
                                        /* CASE variable will be deleted later by FREE, so we can't optimize it */
+                                       Tsource[VAR_NUM(opline->op1.var)] = NULL;
                                        break;
                                }
                                if (opline->op1_type == IS_CONST &&
@@ -811,6 +817,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                                b->end = opline - new_opcodes + n - 1;
                                opline += n;
                        } else {
+                               b->flags |= ZEND_BB_EMPTY;
                                b->start = b->end = opline - new_opcodes;
                        }
                }
@@ -1458,7 +1465,7 @@ next_target_znz:
 static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx)
 {
        int n;
-       zend_basic_block *block;
+       zend_basic_block *block, *next_block;
        uint32_t var_num;
        uint32_t bitset_len;
        zend_bitset usage;
@@ -1474,7 +1481,6 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
 
        checkpoint = zend_arena_checkpoint(ctx->arena);
        bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
-       usage = zend_arena_calloc(&ctx->arena, bitset_len, ZEND_BITSET_ELM_SIZE);
        defined_here = zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
 
        for (n = 1; n < cfg->blocks_count; n++) {
@@ -1486,7 +1492,11 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
 
                opline = op_array->opcodes + block->start;
                end = op_array->opcodes + block->end + 1;
-               zend_bitset_clear(defined_here, bitset_len);
+               if (!(block->flags & ZEND_BB_FOLLOW) ||
+                   (block->flags & ZEND_BB_TARGET)) {
+                       /* Skip continuation of "extended" BB */
+                       zend_bitset_clear(defined_here, bitset_len);
+               }
 
                while (opline<end) {
                        if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
@@ -1551,8 +1561,10 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
                }
        }
 
-       for (n = 0; n < cfg->blocks_count; n++) {
-               block = cfg->blocks + n;
+       usage = defined_here;
+       next_block = NULL;
+       for (n = cfg->blocks_count; n > 0;) {
+               block = cfg->blocks + (--n);
 
                if (!(block->flags & ZEND_BB_REACHABLE)) {
                        continue;
@@ -1560,7 +1572,15 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
 
                opline = op_array->opcodes + block->end;
                end = op_array->opcodes + block->start;
-               zend_bitset_copy(usage, used_ext, bitset_len);
+               if (!next_block ||
+                   !(next_block->flags & ZEND_BB_FOLLOW) ||
+                   (next_block->flags & ZEND_BB_TARGET)) {
+                       /* Skip continuation of "extended" BB */
+                       zend_bitset_copy(usage, used_ext, bitset_len);
+               } else if (block->successors[1] != -1) {
+                       zend_bitset_union(usage, used_ext, bitset_len);
+               }
+               next_block = block;
 
                while (opline >= end) {
                        /* usage checks */
@@ -1753,9 +1773,16 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
 
                /* optimize each basic block separately */
                for (b = blocks; b < end; b++) {
-                       if (b->flags & ZEND_BB_REACHABLE) {
-                               zend_optimize_block(b, op_array, usage, &cfg, Tsource);
+                       if (!(b->flags & ZEND_BB_REACHABLE)) {
+                               continue;
+                       }
+                       /* we track data dependencies only insight a single basic block */
+                       if (!(b->flags & ZEND_BB_FOLLOW) ||
+                           (b->flags & ZEND_BB_TARGET)) {
+                               /* Skip continuation of "extended" BB */
+                               memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
                        }
+                       zend_optimize_block(b, op_array, usage, &cfg, Tsource);
                }
 
                /* Jump optimization for each block */
index 76d1bb44ab32e1be1ecbbac905445bfc92f87082..dcfaa3fbc131347f8b52d2dd82e71441dfa090ac 100644 (file)
@@ -36,6 +36,7 @@
 #define ZEND_BB_FINALLY_END      (1<<8)  /* end of finally block   */
 #define ZEND_BB_GEN_VAR          (1<<9)  /* start of live range    */
 #define ZEND_BB_KILL_VAR         (1<<10) /* end of live range      */
+#define ZEND_BB_EMPTY            (1<<11)
 
 #define ZEND_BB_LOOP_HEADER      (1<<16)
 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
index e411a4bc3a319802c9dd273066f762f3437663c1..e73d8567ffabfcbbc6e49188fe01cb4ad984402a 100644 (file)
@@ -215,11 +215,13 @@ void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, uint
                                }
                                fprintf(stderr, "\n");
 
-                               opline = op_array->opcodes + b->start;
-                               end = op_array->opcodes + b->end + 1;
-                               while (opline < end) {
-                                       zend_dump_op(op_array, b, opline);
-                                       opline++;
+                               if (!(b->flags & ZEND_BB_EMPTY)) {
+                                       opline = op_array->opcodes + b->start;
+                                       end = op_array->opcodes + b->end + 1;
+                                       while (opline < end) {
+                                               zend_dump_op(op_array, b, opline);
+                                               opline++;
+                                       }
                                }
                        }
                }