Skip to content

Commit 7e268d9

Browse files
committed
Move to separate function, don't perform it in main
1 parent 7b5628a commit 7e268d9

File tree

1 file changed

+52
-44
lines changed

1 file changed

+52
-44
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,6 +1066,55 @@ static bool zend_dfa_try_to_replace_result(zend_op_array *op_array, zend_ssa *ss
10661066
return 0;
10671067
}
10681068

1069+
/* Sets a flag on SEND ops when a copy can be a avoided. */
1070+
static void zend_dfa_optimize_send_copies(zend_op_array *op_array, zend_ssa *ssa)
1071+
{
1072+
for (int v = 0; v < ssa->vars_count; v++) {
1073+
int var = ssa->vars[v].var;
1074+
if (var >= op_array->last_var) {
1075+
continue;
1076+
}
1077+
1078+
uint32_t type = ssa->var_info[v].type;
1079+
if (!(type & (MAY_BE_ANY-(MAY_BE_RC1|MAY_BE_ARRAY|MAY_BE_ARRAY_OF_ANY|MAY_BE_STRING|MAY_BE_NULL)))) {
1080+
continue;
1081+
}
1082+
1083+
#if 0
1084+
fprintf(stderr, "cv %d: ", v);
1085+
zend_dump_var(op_array, IS_CV, v);
1086+
fprintf(stderr, "\n");
1087+
fprintf(stderr, "type %x\n", type);
1088+
#endif
1089+
1090+
int use = ssa->vars[v].use_chain;
1091+
if (use >= 0
1092+
&& op_array->opcodes[use].opcode == ZEND_SEND_VAR
1093+
&& op_array->opcodes[use].op2_type == IS_UNUSED) {
1094+
int next_use = zend_ssa_next_use(ssa->ops, v, use);
1095+
#if 0
1096+
if (next_use >= 0 && op_array->opcodes[next_use].opcode == ZEND_ASSIGN) {
1097+
fprintf(stderr, "v=%d next_use %d (%d, %d, %d, %d)\n", v, next_use, ssa->ops[next_use].result_def, ssa->ops[next_use].result_use, ssa->ops[next_use].op1_use, ssa->ops[next_use].op2_use);
1098+
fprintf(stderr, "next_use var: %d (var=%d)\n", ssa->vars[next_use].var, var);
1099+
fprintf(stderr, "OP1: %d (var=%d)\n", ssa->vars[ssa->ops[next_use].op1_def].var, var);
1100+
}
1101+
#endif
1102+
/* The next use must be an assignment, and there should be no uses after that.
1103+
* If there is no next use or the next use is not an assignment, then we cannot safely
1104+
* perform the operation without a copy because the nullified value would be observable indirectly
1105+
* through compact(), func_get_args(), ... */
1106+
if (next_use >= 0
1107+
&& op_array->opcodes[next_use].opcode == ZEND_ASSIGN
1108+
&& ssa->ops[next_use].op1_use == v
1109+
&& ssa->vars[v].var == var
1110+
&& zend_ssa_next_use(ssa->ops, v, next_use) < 0) {
1111+
ZEND_ASSERT(op_array->opcodes[use].extended_value == 0);
1112+
op_array->opcodes[use].extended_value = 1;
1113+
}
1114+
}
1115+
}
1116+
}
1117+
10691118
void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, zend_call_info **call_map)
10701119
{
10711120
if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) {
@@ -1124,50 +1173,9 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
11241173
#endif
11251174
}
11261175

1127-
// TODO: move me to other function?
1128-
for (v = 0; v < ssa->vars_count&&op_array->function_name/*TODO*/; v++) {
1129-
int var = ssa->vars[v].var;
1130-
if (var >= op_array->last_var) {
1131-
continue;
1132-
}
1133-
1134-
uint32_t type = ssa->var_info[v].type;
1135-
if (!(type & (MAY_BE_ANY-(MAY_BE_RC1|MAY_BE_ARRAY|MAY_BE_ARRAY_OF_ANY|MAY_BE_STRING|MAY_BE_NULL)))) {
1136-
continue;
1137-
}
1138-
1139-
#if 0
1140-
fprintf(stderr, "cv %d: ", v);
1141-
zend_dump_var(op_array, IS_CV, v);
1142-
fprintf(stderr, "\n");
1143-
fprintf(stderr, "type %x\n", type);
1144-
#endif
1145-
1146-
int use = ssa->vars[v].use_chain;
1147-
if (use >= 0
1148-
&& op_array->opcodes[use].opcode == ZEND_SEND_VAR
1149-
&& op_array->opcodes[use].op2_type == IS_UNUSED) {
1150-
int next_use = zend_ssa_next_use(ssa->ops, v, use);
1151-
#if 0
1152-
if (next_use >= 0 && op_array->opcodes[next_use].opcode == ZEND_ASSIGN) {
1153-
fprintf(stderr, "v=%d next_use %d (%d, %d, %d, %d)\n", v, next_use, ssa->ops[next_use].result_def, ssa->ops[next_use].result_use, ssa->ops[next_use].op1_use, ssa->ops[next_use].op2_use);
1154-
fprintf(stderr, "next_use var: %d (var=%d)\n", ssa->vars[next_use].var, var);
1155-
fprintf(stderr, "OP1: %d (var=%d)\n", ssa->vars[ssa->ops[next_use].op1_def].var, var);
1156-
}
1157-
#endif
1158-
/* The next use must be an assignment, and there should be no uses after that.
1159-
* If there is no next use or the next use is not an assignment, then we cannot safely
1160-
* perform the operation without a copy because the nullified value would be observable indirectly
1161-
* through compact(), func_get_args(), ... */
1162-
if (next_use >= 0
1163-
&& op_array->opcodes[next_use].opcode == ZEND_ASSIGN
1164-
&& ssa->ops[next_use].op1_use == v
1165-
&& ssa->vars[v].var == var
1166-
&& zend_ssa_next_use(ssa->ops, v, next_use) < 0) {
1167-
ZEND_ASSERT(op_array->opcodes[use].extended_value == 0);
1168-
op_array->opcodes[use].extended_value = 1;
1169-
}
1170-
}
1176+
/* Optimization should not be done on main because of globals */
1177+
if (op_array->function_name) {
1178+
zend_dfa_optimize_send_copies(op_array, ssa);
11711179
}
11721180

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

0 commit comments

Comments
 (0)