]> granicus.if.org Git - php/commitdiff
Various SSA-related tweaks
authorNikita Popov <nikic@php.net>
Sat, 27 Feb 2016 17:51:53 +0000 (18:51 +0100)
committerNikita Popov <nikic@php.net>
Sun, 28 Feb 2016 20:38:34 +0000 (21:38 +0100)
* 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

ext/opcache/Optimizer/zend_dump.c
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_ssa.h

index d224000066c21a58b1cb4805397be6c723302fdb..ba5fb8a0ce536903b95f9d6f3d1804f80bd84dee 100644 (file)
@@ -182,11 +182,13 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst
                        if (first) first = 0; else fprintf(stderr, ", ");
                        fprintf(stderr, "null");
                }
-               if (info & MAY_BE_FALSE) {
+               if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) {
+                       if (first) first = 0; else fprintf(stderr, ", ");
+                       fprintf(stderr, "bool");
+               } else if (info & MAY_BE_FALSE) {
                        if (first) first = 0; else fprintf(stderr, ", ");
                        fprintf(stderr, "false");
-               }
-               if (info & MAY_BE_TRUE) {
+               } else if (info & MAY_BE_TRUE) {
                        if (first) first = 0; else fprintf(stderr, ", ");
                        fprintf(stderr, "true");
                }
@@ -788,7 +790,7 @@ static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_
                                }
                                fprintf(stderr, ")\n");
                        } else {
-                               fprintf(stderr, " = Pi(");
+                               fprintf(stderr, " = Pi<BB%d>(", p->pi);
                                zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags);
                                fprintf(stderr, " &");
                                zend_dump_pi_constraint(op_array, ssa, &p->constraint, dump_flags);
index affdaf7aac24b3b90fea4d575d1beac5300c4a3d..a1e2335fa9e648eb719c5cc28b0ad5e964b56d69 100644 (file)
@@ -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 ||
index 00d6875dfd2a947af5018cc84226c5ae5df5c447..dbf260c4d8de4c01a61939e351c909edae7d3b79 100644 (file)
@@ -122,7 +122,7 @@ int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);
 
 END_EXTERN_C()
 
-static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, int use)
+static zend_always_inline int zend_ssa_next_use(const zend_ssa_op *ssa_op, int var, int use)
 {
        ssa_op += use;
        if (ssa_op->result_use == var) {
@@ -131,7 +131,7 @@ static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, in
        return (ssa_op->op1_use == var) ? ssa_op->op1_use_chain : ssa_op->op2_use_chain;
 }
 
-static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(zend_ssa *ssa, int var, zend_ssa_phi *p)
+static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(const zend_ssa *ssa, int var, const zend_ssa_phi *p)
 {
        if (p->pi >= 0) {
                return p->use_chains[0];