@@ -120,8 +120,17 @@ static uint32_t zend_jit_trace_get_exit_point(const zend_op *to_opline, uint32_t
120
120
static const void * zend_jit_trace_get_exit_addr (uint32_t n );
121
121
static void zend_jit_trace_add_code (const void * start , uint32_t size );
122
122
123
+ static zend_bool dominates (const zend_basic_block * blocks , int a , int b ) {
124
+ while (blocks [b ].level > blocks [a ].level ) {
125
+ b = blocks [b ].idom ;
126
+ }
127
+ return a == b ;
128
+ }
129
+
123
130
static zend_bool zend_ssa_is_last_use (const zend_op_array * op_array , const zend_ssa * ssa , int var , int use )
124
131
{
132
+ int next_use ;
133
+
125
134
if (ssa -> vars [var ].phi_use_chain ) {
126
135
zend_ssa_phi * phi = ssa -> vars [var ].phi_use_chain ;
127
136
do {
@@ -132,8 +141,24 @@ static zend_bool zend_ssa_is_last_use(const zend_op_array *op_array, const zend_
132
141
} while (phi );
133
142
}
134
143
135
- use = zend_ssa_next_use (ssa -> ops , var , use );
136
- return use < 0 || zend_ssa_is_no_val_use (op_array -> opcodes + use , ssa -> ops + use , var );
144
+ next_use = zend_ssa_next_use (ssa -> ops , var , use );
145
+ if (next_use < 0 ) {
146
+ int b = ssa -> cfg .map [use ];
147
+ int prev_use = ssa -> vars [var ].use_chain ;
148
+
149
+ while (prev_use >= 0 && prev_use != use ) {
150
+ if (b != ssa -> cfg .map [prev_use ]
151
+ && dominates (ssa -> cfg .blocks , b , ssa -> cfg .map [prev_use ])
152
+ && !zend_ssa_is_no_val_use (op_array -> opcodes + prev_use , ssa -> ops + prev_use , var )) {
153
+ return 0 ;
154
+ }
155
+ prev_use = zend_ssa_next_use (ssa -> ops , var , prev_use );
156
+ }
157
+ return 1 ;
158
+ } else if (zend_ssa_is_no_val_use (op_array -> opcodes + next_use , ssa -> ops + next_use , var )) {
159
+ return 1 ;
160
+ }
161
+ return 0 ;
137
162
}
138
163
139
164
static zend_bool zend_ival_is_last_use (const zend_lifetime_interval * ival , int use )
0 commit comments