]> granicus.if.org Git - php/commitdiff
Improve previous fix
authorNikita Popov <nikic@php.net>
Sat, 21 May 2016 22:05:06 +0000 (00:05 +0200)
committerNikita Popov <nikic@php.net>
Sat, 21 May 2016 22:05:06 +0000 (00:05 +0200)
Do not mark loop var free blocks as reachable after all -- as we
can't construct SSA for unreachable blocks, this would cause
issues down the line.

Instead add an extra UNREACHABLE_FREE flag and retain only the
FREE instruction during NOP removal. (If we retain all
instructions in the BB we might leave a jump instruction that goes
into the nowhere.)

ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/Optimizer/zend_cfg.h
ext/opcache/Optimizer/zend_dump.c

index 3f4112a7db066e40e17025c9e9ac602bddd038be..40a3dc996b5ea91e14b294f42217b288a021a2b3 100644 (file)
@@ -128,7 +128,14 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
        shiftlist = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last, use_heap);
        memset(shiftlist, 0, sizeof(uint32_t) * op_array->last);
        for (b = blocks; b < end; b++) {
-               if (b->flags & ZEND_BB_REACHABLE) {
+               if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) {
+                       if (b->flags & ZEND_BB_UNREACHABLE_FREE) {
+                               /* Only keep the FREE for the loop var */
+                               ZEND_ASSERT(op_array->opcodes[b->start].opcode == ZEND_FREE
+                                               || op_array->opcodes[b->start].opcode == ZEND_FE_FREE);
+                               b->end = b->start;
+                       }
+
                        i = b->start;
                        b->start = target;
                        while (i <= b->end) {
index c675da1116170ec89f8c38f2c8c6fb77e52580ba..33c34b85c4d5aa8d6401faf7d7bbe3bfa2b949cc 100644 (file)
@@ -114,8 +114,14 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
                                        b = blocks + block_map[op_array->live_range[j].end];
                                        b->flags |= ZEND_BB_KILL_VAR;
                                        if (!(b->flags & ZEND_BB_REACHABLE)) {
-                                               changed = 1;
-                                               zend_mark_reachable(op_array->opcodes, blocks, b);
+                                               if (cfg->split_at_live_ranges) {
+                                                       changed = 1;
+                                                       zend_mark_reachable(op_array->opcodes, blocks, b);
+                                               } else {
+                                                       ZEND_ASSERT(!(b->flags & ZEND_BB_UNREACHABLE_FREE));
+                                                       ZEND_ASSERT(b->start == op_array->live_range[j].end);
+                                                       b->flags |= ZEND_BB_UNREACHABLE_FREE;
+                                               }
                                        }
                                } else {
                                        ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE));
index de94997dd5f537f2f6ed34b325cf0ce6350a43b4..cbf4225a317bdb78d548fc7bbb1a1a2f86491d20 100644 (file)
@@ -32,6 +32,7 @@
 #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_UNREACHABLE_FREE (1<<12) /* unreachable loop free  */
 
 #define ZEND_BB_LOOP_HEADER      (1<<16)
 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
index 986e47034576725a3ba2eca6b5f8d17ea15fdd77..70abe4d317bfc7d649bbc9a5bbd4b5938c937d19 100644 (file)
@@ -399,9 +399,8 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
 
        if (!ssa || !ssa->ops || ssa->ops[opline - op_array->opcodes].result_use < 0) {
                if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
-                       if (ssa && ssa->ops) {
+                       if (ssa && ssa->ops && ssa->ops[opline - op_array->opcodes].result_def >= 0) {
                                int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def;
-                               ZEND_ASSERT(ssa_var_num >= 0);
                                zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags);
                        } else {
                                zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var));