Skip to content

Commit eb43f8a

Browse files
committed
Eliminate more VERIFY_RETURN_TYPE instructions
1 parent 1d44829 commit eb43f8a

File tree

3 files changed

+79
-16
lines changed

3 files changed

+79
-16
lines changed

Zend/Optimizer/dfa_pass.c

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,30 +1293,52 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
12931293
} else if (opline->opcode == ZEND_VERIFY_RETURN_TYPE
12941294
&& opline->op1_type != IS_CONST
12951295
&& ssa->ops[op_1].op1_def == v
1296-
&& ssa->ops[op_1].op1_use >= 0
1297-
&& ssa->ops[op_1].op1_use_chain == -1
1298-
&& can_elide_return_type_check(ctx->script, op_array, ssa, &ssa->ops[op_1])) {
1296+
&& ssa->ops[op_1].op1_use >= 0) {
1297+
int orig_var = ssa->ops[op_1].op1_use;
1298+
int ret = ssa->vars[v].use_chain;
1299+
1300+
if (ssa->ops[op_1].op1_use_chain == -1
1301+
&& can_elide_return_type_check(ctx->script, op_array, ssa, &ssa->ops[op_1])) {
12991302

13001303
// op_1: VERIFY_RETURN_TYPE #orig_var.? [T] -> #v.? [T] => NOP
13011304

1302-
int orig_var = ssa->ops[op_1].op1_use;
1303-
zend_ssa_unlink_use_chain(ssa, op_1, orig_var);
1305+
zend_ssa_unlink_use_chain(ssa, op_1, orig_var);
1306+
1307+
if (ret >= 0) {
1308+
ssa->ops[ret].op1_use = orig_var;
1309+
ssa->ops[ret].op1_use_chain = ssa->vars[orig_var].use_chain;
1310+
ssa->vars[orig_var].use_chain = ret;
1311+
}
1312+
1313+
ssa->vars[v].definition = -1;
1314+
ssa->vars[v].use_chain = -1;
1315+
1316+
ssa->ops[op_1].op1_def = -1;
1317+
ssa->ops[op_1].op1_use = -1;
1318+
1319+
MAKE_NOP(opline);
1320+
remove_nops = 1;
1321+
} else if (ret >= 0
1322+
&& ssa->ops[ret].op1_use == v
1323+
&& ssa->ops[ret].op1_use_chain == -1
1324+
&& can_elide_return_type_check(ctx->script, op_array, ssa, &ssa->ops[op_1])) {
1325+
1326+
// op_1: VERIFY_RETURN_TYPE #orig_var.? [T] -> #v.? [T] => NOP
1327+
1328+
zend_ssa_replace_use_chain(ssa, op_1, ret, orig_var);
13041329

1305-
int ret = ssa->vars[v].use_chain;
1306-
if (ret >= 0) {
13071330
ssa->ops[ret].op1_use = orig_var;
1308-
ssa->ops[ret].op1_use_chain = ssa->vars[orig_var].use_chain;
1309-
ssa->vars[orig_var].use_chain = ret;
1310-
}
1331+
ssa->ops[ret].op1_use_chain = ssa->ops[op_1].op1_use_chain;
13111332

1312-
ssa->vars[v].definition = -1;
1313-
ssa->vars[v].use_chain = -1;
1333+
ssa->vars[v].definition = -1;
1334+
ssa->vars[v].use_chain = -1;
13141335

1315-
ssa->ops[op_1].op1_def = -1;
1316-
ssa->ops[op_1].op1_use = -1;
1336+
ssa->ops[op_1].op1_def = -1;
1337+
ssa->ops[op_1].op1_use = -1;
13171338

1318-
MAKE_NOP(opline);
1319-
remove_nops = 1;
1339+
MAKE_NOP(opline);
1340+
remove_nops = 1;
1341+
}
13201342
}
13211343
}
13221344

Zend/Optimizer/zend_ssa.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,46 @@ void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var) /* {{{ */
12091209
}
12101210
/* }}} */
12111211

1212+
void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var) /* {{{ */
1213+
{
1214+
if (ssa->vars[var].use_chain == op) {
1215+
ssa->vars[var].use_chain = new_op;
1216+
return;
1217+
} else {
1218+
int use = ssa->vars[var].use_chain;
1219+
1220+
while (use >= 0) {
1221+
if (ssa->ops[use].result_use == var) {
1222+
if (ssa->ops[use].res_use_chain == op) {
1223+
ssa->ops[use].res_use_chain = new_op;
1224+
return;
1225+
} else {
1226+
use = ssa->ops[use].res_use_chain;
1227+
}
1228+
} else if (ssa->ops[use].op1_use == var) {
1229+
if (ssa->ops[use].op1_use_chain == op) {
1230+
ssa->ops[use].op1_use_chain = new_op;
1231+
return;
1232+
} else {
1233+
use = ssa->ops[use].op1_use_chain;
1234+
}
1235+
} else if (ssa->ops[use].op2_use == var) {
1236+
if (ssa->ops[use].op2_use_chain == op) {
1237+
ssa->ops[use].op2_use_chain = new_op;
1238+
return;
1239+
} else {
1240+
use = ssa->ops[use].op2_use_chain;
1241+
}
1242+
} else {
1243+
break;
1244+
}
1245+
}
1246+
}
1247+
/* something wrong */
1248+
ZEND_UNREACHABLE();
1249+
}
1250+
/* }}} */
1251+
12121252
void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op) /* {{{ */
12131253
{
12141254
if (ssa_op->result_use >= 0) {

Zend/Optimizer/zend_ssa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ ZEND_API zend_result zend_build_ssa(zend_arena **arena, const zend_script *scrip
149149
ZEND_API void zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa);
150150
ZEND_API int zend_ssa_rename_op(const zend_op_array *op_array, const zend_op *opline, uint32_t k, uint32_t build_flags, int ssa_vars_count, zend_ssa_op *ssa_ops, int *var);
151151
void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);
152+
void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var);
152153

153154
void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to);
154155
void zend_ssa_remove_defs_of_instr(zend_ssa *ssa, zend_ssa_op *ssa_op);

0 commit comments

Comments
 (0)