Skip to content

Commit dc8badf

Browse files
committed
Revert "Implementation using NO_VAL", testing
This reverts commit b81d379.
1 parent b81d379 commit dc8badf

File tree

10 files changed

+59
-90
lines changed

10 files changed

+59
-90
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,7 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
466466
int var_num = ssa_op->op1_use;
467467
zend_ssa_var *var = ssa->vars + var_num;
468468

469-
if (ssa_op->op1_def >= 0) {
470-
zend_ssa_replace_op1_def_op1_use(ssa, ssa_op);
471-
}
472-
469+
ZEND_ASSERT(ssa_op->op1_def < 0);
473470
zend_ssa_unlink_use_chain(ssa, op_num, ssa_op->op1_use);
474471
ssa_op->op1_use = -1;
475472
ssa_op->op1_use_chain = -1;
@@ -1069,48 +1066,73 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss
10691066
return 0;
10701067
}
10711068

1069+
static bool op_dominates(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *a, const zend_op *b)
1070+
{
1071+
uint32_t a_block = ssa->cfg.map[a - op_array->opcodes];
1072+
uint32_t b_block = ssa->cfg.map[b - op_array->opcodes];
1073+
if (a_block == b_block) {
1074+
return a < b;
1075+
} else {
1076+
return dominates(ssa->cfg.blocks, a_block, b_block);
1077+
}
1078+
}
1079+
1080+
static bool op_dominates_all_uses(const zend_op_array *op_array, const zend_ssa *ssa, int start) {
1081+
int use;
1082+
FOREACH_USE(ssa->vars + ssa->ops[start].op1_def, use) {
1083+
if (!op_dominates(op_array, ssa, op_array->opcodes + start, op_array->opcodes + use)) {
1084+
return false;
1085+
}
1086+
} FOREACH_USE_END();
1087+
return true;
1088+
}
1089+
10721090
/* Sets a flag on SEND ops when a copy can be a avoided. */
1073-
static void zend_dfa_optimize_send_copies(zend_op_array *op_array, zend_ssa *ssa)
1091+
static void zend_dfa_optimize_send_copies(zend_op_array *op_array, const zend_ssa *ssa)
10741092
{
1075-
/* func_get_args(), indirect accesses and exceptions could make the optimization observable.
1076-
* The latter two cases are already tested before applying the DFA pass. */
1093+
/* func_get_args() etc could make the optimization observable */
10771094
if (ssa->cfg.flags & ZEND_FUNC_VARARG) {
10781095
return;
10791096
}
10801097

10811098
for (uint32_t i = 0; i < op_array->last; i++) {
1082-
zend_op *opline = op_array->opcodes + i;
1099+
const zend_op *opline = &op_array->opcodes[i];
10831100
if ((opline->opcode != ZEND_SEND_VAR && opline->opcode != ZEND_SEND_VAR_EX) || opline->op2_type != IS_UNUSED || opline->op1_type != IS_CV) {
10841101
continue;
10851102
}
1086-
1087-
zend_ssa_op *ssa_op = ssa->ops + i;
1088-
int op1_def = ssa_op->op1_def;
1089-
if (op1_def == -1) {
1090-
continue;
1091-
}
1092-
1093-
int ssa_cv = ssa_op->op1_use;
1094-
1103+
int ssa_cv = ssa->ops[i].op1_use;
10951104
#if 0
1096-
/* Argument move must not be observable in backtraces */
1105+
/* NULL must not be visible in backtraces */
10971106
if (ssa->vars[ssa_cv].var < op_array->num_args) {
10981107
continue;
10991108
}
11001109
#endif
1101-
11021110
/* Unsetting a CV is always fine if it gets overwritten afterwards.
11031111
* Since type inference often infers very wide types, we are very loose in matching types. */
11041112
uint32_t type = ssa->var_info[ssa_cv].type;
11051113
if ((type & (MAY_BE_REF|MAY_BE_UNDEF)) || !(type & MAY_BE_RC1) || !(type & (MAY_BE_STRING|MAY_BE_ARRAY))) {
11061114
continue;
11071115
}
11081116

1109-
zend_ssa_var *ssa_var = ssa->vars + op1_def;
1110-
1111-
if (ssa_var->no_val && !ssa_var->alias) {
1112-
/* Flag will be used by VM type spec handler */
1113-
opline->extended_value = 1;
1117+
if (opline->opcode == ZEND_SEND_VAR) {
1118+
/* Check if the call dominates the assignment and the assignment dominates all the future uses of this SSA variable */
1119+
int next_use = ssa->ops[i].op1_use_chain;
1120+
if (next_use >= 0
1121+
&& op_array->opcodes[next_use].opcode == ZEND_ASSIGN
1122+
&& ssa->ops[next_use].op1_use == ssa_cv
1123+
&& ssa->ops[next_use].op2_use >= 0
1124+
&& op_dominates(op_array, ssa, opline, op_array->opcodes + next_use)) {
1125+
if (op_dominates_all_uses(op_array, ssa, next_use)) {
1126+
op_array->opcodes[i].extended_value = 1;
1127+
//fprintf(stderr, "yes optimize 1\n");
1128+
}
1129+
}
1130+
} else /* ZEND_SEND_VAR_EX */ {
1131+
ZEND_ASSERT(ssa->ops[i].op1_def != -1);
1132+
if (ssa->vars[ssa->ops[i].op1_def].no_val) {
1133+
op_array->opcodes[i].extended_value = 1;
1134+
//fprintf(stderr, "yes optimize 2\n");
1135+
}
11141136
}
11151137
}
11161138
}
@@ -1176,9 +1198,6 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
11761198
/* Optimization should not be done on main because of globals. */
11771199
if (op_array->function_name) {
11781200
zend_dfa_optimize_send_copies(op_array, ssa);
1179-
#if ZEND_DEBUG_DFA
1180-
ssa_verify_integrity(op_array, ssa, "after optimize send copies");
1181-
#endif
11821201
}
11831202

11841203
for (v = op_array->last_var; v < ssa->vars_count; v++) {

Zend/Optimizer/sccp.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ typedef struct _sccp_ctx {
9898
#define MAKE_TOP(zv) (Z_TYPE_INFO_P(zv) = TOP)
9999
#define MAKE_BOT(zv) (Z_TYPE_INFO_P(zv) = BOT)
100100

101-
static void scp_dump_value(const zval *zv) {
101+
static void scp_dump_value(zval *zv) {
102102
if (IS_TOP(zv)) {
103103
fprintf(stderr, " top");
104104
} else if (IS_BOT(zv)) {
@@ -1050,12 +1050,6 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
10501050
case ZEND_SEND_VAL:
10511051
case ZEND_SEND_VAR:
10521052
{
1053-
SKIP_IF_TOP(op1);
1054-
1055-
if (opline->opcode == ZEND_SEND_VAR) {
1056-
SET_RESULT(op1, op1);
1057-
}
1058-
10591053
/* If the value of a SEND for an ICALL changes, we need to reconsider the
10601054
* ICALL result value. Otherwise we can ignore the opcode. */
10611055
zend_call_info *call;
@@ -1064,7 +1058,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
10641058
}
10651059

10661060
call = ctx->call_map[opline - ctx->scdf.op_array->opcodes];
1067-
if (!call || !call->caller_call_opline
1061+
if (IS_TOP(op1) || !call || !call->caller_call_opline
10681062
|| call->caller_call_opline->opcode != ZEND_DO_ICALL) {
10691063
return;
10701064
}
@@ -2040,14 +2034,8 @@ static int remove_call(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op)
20402034
&ssa->ops[call->caller_init_opline - op_array->opcodes]);
20412035

20422036
for (i = 0; i < call->num_args; i++) {
2043-
zend_op *op = call->arg_info[i].opline;
2044-
zend_ssa_op *this_ssa_op = &ssa->ops[op - op_array->opcodes];
2045-
2046-
if (op->opcode == ZEND_SEND_VAR && this_ssa_op->op1_def >= 0) {
2047-
zend_ssa_replace_op1_def_op1_use(ssa, this_ssa_op);
2048-
}
2049-
2050-
zend_ssa_remove_instr(ssa, op, this_ssa_op);
2037+
zend_ssa_remove_instr(ssa, call->arg_info[i].opline,
2038+
&ssa->ops[call->arg_info[i].opline - op_array->opcodes]);
20512039
}
20522040

20532041
// TODO: remove call_info completely???
@@ -2200,10 +2188,6 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var,
22002188
return 0;
22012189
}
22022190

2203-
if (opline->opcode == ZEND_SEND_VAR) {
2204-
return 0;
2205-
}
2206-
22072191
/* Compound assign or incdec -> convert to direct ASSIGN */
22082192

22092193
if (!value) {
@@ -2346,9 +2330,6 @@ static int replace_constant_operands(sccp_ctx *ctx) {
23462330
FOREACH_USE(var, use) {
23472331
zend_op *opline = &op_array->opcodes[use];
23482332
zend_ssa_op *ssa_op = &ssa->ops[use];
2349-
if (opline->opcode == ZEND_SEND_VAR && ssa_op->op1_use == i && ssa_op->op1_def >= 0) {
2350-
zend_ssa_replace_op1_def_op1_use(ssa, ssa_op);
2351-
}
23522333
if (try_replace_op1(ctx, opline, ssa_op, i, value)) {
23532334
if (opline->opcode == ZEND_NOP) {
23542335
removed_ops++;

Zend/Optimizer/zend_cfg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, ze
761761
}
762762
/* }}} */
763763

764-
static bool dominates(zend_basic_block *blocks, int a, int b) /* {{{ */
764+
bool dominates(const zend_basic_block *blocks, int a, int b) /* {{{ */
765765
{
766766
while (blocks[b].level > blocks[a].level) {
767767
b = blocks[b].idom;

Zend/Optimizer/zend_cfg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *c
120120
ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg);
121121
ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg);
122122
ZEND_API void zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg);
123+
bool dominates(const zend_basic_block *blocks, int a, int b);
123124

124125
END_EXTERN_C()
125126

Zend/Optimizer/zend_dfg.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,6 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_
174174
}
175175
break;
176176
case ZEND_SEND_VAR:
177-
if (opline->op1_type == IS_CV && ((build_flags & ZEND_SSA_RC_INFERENCE) || opline->op2_type == IS_UNUSED)) {
178-
goto add_op1_def;
179-
}
180-
break;
181177
case ZEND_CAST:
182178
case ZEND_QM_ASSIGN:
183179
case ZEND_JMP_SET:

Zend/Optimizer/zend_inference.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,9 +2950,6 @@ static zend_always_inline zend_result _zend_update_type_info(
29502950
if (t1 & (MAY_BE_RC1|MAY_BE_REF)) {
29512951
tmp |= MAY_BE_RCN;
29522952
}
2953-
if ((t1 & (MAY_BE_ARRAY|MAY_BE_STRING)) && (t1 & MAY_BE_RC1) && !(t1 & (MAY_BE_UNDEF|MAY_BE_REF)) && ssa_vars[ssa_op->op1_def].no_val && !ssa_vars[ssa_op->op1_def].alias) {
2954-
tmp |= MAY_BE_UNDEF;
2955-
}
29562953
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
29572954
COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
29582955
}
@@ -2994,9 +2991,6 @@ static zend_always_inline zend_result _zend_update_type_info(
29942991
case ZEND_SEND_FUNC_ARG:
29952992
if (ssa_op->op1_def >= 0) {
29962993
tmp = (t1 & MAY_BE_UNDEF)|MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2997-
if (opline->opcode == ZEND_SEND_VAR_EX && (t1 & (MAY_BE_ARRAY|MAY_BE_STRING)) && (t1 & MAY_BE_RC1) && !(t1 & (MAY_BE_UNDEF|MAY_BE_REF)) && ssa_vars[ssa_op->op1_def].no_val && !ssa_vars[ssa_op->op1_def].alias) {
2998-
tmp |= MAY_BE_UNDEF;
2999-
}
30002994
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
30012995
}
30022996
break;

Zend/Optimizer/zend_ssa.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,13 @@
1818
*/
1919

2020
#include "zend_compile.h"
21+
#include "zend_cfg.h"
2122
#include "zend_dfg.h"
2223
#include "zend_ssa.h"
2324
#include "zend_dump.h"
2425
#include "zend_inference.h"
2526
#include "Optimizer/zend_optimizer_internal.h"
2627

27-
static bool dominates(const zend_basic_block *blocks, int a, int b) {
28-
while (blocks[b].level > blocks[a].level) {
29-
b = blocks[b].idom;
30-
}
31-
return a == b;
32-
}
33-
3428
static bool will_rejoin(
3529
const zend_cfg *cfg, const zend_dfg *dfg, const zend_basic_block *block,
3630
int other_successor, int exclude, int var) {
@@ -703,10 +697,6 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array,
703697
}
704698
break;
705699
case ZEND_SEND_VAR:
706-
if (opline->op1_type == IS_CV && ((build_flags & ZEND_SSA_RC_INFERENCE) || opline->op2_type == IS_UNUSED)) {
707-
goto add_op1_def;
708-
}
709-
break;
710700
case ZEND_CAST:
711701
case ZEND_QM_ASSIGN:
712702
case ZEND_JMP_SET:
@@ -1684,13 +1674,3 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types
16841674
old_var->phi_use_chain = NULL;
16851675
}
16861676
/* }}} */
1687-
1688-
void zend_ssa_replace_op1_def_op1_use(zend_ssa *ssa, zend_ssa_op *ssa_op)
1689-
{
1690-
int op1_new = ssa_op->op1_use;
1691-
ZEND_ASSERT(op1_new >= 0);
1692-
ZEND_ASSERT(ssa_op->op1_def >= 0);
1693-
/* zend_ssa_rename_var_uses() clear use_chain & phi_use_chain for us */
1694-
zend_ssa_rename_var_uses(ssa, ssa_op->op1_def, op1_new, true);
1695-
zend_ssa_remove_op1_def(ssa, ssa_op);
1696-
}

Zend/Optimizer/zend_ssa.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num);
159159
void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int b);
160160
void zend_ssa_rename_var_uses(zend_ssa *ssa, int old_var, int new_var, bool update_types);
161161
void zend_ssa_remove_block_from_cfg(zend_ssa *ssa, int b);
162-
void zend_ssa_replace_op1_def_op1_use(zend_ssa *ssa, zend_ssa_op *ssa_op);
163162

164163
static zend_always_inline void _zend_ssa_remove_def(zend_ssa_var *var)
165164
{

benchmark/benchmark.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ function main() {
1313
global $storeResult;
1414

1515
$data = [];
16-
/* $data['Zend/bench.php'] = runBench(false);
16+
$data['Zend/bench.php'] = runBench(false);
1717
$data['Zend/bench.php JIT'] = runBench(true);
1818
$data['Symfony Demo 2.2.3'] = runSymfonyDemo(false);
19-
$data['Symfony Demo 2.2.3 JIT'] = runSymfonyDemo(true);*/
19+
$data['Symfony Demo 2.2.3 JIT'] = runSymfonyDemo(true);
2020
$data['Wordpress 6.2'] = runWordpress(false);
21-
// $data['Wordpress 6.2 JIT'] = runWordpress(true);
21+
$data['Wordpress 6.2 JIT'] = runWordpress(true);
2222
$result = json_encode($data, JSON_PRETTY_PRINT) . "\n";
2323

2424
fwrite(STDOUT, $result);
@@ -78,7 +78,7 @@ function runWordpress(bool $jit): array {
7878

7979
// Warmup
8080
runPhpCommand([$dir . '/index.php'], $dir);
81-
return runValgrindPhpCgiCommand([$dir . '/index.php'], cwd: $dir, jit: $jit, warmup: 2, repeat: 2);
81+
return runValgrindPhpCgiCommand([$dir . '/index.php'], cwd: $dir, jit: $jit, warmup: 50, repeat: 50);
8282
}
8383

8484
function runPhpCommand(array $args, ?string $cwd = null): ProcessResult {
@@ -97,12 +97,11 @@ function runValgrindPhpCgiCommand(
9797
'valgrind',
9898
'--tool=callgrind',
9999
'--dump-instr=yes',
100-
//'--callgrind-out-file=/dev/null',
100+
'--callgrind-out-file=/dev/null',
101101
'--',
102102
$phpCgi,
103103
'-T' . ($warmup ? $warmup . ',' : '') . $repeat,
104104
'-d max_execution_time=0',
105-
'-c', '/run/media/niels/MoreData/php-src',
106105
'-d opcache.enable=1',
107106
'-d opcache.jit_buffer_size=' . ($jit ? '128M' : '0'),
108107
'-d opcache.validate_timestamps=0',

ext/opcache/jit/zend_jit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ static int zend_jit_assign_to_variable(dasm_State **Dst,
156156
zend_jit_addr res_addr,
157157
bool check_exception);
158158

159-
static bool dominates(const zend_basic_block *blocks, int a, int b) {
159+
bool dominates(const zend_basic_block *blocks, int a, int b) {
160160
while (blocks[b].level > blocks[a].level) {
161161
b = blocks[b].idom;
162162
}

0 commit comments

Comments
 (0)