From: Dmitry Stogov Date: Mon, 29 Aug 2016 17:35:17 +0000 (+0300) Subject: Allow optional splitting of basic blocks at RECV/RECV_INIT opcodes. X-Git-Tag: php-7.1.0RC1~29 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=94fbcbe17265b11e26dee6cfaf2bb7913beef461;p=php Allow optional splitting of basic blocks at RECV/RECV_INIT opcodes. --- diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index 04be6a2e26..f39f9650ae 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -70,6 +70,12 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc b->flags |= ZEND_BB_ENTRY; } } + if (cfg->split_at_recv) { + if (opcode == ZEND_RECV || + opcode == ZEND_RECV_INIT) { + b->flags |= ZEND_BB_RECV_ENTRY; + } + } } } else { b = blocks + successor_0; @@ -283,6 +289,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b cfg->split_at_live_ranges = (build_flags & ZEND_CFG_SPLIT_AT_LIVE_RANGES) != 0; cfg->split_at_calls = (build_flags & ZEND_CFG_STACKLESS) != 0; + cfg->split_at_recv = (build_flags & ZEND_CFG_RECV_ENTRY) != 0 && (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0; cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t)); if (!block_map) { @@ -294,6 +301,12 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b for (i = 0; i < op_array->last; i++) { zend_op *opline = op_array->opcodes + i; switch(opline->opcode) { + case ZEND_RECV: + case ZEND_RECV_INIT: + if (build_flags & ZEND_CFG_RECV_ENTRY) { + BB_START(i + 1); + } + break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: case ZEND_GENERATOR_RETURN: diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index 0682629019..1ffb62add0 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -32,13 +32,14 @@ #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_UNREACHABLE_FREE (1<<11) /* unreachable loop free */ +#define ZEND_BB_RECV_ENTRY (1<<12) /* RECV entry */ #define ZEND_BB_LOOP_HEADER (1<<16) #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17) #define ZEND_BB_REACHABLE (1<<31) -#define ZEND_BB_PROTECTED (ZEND_BB_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR) +#define ZEND_BB_PROTECTED (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR) typedef struct _zend_basic_block { uint32_t flags; @@ -88,6 +89,7 @@ typedef struct _zend_cfg { uint32_t *map; unsigned int split_at_live_ranges : 1; unsigned int split_at_calls : 1; + unsigned int split_at_recv : 1; } zend_cfg; /* Build Flags */ @@ -98,6 +100,7 @@ typedef struct _zend_cfg { #define ZEND_SSA_RC_INFERENCE (1<<27) #define ZEND_CFG_SPLIT_AT_LIVE_RANGES (1<<26) #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25) +#define ZEND_CFG_RECV_ENTRY (1<<24) #define CRT_CONSTANT_EX(op_array, node, rt_constants) \ ((rt_constants) ? \ diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index a611b55cd5..ed9b6a59d9 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -669,7 +669,7 @@ static void zend_dump_block_info(const zend_cfg *cfg, int n, uint32_t dump_flags if (b->flags & ZEND_BB_EXIT) { fprintf(stderr, " exit"); } - if (b->flags & ZEND_BB_ENTRY) { + if (b->flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) { fprintf(stderr, " entry"); } if (b->flags & ZEND_BB_TRY) {