Commit fc05c9bf248 for php
commit fc05c9bf2486d3d66593501bf78c1d83c32ecbc5
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date: Sun Oct 18 12:09:49 2026 +0200
Fix GH-24396: Assertion failure in zend_jit_def_reg() "reg forwarding" with chained Pi nodes
It's possible for back-edge Pi nodes, that it gets forwarded, but due to
the ordering in which BBs are generated, that at the point it wants to
get forwarded that it was not generated yet.
Closes GH-24403.
diff --git a/NEWS b/NEWS
index cb68d41c333..a70e913cd49 100644
--- a/NEWS
+++ b/NEWS
@@ -99,6 +99,8 @@ PHP NEWS
exits with an uninitialized opline). (waroad)
. Fixed use-after-free in JIT ASSIGN_DIM_OP when concatenating into an
empty array element. (jorgsowa)
+ . Fixed bug GH-24396 (Assertion failure in zend_jit_def_reg() "reg forwarding"
+ with chained Pi nodes). (ndossche)
- PDO:
. Fixed invalid ATTR_ORACLE_NULLS values being accepted and truncated.
diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c
index 536cef3dac7..fc38dd5647f 100644
--- a/ext/opcache/jit/zend_jit_ir.c
+++ b/ext/opcache/jit/zend_jit_ir.c
@@ -1398,7 +1398,9 @@ static void zend_jit_def_reg(zend_jit_ctx *jit, zend_jit_addr addr, ir_ref val)
if (dst_phi->pi >= 0) {
jit->ra[src_var].ref = val;
src_var = dst_phi->ssa_var;
- if (!(jit->ra[src_var].flags & ZREG_FORWARD)) {
+ if (!(jit->ra[src_var].flags & ZREG_FORWARD)
+ /* Pi in a block that is not generated yet. It forwards later on its own. */
+ || (jit->bb_start_ref && !jit->bb_start_ref[dst_phi->block])) {
phi = zend_ssa_next_use_phi(jit->ssa, var, phi);
continue;
}
diff --git a/ext/opcache/tests/jit/gh24396.phpt b/ext/opcache/tests/jit/gh24396.phpt
new file mode 100644
index 00000000000..0ad5696b208
--- /dev/null
+++ b/ext/opcache/tests/jit/gh24396.phpt
@@ -0,0 +1,22 @@
+--TEST--
+GH-24396: Assertion failure in zend_jit_def_reg() "reg forwarding" with chained Pi nodes
+--EXTENSIONS--
+opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.file_update_protection=0
+opcache.jit=function
+--FILE--
+<?php
+function f() {
+ $i = 0;
+ do {
+ $i = ($i + 1) & 255;
+ } while ($i < 2 || $i > 200);
+ return $i;
+}
+var_dump(f());
+?>
+--EXPECT--
+int(2)