Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 8 additions & 7 deletions ext/opcache/jit/zend_jit_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
}
Expand Down
39 changes: 39 additions & 0 deletions ext/opcache/tests/jit/gh24214.phpt
Original file line number Diff line number Diff line change
@@ -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--
<?php
function markTokens(array $tokens): array {
$n = count($tokens);
for ($i = 0; $i < $n; ++$i) {
$tokens[$i][4] = true;
}
return $tokens;
}

var_dump(markTokens([[], [], []]) === [[4 => 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)
39 changes: 39 additions & 0 deletions ext/opcache/tests/jit/gh24214_002.phpt
Original file line number Diff line number Diff line change
@@ -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--
<?php
function markTokens(array $tokens): array {
$n = (float) count($tokens);
for ($i = 0; $i < $n; ++$i) {
$tokens[$i][4] = true;
}
return $tokens;
}

var_dump(markTokens([[], [], []]) === [[4 => 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)
Loading