Skip to content

Proposal: Run the Control Flow Graph pass twice #5097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ext/opcache/Optimizer/block_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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++) {
Expand Down
19 changes: 19 additions & 0 deletions ext/opcache/Optimizer/zend_optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 3 additions & 4 deletions ext/opcache/tests/opt/sccp_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 3 additions & 4 deletions ext/opcache/tests/opt/sccp_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 3 additions & 4 deletions ext/opcache/tests/opt/sccp_004.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 3 additions & 4 deletions ext/opcache/tests/opt/sccp_010.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 3 additions & 4 deletions ext/opcache/tests/opt/sccp_012.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
17 changes: 8 additions & 9 deletions ext/opcache/tests/opt/sccp_026.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function test($var) {
return;
}

var_dump($username);
var_dump($username);
}
?>
--EXPECTF--
Expand All @@ -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