diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-12-24 14:30:41 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-12-24 14:30:41 +0300 |
commit | b4def0ee884a32c5169123b9feed630e4906b366 (patch) | |
tree | b489952a01ebb047b42c49507dd5fbe73897b1c8 | |
parent | a882d0fd7bc3238f59a4bb3d3f3d9e86ec5c3fe1 (diff) | |
download | php-git-b4def0ee884a32c5169123b9feed630e4906b366.tar.gz |
Added call-graph analyses
-rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 8 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 68 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.h | 2 | ||||
-rw-r--r-- | ext/opcache/ZendAccelerator.c | 4 |
4 files changed, 66 insertions, 16 deletions
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index ac7a193675..a2a94af073 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -30,10 +30,6 @@ #include "zend_inference.h" #include "zend_dump.h" -#ifndef HAVE_DFA_PASS -# define HAVE_DFA_PASS 0 -#endif - void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx) { void *checkpoint; @@ -41,10 +37,6 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx) uint32_t flags = 0; zend_ssa ssa; -#if !HAVE_DFA_PASS - return; -#endif - /* Build SSA */ memset(&ssa, 0, sizeof(ssa)); checkpoint = zend_arena_checkpoint(ctx->arena); diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 4434101081..01d56b3c33 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -28,8 +28,13 @@ #include "zend_vm.h" #include "zend_cfg.h" #include "zend_func_info.h" +#include "zend_call_graph.h" #include "zend_dump.h" +#ifndef HAVE_DFA_PASS +# define HAVE_DFA_PASS 0 +#endif + static void zend_optimizer_zval_dtor_wrapper(zval *zvalue) { zval_dtor(zvalue); @@ -606,15 +611,18 @@ static void zend_optimize(zend_op_array *op_array, } } +#if HAVE_DFA_PASS /* pass 6: * - DFA optimization */ - if (ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) { + if ((ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) && + !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level)) { optimize_dfa(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_6) { zend_dump_op_array(op_array, 0, "after pass 6", NULL); } } +#endif /* pass 9: * - Optimize temp variables usage @@ -651,12 +659,10 @@ static void zend_optimize(zend_op_array *op_array, } } -static void zend_optimize_op_array(zend_op_array *op_array, - zend_optimizer_ctx *ctx) +static void zend_revert_pass_two(zend_op_array *op_array) { zend_op *opline, *end; - /* Revert pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { @@ -668,11 +674,12 @@ static void zend_optimize_op_array(zend_op_array *op_array, } opline++; } +} - /* Do actual optimizations */ - zend_optimize(op_array, ctx); +static void zend_redo_pass_two(zend_op_array *op_array) +{ + zend_op *opline, *end; - /* Redo pass_two() */ opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { @@ -687,6 +694,19 @@ static void zend_optimize_op_array(zend_op_array *op_array, } } +static void zend_optimize_op_array(zend_op_array *op_array, + zend_optimizer_ctx *ctx) +{ + /* Revert pass_two() */ + zend_revert_pass_two(op_array); + + /* Do actual optimizations */ + zend_optimize(op_array, ctx); + + /* Redo pass_two() */ + zend_redo_pass_two(op_array); +} + static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_function *func; @@ -714,6 +734,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend zend_class_entry *ce; zend_op_array *op_array; zend_optimizer_ctx ctx; + zend_call_graph call_graph; ctx.arena = zend_arena_create(64 * 1024); ctx.script = script; @@ -751,6 +772,39 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend } } +#if HAVE_DFA_PASS + if ((ZEND_OPTIMIZER_PASS_6 & optimization_level) && + (ZEND_OPTIMIZER_PASS_7 & optimization_level) && + zend_build_call_graph(&ctx.arena, script, ZEND_RT_CONSTANTS, &call_graph) == SUCCESS) { + /* Optimize using call-graph */ + uint32_t i; + zend_func_info *func_info; + + for (i = 0; i < call_graph.op_arrays_count; i++) { + zend_revert_pass_two(call_graph.op_arrays[i]); + func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]); + if (func_info) { + func_info->ssa.rt_constants = 0; + } + } + + for (i = 0; i < call_graph.op_arrays_count; i++) { + optimize_dfa(call_graph.op_arrays[i], &ctx); + } + + if (debug_level & ZEND_DUMP_AFTER_PASS_7) { + for (i = 0; i < call_graph.op_arrays_count; i++) { + zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 7", NULL); + } + } + + for (i = 0; i < call_graph.op_arrays_count; i++) { + zend_redo_pass_two(call_graph.op_arrays[i]); + ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL); + } + } +#endif + if (ZEND_OPTIMIZER_PASS_12 & optimization_level) { zend_adjust_fcall_stack_size(&script->main_op_array, &ctx); diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h index 5ec7d8fd8d..5743ab6e3e 100644 --- a/ext/opcache/Optimizer/zend_optimizer.h +++ b/ext/opcache/Optimizer/zend_optimizer.h @@ -31,7 +31,7 @@ #define ZEND_OPTIMIZER_PASS_4 (1<<3) /* INIT_FCALL_BY_NAME -> DO_FCALL */ #define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */ #define ZEND_OPTIMIZER_PASS_6 (1<<5) /* DFA based optimization */ -#define ZEND_OPTIMIZER_PASS_7 (1<<6) +#define ZEND_OPTIMIZER_PASS_7 (1<<6) /* CALL GRAPH optimization */ #define ZEND_OPTIMIZER_PASS_8 (1<<7) #define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */ #define ZEND_OPTIMIZER_PASS_10 (1<<9) /* NOP removal */ diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 51500a95ff..ca7ad67fd0 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2768,6 +2768,8 @@ file_cache_fallback: zend_accel_blacklist_load(&accel_blacklist, ZCG(accel_directives.user_blacklist_filename)); } + zend_optimizer_startup(); + return SUCCESS; } @@ -2785,6 +2787,8 @@ void accel_shutdown(void) zend_ini_entry *ini_entry; zend_bool file_cache_only = 0; + zend_optimizer_shutdown(); + zend_accel_blacklist_shutdown(&accel_blacklist); if (!ZCG(enabled) || !accel_startup_ok) { |