@@ -32,16 +32,30 @@ static zend_bool dominates(const zend_basic_block *blocks, int a, int b) {
32
32
return a == b ;
33
33
}
34
34
35
- static zend_bool dominates_other_predecessors (
36
- const zend_cfg * cfg , const zend_basic_block * block , int check , int exclude ) {
35
+ static zend_bool will_rejoin (
36
+ const zend_cfg * cfg , const zend_dfg * dfg , const zend_basic_block * block ,
37
+ int other_successor , int exclude , int var ) {
37
38
int i ;
38
39
for (i = 0 ; i < block -> predecessors_count ; i ++ ) {
39
40
int predecessor = cfg -> predecessors [block -> predecessor_offset + i ];
40
- if (predecessor != exclude && !dominates (cfg -> blocks , check , predecessor )) {
41
- return 0 ;
41
+ if (predecessor == exclude ) {
42
+ continue ;
43
+ }
44
+
45
+ /* The variable is changed in this predecessor,
46
+ * so we will not rejoin with the original value. */
47
+ // TODO: This should not be limited to the direct predecessor block.
48
+ if (DFG_ISSET (dfg -> def , dfg -> size , predecessor , var )) {
49
+ continue ;
50
+ }
51
+
52
+ /* The other successor dominates this predecessor,
53
+ * so we will get the original value from it. */
54
+ if (dominates (cfg -> blocks , other_successor , predecessor )) {
55
+ return 1 ;
42
56
}
43
57
}
44
- return 1 ;
58
+ return 0 ;
45
59
}
46
60
47
61
static zend_bool needs_pi (const zend_op_array * op_array , zend_dfg * dfg , zend_ssa * ssa , int from , int to , int var ) /* {{{ */
@@ -68,11 +82,11 @@ static zend_bool needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa
68
82
return 1 ;
69
83
}
70
84
71
- /* Check that the other successor of the from block does not dominate all other predecessors.
72
- * If it does, we'd probably end up annihilating a positive+negative pi assertion . */
85
+ /* Check whether we will rejoin with the original value coming from the other successor,
86
+ * in which case the pi node will not have an effect . */
73
87
other_successor = from_block -> successors [0 ] == to
74
88
? from_block -> successors [1 ] : from_block -> successors [0 ];
75
- return !dominates_other_predecessors (& ssa -> cfg , to_block , other_successor , from );
89
+ return !will_rejoin (& ssa -> cfg , dfg , to_block , other_successor , from , var );
76
90
}
77
91
/* }}} */
78
92
@@ -252,6 +266,14 @@ static void place_essa_pis(
252
266
bt = blocks [j ].successors [0 ];
253
267
bf = blocks [j ].successors [1 ];
254
268
break ;
269
+ case ZEND_COALESCE :
270
+ if (opline -> op1_type == IS_CV ) {
271
+ int var = EX_VAR_TO_NUM (opline -> op1 .var );
272
+ if ((pi = add_pi (arena , op_array , dfg , ssa , j , blocks [j ].successors [0 ], var ))) {
273
+ pi_not_type_mask (pi , MAY_BE_NULL );
274
+ }
275
+ }
276
+ continue ;
255
277
default :
256
278
continue ;
257
279
}
0 commit comments