1
0
mirror of https://github.com/php/php-src.git synced 2026-03-27 17:52:16 +01:00

Optimize constant SWITCH_LONG and SWITCH_STRING

This commit is contained in:
Dmitry Stogov
2019-04-24 00:08:17 +03:00
parent 4d0d7ce349
commit db2ffcf157
2 changed files with 107 additions and 0 deletions

View File

@@ -490,6 +490,19 @@ static zend_always_inline void take_successor_1(zend_ssa *ssa, int block_num, ze
}
}
static zend_always_inline void take_successor_ex(zend_ssa *ssa, int block_num, zend_basic_block *block, int target_block)
{
int i;
for (i = 0; i < block->successors_count; i++) {
if (block->successors[i] != target_block) {
zend_ssa_remove_predecessor(ssa, block_num, block->successors[i]);
}
}
block->successors[0] = target_block;
block->successors_count = 1;
}
static void compress_block(zend_op_array *op_array, zend_basic_block *block)
{
while (block->len > 0) {
@@ -857,6 +870,64 @@ optimize_jmpnz:
}
break;
}
case ZEND_SWITCH_LONG:
if (opline->op1_type == IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
if (Z_TYPE_P(zv) != IS_LONG) {
removed_ops++;
MAKE_NOP(opline);
opline->extended_value = 0;
take_successor_ex(ssa, block_num, block, block->successors[0]);
goto optimize_nop;
} else {
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(zv));
uint32_t target;
if (jmp_zv) {
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
} else {
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
}
opline->opcode = ZEND_JMP;
opline->extended_value = 0;
SET_UNUSED(opline->op1);
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
SET_UNUSED(opline->op2);
take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
goto optimize_jmp;
}
}
break;
case ZEND_SWITCH_STRING:
if (opline->op1_type == IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
if (Z_TYPE_P(zv) != IS_STRING) {
removed_ops++;
MAKE_NOP(opline);
opline->extended_value = 0;
take_successor_ex(ssa, block_num, block, block->successors[0]);
goto optimize_nop;
} else {
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(zv));
uint32_t target;
if (jmp_zv) {
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
} else {
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
}
opline->opcode = ZEND_JMP;
opline->extended_value = 0;
SET_UNUSED(opline->op1);
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
SET_UNUSED(opline->op2);
take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
goto optimize_jmp;
}
}
break;
case ZEND_NOP:
optimize_nop:
compress_block(op_array, block);

View File

@@ -1884,6 +1884,42 @@ static void sccp_mark_feasible_successors(
}
s = zend_hash_num_elements(Z_ARR_P(op1)) != 0;
break;
case ZEND_SWITCH_LONG:
if (Z_TYPE_P(op1) == IS_LONG) {
zend_op_array *op_array = scdf->op_array;
zend_ssa *ssa = scdf->ssa;
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(op1));
int target;
if (jmp_zv) {
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
} else {
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
}
scdf_mark_edge_feasible(scdf, block_num, target);
return;
}
s = 0;
break;
case ZEND_SWITCH_STRING:
if (Z_TYPE_P(op1) == IS_STRING) {
zend_op_array *op_array = scdf->op_array;
zend_ssa *ssa = scdf->ssa;
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(op1));
int target;
if (jmp_zv) {
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
} else {
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
}
scdf_mark_edge_feasible(scdf, block_num, target);
return;
}
s = 0;
break;
default:
for (s = 0; s < block->successors_count; s++) {
scdf_mark_edge_feasible(scdf, block_num, block->successors[s]);