diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index bd1946e960b08..56a93558bd5e6 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -22,6 +22,7 @@ #include "php.h" #include "Optimizer/zend_optimizer.h" #include "Optimizer/zend_optimizer_internal.h" +#include "Optimizer/zend_call_graph.h" #include "zend_API.h" #include "zend_constants.h" #include "zend_execute.h" @@ -924,12 +925,14 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array /* Rebuild plain (optimized) op_array from CFG */ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_optimizer_ctx *ctx) { + zend_func_info *func_info; zend_basic_block *blocks = cfg->blocks; zend_basic_block *end = blocks + cfg->blocks_count; zend_basic_block *b; zend_op *new_opcodes; zend_op *opline; uint32_t len = 0; + size_t opline_delta; int n; for (b = blocks; b < end; b++) { @@ -970,6 +973,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op } new_opcodes = emalloc(len * sizeof(zend_op)); + opline_delta = ((uint8_t *)new_opcodes) - ((uint8_t *)op_array->opcodes); opline = new_opcodes; /* Copy code of reachable blocks into a single buffer */ @@ -1095,6 +1099,17 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op zend_build_delayed_early_binding_list(op_array); } + /* update call graph (needed in second run of pass 5) */ + func_info = ZEND_FUNC_INFO(op_array); + if (func_info) { + zend_call_info *call_info = func_info->callee_info; + while (call_info) { + call_info->caller_init_opline = (zend_op *)(((uint8_t *)call_info->caller_init_opline) + opline_delta); + call_info->caller_call_opline = (zend_op *)(((uint8_t *)call_info->caller_call_opline) + opline_delta); + call_info = call_info->next_callee; + } + } + /* rebuild map (just for printing) */ memset(cfg->map, -1, sizeof(int) * op_array->last); for (n = 0; n < cfg->blocks_count; n++) { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 84d4c61831bb7..be2a185a3d329 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -1300,6 +1300,16 @@ static void zend_optimize_op_array(zend_op_array *op_array, /* Redo pass_two() */ zend_redo_pass_two(op_array); + /* pass 5: + * - CFG optimization (again) after converting code to no-ops. + */ + if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) { + zend_optimize_cfg(op_array, ctx); + if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_5) { + zend_dump_op_array(op_array, 0, "after repeating pass 5", NULL); + } + } + if (op_array->live_range) { zend_recalc_live_ranges(op_array, NULL); } @@ -1417,6 +1427,15 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend } } + if (ZEND_OPTIMIZER_PASS_5 & optimization_level) { + for (i = 0; i < call_graph.op_arrays_count; i++) { + zend_optimize_cfg(call_graph.op_arrays[i], &ctx); + if (debug_level & ZEND_DUMP_AFTER_PASS_5) { + zend_dump_op_array(call_graph.op_arrays[i], 0, "after repeating pass 5", NULL); + } + } + } + if (ZEND_OPTIMIZER_PASS_11 & optimization_level) { for (i = 0; i < call_graph.op_arrays_count; i++) { zend_optimizer_compact_literals(call_graph.op_arrays[i], &ctx); diff --git a/ext/opcache/tests/opt/sccp_002.phpt b/ext/opcache/tests/opt/sccp_002.phpt index 0fd10f2ac57ad..373c24bfef63d 100644 --- a/ext/opcache/tests/opt/sccp_002.phpt +++ b/ext/opcache/tests/opt/sccp_002.phpt @@ -28,10 +28,9 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %ssccp_002.php:1-14 L0 (14): RETURN int(1) -foo: ; (lines=4, args=1, vars=1, tmps=0) +foo: ; (lines=3, args=1, vars=1, tmps=0) ; (after optimizer) ; %ssccp_002.php:2-12 L0 (2): CV0($x) = RECV 1 -L1 (9): ECHO int(1) -L2 (11): ECHO int(1) -L3 (12): RETURN null +L1 (11): ECHO string("11") +L2 (12): RETURN null diff --git a/ext/opcache/tests/opt/sccp_003.phpt b/ext/opcache/tests/opt/sccp_003.phpt index 282a5788e628b..1ae7dde91fc82 100644 --- a/ext/opcache/tests/opt/sccp_003.phpt +++ b/ext/opcache/tests/opt/sccp_003.phpt @@ -28,9 +28,8 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %ssccp_003.php:1-14 L0 (14): RETURN int(1) -foo: ; (lines=3, args=0, vars=0, tmps=0) +foo: ; (lines=2, args=0, vars=0, tmps=0) ; (after optimizer) ; %ssccp_003.php:2-12 -L0 (9): ECHO int(1) -L1 (11): ECHO int(1) -L2 (12): RETURN null +L0 (11): ECHO string("11") +L1 (12): RETURN null diff --git a/ext/opcache/tests/opt/sccp_004.phpt b/ext/opcache/tests/opt/sccp_004.phpt index d82212e0ef004..5d09fe9bbc506 100644 --- a/ext/opcache/tests/opt/sccp_004.phpt +++ b/ext/opcache/tests/opt/sccp_004.phpt @@ -31,10 +31,9 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %ssccp_004.php:1-17 L0 (17): RETURN int(1) -foo: ; (lines=4, args=1, vars=1, tmps=0) +foo: ; (lines=3, args=1, vars=1, tmps=0) ; (after optimizer) ; %ssccp_004.php:2-15 L0 (2): CV0($x) = RECV 1 -L1 (11): ECHO bool(true) -L2 (14): ECHO int(1) -L3 (15): RETURN null +L1 (14): ECHO string("11") +L2 (15): RETURN null diff --git a/ext/opcache/tests/opt/sccp_010.phpt b/ext/opcache/tests/opt/sccp_010.phpt index e88bf579f7178..82e3a6546b0fb 100644 --- a/ext/opcache/tests/opt/sccp_010.phpt +++ b/ext/opcache/tests/opt/sccp_010.phpt @@ -29,9 +29,8 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %ssccp_010.php:1-15 L0 (15): RETURN int(1) -foo: ; (lines=3, args=0, vars=0, tmps=0) +foo: ; (lines=2, args=0, vars=0, tmps=0) ; (after optimizer) ; %ssccp_010.php:2-13 -L0 (10): ECHO int(1) -L1 (12): ECHO int(1) -L2 (13): RETURN null +L0 (12): ECHO string("11") +L1 (13): RETURN null diff --git a/ext/opcache/tests/opt/sccp_012.phpt b/ext/opcache/tests/opt/sccp_012.phpt index 5d2f3e9a01c9b..3948063762650 100644 --- a/ext/opcache/tests/opt/sccp_012.phpt +++ b/ext/opcache/tests/opt/sccp_012.phpt @@ -31,9 +31,8 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %ssccp_012.php:1-17 L0 (17): RETURN int(1) -foo: ; (lines=3, args=0, vars=0, tmps=0) +foo: ; (lines=2, args=0, vars=0, tmps=0) ; (after optimizer) ; %ssccp_012.php:2-15 -L0 (10): ECHO int(1) -L1 (14): ECHO int(4) -L2 (15): RETURN null +L0 (14): ECHO string("14") +L1 (15): RETURN null diff --git a/ext/opcache/tests/opt/sccp_026.phpt b/ext/opcache/tests/opt/sccp_026.phpt index 132c9ddef3bd3..7948b379a0b2c 100644 --- a/ext/opcache/tests/opt/sccp_026.phpt +++ b/ext/opcache/tests/opt/sccp_026.phpt @@ -15,7 +15,7 @@ function test($var) { return; } - var_dump($username); + var_dump($username); } ?> --EXPECTF-- @@ -24,15 +24,14 @@ $_main: ; (lines=1, args=0, vars=0, tmps=0) ; %s:1-10 L0 (10): RETURN int(1) -test: ; (lines=9, args=1, vars=2, tmps=1) +test: ; (lines=8, args=1, vars=2, tmps=1) ; (after optimizer) ; %s:2-8 L0 (2): CV0($var) = RECV 1 L1 (3): T2 = TYPE_CHECK (string) CV0($var) -L2 (3): JMPZ T2 L4 -L3 (3): JMP L5 -L4 (4): RETURN null -L5 (7): INIT_FCALL 1 %d string("var_dump") -L6 (7): SEND_VAR CV1($username) 1 -L7 (7): DO_ICALL -L8 (8): RETURN null +L2 (3): JMPNZ T2 L4 +L3 (4): RETURN null +L4 (7): INIT_FCALL 1 96 string("var_dump") +L5 (7): SEND_VAR CV1($username) 1 +L6 (7): DO_ICALL +L7 (8): RETURN null