mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Initial implementation of Escape Analysis (disabled yet).
This commit is contained in:
parent
1fdfcc2bb0
commit
3cb6407e86
@ -39,6 +39,10 @@
|
||||
# include "ssa_integrity.c"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ESCAPE_ANALYSIS
|
||||
# define HAVE_ESCAPE_ANALYSIS 0
|
||||
#endif
|
||||
|
||||
int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, uint32_t *flags)
|
||||
{
|
||||
uint32_t build_flags;
|
||||
@ -107,6 +111,12 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
#if HAVE_ESCAPE_ANALYSIS
|
||||
if (zend_ssa_escape_analysis(op_array, ssa) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (zend_ssa_find_sccs(op_array, ssa) != SUCCESS){
|
||||
return FAILURE;
|
||||
}
|
||||
|
461
ext/opcache/Optimizer/escape_analysis.c
Normal file
461
ext/opcache/Optimizer/escape_analysis.c
Normal file
@ -0,0 +1,461 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend OPcache, Escape Analysis |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2017 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.01 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_01.txt |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
#include "Optimizer/zend_optimizer.h"
|
||||
#include "Optimizer/zend_optimizer_internal.h"
|
||||
#include "zend_bitset.h"
|
||||
#include "zend_cfg.h"
|
||||
#include "zend_ssa.h"
|
||||
#include "zend_dump.h"
|
||||
|
||||
/*
|
||||
* T. Kotzmann and H. Mossenbock. Escape analysis in the context of dynamic
|
||||
* compilation and deoptimization. In Proceedings of the International
|
||||
* Conference on Virtual Execution Environments, pages 111-120, Chicago,
|
||||
* June 2005
|
||||
*/
|
||||
|
||||
static zend_always_inline void union_find_init(int *parent, int *size, int count) /* {{{ */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
parent[i] = i;
|
||||
size[i] = 1;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline int union_find_root(int *parent, int i) /* {{{ */
|
||||
{
|
||||
int p = parent[i];
|
||||
|
||||
while (i != p) {
|
||||
p = parent[p];
|
||||
parent[i] = p;
|
||||
i = p;
|
||||
p = parent[i];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_always_inline void union_find_unite(int *parent, int *size, int i, int j) /* {{{ */
|
||||
{
|
||||
int r1 = union_find_root(parent, i);
|
||||
int r2 = union_find_root(parent, j);
|
||||
|
||||
if (r1 != r2) {
|
||||
if (size[r1] < size[r2]) {
|
||||
parent[r1] = r2;
|
||||
size[r2] += size[r1];
|
||||
} else {
|
||||
parent[r2] = r1;
|
||||
size[r1] += size[r2];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int zend_build_equi_escape_sets(int *parent, zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
|
||||
{
|
||||
zend_ssa_var *ssa_vars = ssa->vars;
|
||||
int ssa_vars_count = ssa->vars_count;
|
||||
zend_ssa_phi *p;
|
||||
int i, j;
|
||||
int *size;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
size = do_alloca(sizeof(int) * ssa_vars_count, use_heap);
|
||||
if (!size) {
|
||||
return FAILURE;
|
||||
}
|
||||
union_find_init(parent, size, ssa_vars_count);
|
||||
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
if (ssa_vars[i].no_val) {
|
||||
/* skip */
|
||||
} else if (ssa_vars[i].definition_phi) {
|
||||
p = ssa_vars[i].definition_phi;
|
||||
if (p->pi >= 0) {
|
||||
union_find_unite(parent, size, i, p->sources[0]);
|
||||
} else {
|
||||
for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
|
||||
union_find_unite(parent, size, i, p->sources[j]);
|
||||
}
|
||||
}
|
||||
} else if (ssa_vars[i].definition >= 0) {
|
||||
int def = ssa_vars[i].definition;
|
||||
zend_ssa_op *op = ssa->ops + def;
|
||||
zend_op *opline = op_array->opcodes + def;
|
||||
|
||||
if (op->op1_def >= 0) {
|
||||
if (op->op1_use >= 0) {
|
||||
if (opline->opcode != ZEND_ASSIGN) {
|
||||
union_find_unite(parent, size, op->op1_def, op->op1_use);
|
||||
}
|
||||
}
|
||||
if (opline->opcode == ZEND_ASSIGN && op->op2_use >= 0) {
|
||||
union_find_unite(parent, size, op->op1_def, op->op2_use);
|
||||
}
|
||||
}
|
||||
if (op->op2_def >= 0) {
|
||||
if (op->op2_use >= 0) {
|
||||
union_find_unite(parent, size, op->op2_def, op->op2_use);
|
||||
}
|
||||
}
|
||||
if (op->result_def >= 0) {
|
||||
if (op->result_use >= 0) {
|
||||
if (opline->opcode != ZEND_QM_ASSIGN) {
|
||||
union_find_unite(parent, size, op->result_def, op->result_use);
|
||||
}
|
||||
}
|
||||
if (opline->opcode == ZEND_QM_ASSIGN && op->op1_use >= 0) {
|
||||
union_find_unite(parent, size, op->result_def, op->op1_use);
|
||||
}
|
||||
if (opline->opcode == ZEND_ASSIGN && op->op2_use >= 0) {
|
||||
union_find_unite(parent, size, op->result_def, op->op2_use);
|
||||
}
|
||||
if (opline->opcode == ZEND_ASSIGN && op->op1_def >= 0) {
|
||||
union_find_unite(parent, size, op->result_def, op->op1_def);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
parent[i] = union_find_root(parent, i);
|
||||
}
|
||||
|
||||
free_alloca(size, use_heap);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline zend_class_entry *get_class_entry(const zend_script *script, zend_string *lcname) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL;
|
||||
if (ce) {
|
||||
return ce;
|
||||
}
|
||||
|
||||
ce = zend_hash_find_ptr(CG(class_table), lcname);
|
||||
if (ce && ce->type == ZEND_INTERNAL_CLASS) {
|
||||
return ce;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, int var) /* {{{ */
|
||||
{
|
||||
zend_ssa_op *op = ssa->ops + def;
|
||||
zend_op *opline = op_array->opcodes + def;
|
||||
|
||||
if (op->result_def == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_INIT_ARRAY:
|
||||
return 1;
|
||||
case ZEND_NEW:
|
||||
/* objects with destructors should escape */
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
zend_class_entry *ce = get_class_entry(NULL, Z_STR_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)+1));
|
||||
if (ce && !ce->create_object &&
|
||||
!ce->destructor && !ce->__get && !ce->__set) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_QM_ASSIGN:
|
||||
if (opline->op1_type == IS_CONST
|
||||
&& Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)) == IS_ARRAY) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (op->op1_def == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN:
|
||||
if (opline->op2_type == IS_CONST
|
||||
&& Z_TYPE_P(CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants)) == IS_ARRAY) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
// TODO: implicit object/array allocation
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
return 1;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
case ZEND_ASSIGN_MUL:
|
||||
case ZEND_ASSIGN_DIV:
|
||||
case ZEND_ASSIGN_MOD:
|
||||
case ZEND_ASSIGN_SL:
|
||||
case ZEND_ASSIGN_SR:
|
||||
case ZEND_ASSIGN_CONCAT:
|
||||
case ZEND_ASSIGN_BW_OR:
|
||||
case ZEND_ASSIGN_BW_AND:
|
||||
case ZEND_ASSIGN_BW_XOR:
|
||||
case ZEND_ASSIGN_POW:
|
||||
if (opline->extended_value) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int var) /* {{{ */
|
||||
{
|
||||
zend_ssa_op *op = ssa->ops + use;
|
||||
zend_op *opline = op_array->opcodes + use;
|
||||
|
||||
if (op->op1_use == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN:
|
||||
/* no_val */
|
||||
break;
|
||||
case ZEND_QM_ASSIGN:
|
||||
#if 0
|
||||
if (opline->op1_type == IS_CV) {
|
||||
/* array duplication */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case ZEND_FETCH_DIM_R:
|
||||
case ZEND_FETCH_OBJ_R:
|
||||
// case ZEND_FETCH_DIM_W:
|
||||
// case ZEND_FETCH_OBJ_W:
|
||||
case ZEND_FETCH_DIM_RW:
|
||||
case ZEND_FETCH_OBJ_RW:
|
||||
case ZEND_FETCH_DIM_IS:
|
||||
case ZEND_FETCH_OBJ_IS:
|
||||
// case ZEND_FETCH_DIM_FUNC_ARG:
|
||||
// case ZEND_FETCH_OBJ_FUNC_ARG:
|
||||
// case ZEND_FETCH_DIM_UNSET:
|
||||
// case ZEND_FETCH_OBJ_UNSET:
|
||||
break;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
case ZEND_ASSIGN_MUL:
|
||||
case ZEND_ASSIGN_DIV:
|
||||
case ZEND_ASSIGN_MOD:
|
||||
case ZEND_ASSIGN_SL:
|
||||
case ZEND_ASSIGN_SR:
|
||||
case ZEND_ASSIGN_CONCAT:
|
||||
case ZEND_ASSIGN_BW_OR:
|
||||
case ZEND_ASSIGN_BW_AND:
|
||||
case ZEND_ASSIGN_BW_XOR:
|
||||
case ZEND_ASSIGN_POW:
|
||||
if (!opline->extended_value) {
|
||||
return 1;
|
||||
}
|
||||
/* break missing intentionally */
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (op->op2_use == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
/* reference dependencies processed separately */
|
||||
break;
|
||||
case ZEND_ASSIGN:
|
||||
#if 0
|
||||
if (opline->op2_type == IS_CV) {
|
||||
/* array duplication */
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (op->result_use == var) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_QM_ASSIGN:
|
||||
case ZEND_INIT_ARRAY:
|
||||
case ZEND_ADD_ARRAY_ELEMENT:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_ssa_escape_analysis(zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
|
||||
{
|
||||
zend_ssa_var *ssa_vars = ssa->vars;
|
||||
int ssa_vars_count = ssa->vars_count;
|
||||
int i, root, use;
|
||||
int *ees;
|
||||
zend_bool has_allocations;
|
||||
int num_non_escaped;
|
||||
ALLOCA_FLAG(use_heap)
|
||||
|
||||
if (!ssa->vars) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
has_allocations = 0;
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
if (ssa_vars[i].definition >= 0) {
|
||||
if (is_allocation_def(op_array, ssa, ssa_vars[i].definition, i)) {
|
||||
has_allocations = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!has_allocations) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* 1. Build EES (Equi-Esape Sets) */
|
||||
ees = do_alloca(sizeof(int) * ssa->vars_count, use_heap);
|
||||
if (!ees) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (zend_build_equi_escape_sets(ees, op_array, ssa) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* 2. Identify Allocations */
|
||||
num_non_escaped = 0;
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
if (ssa_vars[i].definition >= 0) {
|
||||
root = ees[i];
|
||||
if (ssa_vars[root].escape_state == ESCAPE_STATE_UNKNOWN) {
|
||||
if (is_allocation_def(op_array, ssa, ssa_vars[i].definition, i)) {
|
||||
ssa_vars[root].escape_state = ESCAPE_STATE_NO_ESCAPE;
|
||||
num_non_escaped++;
|
||||
} else {
|
||||
ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 3. Mark escaped EES */
|
||||
if (num_non_escaped) {
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
if (ssa_vars[i].use_chain >= 0) {
|
||||
root = ees[i];
|
||||
if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
|
||||
FOREACH_USE(ssa->vars + i, use) {
|
||||
if (is_escape_use(op_array, ssa, use, i)) {
|
||||
ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
|
||||
num_non_escaped--;
|
||||
if (num_non_escaped == 0) {
|
||||
i = ssa_vars_count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} FOREACH_USE_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. Process referential dependencies */
|
||||
if (num_non_escaped) {
|
||||
zend_bool changed;
|
||||
|
||||
do {
|
||||
changed = 0;
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
if (ssa_vars[i].use_chain >= 0) {
|
||||
root = ees[i];
|
||||
if (ssa_vars[root].escape_state == ESCAPE_STATE_NO_ESCAPE) {
|
||||
FOREACH_USE(ssa->vars + i, use) {
|
||||
zend_ssa_op *op = ssa->ops + use;
|
||||
zend_op *opline = op_array->opcodes + use;
|
||||
|
||||
if ((opline->opcode == ZEND_ASSIGN_DIM ||
|
||||
opline->opcode == ZEND_ASSIGN_OBJ) &&
|
||||
op->op2_use == i &&
|
||||
op->op1_use >= 0) {
|
||||
int root2 = ees[op->op1_use];
|
||||
|
||||
if (ssa_vars[root2].escape_state == ESCAPE_STATE_UNKNOWN ||
|
||||
ssa_vars[root2].escape_state > ssa_vars[root].escape_state) {
|
||||
if (ssa_vars[root2].escape_state == ESCAPE_STATE_UNKNOWN) {
|
||||
ssa_vars[root].escape_state = ESCAPE_STATE_GLOBAL_ESCAPE;
|
||||
} else {
|
||||
ssa_vars[root].escape_state = ssa_vars[root2].escape_state;
|
||||
}
|
||||
if (ssa_vars[root].escape_state == ESCAPE_STATE_GLOBAL_ESCAPE) {
|
||||
num_non_escaped--;
|
||||
if (num_non_escaped == 0) {
|
||||
i = ssa_vars_count;
|
||||
changed = 0;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} FOREACH_USE_END();
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
/* 5. Propagate values of escape sets to variables */
|
||||
for (i = 0; i < ssa_vars_count; i++) {
|
||||
root = ees[i];
|
||||
if (i != root) {
|
||||
ssa_vars[i].escape_state = ssa_vars[root].escape_state;
|
||||
}
|
||||
}
|
||||
|
||||
free_alloca(ees, use_heap);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
@ -320,9 +320,12 @@ static void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa
|
||||
zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : var_type), var_num);
|
||||
|
||||
if (ssa_var_num >= 0 && ssa->vars) {
|
||||
if (ssa_var_num >= 0 && ssa->vars[ssa_var_num].no_val) {
|
||||
if (ssa->vars[ssa_var_num].no_val) {
|
||||
fprintf(stderr, " NOVAL");
|
||||
}
|
||||
if (ssa->vars[ssa_var_num].escape_state == ESCAPE_STATE_NO_ESCAPE) {
|
||||
fprintf(stderr, " NOESC");
|
||||
}
|
||||
if (ssa->var_info) {
|
||||
zend_dump_ssa_var_info(ssa, ssa_var_num, dump_flags);
|
||||
if (ssa->var_info[ssa_var_num].has_range) {
|
||||
|
@ -114,5 +114,6 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_
|
||||
zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode);
|
||||
int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map);
|
||||
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reorder_dtor_effects);
|
||||
int zend_ssa_escape_analysis(zend_op_array *op_array, zend_ssa *ssa);
|
||||
|
||||
#endif
|
||||
|
@ -99,6 +99,13 @@ typedef enum _zend_ssa_alias_kind {
|
||||
HTTP_RESPONSE_HEADER_ALIAS
|
||||
} zend_ssa_alias_kind;
|
||||
|
||||
typedef enum _zend_ssa_escape_state {
|
||||
ESCAPE_STATE_UNKNOWN,
|
||||
ESCAPE_STATE_NO_ESCAPE,
|
||||
ESCAPE_STATE_FUNCTION_ESCAPE,
|
||||
ESCAPE_STATE_GLOBAL_ESCAPE
|
||||
} zend_ssa_escape_state;
|
||||
|
||||
typedef struct _zend_ssa_var {
|
||||
int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */
|
||||
int scc; /* strongly connected component */
|
||||
@ -110,6 +117,7 @@ typedef struct _zend_ssa_var {
|
||||
unsigned int no_val : 1; /* value doesn't mater (used as op1 in ZEND_ASSIGN) */
|
||||
unsigned int scc_entry : 1;
|
||||
zend_ssa_alias_kind alias : 2; /* value may be changed indirectly */
|
||||
zend_ssa_escape_state escape_state : 2;
|
||||
} zend_ssa_var;
|
||||
|
||||
typedef struct _zend_ssa_var_info {
|
||||
|
@ -413,6 +413,7 @@ fi
|
||||
Optimizer/sccp.c \
|
||||
Optimizer/scdf.c \
|
||||
Optimizer/dce.c \
|
||||
Optimizer/escape_analysis.c \
|
||||
Optimizer/compact_vars.c \
|
||||
Optimizer/zend_dump.c,
|
||||
shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes)
|
||||
|
@ -23,7 +23,7 @@ if (PHP_OPCACHE != "no") {
|
||||
zend_shared_alloc.c \
|
||||
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c sccp.c scdf.c dce.c compact_vars.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c sccp.c scdf.c dce.c escape_analysis.c compact_vars.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
|
||||
|
||||
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
|
||||
|
Loading…
Reference in New Issue
Block a user