Skip to content

Commit 74daa98

Browse files
committed
Added simple DFA optimisation pattern (just to prove the concept)
1 parent 4af9d09 commit 74daa98

File tree

3 files changed

+97
-1
lines changed

3 files changed

+97
-1
lines changed

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,62 @@ void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
128128
zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", &ssa);
129129
}
130130

131-
//TODO: Add optimization???
131+
//TODO: Add optimization patterns ???
132+
if (ssa.var_info) {
133+
int i;
134+
// 1: #1.T = OP_Y | #3.CV = OP_Y
135+
// 2: ASSIGN #2.CV [undef,null,bool] -> #3.cv, #1.T | NOP
136+
for (i = 0; i < ssa.vars_count; i++) {
137+
int op2 = ssa.vars[i].definition;
138+
139+
if (op2 >= 0
140+
&& op_array->opcodes[op2].opcode == ZEND_ASSIGN
141+
&& op_array->opcodes[op2].op1_type == IS_CV
142+
&& (op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR))
143+
&& !RETURN_VALUE_USED(&op_array->opcodes[op2])
144+
) {
145+
146+
int var1 = ssa.ops[op2].op2_use;
147+
int var2 = ssa.ops[op2].op1_use;
148+
149+
if (var1 >= 0
150+
&& var2 >= 0
151+
&& !(ssa.var_info[var2].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
152+
&& !(ssa.var_info[var1].type & MAY_BE_REF)
153+
&& ssa.vars[var1].definition >= 0
154+
&& ssa.ops[ssa.vars[var1].definition].result_def == var1
155+
&& ssa.ops[ssa.vars[var1].definition].result_use < 0
156+
&& ssa.vars[var1].use_chain == op2
157+
&& ssa.ops[op2].op2_use_chain < 0
158+
&& !ssa.vars[var1].phi_use_chain
159+
&& !ssa.vars[var1].sym_use_chain
160+
) {
161+
int op1 = ssa.vars[var1].definition;
162+
int var3 = i;
163+
164+
if (zend_ssa_unlink_use_chain(&ssa, op2, var2)) {
165+
/* Reconstruct SSA */
166+
ssa.vars[var3].definition = op1;
167+
ssa.ops[op1].result_def = var3;
168+
169+
ssa.vars[var1].definition = -1;
170+
ssa.vars[var1].use_chain = -1;
171+
172+
ssa.ops[op2].op1_use = -1;
173+
ssa.ops[op2].op2_use = -1;
174+
ssa.ops[op2].op1_def = -1;
175+
ssa.ops[op2].op1_use_chain = -1;
176+
177+
/* Update opcodes */
178+
op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type;
179+
op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var;
180+
MAKE_NOP(&op_array->opcodes[op2]);
181+
}
182+
}
183+
}
184+
}
185+
}
186+
132187

133188
if (ctx->debug_level & ZEND_DUMP_AFTER_DFA_PASS) {
134189
zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "after dfa pass", &ssa);

ext/opcache/Optimizer/zend_ssa.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,46 @@ int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_
994994
}
995995
/* }}} */
996996

997+
int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var)
998+
{
999+
if (ssa->vars[var].use_chain == op) {
1000+
ssa->vars[var].use_chain = zend_ssa_next_use(ssa->ops, var, op);
1001+
return 1;
1002+
} else {
1003+
int use = ssa->vars[var].use_chain;
1004+
1005+
while (use >= 0) {
1006+
if (ssa->ops[use].result_use == var) {
1007+
if (ssa->ops[use].res_use_chain == op) {
1008+
ssa->ops[use].res_use_chain = zend_ssa_next_use(ssa->ops, var, op);
1009+
return 1;
1010+
} else {
1011+
use = ssa->ops[use].res_use_chain;
1012+
}
1013+
} else if (ssa->ops[use].op1_use == var) {
1014+
if (ssa->ops[use].op1_use_chain == op) {
1015+
ssa->ops[use].op1_use_chain = zend_ssa_next_use(ssa->ops, var, op);
1016+
return 1;
1017+
} else {
1018+
use = ssa->ops[use].op1_use_chain;
1019+
}
1020+
} else if (ssa->ops[use].op2_use == var) {
1021+
if (ssa->ops[use].op2_use_chain == op) {
1022+
ssa->ops[use].op2_use_chain = zend_ssa_next_use(ssa->ops, var, op);
1023+
return 1;
1024+
} else {
1025+
use = ssa->ops[use].op2_use_chain;
1026+
}
1027+
} else {
1028+
break;
1029+
}
1030+
}
1031+
/* something wrong */
1032+
ZEND_ASSERT(0);
1033+
return 0;
1034+
}
1035+
}
1036+
9971037
/*
9981038
* Local variables:
9991039
* tab-width: 4

ext/opcache/Optimizer/zend_ssa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ BEGIN_EXTERN_C()
117117

118118
int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags);
119119
int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa);
120+
int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);
120121

121122
END_EXTERN_C()
122123

0 commit comments

Comments
 (0)