diff --git a/NEWS b/NEWS index ea8935bd64ae..f6b9c81c3c19 100644 --- a/NEWS +++ b/NEWS @@ -149,6 +149,8 @@ PHP NEWS - Opcache: . Fixed bug GH-24397 (Assertion failure when dumping JIT IR). (Ilia Alshanetsky) + . Fixed bug GH-24214 (Function JIT fails to restore shared assignment values + at loop entries when DFA optimization is disabled). (Alessio Attilio) . Fixed tracing JIT returning a wrapped integer instead of a float on integer overflow after an integer was compared with a float or numeric-string literal. (Ilia Alshanetsky) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 53959a536a4a..f412cdbc280f 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -1354,13 +1354,6 @@ static bool zend_jit_spilling_may_cause_conflict(zend_jit_ctx *jit, int var, ir_ && (jit->ssa->cfg.blocks[jit->ssa->vars[jit->ssa->ops[jit->ssa->vars[var].definition].op1_use].definition_phi->block].flags & ZEND_BB_LOOP_HEADER)) { /* Avoid moving spill store out of loop */ return 1; - } else if (jit->ssa->vars[var].definition >= 0 - && jit->ssa->ops[jit->ssa->vars[var].definition].op1_def == var - && jit->ssa->ops[jit->ssa->vars[var].definition].op1_use >= 0 - && jit->ssa->ops[jit->ssa->vars[var].definition].op2_use >= 0 - && jit->ra[jit->ssa->ops[jit->ssa->vars[var].definition].op2_use].ref == val) { - /* Avoid spill conflict between of ASSIGN.op1_def and ASSIGN.op1_use */ - return 1; } return 0; } @@ -1387,6 +1380,14 @@ static void zend_jit_def_reg(zend_jit_ctx *jit, zend_jit_addr addr, ir_ref val) val = ir_emit2(&jit->ctx, IR_OPT(IR_COPY, jit->ctx.ir_base[val].type), val, 1); } } + if (jit->ssa->vars[var].var < jit->current_op_array->last_var + && jit->ssa->vars[var].definition >= 0 + && jit->ssa->ops[jit->ssa->vars[var].definition].op1_def == var + && jit->ssa->ops[jit->ssa->vars[var].definition].op1_use >= 0 + && jit->ssa->ops[jit->ssa->vars[var].definition].op2_use >= 0 + && jit->ra[jit->ssa->ops[jit->ssa->vars[var].definition].op2_use].ref == val) { + val = ir_emit2(&jit->ctx, IR_OPT(IR_COPY, jit->ctx.ir_base[val].type), val, 1); + } if (!zend_jit_spilling_may_cause_conflict(jit, var, val)) { val = ir_bind(&jit->ctx, -EX_NUM_TO_VAR(jit->ssa->vars[var].var), val); } diff --git a/ext/opcache/tests/jit/gh24214.phpt b/ext/opcache/tests/jit/gh24214.phpt new file mode 100644 index 000000000000..15fd6fc49683 --- /dev/null +++ b/ext/opcache/tests/jit/gh24214.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-24214 (Shared assignment values must be restored at function JIT loop entries) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=1235 +opcache.jit_buffer_size=64M +opcache.jit_hot_loop=1 +opcache.optimization_level=0x7FFEBFDF +--FILE-- + true], [4 => true], [4 => true]]); + +foreach ([3, 0, 1, 64] as $size) { + $tokens = markTokens(array_fill(0, $size, [])); + var_dump(count($tokens) === $size); + var_dump($tokens === array_fill(0, $size, [4 => true])); +} +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) diff --git a/ext/opcache/tests/jit/gh24214_002.phpt b/ext/opcache/tests/jit/gh24214_002.phpt new file mode 100644 index 000000000000..0be17248e663 --- /dev/null +++ b/ext/opcache/tests/jit/gh24214_002.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-24214 (Shared floating-point assignment values must be restored at function JIT loop entries) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=1235 +opcache.jit_buffer_size=64M +opcache.jit_hot_loop=1 +opcache.optimization_level=0x7FFEBFDF +--FILE-- + true], [4 => true], [4 => true]]); + +foreach ([3, 0, 1, 64] as $size) { + $tokens = markTokens(array_fill(0, $size, [])); + var_dump(count($tokens) === $size); + var_dump($tokens === array_fill(0, $size, [4 => true])); +} +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true)