summaryrefslogtreecommitdiff
path: root/ext/opcache/Optimizer/zend_inference.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-02-27 18:51:53 +0100
committerNikita Popov <nikic@php.net>2016-02-28 21:38:34 +0100
commita1c48d5e3a1e8ffbb75bdf51ae07c6596574282d (patch)
tree63fc1d54b154213295d82e7230177213d5dd01d6 /ext/opcache/Optimizer/zend_inference.c
parentff1f178d84e41b368102eb25cc96c6705f1c37b9 (diff)
downloadphp-git-a1c48d5e3a1e8ffbb75bdf51ae07c6596574282d.tar.gz
Various SSA-related tweaks
* Add FETCH_LIST to inference * Restrict JMP_SET/COALESCE result type * Fix typos in range inference * Add const annotations in zend_ssa.h * For pi statements dump the associated predecessor block * If type can be both true and false, dump bool instead
Diffstat (limited to 'ext/opcache/Optimizer/zend_inference.c')
-rw-r--r--ext/opcache/Optimizer/zend_inference.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index affdaf7aac..a1e2335fa9 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -962,7 +962,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
op2_max = OP2_MAX_RANGE();
tmp->min = (op1_min == op1_max &&
- op2_min == op2_min &&
+ op2_min == op2_max &&
op1_min == op2_max);
tmp->max = (op1_min <= op2_max && op1_max >= op2_min);
return 1;
@@ -984,7 +984,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
tmp->min = (op1_min > op2_max || op1_max < op2_min);
tmp->max = (op1_min != op1_max ||
- op2_min != op2_min ||
+ op2_min != op2_max ||
op1_min != op2_max);
return 1;
} else {
@@ -2359,6 +2359,14 @@ static void zend_update_type_info(const zend_op_array *op_array,
if (opline->op1_type & (IS_CV|IS_VAR)) {
tmp |= MAY_BE_RCN;
}
+ if (opline->opcode != ZEND_QM_ASSIGN) {
+ /* COALESCE and JMP_SET result can't be null */
+ tmp &= ~MAY_BE_NULL;
+ if (opline->opcode == ZEND_JMP_SET) {
+ /* JMP_SET result can't be false either */
+ tmp &= ~MAY_BE_FALSE;
+ }
+ }
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
@@ -3438,6 +3446,7 @@ static void zend_update_type_info(const zend_op_array *op_array,
case ZEND_FETCH_DIM_W:
case ZEND_FETCH_DIM_UNSET:
case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_LIST:
if (ssa_ops[i].op1_def >= 0) {
tmp = t1;
if (opline->opcode == ZEND_FETCH_DIM_W ||
@@ -3520,9 +3529,11 @@ static void zend_update_type_info(const zend_op_array *op_array,
UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def);
}
}
+ /* FETCH_LIST on a string behaves like FETCH_R on null */
tmp = zend_array_element_type(
- t1,
- (opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS),
+ opline->opcode != ZEND_FETCH_LIST ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
+ opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS
+ && opline->opcode != ZEND_FETCH_LIST,
opline->op2_type == IS_UNUSED);
if (opline->opcode == ZEND_FETCH_DIM_W ||
opline->opcode == ZEND_FETCH_DIM_RW ||