Skip to content

Commit 07f45d8

Browse files
committed
Properly unlinking dead blocks from predecessors/successors and dominators
1 parent 502002a commit 07f45d8

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

ext/opcache/Optimizer/zend_ssa.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,31 +1262,34 @@ static inline void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa
12621262
}
12631263
/* }}} */
12641264

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) /* {{{ */
12661266
{
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+
}
12681273

12691274
/* Check if they same var is used in a different phi operand as well, in this case we don't
12701275
* 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++) {
12721277
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);
12751280
return;
12761281
}
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;
12811285
return;
12821286
}
12831287
}
12841288
}
12851289

12861290
/* Variable only used in one operand, remove the phi from the use chain. */
12871291
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;
12901293
}
12911294
/* }}} */
12921295

@@ -1387,13 +1390,17 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
13871390
}
13881391
} else {
13891392
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);
13911394
}
13921395
}
13931396
}
13941397

13951398
/* 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+
}
13971404
}
13981405

13991406
/* Remove successors of predecessors */
@@ -1413,6 +1420,29 @@ void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i) /* {{{
14131420
}
14141421
}
14151422
}
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;
14161446
}
14171447
/* }}} */
14181448

0 commit comments

Comments
 (0)