@@ -1262,31 +1262,34 @@ static inline void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa
1262
1262
}
1263
1263
/* }}} */
1264
1264
1265
- static inline void zend_ssa_remove_phi_source (zend_ssa * ssa , zend_ssa_phi * phi , int i ) /* {{{ */
1265
+ static inline void zend_ssa_remove_phi_source (zend_ssa * ssa , zend_ssa_phi * phi , int pred_offset , int predecessors_count ) /* {{{ */
1266
1266
{
1267
- int j , var_num = phi -> sources [i ];
1267
+ int j , var_num = phi -> sources [pred_offset ];
1268
+
1269
+ predecessors_count -- ;
1270
+ if (pred_offset < predecessors_count ) {
1271
+ memmove (phi -> sources + pred_offset , phi -> sources + pred_offset + 1 , (predecessors_count - pred_offset ) * sizeof (uint32_t ));
1272
+ }
1268
1273
1269
1274
/* Check if they same var is used in a different phi operand as well, in this case we don't
1270
1275
* need to adjust the use chain (but may have to move the next pointer). */
1271
- for (j = 0 ; j < ssa -> cfg . blocks [ phi -> block ]. predecessors_count ; j ++ ) {
1276
+ for (j = 0 ; j < predecessors_count ; j ++ ) {
1272
1277
if (phi -> sources [j ] == var_num ) {
1273
- if (j < i ) {
1274
- phi -> sources [ i ] = -1 ;
1278
+ if (j < pred_offset ) {
1279
+ ZEND_ASSERT ( phi -> use_chains [ pred_offset ] == NULL ) ;
1275
1280
return ;
1276
1281
}
1277
- if (j > i ) {
1278
- phi -> use_chains [j ] = phi -> use_chains [i ];
1279
- phi -> use_chains [i ] = NULL ;
1280
- phi -> sources [i ] = -1 ;
1282
+ if (j >= pred_offset ) {
1283
+ phi -> use_chains [j ] = phi -> use_chains [pred_offset ];
1284
+ phi -> use_chains [pred_offset ] = NULL ;
1281
1285
return ;
1282
1286
}
1283
1287
}
1284
1288
}
1285
1289
1286
1290
/* Variable only used in one operand, remove the phi from the use chain. */
1287
1291
zend_ssa_remove_use_of_phi_source (ssa , phi , var_num );
1288
- phi -> sources [i ] = -1 ;
1289
- phi -> use_chains [i ] = NULL ;
1292
+ phi -> use_chains [pred_offset ] = NULL ;
1290
1293
}
1291
1294
/* }}} */
1292
1295
@@ -1387,13 +1390,17 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
1387
1390
}
1388
1391
} else {
1389
1392
if (phi -> sources [pred_offset ] >= 0 ) {
1390
- zend_ssa_remove_phi_source (ssa , phi , pred_offset );
1393
+ zend_ssa_remove_phi_source (ssa , phi , pred_offset , next_block -> predecessors_count );
1391
1394
}
1392
1395
}
1393
1396
}
1394
1397
1395
1398
/* Remove this predecessor */
1396
- predecessors [pred_offset ] = -1 ;
1399
+ next_block -> predecessors_count -- ;
1400
+ if (pred_offset < next_block -> predecessors_count ) {
1401
+ predecessors = & ssa -> cfg .predecessors [next_block -> predecessor_offset + pred_offset ];
1402
+ memmove (predecessors , predecessors + 1 , (next_block -> predecessors_count - pred_offset ) * sizeof (uint32_t ));
1403
+ }
1397
1404
}
1398
1405
1399
1406
/* Remove successors of predecessors */
@@ -1413,6 +1420,29 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
1413
1420
}
1414
1421
}
1415
1422
}
1423
+
1424
+ block -> successors_count = 0 ;
1425
+ block -> predecessors_count = 0 ;
1426
+
1427
+ /* Remove from dominators tree */
1428
+ if (block -> idom >= 0 ) {
1429
+ j = ssa -> cfg .blocks [block -> idom ].children ;
1430
+ if (j == i ) {
1431
+ ssa -> cfg .blocks [block -> idom ].children = block -> next_child ;
1432
+ } else if (j >= 0 ) {
1433
+ while (ssa -> cfg .blocks [j ].next_child >= 0 ) {
1434
+ if (ssa -> cfg .blocks [j ].next_child == i ) {
1435
+ ssa -> cfg .blocks [j ].next_child = block -> next_child ;
1436
+ break ;
1437
+ }
1438
+ j = ssa -> cfg .blocks [j ].next_child ;
1439
+ }
1440
+ }
1441
+ }
1442
+ block -> idom = -1 ;
1443
+ block -> level = -1 ;
1444
+ block -> children = -1 ;
1445
+ block -> next_child = -1 ;
1416
1446
}
1417
1447
/* }}} */
1418
1448
0 commit comments