Skip to content

Commit 4e2f958

Browse files
committed
Revert "JIT build fix"
This reverts commit f1df587. wip Revert "Deduplicate dominates() function" This reverts commit 8e9ab17. Simplify implementation a lot Fix WIP Remove debug Set op1 result earlier Testing Only clear it if it needs to be cleared Cleanup and fix condition Move some stuff Test nope
1 parent 23511ec commit 4e2f958

File tree

9 files changed

+79
-61
lines changed

9 files changed

+79
-61
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,10 @@ 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-
ZEND_ASSERT(ssa_op->op1_def < 0);
469+
if (ssa_op->op1_def >= 0) {
470+
zend_ssa_replace_op1_def_op1_use(ssa, ssa_op);
471+
}
472+
470473
zend_ssa_unlink_use_chain(ssa, op_num, ssa_op->op1_use);
471474
ssa_op->op1_use = -1;
472475
ssa_op->op1_use_chain = -1;
@@ -1066,46 +1069,34 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss
10661069
return 0;
10671070
}
10681071

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-
10901072
/* Sets a flag on SEND ops when a copy can be a avoided. */
1091-
static void zend_dfa_optimize_send_copies(zend_op_array *op_array, const zend_ssa *ssa)
1073+
static void zend_dfa_optimize_send_copies(zend_op_array *op_array, zend_ssa *ssa)
10921074
{
1093-
/* func_get_args() etc could make the optimization observable */
1094-
if (ssa->cfg.flags & ZEND_FUNC_VARARG) {
1075+
/* func_get_args() and indirect accesses could make the optimization observable */
1076+
if (ssa->cfg.flags & (ZEND_FUNC_VARARG | ZEND_FUNC_INDIRECT_VAR_ACCESS)) {
10951077
return;
10961078
}
10971079

10981080
for (uint32_t i = 0; i < op_array->last; i++) {
1099-
const zend_op *opline = &op_array->opcodes[i];
1081+
zend_op *opline = op_array->opcodes + i;
11001082
if ((opline->opcode != ZEND_SEND_VAR && opline->opcode != ZEND_SEND_VAR_EX) || opline->op2_type != IS_UNUSED || opline->op1_type != IS_CV) {
11011083
continue;
11021084
}
11031085

1104-
/* NULL must not be visible in backtraces */
1105-
int ssa_cv = ssa->ops[i].op1_use;
1086+
zend_ssa_op *ssa_op = ssa->ops + i;
1087+
int op1_def = ssa_op->op1_def;
1088+
if (op1_def == -1) {
1089+
continue;
1090+
}
1091+
1092+
int ssa_cv = ssa_op->op1_use;
1093+
1094+
#if 0
1095+
/* Argument move must not be observable in backtraces */
11061096
if (ssa->vars[ssa_cv].var < op_array->num_args) {
11071097
continue;
11081098
}
1099+
#endif
11091100

11101101
/* Unsetting a CV is always fine if it gets overwritten afterwards.
11111102
* Since type inference often infers very wide types, we are very loose in matching types. */
@@ -1114,25 +1105,13 @@ static void zend_dfa_optimize_send_copies(zend_op_array *op_array, const zend_ss
11141105
continue;
11151106
}
11161107

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-
}
1108+
zend_ssa_var *ssa_var = ssa->vars + op1_def;
1109+
1110+
if (ssa_var->no_val && !ssa_var->alias) {
1111+
/* Flag will be used by VM type spec handler */
1112+
opline->extended_value = 1;
1113+
} else if (opline->opcode == ZEND_SEND_VAR) {
1114+
zend_ssa_replace_op1_def_op1_use(ssa, ssa_op);
11361115
}
11371116
}
11381117
}
@@ -1155,6 +1134,14 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
11551134
ssa_verify_integrity(op_array, ssa, "before dfa");
11561135
#endif
11571136

