mirror of
https://github.com/php/php-src.git
synced 2025-01-26 21:54:16 +08:00
More accurate "vararg" handling in DCE
This commit is contained in:
parent
665ed8491c
commit
94c9b26695
@ -457,14 +457,29 @@ static void try_remove_trivial_phi(context *ctx, zend_ssa_phi *phi) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline zend_bool may_break_varargs(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_op *ssa_op) {
|
||||
if (ssa_op->op1_def >= 0
|
||||
&& ssa->vars[ssa_op->op1_def].var < op_array->num_args) {
|
||||
return 1;
|
||||
}
|
||||
if (ssa_op->op2_def >= 0
|
||||
&& ssa->vars[ssa_op->op2_def].var < op_array->num_args) {
|
||||
return 1;
|
||||
}
|
||||
if (ssa_op->result_def >= 0
|
||||
&& ssa->vars[ssa_op->result_def].var < op_array->num_args) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reorder_dtor_effects) {
|
||||
int i;
|
||||
zend_ssa_phi *phi;
|
||||
int removed_ops = 0;
|
||||
|
||||
/* DCE of CV operations may affect vararg functions. For now simply treat all instructions
|
||||
* as live if varargs in use and only collect dead phis. */
|
||||
zend_bool has_varargs = (ZEND_FUNC_INFO(op_array)->flags & ZEND_FUNC_VARARG) != 0;
|
||||
/* DCE of CV operations that changes arguments may affect vararg functions. */
|
||||
zend_bool has_varargs = ssa->cfg.vararg;
|
||||
|
||||
context ctx;
|
||||
ctx.ssa = ssa;
|
||||
@ -504,7 +519,7 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
|
||||
add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], 0);
|
||||
} else if (may_have_side_effects(op_array, ssa, &op_array->opcodes[i], &ssa->ops[i], ctx.reorder_dtor_effects)
|
||||
|| zend_may_throw(&op_array->opcodes[i], op_array, ssa)
|
||||
|| has_varargs) {
|
||||
|| (has_varargs && may_break_varargs(op_array, ssa, &ssa->ops[i]))) {
|
||||
add_operands_to_worklists(&ctx, &op_array->opcodes[i], &ssa->ops[i], 0);
|
||||
} else {
|
||||
zend_bitset_incl(ctx.instr_dead, i);
|
||||
|
@ -441,6 +441,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS;
|
||||
}
|
||||
break;
|
||||
case ZEND_FUNC_GET_ARGS:
|
||||
flags |= ZEND_FUNC_VARARG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,7 +601,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
|
||||
/* Build CFG, Step 4, Mark Reachable Basic Blocks */
|
||||
zend_mark_reachable_blocks(op_array, cfg, 0);
|
||||
|
||||
cfg->dynamic = (flags & ZEND_FUNC_INDIRECT_VAR_ACCESS);
|
||||
cfg->dynamic = (flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0;
|
||||
cfg->vararg = (flags & ZEND_FUNC_VARARG) != 0;
|
||||
|
||||
if (func_flags) {
|
||||
*func_flags |= flags;
|
||||
|
@ -93,6 +93,7 @@ typedef struct _zend_cfg {
|
||||
unsigned int split_at_calls : 1;
|
||||
unsigned int split_at_recv : 1;
|
||||
unsigned int dynamic : 1; /* accesses varables by name */
|
||||
unsigned int vararg : 1; /* uses func_get_args() */
|
||||
} zend_cfg;
|
||||
|
||||
/* Build Flags */
|
||||
|
Loading…
Reference in New Issue
Block a user