Commit f0734254264 for php.net

commit f07342542645d1e297605a381da4e388163ed24f
Author: Dmitry Stogov <dmitry@php.net>
Date:   Wed Feb 25 17:18:25 2026 +0300

    Update IR

    IR commit: d8fbd3b198007f633a255b855cad036758deefb6

    Fixes function JIT failures introduced by e792511179199a6ec12ddabad5e7bd7e7d785271

diff --git a/ext/opcache/jit/ir/ir_cfg.c b/ext/opcache/jit/ir/ir_cfg.c
index 357b985e63c..ca57845a0c7 100644
--- a/ext/opcache/jit/ir/ir_cfg.c
+++ b/ext/opcache/jit/ir/ir_cfg.c
@@ -1034,8 +1034,6 @@ static IR_NEVER_INLINE void ir_collect_irreducible_loops(ir_ctx *ctx, uint32_t *
 			do {
 				uint32_t pred = *p;
 				if (ENTRY_TIME(pred) > ENTRY_TIME(hdr) && EXIT_TIME(pred) < EXIT_TIME(hdr)) {
-					IR_ASSERT(blocks[pred].loop_header == 0);
-					// blocks[pred].loop_header = 0; /* support for merged loops */
 					ir_worklist_push(work, pred);
 				}
 				p++;
@@ -1046,7 +1044,9 @@ static IR_NEVER_INLINE void ir_collect_irreducible_loops(ir_ctx *ctx, uint32_t *
 				uint32_t b = ir_worklist_pop(work);

 				bb = &blocks[b];
-				bb->loop_header = hdr;
+				if (!bb->loop_header) {
+					bb->loop_header = hdr;
+				}

 				uint32_t *p = &edges[bb->predecessors];
 				uint32_t n = bb->predecessors_count;
@@ -1175,8 +1175,6 @@ int ir_find_loops(ir_ctx *ctx)
 						if (!ir_worklist_len(&work)) {
 							ir_bitset_clear(work.visited, ir_bitset_len(ir_worklist_capasity(&work)));
 						}
-						IR_ASSERT(!blocks[pred].loop_header);
-						// blocks[pred].loop_header = 0; /* support for merged loops */
 						ir_worklist_push(&work, pred);
 					} else {
 						/* Otherwise it's a back-edge of irreducible loop. */
@@ -1214,8 +1212,9 @@ int ir_find_loops(ir_ctx *ctx)
 					if (b != hdr) {
 						ir_block *bb = &blocks[b];

-						IR_ASSERT(!bb->loop_header);
-						bb->loop_header = hdr;
+						if (!bb->loop_header) {
+							bb->loop_header = hdr;
+						}

 						uint32_t *p = &edges[bb->predecessors];
 						uint32_t n = bb->predecessors_count;
@@ -1479,6 +1478,19 @@ static void ir_dump_chains(ir_ctx *ctx, ir_chain *chains)
 		}
 	}
 }
+
+static bool ir_is_merged_loop_back_edge(ir_ctx *ctx, uint32_t hdr, uint32_t b)
+{
+	if (ctx->cfg_blocks[hdr].flags & IR_BB_LOOP_HEADER) {
+		uint32_t loop_depth = ctx->cfg_blocks[hdr].loop_depth;
+
+		while (ctx->cfg_blocks[b].loop_depth > loop_depth) {
+			b = ctx->cfg_blocks[b].loop_header;
+		}
+		return b == hdr;
+	}
+	return 0;
+}
 #endif

 static int ir_schedule_blocks_bottom_up(ir_ctx *ctx)
@@ -1535,7 +1547,8 @@ static int ir_schedule_blocks_bottom_up(ir_ctx *ctx)
 					}
 				} else if (b != predecessor && ctx->cfg_blocks[predecessor].loop_header != b) {
 					/* not a loop back-edge */
-					IR_ASSERT(b == predecessor || ctx->cfg_blocks[predecessor].loop_header == b);
+					IR_ASSERT(b == predecessor || ctx->cfg_blocks[predecessor].loop_header == b ||
+						ir_is_merged_loop_back_edge(ctx, b, predecessor));
 				}
 			}
 		}