1137+
/* Optimization should not be done on main because of globals. */
1138+
if (op_array->function_name) {
1139+
zend_dfa_optimize_send_copies(op_array, ssa);
1140+
#if ZEND_DEBUG_DFA
1141+
ssa_verify_integrity(op_array, ssa, "after optimize send copies");
1142+
#endif
1143+
}
1144+
11581145
if (ZEND_OPTIMIZER_PASS_8 & ctx->optimization_level) {
11591146
if (sccp_optimize_op_array(ctx, op_array, ssa, call_map)) {
11601147
remove_nops = 1;
@@ -1195,11 +1182,6 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
11951182
#endif
11961183
}
11971184

1198-
/* Optimization should not be done on main because of globals. */
1199-
if (op_array->function_name) {
1200-
zend_dfa_optimize_send_copies(op_array, ssa);
1201-
}
1202-
12031185
for (v = op_array->last_var; v < ssa->vars_count; v++) {
12041186

12051187
op_1 = ssa->vars[v].definition;

Zend/Optimizer/sccp.c

Lines changed: 17 additions & 3 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(zval *zv) {
101+
static void scp_dump_value(const zval *zv) {
102102
if (IS_TOP(zv)) {
103103
fprintf(stderr, " top");
104104
} else if (IS_BOT(zv)) {
@@ -245,6 +245,8 @@ static bool can_replace_op1(
245245
case ZEND_SEND_USER:
246246
case ZEND_FE_RESET_RW:
247247
return 0;
248+
case ZEND_SEND_VAR:
249+
return ssa_op->op1_def == -1;
248250
/* Do not accept CONST */
249251
case ZEND_ROPE_ADD:
250252
case ZEND_ROPE_END:
@@ -1050,6 +1052,12 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
10501052
case ZEND_SEND_VAL:
10511053
case ZEND_SEND_VAR:
10521054
{
1055+
if (opline->opcode == ZEND_SEND_VAR) {
1056+
/* TODO ? */
1057+
/* Can be UNDEF or a value copy */
1058+
SET_RESULT_BOT(op1);
1059+
}
1060+
10531061
/* If the value of a SEND for an ICALL changes, we need to reconsider the
10541062
* ICALL result value. Otherwise we can ignore the opcode. */
10551063
zend_call_info *call;
@@ -2034,8 +2042,14 @@ static int remove_call(sccp_ctx *ctx, zend_op *opline, zend_ssa_op *ssa_op)
20342042
&ssa->ops[call->caller_init_opline - op_array->opcodes]);
20352043

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

20412055
// TODO: remove call_info completely???

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-
bool dominates(const zend_basic_block *blocks, int a, int b) /* {{{ */
764+
static bool dominates(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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ 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);
124123

125124
END_EXTERN_C()
126125

Zend/Optimizer/zend_dfg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_
152152
case ZEND_BIND_STATIC:
153153
case ZEND_SEND_VAR_NO_REF:
154154
case ZEND_SEND_VAR_NO_REF_EX:
155+
case ZEND_SEND_VAR:
155156
case ZEND_SEND_VAR_EX:
156157
case ZEND_SEND_FUNC_ARG:
157158
case ZEND_SEND_REF:
@@ -173,7 +174,6 @@ static zend_always_inline void _zend_dfg_add_use_def_op(const zend_op_array *op_
173174
goto add_op1_def;
174175
}
175176
break;
176-
case ZEND_SEND_VAR:
177177
case ZEND_CAST:
178178
case ZEND_QM_ASSIGN:
179179
case ZEND_JMP_SET:

Zend/Optimizer/zend_inference.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,6 +2950,9 @@ 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+
}
29532956
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
29542957
COPY_SSA_OBJ_TYPE(ssa_op->op1_use, ssa_op->op1_def);
29552958
}
@@ -2991,6 +2994,9 @@ static zend_always_inline zend_result _zend_update_type_info(
29912994
case ZEND_SEND_FUNC_ARG:
29922995
if (ssa_op->op1_def >= 0) {
29932996
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+
}
29943000
UPDATE_SSA_TYPE(tmp, ssa_op->op1_def);
29953001
}
29963002
break;

Zend/Optimizer/zend_ssa.c

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

2020
#include "zend_compile.h"
21-
#include "zend_cfg.h"
2221
#include "zend_dfg.h"
2322
#include "zend_ssa.h"
2423
#include "zend_dump.h"
2524
#include "zend_inference.h"
2625
#include "Optimizer/zend_optimizer_internal.h"
2726

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+
2834
static bool will_rejoin(
2935
const zend_cfg *cfg, const zend_dfg *dfg, const zend_basic_block *block,
3036
int other_successor, int exclude, int var) {
@@ -676,6 +682,7 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array,
676682
case ZEND_SEND_VAR_NO_REF:
677683
case ZEND_SEND_VAR_NO_REF_EX:
678684
case ZEND_SEND_VAR_EX:
685+
case ZEND_SEND_VAR:
679686
case ZEND_SEND_FUNC_ARG:
680687
case ZEND_SEND_REF:
681688
case ZEND_SEND_UNPACK:
@@ -696,7 +703,6 @@ static zend_always_inline int _zend_ssa_rename_op(const zend_op_array *op_array,
696703
goto add_op1_def;
697704
}
698705
break;
699-
case ZEND_SEND_VAR:
700706
case ZEND_CAST:
701707
case ZEND_QM_ASSIGN:
702708
case ZEND_JMP_SET:
@@ -1674,3 +1680,13 @@ void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types
16741680
old_var->phi_use_chain = NULL;
16751681
}
16761682
/* }}} */
1683+
1684+
void zend_ssa_replace_op1_def_op1_use(zend_ssa *ssa, zend_ssa_op *ssa_op)
1685+
{
1686+
int op1_new = ssa_op->op1_use;
1687+
ZEND_ASSERT(op1_new >= 0);
1688+
ZEND_ASSERT(ssa_op->op1_def >= 0);
1689+
/* zend_ssa_rename_var_uses() clear use_chain & phi_use_chain for us */
1690+
zend_ssa_rename_var_uses(ssa, ssa_op->op1_def, op1_new, true);
1691+
zend_ssa_remove_op1_def(ssa, ssa_op);
1692+
}

Zend/Optimizer/zend_ssa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ 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);
162163

163164
static zend_always_inline void _zend_ssa_remove_def(zend_ssa_var *var)
164165
{

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-
bool dominates(const zend_basic_block *blocks, int a, int b) {
159+
static 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)