Skip to content

Commit db2ffcf

Browse files
committed
Optimize constant SWITCH_LONG and SWITCH_STRING
1 parent 4d0d7ce commit db2ffcf

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,19 @@ static zend_always_inline void take_successor_1(zend_ssa *ssa, int block_num, ze
490490
}
491491
}
492492

493+
static zend_always_inline void take_successor_ex(zend_ssa *ssa, int block_num, zend_basic_block *block, int target_block)
494+
{
495+
int i;
496+
497+
for (i = 0; i < block->successors_count; i++) {
498+
if (block->successors[i] != target_block) {
499+
zend_ssa_remove_predecessor(ssa, block_num, block->successors[i]);
500+
}
501+
}
502+
block->successors[0] = target_block;
503+
block->successors_count = 1;
504+
}
505+
493506
static void compress_block(zend_op_array *op_array, zend_basic_block *block)
494507
{
495508
while (block->len > 0) {
@@ -857,6 +870,64 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
857870
}
858871
break;
859872
}
873+
case ZEND_SWITCH_LONG:
874+
if (opline->op1_type == IS_CONST) {
875+
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
876+
if (Z_TYPE_P(zv) != IS_LONG) {
877+
removed_ops++;
878+
MAKE_NOP(opline);
879+
opline->extended_value = 0;
880+
take_successor_ex(ssa, block_num, block, block->successors[0]);
881+
goto optimize_nop;
882+
} else {
883+
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
884+
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(zv));
885+
uint32_t target;
886+
887+
if (jmp_zv) {
888+
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
889+
} else {
890+
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
891+
}
892+
opline->opcode = ZEND_JMP;
893+
opline->extended_value = 0;
894+
SET_UNUSED(opline->op1);
895+
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
896+
SET_UNUSED(opline->op2);
897+
take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
898+
goto optimize_jmp;
899+
}
900+
}
901+
break;
902+
case ZEND_SWITCH_STRING:
903+
if (opline->op1_type == IS_CONST) {
904+
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
905+
if (Z_TYPE_P(zv) != IS_STRING) {
906+
removed_ops++;
907+
MAKE_NOP(opline);
908+
opline->extended_value = 0;
909+
take_successor_ex(ssa, block_num, block, block->successors[0]);
910+
goto optimize_nop;
911+
} else {
912+
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
913+
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(zv));
914+
uint32_t target;
915+
916+
if (jmp_zv) {
917+
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv));
918+
} else {
919+
target = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
920+
}
921+
opline->opcode = ZEND_JMP;
922+
opline->extended_value = 0;
923+
SET_UNUSED(opline->op1);
924+
ZEND_SET_OP_JMP_ADDR(opline, opline->op1, op_array->opcodes + target);
925+
SET_UNUSED(opline->op2);
926+
take_successor_ex(ssa, block_num, block, ssa->cfg.map[target]);
927+
goto optimize_jmp;
928+
}
929+
}
930+
break;
860931
case ZEND_NOP:
861932
optimize_nop:
862933
compress_block(op_array, block);

ext/opcache/Optimizer/sccp.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,42 @@ static void sccp_mark_feasible_successors(
18841884
}
18851885
s = zend_hash_num_elements(Z_ARR_P(op1)) != 0;
18861886
break;
1887+
case ZEND_SWITCH_LONG:
1888+
if (Z_TYPE_P(op1) == IS_LONG) {
1889+
zend_op_array *op_array = scdf->op_array;
1890+
zend_ssa *ssa = scdf->ssa;
1891+
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
1892+
zval *jmp_zv = zend_hash_index_find(jmptable, Z_LVAL_P(op1));
1893+
int target;
1894+
1895+
if (jmp_zv) {
1896+
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
1897+
} else {
1898+
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
1899+
}
1900+
scdf_mark_edge_feasible(scdf, block_num, target);
1901+
return;
1902+
}
1903+
s = 0;
1904+
break;
1905+
case ZEND_SWITCH_STRING:
1906+
if (Z_TYPE_P(op1) == IS_STRING) {
1907+
zend_op_array *op_array = scdf->op_array;
1908+
zend_ssa *ssa = scdf->ssa;
1909+
HashTable *jmptable = Z_ARRVAL_P(CT_CONSTANT_EX(op_array, opline->op2.constant));
1910+
zval *jmp_zv = zend_hash_find(jmptable, Z_STR_P(op1));
1911+
int target;
1912+
1913+
if (jmp_zv) {
1914+
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(jmp_zv))];
1915+
} else {
1916+
target = ssa->cfg.map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)];
1917+
}
1918+
scdf_mark_edge_feasible(scdf, block_num, target);
1919+
return;
1920+
}
1921+
s = 0;
1922+
break;
18871923
default:
18881924
for (s = 0; s < block->successors_count; s++) {
18891925
scdf_mark_edge_feasible(scdf, block_num, block->successors[s]);

0 commit comments

Comments
 (0)