]> granicus.if.org Git - php/commitdiff
Replace BB end with BB len
authorNikita Popov <nikic@php.net>
Wed, 18 May 2016 16:03:05 +0000 (18:03 +0200)
committerNikita Popov <nikic@php.net>
Tue, 24 May 2016 16:29:44 +0000 (18:29 +0200)
And support empty blocks everywhere.

ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/Optimizer/zend_cfg.h
ext/opcache/Optimizer/zend_dfg.c
ext/opcache/Optimizer/zend_dump.c
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_ssa.c

index 6ad5110999b318d86cea974688fd34c31d6891ae..2e84b73252f509c31dfb6b0a8e2b67578d695fbc 100644 (file)
@@ -90,8 +90,9 @@ static void strip_leading_nops(zend_op_array *op_array, zend_basic_block *b)
 {
        zend_op *opcodes = op_array->opcodes;
 
-       while (opcodes[b->start].opcode == ZEND_NOP && b->start < b->end) {
+       while (b->len > 0 && opcodes[b->start].opcode == ZEND_NOP) {
                b->start++;
+               b->len--;
        }
 }
 
@@ -100,10 +101,13 @@ static void strip_nops(zend_op_array *op_array, zend_basic_block *b)
        uint32_t i, j;
 
        strip_leading_nops(op_array, b);
+       if (b->len == 0) {
+               return;
+       }
 
        /* strip the inside NOPs */
        i = j = b->start + 1;
-       while (i <= b->end) {
+       while (i < b->start + b->len) {
                if (op_array->opcodes[i].opcode != ZEND_NOP) {
                        if (i != j) {
                                op_array->opcodes[j] = op_array->opcodes[i];
@@ -112,7 +116,7 @@ static void strip_nops(zend_op_array *op_array, zend_basic_block *b)
                }
                i++;
        }
-       b->end = j - 1;
+       b->len = j - b->start;
        while (j < i) {
                MAKE_NOP(op_array->opcodes + j);
                j++;
@@ -128,9 +132,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
        strip_leading_nops(op_array, block);
 
        opline = op_array->opcodes + block->start;
-       end = op_array->opcodes + block->end + 1;
+       end = opline + block->len;
        while (opline < end) {
-
                /* Constant Propagation: strip X = QM_ASSIGN(const) */
                if ((opline->op1_type & (IS_TMP_VAR|IS_VAR)) &&
                    opline->opcode != ZEND_FREE) {
@@ -769,34 +772,32 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        int n;
 
        for (b = blocks; b < end; b++) {
+               if (b->len == 0) {
+                       continue;
+               }
                if (b->flags & ZEND_BB_REACHABLE) {
-                       ZEND_ASSERT(b->start <= b->end);
-                       opline = op_array->opcodes + b->end;
+                       opline = op_array->opcodes + b->start + b->len - 1;
                        if (opline->opcode == ZEND_JMP) {
                                zend_basic_block *next = b + 1;
 
-                               while (next < end && (!(next->flags & ZEND_BB_REACHABLE) || next->start > next->end)) {
+                               while (next < end && !(next->flags & ZEND_BB_REACHABLE)) {
                                        next++;
                                }
                                if (next < end && next == blocks + b->successors[0]) {
                                        /* JMP to the next block - strip it */
                                        MAKE_NOP(opline);
-                                       if (b->end == 0) {
-                                               b->start++;
-                                       } else {
-                                               b->end--;
-                                       }
+                                       b->len--;
                                }
-                       } else if (b->start == b->end && opline->opcode == ZEND_NOP) {
+                       } else if (b->len == 1 && opline->opcode == ZEND_NOP) {
                                /* skip empty block */
-                               b->start++;
+                               b->len--;
                        }
-                       len += b->end - b->start + 1;
-               } else if (b->start <= b->end) {
+                       len += b->len;
+               } else {
                        /* this block will not be used, delete all constants there */
-                       zend_op *op;
-                       zend_op *end = op_array->opcodes + b->end ;
-                       for (op = op_array->opcodes + b->start; op <= end; op++) {
+                       zend_op *op = op_array->opcodes + b->start;
+                       zend_op *end = op + b->len;
+                       for (; op < end; op++) {
                                if (ZEND_OP1_TYPE(op) == IS_CONST) {
                                        literal_dtor(&ZEND_OP1_LITERAL(op));
                                }
@@ -813,16 +814,9 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        /* Copy code of reachable blocks into a single buffer */
        for (b = blocks; b < end; b++) {
                if (b->flags & ZEND_BB_REACHABLE) {
-                       if (b->start <= b->end) {
-                               uint32_t n = b->end - b->start + 1;
-                               memcpy(opline, op_array->opcodes + b->start, n * sizeof(zend_op));
-                               b->start = opline - new_opcodes;
-                               b->end = opline - new_opcodes + n - 1;
-                               opline += n;
-                       } else {
-                               b->flags |= ZEND_BB_EMPTY;
-                               b->start = b->end = opline - new_opcodes;
-                       }
+                       memcpy(opline, op_array->opcodes + b->start, b->len * sizeof(zend_op));
+                       b->start = opline - new_opcodes;
+                       opline += b->len;
                }
        }
 
@@ -832,10 +826,10 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        op_array->last = len;
 
        for (b = blocks; b < end; b++) {
-               if (!(b->flags & ZEND_BB_REACHABLE) || b->start > b->end) {
+               if (!(b->flags & ZEND_BB_REACHABLE) || b->len == 0) {
                        continue;
                }
-               opline = op_array->opcodes + b->end;
+               opline = op_array->opcodes + b->start + b->len - 1;
                switch (opline->opcode) {
                        case ZEND_FAST_CALL:
                        case ZEND_JMP:
@@ -1002,8 +996,11 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
        zend_basic_block *blocks = cfg->blocks;
        zend_op *last_op;
 
-       ZEND_ASSERT(block->start <= block->end);
-       last_op = op_array->opcodes + block->end;
+       if (block->len == 0) {
+               return;
+       }
+
+       last_op = op_array->opcodes + block->start + block->len - 1;
        switch (last_op->opcode) {
                case ZEND_JMP:
                        {
@@ -1019,9 +1016,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
                                /* JMP(next) -> NOP */
                                if (block->successors[0] == next) {
                                        MAKE_NOP(last_op);
-                                       if (block->start != block->end) {
-                                               block->end--;
-                                       }
+                                       block->len--;
                                        break;
                                }
 
@@ -1165,7 +1160,7 @@ static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_arr
 
 next_target:
                                target = op_array->opcodes + target_block->start;
-                               target_end = op_array->opcodes + target_block->end + 1;
+                               target_end = target + target_block->len;
                                while (target < target_end && target->opcode == ZEND_NOP) {
                                        target++;
                                }
@@ -1301,7 +1296,7 @@ next_target:
                                target_block = blocks + block->successors[0];
 next_target_ex:
                                target = op_array->opcodes + target_block->start;
-                               target_end = op_array->opcodes + target_block->end + 1;
+                               target_end = target + target_block->len;
                                while (target < target_end && target->opcode == ZEND_NOP) {
                                        target++;
                                }
@@ -1424,7 +1419,7 @@ next_target_ex:
 
 next_target_znz:
                                target = op_array->opcodes + target_block->start;
-                               target_end = op_array->opcodes + target_block->end + 1;
+                               target_end = target + target_block->len;
                                while (target < target_end && target->opcode == ZEND_NOP) {
                                        target++;
                                }
@@ -1497,7 +1492,7 @@ 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;
+               end = opline + block->len;
                if (!(block->flags & ZEND_BB_FOLLOW) ||
                    (block->flags & ZEND_BB_TARGET)) {
                        /* Skip continuation of "extended" BB */
@@ -1572,12 +1567,12 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
        for (n = cfg->blocks_count; n > 0;) {
                block = cfg->blocks + (--n);
 
-               if (!(block->flags & ZEND_BB_REACHABLE)) {
+               if (!(block->flags & ZEND_BB_REACHABLE) || block->len == 0) {
                        continue;
                }
 
-               opline = op_array->opcodes + block->end;
                end = op_array->opcodes + block->start;
+               opline = end + block->len - 1;
                if (!next_block ||
                    !(next_block->flags & ZEND_BB_FOLLOW) ||
                    (next_block->flags & ZEND_BB_TARGET)) {
@@ -1697,16 +1692,17 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg)
                        if ((b->flags & ZEND_BB_FOLLOW) &&
                            !(b->flags & (ZEND_BB_TARGET | ZEND_BB_PROTECTED)) &&
                            prev &&
-                           prev->successors[0] == i && prev->successors[1] == -1) {
-
-                               if (op_array->opcodes[prev->end].opcode == ZEND_JMP) {
-                                       MAKE_NOP(op_array->opcodes + prev->end);
+                           prev->successors[0] == i && prev->successors[1] == -1)
+                       {
+                               zend_op *last_op = op_array->opcodes + prev->start + prev->len - 1;
+                               if (prev->len != 0 && last_op->opcode == ZEND_JMP) {
+                                       MAKE_NOP(last_op);
                                }
 
                                for (bb = prev + 1; bb != b; bb++) {
                                        zend_op *op = op_array->opcodes + bb->start;
-                                       zend_op *end = op_array->opcodes + bb->end;
-                                       while (op <= end) {
+                                       zend_op *end = op + bb->len;
+                                       while (op < end) {
                                                if (ZEND_OP1_TYPE(op) == IS_CONST) {
                                                        literal_dtor(&ZEND_OP1_LITERAL(op));
                                                }
@@ -1717,18 +1713,18 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg)
                                                op++;
                                        }
                                        /* make block empty */
-                                       bb->start = bb->end + 1;
+                                       bb->len = 0;
                                }
 
                                /* re-link */
-                           prev->flags |= (b->flags & ZEND_BB_EXIT);
-                               prev->end = b->end;
+                               prev->flags |= (b->flags & ZEND_BB_EXIT);
+                               prev->len = b->start + b->len - prev->start;
                                prev->successors[0] = b->successors[0];
                                prev->successors[1] = b->successors[1];
 
                                /* unlink & make block empty and unreachable */
                                b->flags = 0;
-                               b->start = b->end + 1;
+                               b->len = 0;
                                b->successors[0] = -1;
                                b->successors[1] = -1;
                        } else {
index 40a3dc996b5ea91e14b294f42217b288a021a2b3..f7cae772fbb1600930e8f77bf2de3b2a954fed38 100644 (file)
@@ -129,16 +129,18 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
        memset(shiftlist, 0, sizeof(uint32_t) * op_array->last);
        for (b = blocks; b < end; b++) {
                if (b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE)) {
+                       uint32_t end;
                        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;
+                               b->len = 1;
                        }
 
+                       end = b->start + b->len;
                        i = b->start;
                        b->start = target;
-                       while (i <= b->end) {
+                       while (i < end) {
                                if (EXPECTED(op_array->opcodes[i].opcode != ZEND_NOP) ||
                                   /*keep NOP to support ZEND_VM_SMART_BRANCH */
                                   (i > 0 &&
@@ -168,13 +170,13 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
                                }
                                i++;
                        }
-                       if (b->end != target - 1) {
+                       if (target != end && b->len != 0) {
                                zend_op *opline;
                                zend_op *new_opline;
 
-                               opline = op_array->opcodes + b->end;
-                               b->end = target - 1;
-                               new_opline = op_array->opcodes + b->end;
+                               opline = op_array->opcodes + end - 1;
+                               b->len = target - b->start;
+                               new_opline = op_array->opcodes + target - 1;
                                switch (new_opline->opcode) {
                                        case ZEND_JMP:
                                        case ZEND_FAST_CALL:
@@ -239,8 +241,8 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
 
                /* update branch targets */
                for (b = blocks; b < end; b++) {
-                       if (b->flags & ZEND_BB_REACHABLE) {
-                               zend_op *opline = op_array->opcodes + b->end;
+                       if ((b->flags & ZEND_BB_REACHABLE) && b->len != 0) {
+                               zend_op *opline = op_array->opcodes + b->start + b->len - 1;
 
                                switch (opline->opcode) {
                                        case ZEND_JMP:
index 33c34b85c4d5aa8d6401faf7d7bbe3bfa2b949cc..2bf43fe9c5ac14eb04351c2641166579198a862e 100644 (file)
@@ -39,15 +39,17 @@ static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend
                                if (!(b0->flags & ZEND_BB_REACHABLE)) {
                                        zend_mark_reachable(opcodes, blocks, b0);
                                }
-                               opcode = opcodes[b->end].opcode;
+
+                               ZEND_ASSERT(b->len != 0);
+                               opcode = opcodes[b->start + b->len - 1].opcode;
                                b = blocks + successor_1;
                                if (opcode == ZEND_JMPZNZ) {
                                        b->flags |= ZEND_BB_TARGET;
                                } else {
                                        b->flags |= ZEND_BB_FOLLOW;
                                }
-                       } else {
-                               opcode = opcodes[b->end].opcode;
+                       } else if (b->len != 0) {
+                               opcode = opcodes[b->start + b->len - 1].opcode;
                                b = blocks + successor_0;
                                if (opcode == ZEND_JMP) {
                                        b->flags |= ZEND_BB_TARGET;
@@ -67,6 +69,9 @@ static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend
                                                }
                                        }
                                }
+                       } else {
+                               b = blocks + successor_0;
+                               b->flags |= ZEND_BB_FOLLOW;
                        }
                        if (b->flags & ZEND_BB_REACHABLE) return;
                } else {
@@ -94,24 +99,24 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
 
                        /* Add live range paths */
                        for (j = 0; j < op_array->last_live_range; j++) {
-                               if (op_array->live_range[j].var == (uint32_t)-1) {
+                               zend_live_range *live_range = &op_array->live_range[j];
+                               if (live_range->var == (uint32_t)-1) {
                                        /* this live range already removed */
                                        continue;
                                }
-                               b = blocks + block_map[op_array->live_range[j].start];
+                               b = blocks + block_map[live_range->start];
                                if (b->flags & ZEND_BB_REACHABLE) {
-                                       while (op_array->opcodes[b->start].opcode == ZEND_NOP && b->start != b->end) {
+                                       while (b->len > 0 && op_array->opcodes[b->start].opcode == ZEND_NOP) {
                                                b->start++;
+                                               b->len--;
                                        }
-                                       if (op_array->opcodes[b->start].opcode == ZEND_NOP &&
-                                               b->start == b->end &&
-                                               b->successors[0] == block_map[op_array->live_range[j].end]) {
+                                       if (b->len == 0 && b->successors[0] == block_map[live_range->end]) {
                                                /* mark as removed (empty live range) */
-                                               op_array->live_range[j].var = (uint32_t)-1;
+                                               live_range->var = (uint32_t)-1;
                                                continue;
                                        }
                                        b->flags |= ZEND_BB_GEN_VAR;
-                                       b = blocks + block_map[op_array->live_range[j].end];
+                                       b = blocks + block_map[live_range->end];
                                        b->flags |= ZEND_BB_KILL_VAR;
                                        if (!(b->flags & ZEND_BB_REACHABLE)) {
                                                if (cfg->split_at_live_ranges) {
@@ -119,12 +124,12 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
                                                        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);
+                                                       ZEND_ASSERT(b->start == live_range->end);
                                                        b->flags |= ZEND_BB_UNREACHABLE_FREE;
                                                }
                                        }
                                } else {
-                                       ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE));
+                                       ZEND_ASSERT(!(blocks[block_map[live_range->end]].flags & ZEND_BB_REACHABLE));
                                }
                        }
 
@@ -435,7 +440,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
        for (i = 0, blocks_count = -1; i < op_array->last; i++) {
                if (block_map[i]) {
                        if (blocks_count >= 0) {
-                               blocks[blocks_count].end = i - 1;
+                               blocks[blocks_count].len = i - blocks[blocks_count].start;
                        }
                        blocks_count++;
                        blocks[blocks_count].flags = 0;
@@ -453,13 +458,19 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                block_map[i] = blocks_count;
        }
 
-       blocks[blocks_count].end = i - 1;
+       blocks[blocks_count].len = i - blocks[blocks_count].start;
        blocks_count++;
 
        /* Build CFG, Step 3: Calculate successors */
        for (j = 0; j < blocks_count; j++) {
-               zend_op *opline = op_array->opcodes + blocks[j].end;
-               switch(opline->opcode) {
+               zend_op *opline;
+               if (blocks[j].len == 0) {
+                       record_successor(blocks, j, 0, j + 1);
+                       continue;
+               }
+
+               opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
+               switch (opline->opcode) {
                        case ZEND_FAST_RET:
                        case ZEND_RETURN:
                        case ZEND_RETURN_BY_REF:
index cbf4225a317bdb78d548fc7bbb1a1a2f86491d20..244a2ade97420fade2eb9e12e4efebb011d59705 100644 (file)
@@ -31,8 +31,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_UNREACHABLE_FREE (1<<12) /* unreachable loop free  */
+#define ZEND_BB_UNREACHABLE_FREE (1<<11) /* unreachable loop free  */
 
 #define ZEND_BB_LOOP_HEADER      (1<<16)
 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
@@ -44,7 +43,7 @@
 typedef struct _zend_basic_block {
        uint32_t          flags;
        uint32_t          start;              /* first opcode number         */
-       uint32_t          end;                /* last opcode number          */
+       uint32_t          len;                /* number of opcodes           */
        int               successors[2];      /* up to 2 successor blocks    */
        int               predecessors_count; /* number of predecessors      */
        int               predecessor_offset; /* offset of 1-st predecessor  */
index c1972128d5485304451d256b2cfdad071b931c3c..abc9b3a1f5497a0be96b78fe6f50ffa83998cc4c 100644 (file)
@@ -26,7 +26,6 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
        zend_basic_block *blocks = cfg->blocks;
        int blocks_count = cfg->blocks_count;
        zend_bitset tmp, def, use, in, out;
-       zend_op *opline;
        uint32_t k, var_num;
        int j;
 
@@ -39,15 +38,17 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
 
        /* Collect "def" and "use" sets */
        for (j = 0; j < blocks_count; j++) {
+               zend_op *opline, *end;
                if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
                        continue;
                }
-               for (k = blocks[j].start; k <= blocks[j].end; k++) {
-                       opline = op_array->opcodes + k;
+
+               opline = op_array->opcodes + blocks[j].start;
+               end = opline + blocks[j].len;
+               for (; opline < end; opline++) {
                        if (opline->opcode != ZEND_OP_DATA) {
                                zend_op *next = opline + 1;
-                               if (k < blocks[j].end &&
-                                       next->opcode == ZEND_OP_DATA) {
+                               if (next < end && next->opcode == ZEND_OP_DATA) {
                                        if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
                                                var_num = EX_VAR_TO_NUM(next->op1.var);
                                                if (!DFG_ISSET(def, set_size, j, var_num)) {
index 70abe4d317bfc7d649bbc9a5bbd4b5938c937d19..d85fb82d8394ec6e901be820da5aa1de94a19e66 100644 (file)
@@ -722,7 +722,11 @@ static void zend_dump_block_info(const zend_cfg *cfg, int n, uint32_t dump_flags
        if (b->flags & ZEND_BB_IRREDUCIBLE_LOOP) {
                fprintf(stderr, " irreducible");
        }
-       fprintf(stderr, " lines=[%d-%d]", b->start, b->end);
+       if (b->len != 0) {
+               fprintf(stderr, " lines=[%d-%d]", b->start, b->start + b->len - 1);
+       } else {
+               fprintf(stderr, " empty");
+       }
        fprintf(stderr, "\n");
 
        if (b->predecessors_count) {
@@ -936,13 +940,11 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons
                                const zend_op *end;
 
                                zend_dump_block_header(cfg, op_array, ssa, n, dump_flags);
-                               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, dump_flags, data);
-                                               opline++;
-                                       }
+                               opline = op_array->opcodes + b->start;
+                               end = opline + b->len;
+                               while (opline < end) {
+                                       zend_dump_op(op_array, b, opline, dump_flags, data);
+                                       opline++;
                                }
                        }
                }
index fd39baf749e0acf4566a1e65c6d162e7884fd2f2..168609f9a0b59a37257f449ffaf6729bc68d5dc8 100644 (file)
@@ -3613,8 +3613,8 @@ void zend_func_return_info(const zend_op_array   *op_array,
        }
 
        for (j = 0; j < blocks_count; j++) {
-               if (blocks[j].flags & ZEND_BB_REACHABLE) {
-                       zend_op *opline = op_array->opcodes + blocks[j].end;
+               if ((blocks[j].flags & ZEND_BB_REACHABLE) && blocks[j].len != 0) {
+                       zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
 
                        if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) {
                                if (!recursive &&
index a008e1029bb9163dbdc93539ccd4787b84c78bfb..3c3e758b0d0d3f6ba6b7b4ce91a22d9d6f4f4485 100644 (file)
@@ -225,11 +225,11 @@ static void place_essa_pis(
        int j, blocks_count = ssa->cfg.blocks_count;
        for (j = 0; j < blocks_count; j++) {
                zend_ssa_phi *pi;
-               zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].end;
+               zend_op *opline = op_array->opcodes + blocks[j].start + blocks[j].len - 1;
                int bt; /* successor block number if a condition is true */
                int bf; /* successor block number if a condition is false */
 
-               if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
+               if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0 || blocks[j].len == 0) {
                        continue;
                }
                /* the last instruction of basic block is conditional branch,
@@ -238,12 +238,12 @@ static void place_essa_pis(
                switch (opline->opcode) {
                        case ZEND_JMPZ:
                        case ZEND_JMPZNZ:
-                               bf = ssa->cfg.blocks[j].successors[0];
-                               bt = ssa->cfg.blocks[j].successors[1];
+                               bf = blocks[j].successors[0];
+                               bt = blocks[j].successors[1];
                                break;
                        case ZEND_JMPNZ:
-                               bt = ssa->cfg.blocks[j].successors[0];
-                               bf = ssa->cfg.blocks[j].successors[1];
+                               bt = blocks[j].successors[0];
+                               bf = blocks[j].successors[1];
                                break;
                        default:
                                continue;
@@ -493,8 +493,7 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags,
        zend_ssa_op *ssa_ops = ssa->ops;
        int ssa_vars_count = ssa->vars_count;
        int i, j;
-       uint32_t k;
-       zend_op *opline;
+       zend_op *opline, *end;
        int *tmp = NULL;
        ALLOCA_FLAG(use_heap);
 
@@ -519,12 +518,13 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags,
                } while (phi);
        }
 
-       for (k = blocks[n].start; k <= blocks[n].end; k++) {
-               opline = op_array->opcodes + k;
+       opline = op_array->opcodes + blocks[n].start;
+       end = opline + blocks[n].len;
+       for (; opline < end; opline++) {
+               uint32_t k = opline - op_array->opcodes;
                if (opline->opcode != ZEND_OP_DATA) {
                        zend_op *next = opline + 1;
-                       if (k < blocks[n].end &&
-                           next->opcode == ZEND_OP_DATA) {
+                       if (next < end && next->opcode == ZEND_OP_DATA) {
                                if (next->op1_type == IS_CV) {
                                        ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)];
                                        //USE_SSA_VAR(next->op1.var);