Commit 6173a9a1098 for php.net

commit 6173a9a10989fa887240590a34c2b0eec50f003e
Author: Ilija Tovilo <ilija.tovilo@me.com>
Date:   Sat Jan 31 19:44:56 2026 +0100

    VAR|TMP overhaul (GH-20628)

    The aim of this PR is twofold:

    - Reduce the number of highly similar TMP|VAR handlers
    - Avoid ZVAL_DEREF in most of these cases

    This is achieved by guaranteeing that all zend_compile_expr() calls, as well as
    all other compile calls with BP_VAR_{R,IS}, will result in a TMP variable. This
    implies that the result will not contain an IS_INDIRECT or IS_REFERENCE value,
    which was mostly already the case, with two exceptions:

    - Calls to return-by-reference functions. Because return-by-reference functions
      are quite rare, this is solved by delegating the DEREF to the RETURN_BY_REF
      handler, which will examine the stack to check whether the caller expects a
      VAR or TMP to understand whether the DEREF is needed. Internal functions will
      also need to adjust by calling the zend_return_unwrap_ref() function.

    - By-reference assignments, including both $a = &$b, as well as $a = [&$b]. When
      the result of these expressions is used in a BP_VAR_R context, the reference
      is unwrapped via a ZEND_QM_ASSIGN opcode beforehand. This is exceptionally
      rare.

    Closes GH-20628

diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index f23a610b849..e35baa3df56 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -56,6 +56,10 @@ PHP 8.6 INTERNALS UPGRADE NOTES
     node.
   . The zend_exception_save() and zend_exception_restore() functions were
     removed.
+  . Internal functions that return by reference are now expected to
+    automatically unwrap references when the result of the call is stored in an
+    IS_TMP_VAR variable. This may be achieved by calling the
+    zend_return_unwrap_ref() function.

 ========================
 2. Build system changes
diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c
index 79e95ed3fab..7f97caa1fda 100644
--- a/Zend/Optimizer/block_pass.c
+++ b/Zend/Optimizer/block_pass.c
@@ -289,20 +289,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
 								MAKE_NOP(opline);
 								++(*opt_count);
 								break;
-							case ZEND_ASSIGN:
-							case ZEND_ASSIGN_DIM:
-							case ZEND_ASSIGN_OBJ:
-							case ZEND_ASSIGN_STATIC_PROP:
-							case ZEND_ASSIGN_OP:
-							case ZEND_ASSIGN_DIM_OP:
-							case ZEND_ASSIGN_OBJ_OP:
-							case ZEND_ASSIGN_STATIC_PROP_OP:
-							case ZEND_PRE_INC:
-							case ZEND_PRE_DEC:
-							case ZEND_PRE_INC_OBJ:
-							case ZEND_PRE_DEC_OBJ:
-							case ZEND_PRE_INC_STATIC_PROP:
-							case ZEND_PRE_DEC_STATIC_PROP:
+							case ZEND_QM_ASSIGN:
 								if (src < op_array->opcodes + block->start) {
 									break;
 								}
@@ -310,8 +297,26 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
 								VAR_SOURCE(opline->op1) = NULL;
 								MAKE_NOP(opline);
 								++(*opt_count);
+								if (src->op1_type & (IS_VAR|IS_TMP_VAR)) {
+									src->opcode = ZEND_FREE;
+								} else if (src->op1_type == IS_CONST) {
+									MAKE_NOP(src);
+								} else if (src->op1_type == IS_CV) {
+									src->opcode = ZEND_CHECK_VAR;
+									SET_UNUSED(src->result);
+								}
 								break;
 							default:
+								if (!zend_op_may_elide_result(src->opcode)) {
+									break;
+								}
+								if (src < op_array->opcodes + block->start) {
+									break;
+								}
+								src->result_type = IS_UNUSED;
+								VAR_SOURCE(opline->op1) = NULL;
+								MAKE_NOP(opline);
+								++(*opt_count);
 								break;
 						}
 					}
@@ -985,6 +990,8 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
 					src = VAR_SOURCE(opline->op1);
 					if (src &&
 						src->opcode != ZEND_COPY_TMP &&
+						/* See gh20628_borked_live_range_calc.phpt. */
+						src->opcode != ZEND_NEW &&
 						src->opcode != ZEND_ADD_ARRAY_ELEMENT &&
 						src->opcode != ZEND_ADD_ARRAY_UNPACK &&
 						(src->opcode != ZEND_DECLARE_LAMBDA_FUNCTION ||
diff --git a/Zend/Optimizer/dce.c b/Zend/Optimizer/dce.c
index 41fd0f6c30a..6c5a885fba4 100644
--- a/Zend/Optimizer/dce.c
+++ b/Zend/Optimizer/dce.c
@@ -162,10 +162,16 @@ static inline bool may_have_side_effects(
 		case ZEND_EXT_FCALL_END:
 		case ZEND_TICKS:
 		case ZEND_YIELD:
-		case ZEND_YIELD_FROM:
 		case ZEND_VERIFY_NEVER_TYPE:
 			/* Intrinsic side effects */
 			return true;
+		case ZEND_YIELD_FROM: {
+			uint32_t t1 = OP1_INFO();
+			if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && MAY_BE_EMPTY_ONLY(t1)) {
+				return false;
+			}
+			return true;
+		}
 		case ZEND_DO_FCALL:
 		case ZEND_DO_FCALL_BY_NAME:
 		case ZEND_DO_ICALL:
diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c
index 9b5561e7fbe..6963fc63dd1 100644
--- a/Zend/Optimizer/zend_inference.c
+++ b/Zend/Optimizer/zend_inference.c
@@ -5336,6 +5336,13 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
 				return 1;
 			}
 			return 0;
+		case ZEND_YIELD_FROM: {
+			uint32_t t1 = OP1_INFO();
+			if ((t1 & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY && MAY_BE_EMPTY_ONLY(t1)) {
+				return false;
+			}
+			return true;
+		}
 		default:
 			return 1;
 	}
diff --git a/Zend/tests/gh20628_001.phpt b/Zend/tests/gh20628_001.phpt
new file mode 100644
index 00000000000..7b9534c9713
--- /dev/null
+++ b/Zend/tests/gh20628_001.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Nullsafe operator does not support BP_VAR_W
+--FILE--
+<?php
+
+function &test($foo) {
+    return $foo?->bar();
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot take reference of a nullsafe chain in %s on line %d
diff --git a/Zend/tests/gh20628_002.phpt b/Zend/tests/gh20628_002.phpt
new file mode 100644
index 00000000000..509db5ff3d6
--- /dev/null
+++ b/Zend/tests/gh20628_002.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Pipes support return-by-reference
+--FILE--
+<?php
+
+function &foo($val) {
+    global $x;
+    $x = $val;
+    return $x;
+}
+
+function &bar() {
+    return 42 |> foo(...);
+}
+
+$xRef = &bar();
+$xRef++;
+var_dump($x);
+
+?>
+--EXPECT--
+int(43)
diff --git a/Zend/tests/gh20628_003.phpt b/Zend/tests/gh20628_003.phpt
new file mode 100644
index 00000000000..ef23c8276b0
--- /dev/null
+++ b/Zend/tests/gh20628_003.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Missing separation for ASSIGN_DIM with ref OP_DATA
+--FILE--
+<?php
+
+function a() {
+    $a[] = $b[] = &$a;
+    var_dump($a, $b);
+}
+
+function b() {
+    $a = [];
+    $b = [];
+    $a[] = $b[] = &$a;
+    var_dump($a, $b);
+}
+
+function c() {
+    $a[] = $b = &$a;
+    var_dump($a, $b);
+}
+
+function d() {
+    $a = $b[] = &$a;
+    var_dump($a, $b);
+}
+
+a();
+b();
+c();
+d();
+
+?>
+--EXPECT--
+array(1) {
+  [0]=>
+  NULL
+}
+array(1) {
+  [0]=>
+  &array(1) {
+    [0]=>
+    NULL
+  }
+}
+array(1) {
+  [0]=>
+  array(0) {
+  }
+}
+array(1) {
+  [0]=>
+  &array(1) {
+    [0]=>
+    array(0) {
+    }
+  }
+}
+array(1) {
+  [0]=>
+  NULL
+}
+array(1) {
+  [0]=>
+  NULL
+}
+NULL
+array(1) {
+  [0]=>
+  &NULL
+}
diff --git a/Zend/tests/gh20628_004.inc b/Zend/tests/gh20628_004.inc
new file mode 100644
index 00000000000..970b43ec193
--- /dev/null
+++ b/Zend/tests/gh20628_004.inc
@@ -0,0 +1,3 @@
+<?php
+
+$this->bar();
diff --git a/Zend/tests/gh20628_004.phpt b/Zend/tests/gh20628_004.phpt
new file mode 100644
index 00000000000..29851a717bc
--- /dev/null
+++ b/Zend/tests/gh20628_004.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Invalid opcode for method call with FETCH_THIS
+--FILE--
+<?php
+
+class Foo {
+    public function bar() {
+        var_dump($this, __METHOD__);
+    }
+
+    public function test() {
+        require __DIR__ . '/gh20628_004.inc';
+    }
+}
+
+(new Foo)->test();
+
+?>
+--EXPECTF--
+object(Foo)#%d (0) {
+}
+string(8) "Foo::bar"
diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt
index a08032226e5..904ac402b37 100644
--- a/Zend/tests/operator_unsupported_types.phpt
+++ b/Zend/tests/operator_unsupported_types.phpt
@@ -287,7 +287,7 @@ function evalAssignOp(string $op, string $value1, string $value2) {
 Unsupported operand types: stdClass * resource
 Unsupported operand types: stdClass * string
 Unsupported operand types: resource * array
-Unsupported operand types: stdClass * resource
+Unsupported operand types: resource * stdClass
 Unsupported operand types: resource * resource
 Unsupported operand types: resource * string
 Unsupported operand types: string * array
@@ -753,7 +753,7 @@ function evalAssignOp(string $op, string $value1, string $value2) {
 Unsupported operand types: stdClass & resource
 Unsupported operand types: stdClass & string
 Unsupported operand types: resource & array
-Unsupported operand types: stdClass & resource
+Unsupported operand types: resource & stdClass
 Unsupported operand types: resource & resource
 Unsupported operand types: resource & string
 Unsupported operand types: string & array
@@ -828,7 +828,7 @@ function evalAssignOp(string $op, string $value1, string $value2) {
 Unsupported operand types: stdClass | resource
 Unsupported operand types: stdClass | string
 Unsupported operand types: resource | array
-Unsupported operand types: stdClass | resource
+Unsupported operand types: resource | stdClass
 Unsupported operand types: resource | resource
 Unsupported operand types: resource | string
 Unsupported operand types: string | array
@@ -903,7 +903,7 @@ function evalAssignOp(string $op, string $value1, string $value2) {
 Unsupported operand types: stdClass ^ resource
 Unsupported operand types: stdClass ^ string
 Unsupported operand types: resource ^ array
-Unsupported operand types: stdClass ^ resource
+Unsupported operand types: resource ^ stdClass
 Unsupported operand types: resource ^ resource
 Unsupported operand types: resource ^ string
 Unsupported operand types: string ^ array
diff --git a/Zend/tests/stack_limit/stack_limit_015.phpt b/Zend/tests/stack_limit/stack_limit_015.phpt
index b725523b784..88ff544e9f3 100644
--- a/Zend/tests/stack_limit/stack_limit_015.phpt
+++ b/Zend/tests/stack_limit/stack_limit_015.phpt
@@ -9,7 +9,7 @@
 --EXTENSIONS--
 zend_test
 --INI--
-zend.max_allowed_stack_size=128K
+zend.max_allowed_stack_size=64K
 --FILE--
 <?php

diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 43eefbeff9d..cca69985a0d 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -339,7 +339,7 @@ static ZEND_NAMED_FUNCTION(zend_closure_call_magic) /* {{{ */ {
 	fcc.called_scope = zend_get_called_scope(EG(current_execute_data));

 	zend_call_function(&fci, &fcc);
-
+	zend_return_unwrap_ref(EG(current_execute_data), return_value);
 	zval_ptr_dtor(&fci.params[1]);
 }
 /* }}} */
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index d2d0090a707..325953e158e 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -101,7 +101,7 @@ static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bo
 static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref);
 static void zend_compile_expr(znode *result, zend_ast *ast);
 static void zend_compile_stmt(zend_ast *ast);
-static void zend_compile_assign(znode *result, zend_ast *ast);
+static void zend_compile_assign(znode *result, zend_ast *ast, bool stmt, uint32_t type);

 #ifdef ZEND_CHECK_STACK_LIMIT
 zend_never_inline static void zend_stack_limit_error(void)
@@ -753,6 +753,36 @@ static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
 }
 /* }}} */

+bool zend_op_may_elide_result(uint8_t opcode)
+{
+	switch (opcode) {
+		case ZEND_ASSIGN:
+		case ZEND_ASSIGN_DIM:
+		case ZEND_ASSIGN_OBJ:
+		case ZEND_ASSIGN_STATIC_PROP:
+		case ZEND_ASSIGN_OP:
+		case ZEND_ASSIGN_DIM_OP:
+		case ZEND_ASSIGN_OBJ_OP:
+		case ZEND_ASSIGN_STATIC_PROP_OP:
+		case ZEND_PRE_INC_STATIC_PROP:
+		case ZEND_PRE_DEC_STATIC_PROP:
+		case ZEND_PRE_INC_OBJ:
+		case ZEND_PRE_DEC_OBJ:
+		case ZEND_PRE_INC:
+		case ZEND_PRE_DEC:
+		case ZEND_DO_FCALL:
+		case ZEND_DO_ICALL:
+		case ZEND_DO_UCALL:
+		case ZEND_DO_FCALL_BY_NAME:
+		case ZEND_YIELD:
+		case ZEND_YIELD_FROM:
+		case ZEND_INCLUDE_OR_EVAL:
+			return true;
+		default:
+			return false;
+	}
+}
+
 static void zend_do_free(znode *op1) /* {{{ */
 {
 	if (op1->op_type == IS_TMP_VAR) {
@@ -779,22 +809,12 @@ static void zend_do_free(znode *op1) /* {{{ */
 					opline->opcode -= 2;
 					SET_UNUSED(opline->result);
 					return;
-				case ZEND_ASSIGN:
-				case ZEND_ASSIGN_DIM:
-				case ZEND_ASSIGN_OBJ:
-				case ZEND_ASSIGN_STATIC_PROP:
-				case ZEND_ASSIGN_OP:
-				case ZEND_ASSIGN_DIM_OP:
-				case ZEND_ASSIGN_OBJ_OP:
-				case ZEND_ASSIGN_STATIC_PROP_OP:
-				case ZEND_PRE_INC_STATIC_PROP:
-				case ZEND_PRE_DEC_STATIC_PROP:
-				case ZEND_PRE_INC_OBJ:
-				case ZEND_PRE_DEC_OBJ:
-				case ZEND_PRE_INC:
-				case ZEND_PRE_DEC:
-					SET_UNUSED(opline->result);
-					return;
+				default:
+					if (zend_op_may_elide_result(opline->opcode)) {
+						SET_UNUSED(opline->result);
+						return;
+					}
+					break;
 			}
 		}

@@ -2578,7 +2598,9 @@ static void zend_emit_jmp_null(znode *obj_node, uint32_t bp_type)
 	zend_stack_push(&CG(short_circuiting_opnums), &jmp_null_opnum);
 }

-static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */
+static inline bool zend_is_variable_or_call(const zend_ast *ast);
+
+static void zend_compile_memoized_expr(znode *result, zend_ast *expr, uint32_t type) /* {{{ */
 {
 	const zend_memoize_mode memoize_mode = CG(memoize_mode);
 	if (memoize_mode == ZEND_MEMOIZE_COMPILE) {
@@ -2586,7 +2608,11 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */

 		/* Go through normal compilation */
 		CG(memoize_mode) = ZEND_MEMOIZE_NONE;
-		zend_compile_expr(result, expr);
+		if (zend_is_variable_or_call(expr)) {
+			zend_compile_var(result, expr, type, /* by_ref */ false);
+		} else {
+			zend_compile_expr(result, expr);
+		}
 		CG(memoize_mode) = ZEND_MEMOIZE_COMPILE;

 		if (result->op_type == IS_VAR) {
@@ -2709,13 +2735,24 @@ void zend_emit_final_return(bool return_one) /* {{{ */
 }
 /* }}} */

+static bool zend_propagate_list_refs(zend_ast *ast);
+
 static inline bool zend_is_variable(const zend_ast *ast) /* {{{ */
 {
-	return ast->kind == ZEND_AST_VAR
+	if (ast->kind == ZEND_AST_VAR
 		|| ast->kind == ZEND_AST_DIM
 		|| ast->kind == ZEND_AST_PROP
 		|| ast->kind == ZEND_AST_NULLSAFE_PROP
-		|| ast->kind == ZEND_AST_STATIC_PROP;
+		|| ast->kind == ZEND_AST_STATIC_PROP
+		|| ast->kind == ZEND_AST_ASSIGN_REF) {
+		return true;
+	}
+	if (ast->kind == ZEND_AST_ASSIGN
+	 && UNEXPECTED(ast->child[0]->kind == ZEND_AST_ARRAY)
+	 && zend_propagate_list_refs(ast->child[0])) {
+		return true;
+	}
+	return false;
 }
 /* }}} */

@@ -3126,7 +3163,11 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
 		if (this_guaranteed_exists()) {
 			obj_node.op_type = IS_UNUSED;
 		} else {
-			zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
+			opline = zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
+			if ((type == BP_VAR_R) || (type == BP_VAR_IS)) {
+				opline->result_type = IS_TMP_VAR;
+				obj_node.op_type = IS_TMP_VAR;
+			}
 		}
 		CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;

@@ -3290,7 +3331,7 @@ static bool list_is_keyed(const zend_ast_list *list)
 }

 static void zend_compile_list_assign(
-		znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style) /* {{{ */
+		znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style, uint32_t type) /* {{{ */
 {
 	zend_ast_list *list = zend_ast_get_list(ast);
 	uint32_t i;
@@ -3350,6 +3391,10 @@ static void zend_compile_list_assign(

 		opline = zend_emit_op(&fetch_result,
 			elem_ast->attr ? (expr_node->op_type == IS_CV ? ZEND_FETCH_DIM_W : ZEND_FETCH_LIST_W) : ZEND_FETCH_LIST_R, expr_node, &dim_node);
+		if (opline->opcode == ZEND_FETCH_LIST_R) {
+			opline->result_type = IS_TMP_VAR;
+			fetch_result.op_type = IS_TMP_VAR;
+		}

 		if (dim_node.op_type == IS_CONST) {
 			zend_handle_numeric_dim(opline, &dim_node);
@@ -3359,7 +3404,7 @@ static void zend_compile_list_assign(
 			zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL);
 		}
 		if (var_ast->kind == ZEND_AST_ARRAY) {
-			zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr);
+			zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr, type);
 		} else if (elem_ast->attr) {
 			zend_emit_assign_ref_znode(var_ast, &fetch_result);
 		} else {
@@ -3372,7 +3417,12 @@ static void zend_compile_list_assign(
 	}

 	if (result) {
-		*result = *expr_node;
+		if ((type == BP_VAR_R || type == BP_VAR_IS) && expr_node->op_type == IS_VAR) {
+			/* Deref. */
+			zend_emit_op_tmp(result, ZEND_QM_ASSIGN, expr_node, NULL);
+		} else {
+			*result = *expr_node;
+		}
 	} else {
 		zend_do_free(expr_node);
 	}
@@ -3443,7 +3493,7 @@ static void zend_compile_expr_with_potential_assign_to_self(
 	}
 }

-static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
+static void zend_compile_assign(znode *result, zend_ast *ast, bool stmt, uint32_t type) /* {{{ */
 {
 	zend_ast *var_ast = ast->child[0];
 	zend_ast *expr_ast = ast->child[1];
@@ -3533,14 +3583,17 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
 				}
 			}

-			zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr);
+			zend_compile_list_assign(!stmt ? result : NULL, var_ast, &expr_node, var_ast->attr, type);
+			if (stmt) {
+				result->op_type = IS_UNUSED;
+			}
 			return;
 		EMPTY_SWITCH_DEFAULT_CASE();
 	}
 }
 /* }}} */

-static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
+static void zend_compile_assign_ref(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
 {
 	zend_ast *target_ast = ast->child[0];
 	zend_ast *source_ast = ast->child[1];
@@ -3587,28 +3640,40 @@ static void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
 		opline->opcode = ZEND_ASSIGN_OBJ_REF;
 		opline->extended_value &= ~ZEND_FETCH_REF;
 		opline->extended_value |= flags;
+		if (result) {
+			*result = target_node;
+		} else {
+			SET_UNUSED(opline->result);
+		}
 		zend_emit_op_data(&source_node);
-		*result = target_node;
 	} else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) {
 		opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF;
 		opline->extended_value &= ~ZEND_FETCH_REF;
 		opline->extended_value |= flags;
+		if (result) {
+			*result = target_node;
+		} else {
+			SET_UNUSED(opline->result);
+		}
 		zend_emit_op_data(&source_node);
-		*result = target_node;
 	} else {
 		opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
 		opline->extended_value = flags;
 	}
+
+	if (result && (type == BP_VAR_R || type == BP_VAR_IS)) {
+		/* Deref. */
+		znode tmp_result = *result;
+		zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &tmp_result, NULL);
+	}
 }
 /* }}} */

 static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, const znode *value_node) /* {{{ */
 {
-	znode dummy_node;
 	zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
 		zend_ast_create_znode(value_node));
-	zend_compile_expr(&dummy_node, assign_ast);
-	zend_do_free(&dummy_node);
+	zend_compile_stmt(assign_ast);
 }
 /* }}} */

@@ -3785,7 +3850,9 @@ static uint32_t zend_compile_args(
 		/* Treat passing of $GLOBALS the same as passing a call.
 		 * This will error at runtime if the argument is by-ref. */
 		if (zend_is_call(arg) || is_globals_fetch(arg)) {
-			zend_compile_var(&arg_node, arg, BP_VAR_R, false);
+			uint32_t type = is_globals_fetch(arg) || (fbc && !ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num))
+				? BP_VAR_R : BP_VAR_FUNC_ARG;
+			zend_compile_var(&arg_node, arg, type, /* by_ref */ false);
 			if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
 				/* Function call was converted into builtin instruction */
 				if (!fbc || ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
@@ -3933,7 +4000,7 @@ ZEND_API uint8_t zend_get_call_op(const zend_op *init_op, const zend_function *f
 }
 /* }}} */

-static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const zend_function *fbc, uint32_t lineno) /* {{{ */
+static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const zend_function *fbc, uint32_t lineno, uint32_t type) /* {{{ */
 {
 	zend_op *opline;
 	uint32_t opnum_init = get_next_op_number() - 1;
@@ -3975,8 +4042,9 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const ze

 	opline = &CG(active_op_array)->opcodes[opnum_init];
 	opline->extended_value = arg_count;
+	uint8_t init_opcode = opline->opcode;

-	if (opline->opcode == ZEND_INIT_FCALL) {
+	if (init_opcode == ZEND_INIT_FCALL) {
 		opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
 	}

@@ -3990,6 +4058,12 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, const ze
 		false
 	);
 	opline = zend_emit_op(result, call_op, NULL, NULL);
+	if (type == BP_VAR_R || type == BP_VAR_IS) {
+		if (init_opcode != ZEND_NEW && opline->result_type == IS_VAR) {
+			opline->result_type = IS_TMP_VAR;
+			result->op_type = IS_TMP_VAR;
+		}
+	}
 	if (may_have_extra_named_args) {
 		opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
 	}
@@ -4012,7 +4086,7 @@ static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /*
 }
 /* }}} */

-static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */
+static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno, uint32_t type) /* {{{ */
 {
 	if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
 		const char *colon;
@@ -4042,7 +4116,7 @@ static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast
 		zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
 	}

-	zend_compile_call_common(result, args_ast, NULL, lineno);
+	zend_compile_call_common(result, args_ast, NULL, lineno, type);
 }
 /* }}} */

@@ -4284,7 +4358,7 @@ static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, z
 /* }}} */

 /* cufa = call_user_func_array */
-static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
+static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname, uint32_t type) /* {{{ */
 {
 	znode arg_node;
 	zend_op *opline;
@@ -4319,7 +4393,11 @@ static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, ze
 				zend_compile_expr(&len_node, list->child[2]);
 				opline = zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, &len_node);
 				opline->extended_value = Z_LVAL_P(zv);
-				zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
+				opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
+				if (type == BP_VAR_R || type == BP_VAR_IS) {
+					opline->result_type = IS_TMP_VAR;
+					result->op_type = IS_TMP_VAR;
+				}
 				zend_string_release_ex(name, 0);
 				return SUCCESS;
 			}
@@ -4330,6 +4408,10 @@ static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, ze
 	zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
 	zend_emit_op(NULL, ZEND_CHECK_UNDEF_ARGS, NULL, NULL);
 	opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
+	if (type == BP_VAR_R || type == BP_VAR_IS) {
+		opline->result_type = IS_TMP_VAR;
+		result->op_type = IS_TMP_VAR;
+	}
 	opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;

 	return SUCCESS;
@@ -4337,7 +4419,7 @@ static zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, ze
 /* }}} */

 /* cuf = call_user_func */
-static zend_result zend_compile_func_cuf(znode *result, const zend_ast_list *args, zend_string *lcname) /* {{{ */
+static zend_result zend_compile_func_cuf(znode *result, const zend_ast_list *args, zend_string *lcname, uint32_t type) /* {{{ */
 {
 	uint32_t i;

@@ -4357,13 +4439,17 @@ static zend_result zend_compile_func_cuf(znode *result, const zend_ast_list *arg
 		opline->op2.num = i;
 		opline->result.var = EX_NUM_TO_VAR(i - 1);
 	}
-	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
+	zend_op *opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
+	if (type == BP_VAR_R || type == BP_VAR_IS) {
+		opline->result_type = IS_TMP_VAR;
+		result->op_type = IS_TMP_VAR;
+	}

 	return SUCCESS;
 }
 /* }}} */

-static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, const zend_function *fbc, uint32_t lineno) /* {{{ */
+static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, const zend_function *fbc, uint32_t lineno, uint32_t type) /* {{{ */
 {
 	if (EG(assertions) >= 0) {
 		znode name_node;
@@ -4398,7 +4484,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string
 			args = (zend_ast_list *)zend_ast_list_add((zend_ast *) args, arg);
 		}

-		zend_compile_call_common(result, (zend_ast*)args, fbc, lineno);
+		zend_compile_call_common(result, (zend_ast*)args, fbc, lineno, type);

 		opline = &CG(active_op_array)->opcodes[check_op_number];
 		opline->op2.opline_num = get_next_op_number();
@@ -4649,10 +4735,6 @@ static const zend_frameless_function_info *find_frameless_function_info(const ze
 		return NULL;
 	}

-	if (type != BP_VAR_R) {
-		return NULL;
-	}
-
 	if (ZEND_USER_CODE(fbc->type)) {
 		return NULL;
 	}
@@ -4763,7 +4845,7 @@ static void zend_compile_ns_call(znode *result, const znode *name_node, zend_ast
 	opline->op2_type = IS_CONST;
 	opline->op2.constant = name_constants;
 	opline->result.num = zend_alloc_cache_slot();
-	zend_compile_call_common(result, args_ast, NULL, lineno);
+	zend_compile_call_common(result, args_ast, NULL, lineno, type);

 	/* Compile frameless call. */
 	if (frameless_function_info) {
@@ -5177,9 +5259,9 @@ static zend_result zend_try_compile_special_func_ex(znode *result, zend_string *
 	} else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) {
 		return zend_compile_func_ord(result, args);
 	} else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
-		return zend_compile_func_cufa(result, args, lcname);
+		return zend_compile_func_cufa(result, args, lcname, type);
 	} else if (zend_string_equals_literal(lcname, "call_user_func")) {
-		return zend_compile_func_cuf(result, args, lcname);
+		return zend_compile_func_cuf(result, args, lcname, type);
 	} else if (zend_string_equals_literal(lcname, "in_array")) {
 		return zend_compile_func_in_array(result, args);
 	} else if (zend_string_equals(lcname, ZSTR_KNOWN(ZEND_STR_COUNT))
@@ -5314,7 +5396,7 @@ static bool zend_compile_parent_property_hook_call(znode *result, const zend_ast
 	opline->op1.constant = zend_add_literal_string(&property_name);
 	opline->op2.num = hook_kind;

-	zend_compile_call_common(result, args_ast, NULL, zend_ast_get_lineno(method_ast));
+	zend_compile_call_common(result, args_ast, NULL, zend_ast_get_lineno(method_ast), BP_VAR_R);

 	return true;
 }
@@ -5329,7 +5411,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)

 	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
 		zend_compile_expr(&name_node, name_ast);
-		zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
+		zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno, type);
 		return;
 	}

@@ -5338,7 +5420,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)
 		if (runtime_resolution) {
 			if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")
 					&& !is_callable_convert) {
-				zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno);
+				zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno, type);
 			} else {
 				zend_compile_ns_call(result, &name_node, args_ast, ast->lineno, type);
 			}
@@ -5355,7 +5437,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)

 		/* Special assert() handling should apply independently of compiler flags. */
 		if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) {
-			zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno);
+			zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno, type);
 			zend_string_release(lcname);
 			zval_ptr_dtor(&name_node.u.constant);
 			return;
@@ -5365,7 +5447,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)
 		 || !fbc_is_finalized(fbc)
 		 || zend_compile_ignore_function(fbc, CG(active_op_array)->filename)) {
 			zend_string_release_ex(lcname, 0);
-			zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
+			zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno, type);
 			return;
 		}

@@ -5390,7 +5472,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type)
 			Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData;
 		}

-		zend_compile_call_common(result, args_ast, fbc, ast->lineno);
+		zend_compile_call_common(result, args_ast, fbc, ast->lineno, type);
 	}
 }
 /* }}} */
@@ -5411,7 +5493,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type
 		if (this_guaranteed_exists()) {
 			obj_node.op_type = IS_UNUSED;
 		} else {
-			zend_emit_op(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
+			zend_emit_op_tmp(&obj_node, ZEND_FETCH_THIS, NULL, NULL);
 		}
 		CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;

@@ -5454,7 +5536,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type
 		}
 	}

-	if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) {
+	if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast), type)) {
 		if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) {
 			zend_error_noreturn(E_COMPILE_ERROR,
 				"Cannot combine nullsafe operator with Closure creation");
@@ -5569,7 +5651,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
 		}
 	}

-	zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
+	zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast), type);
 }
 /* }}} */

@@ -5590,7 +5672,7 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
 		zend_compile_class_ref(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
 	}

-	opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
+	opline = zend_emit_op_tmp(result, ZEND_NEW, NULL, NULL);

 	zend_set_class_name_op1(opline, &class_node);

@@ -5625,7 +5707,7 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
 		fbc = ce->constructor;
 	}

-	zend_compile_call_common(&ctor_result, args_ast, fbc, ast->lineno);
+	zend_compile_call_common(&ctor_result, args_ast, fbc, ast->lineno, BP_VAR_R);
 	zend_do_free(&ctor_result);
 }
 /* }}} */
@@ -5900,7 +5982,7 @@ static void zend_compile_return(const zend_ast *ast) /* {{{ */
 	if (!expr_ast) {
 		expr_node.op_type = IS_CONST;
 		ZVAL_NULL(&expr_node.u.constant);
-	} else if (by_ref && zend_is_variable(expr_ast)) {
+	} else if (by_ref && zend_is_variable_or_call(expr_ast)) {
 		zend_assert_not_short_circuited(expr_ast);
 		zend_compile_var(&expr_node, expr_ast, BP_VAR_W, true);
 	} else {
@@ -6290,7 +6372,8 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */
 	zend_ast *key_ast = ast->child[2];
 	zend_ast *stmt_ast = ast->child[3];
 	bool by_ref = value_ast->kind == ZEND_AST_REF;
-	bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
+	bool is_variable = (zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast))
+		|| zend_is_call(expr_ast);

 	znode expr_node, reset_node, value_node, key_node;
 	zend_op *opline;
@@ -6325,6 +6408,10 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */

 	opnum_reset = get_next_op_number();
 	opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
+	if (!by_ref) {
+		opline->result_type = IS_TMP_VAR;
+		reset_node.op_type = IS_TMP_VAR;
+	}

 	zend_begin_loop(ZEND_FE_FREE, &reset_node, false);

@@ -6337,11 +6424,11 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */
 		zend_try_compile_cv(&value_node, value_ast, BP_VAR_R) == SUCCESS) {
 		SET_NODE(opline->op2, &value_node);
 	} else {
-		opline->op2_type = IS_VAR;
+		opline->op2_type = by_ref ? IS_VAR : IS_TMP_VAR;
 		opline->op2.var = get_temporary_variable();
 		GET_NODE(&value_node, opline->op2);
 		if (value_ast->kind == ZEND_AST_ARRAY) {
-			zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr);
+			zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr, BP_VAR_R);
 		} else if (by_ref) {
 			zend_emit_assign_ref_znode(value_ast, &value_node);
 		} else {
@@ -6679,7 +6766,7 @@ static bool zend_is_pipe_optimizable_callable_name(zend_ast *ast)
 	return true;
 }

-static void zend_compile_pipe(znode *result, zend_ast *ast)
+static void zend_compile_pipe(znode *result, zend_ast *ast, uint32_t type)
 {
 	zend_ast *operand_ast = ast->child[0];
 	zend_ast *callable_ast = ast->child[1];
@@ -6734,7 +6821,7 @@ static void zend_compile_pipe(znode *result, zend_ast *ast)

 	zend_do_extended_stmt(&operand_result);

-	zend_compile_expr(result, fcall_ast);
+	zend_compile_var(result, fcall_ast, type, /* by_ref */ false);
 }

 static void zend_compile_match(znode *result, zend_ast *ast)
@@ -10756,7 +10843,7 @@ static void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */

 	zend_compile_expr(&false_node, false_ast);

-	opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
+	opline_qm_assign2 = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
 	SET_NODE(opline_qm_assign2->result, result);

 	zend_update_jump_target_to_next(opnum_jmp);
@@ -10932,7 +11019,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
 	}

 	if (value_ast) {
-		if (returns_by_ref && zend_is_variable(value_ast)) {
+		if (returns_by_ref && zend_is_variable_or_call(value_ast)) {
 			zend_assert_not_short_circuited(value_ast);
 			zend_compile_var(&value_node, value_ast, BP_VAR_W, true);
 		} else {
@@ -10941,7 +11028,7 @@ static void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
 		value_node_ptr = &value_node;
 	}

-	opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
+	opline = zend_emit_op_tmp(result, ZEND_YIELD, value_node_ptr, key_node_ptr);

 	if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
 		opline->extended_value = ZEND_RETURNS_FUNCTION;
@@ -11007,7 +11094,7 @@ static void zend_compile_include_or_eval(znode *result, const zend_ast *ast) /*
 	zend_do_extended_fcall_begin();
 	zend_compile_expr(&expr_node, expr_ast);

-	opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
+	opline = zend_emit_op_tmp(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
 	opline->extended_value = ast->attr;

 	zend_do_extended_fcall_end();
@@ -11989,6 +12076,15 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
 		case ZEND_AST_CAST_VOID:
 			zend_compile_void_cast(NULL, ast);
 			break;
+		case ZEND_AST_ASSIGN: {
+			znode result;
+			zend_compile_assign(&result, ast, /* stmt */ true, BP_VAR_R);
+			zend_do_free(&result);
+			return;
+		}
+		case ZEND_AST_ASSIGN_REF:
+			zend_compile_assign_ref(NULL, ast, BP_VAR_R);
+			return;
 		default:
 		{
 			znode result;
@@ -12009,7 +12105,7 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
 	CG(zend_lineno) = zend_ast_get_lineno(ast);

 	if (CG(memoize_mode) != ZEND_MEMOIZE_NONE) {
-		zend_compile_memoized_expr(result, ast);
+		zend_compile_memoized_expr(result, ast, BP_VAR_R);
 		return;
 	}

@@ -12031,13 +12127,14 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
 		case ZEND_AST_NULLSAFE_METHOD_CALL:
 		case ZEND_AST_STATIC_CALL:
 		case ZEND_AST_PARENT_PROPERTY_HOOK_CALL:
+		case ZEND_AST_PIPE:
 			zend_compile_var(result, ast, BP_VAR_R, false);
 			return;
 		case ZEND_AST_ASSIGN:
-			zend_compile_assign(result, ast);
+			zend_compile_assign(result, ast, /* stmt */ false, BP_VAR_R);
 			return;
 		case ZEND_AST_ASSIGN_REF:
-			zend_compile_assign_ref(result, ast);
+			zend_compile_assign_ref(result, ast, BP_VAR_R);
 			return;
 		case ZEND_AST_NEW:
 			zend_compile_new(result, ast);
@@ -12136,9 +12233,6 @@ static void zend_compile_expr_inner(znode *result, zend_ast *ast) /* {{{ */
 		case ZEND_AST_MATCH:
 			zend_compile_match(result, ast);
 			return;
-		case ZEND_AST_PIPE:
-			zend_compile_pipe(result, ast);
-			return;
 		default:
 			ZEND_ASSERT(0 /* not supported */);
 	}
@@ -12152,6 +12246,12 @@ static void zend_compile_expr(znode *result, zend_ast *ast)
 	uint32_t checkpoint = zend_short_circuiting_checkpoint();
 	zend_compile_expr_inner(result, ast);
 	zend_short_circuiting_commit(checkpoint, result, ast);
+#if ZEND_DEBUG
+	if (result) {
+		/* BP_VAR_R is not allowed to produce IS_VAR. */
+		ZEND_ASSERT(result->op_type != IS_VAR);
+	}
+#endif
 }

 static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t type, bool by_ref)
@@ -12164,7 +12264,7 @@ static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t ty
 			case ZEND_AST_METHOD_CALL:
 			case ZEND_AST_NULLSAFE_METHOD_CALL:
 			case ZEND_AST_STATIC_CALL:
-				zend_compile_memoized_expr(result, ast);
+				zend_compile_memoized_expr(result, ast, BP_VAR_W);
 				/* This might not actually produce an opcode, e.g. for expressions evaluated at comptime. */
 				return NULL;
 		}
@@ -12193,9 +12293,19 @@ static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t ty
 		case ZEND_AST_STATIC_CALL:
 			zend_compile_static_call(result, ast, type);
 			return NULL;
+		case ZEND_AST_PIPE:
+			zend_compile_pipe(result, ast, type);
+			return NULL;
 		case ZEND_AST_ZNODE:
 			*result = *zend_ast_get_znode(ast);
 			return NULL;
+		case ZEND_AST_ASSIGN_REF:
+			zend_compile_assign_ref(result, ast, type);
+			return NULL;
+		case ZEND_AST_ASSIGN:
+			ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(ast->child[0]));
+			zend_compile_assign(result, ast, false, type);
+			return NULL;
 		default:
 			if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
 				zend_error_noreturn(E_COMPILE_ERROR,
@@ -12214,6 +12324,16 @@ static zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bo
 	uint32_t checkpoint = zend_short_circuiting_checkpoint();
 	zend_op *opcode = zend_compile_var_inner(result, ast, type, by_ref);
 	zend_short_circuiting_commit(checkpoint, result, ast);
+#if ZEND_DEBUG
+	if (result
+	 && (type == BP_VAR_R || type == BP_VAR_IS)
+	 /* Don't check memoized result, as it will force BP_VAR_W even for BP_VAR_IS. */
+	 && CG(memoize_mode) == ZEND_MEMOIZE_NONE
+	) {
+		/* BP_VAR_{R,IS} is not allowed to produce IS_VAR. */
+		ZEND_ASSERT(result->op_type != IS_VAR);
+	}
+#endif
 	return opcode;
 }

diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 006a89597ae..587ae485ec8 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -1324,4 +1324,6 @@ ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op);

 bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1);

+bool zend_op_may_elide_result(uint8_t opcode);
+
 #endif /* ZEND_COMPILE_H */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 42f8d46d5a3..37278c5cb9a 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -5938,3 +5938,29 @@ ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode
 	}
 	return ret;
 }
+
+ZEND_API void zend_return_unwrap_ref(zend_execute_data *execute_data, zval *return_value)
+{
+	if (!return_value || !Z_ISREF_P(return_value)) {
+		return;
+	}
+
+	zend_execute_data *prev_ex = EX(prev_execute_data);
+	if (!prev_ex || !prev_ex->func || !ZEND_USER_CODE(prev_ex->func->type)) {
+		return;
+	}
+
+	const zend_op *do_opline = prev_ex->opline;
+	if (do_opline->result_type != IS_TMP_VAR) {
+		return;
+	}
+
+	if (do_opline->opcode != ZEND_DO_FCALL
+	 && do_opline->opcode != ZEND_DO_FCALL_BY_NAME
+	 && do_opline->opcode != ZEND_DO_ICALL
+	 && do_opline->opcode != ZEND_DO_UCALL) {
+		return;
+	}
+
+	zend_unwrap_reference(return_value);
+}
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 8858f9fce96..89a9e79143a 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -632,6 +632,8 @@ static zend_always_inline void *zend_get_bad_ptr(void)
 	return NULL;
 }

+ZEND_API void zend_return_unwrap_ref(zend_execute_data *call, zval *return_value);
+
 END_EXTERN_C()

 #endif /* ZEND_EXECUTE_H */
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index d85c0f2da4a..3bec062e9ce 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -654,7 +654,9 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
 			} else {
 				zval_ptr_dtor(&new_root->value);
 				ZVAL_COPY(&new_root->value, &new_root_parent->value);
-				ZVAL_COPY(ZEND_CALL_VAR(new_root->execute_data, yield_from->result.var), &new_root_parent->retval);
+				if (yield_from->result_type != IS_UNUSED) {
+					ZVAL_COPY(ZEND_CALL_VAR(new_root->execute_data, yield_from->result.var), &new_root_parent->retval);
+				}
 			}
 		}
 	}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 2d059159a23..7723650cb1c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -203,7 +203,7 @@ ZEND_VM_C_LABEL(mul_double):
 	ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper, op_1, op1, op_2, op2);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(4, ZEND_DIV, CONST|TMP|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -357,7 +357,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV)
 	ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper, op_1, op1, op_2, op2);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMP|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -371,7 +371,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_CONST))
+ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMP|CV, CONST|TMP|CV, SPEC(NO_CONST_CONST))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -448,7 +448,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
 	}
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|CV, CONST|TMP|CV, SPEC(COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -463,7 +463,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T
 	ZEND_VM_SMART_BRANCH(result, 1);
 }

-ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP|VAR, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -477,7 +477,7 @@ ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP|VAR, CONST|TMP|VAR|CV)
 	ZEND_VM_SMART_BRANCH(result, 1);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|CV, CONST|TMP|CV, SPEC(COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -514,7 +514,7 @@ ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
 	ZEND_VM_SMART_BRANCH(ret == 0, 1);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMP|CV, CONST|TMP|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -594,7 +594,7 @@ ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
 	ZEND_VM_SMART_BRANCH(ret != 0, 1);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMP|CV, CONST|TMP|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -786,7 +786,7 @@ ZEND_VM_C_LABEL(is_smaller_or_equal_double):
 	ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper, op_1, op1, op_2, op2);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMP|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -917,7 +917,7 @@ ZEND_VM_HOT_NOCONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV
 	ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper, op_1, op1, op_2, op2);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMP|CV, CONST|TMP|CV, SPEC(COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -958,7 +958,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(13, ZEND_BW_NOT, CONST|TMPVARCV, ANY)
 	ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper, op_1, op1);
 }

-ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zval *val;
@@ -1005,7 +1005,7 @@ ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY)
 	HANDLE_EXCEPTION();
 }

-ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
+ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMP|CV, OP)
 {
 	USE_OPLINE
 	zval *object;
@@ -1097,7 +1097,7 @@ ZEND_VM_C_LABEL(assign_op_object):
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */
+/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP)
 {
 	/* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */
@@ -1153,7 +1153,7 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP)
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
+ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMP|UNUSED|NEXT|CV, OP)
 {
 	USE_OPLINE
 	zval *var_ptr;
@@ -1254,7 +1254,7 @@ ZEND_VM_C_LABEL(assign_dim_op_ret_null):
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
+ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMP|CV, OP)
 {
 	USE_OPLINE
 	zval *var_ptr;
@@ -1285,7 +1285,7 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *object;
@@ -1350,12 +1350,12 @@ ZEND_VM_C_LABEL(pre_incdec_object):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_OBJ);
 }

-ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *object;
@@ -1418,12 +1418,12 @@ ZEND_VM_C_LABEL(post_incdec_object):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_OBJ);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 {
 	USE_OPLINE
@@ -1451,13 +1451,13 @@ ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(39, ZEND_PRE_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_STATIC_PROP);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 {
 	USE_OPLINE
@@ -1485,7 +1485,7 @@ ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(41, ZEND_POST_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_STATIC_PROP);
@@ -1690,7 +1690,7 @@ ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
 	ZEND_VM_DISPATCH_TO_HELPER(zend_post_dec_helper);
 }

-ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zval *z;
@@ -1719,7 +1719,7 @@ ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
+ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMP|CV, UNUSED, int type)
 {
 	USE_OPLINE
 	zval *varname;
@@ -1820,22 +1820,22 @@ ZEND_VM_C_LABEL(fetch_this):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R);
 }

-ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W);
 }

-ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_RW);
 }

-ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	int fetch_type =
 		(UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ?
@@ -1843,17 +1843,17 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, fetch_type);
 }

-ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
 }

-ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
+ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMP|CV, UNUSED, VAR_FETCH)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_IS);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_INLINE_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type)
 {
 	USE_OPLINE
@@ -1888,25 +1888,25 @@ ZEND_VM_C_LABEL(copy_deref):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, ANY, CLASS_FETCH, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, ANY, CLASS_FETCH, FETCH_REF|DIM_WRITE|CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, ANY, CLASS_FETCH, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_RW);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, ANY, CLASS_FETCH, FETCH_REF|CACHE_SLOT)
 {
 	if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
@@ -1916,32 +1916,36 @@ ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, ANY, CLASS_FETCH, FETCH_RE
 	}
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, ANY, CLASS_FETCH, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, ANY, CLASS_FETCH, CACHE_SLOT)
 {
 	ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_IS);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container, *dim, *value;

 	SAVE_OPLINE();
 	container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+	if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
+		/* Handler accepts VAR only for FUNC_ARG, which will unwrap before dispatching. */
+		ZEND_ASSERT(Z_TYPE_P(container) != IS_REFERENCE);
+	}
 	dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
 	if (OP1_TYPE != IS_CONST) {
 		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 ZEND_VM_C_LABEL(fetch_dim_r_array):
 			value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R EXECUTE_DATA_CC);
 			ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value);
-		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
+		} else if (OP1_TYPE == IS_CV && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
 			container = Z_REFVAL_P(container);
 			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
 				ZEND_VM_C_GOTO(fetch_dim_r_array);
@@ -1963,7 +1967,7 @@ ZEND_VM_C_LABEL(fetch_dim_r_slow):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
+ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|UNUSED|NEXT|CV)
 {
 	USE_OPLINE
 	zval *container;
@@ -1978,7 +1982,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
+ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|UNUSED|NEXT|CV)
 {
 	USE_OPLINE
 	zval *container;
@@ -1993,13 +1997,15 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container;

 	SAVE_OPLINE();
 	container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_IS);
+	/* Unlike FETCH_DIM_R, this may receive references through return-by-ref
+	 * calls using ??=, i.e. foo()['bar'] ??= baz. */
 	zend_fetch_dimension_address_read_IS(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
 	FREE_OP2();
 	FREE_OP1();
@@ -2030,7 +2036,7 @@ ZEND_VM_COLD_HELPER(zend_use_undef_in_read_context_helper, ANY, ANY)
 	HANDLE_EXCEPTION();
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|UNUSED|NEXT|CV)
 {
 #if !ZEND_VM_SPEC
 	USE_OPLINE
@@ -2045,11 +2051,17 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, C
 		if (OP2_TYPE == IS_UNUSED) {
 			ZEND_VM_DISPATCH_TO_HELPER(zend_use_undef_in_read_context_helper);
 		}
+		if (OP1_TYPE & IS_VAR) {
+			zval *op1 = EX_VAR(opline->op1.var);
+			if (Z_TYPE_P(op1) == IS_REFERENCE) {
+				zend_unwrap_reference(op1);
+			}
+		}
 		ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_R);
 	}
 }

-ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container;
@@ -2064,7 +2076,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *container;
@@ -2072,11 +2084,15 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST

 	SAVE_OPLINE();
 	container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
+	if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
+		/* Handler accepts VAR only for FUNC_ARG, which will unwrap before dispatching. */
+		ZEND_ASSERT(Z_TYPE_P(container) != IS_REFERENCE);
+	}

 	if (OP1_TYPE == IS_CONST ||
 	    (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
 		do {
-			if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+			if ((OP1_TYPE & IS_CV) && Z_ISREF_P(container)) {
 				container = Z_REFVAL_P(container);
 				if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
 					break;
@@ -2233,7 +2249,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_finish):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT)
+ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMP|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *property, *container, *result;
@@ -2254,7 +2270,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *property, *container, *result;
@@ -2271,7 +2287,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *container;
@@ -2279,6 +2295,8 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C

 	SAVE_OPLINE();
 	container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
+	/* Unlike FETCH_OBJ_R, this may receive references through return-by-ref
+	 * calls using ??=, i.e. foo()->bar ??= baz. */

 	if (OP1_TYPE == IS_CONST ||
 	    (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
@@ -2392,7 +2410,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_finish):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT)
+ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMP|CV, FETCH_REF|CACHE_SLOT)
 {
 #if !ZEND_VM_SPEC
 	USE_OPLINE
@@ -2405,11 +2423,17 @@ ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THI
 		}
 		ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_W);
 	} else {
+		if (OP1_TYPE == IS_VAR) {
+			zval *op1 = EX_VAR(opline->op1.var);
+			if (Z_TYPE_P(op1) == IS_REFERENCE) {
+				zend_unwrap_reference(op1);
+			}
+		}
 		ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_R);
 	}
 }

-ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *container, *property, *result;
@@ -2426,7 +2450,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container;
@@ -2438,7 +2462,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container, *dim;
@@ -2461,7 +2485,7 @@ ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
+ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|CV))
 {
 	USE_OPLINE
 	zval *object, *value, tmp;
@@ -2614,8 +2638,8 @@ ZEND_VM_C_LABEL(exit_assign_obj):
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
-ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
+ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|CV))
 {
 	USE_OPLINE
 	zval *prop, *value;
@@ -2652,7 +2676,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV))
+ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|CV))
 {
 	USE_OPLINE
 	zval *object_ptr, *orig_object_ptr;
@@ -2805,7 +2829,7 @@ ZEND_VM_C_LABEL(assign_dim_error):
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
+ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|CV, SPEC(RETVAL))
 {
 	USE_OPLINE
 	zval *value;
@@ -2873,7 +2897,7 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV))
+ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV))
 {
 	USE_OPLINE
 	zval *property, *container, *value_ptr;
@@ -2909,7 +2933,7 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CA
 	ZEND_VM_NEXT_OPCODE_EX(1, 2);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|TMP) */
 ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC)
 {
 	USE_OPLINE
@@ -3107,7 +3131,7 @@ ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
 	ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0);
 }

-ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
+ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *val;
@@ -3141,7 +3165,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
 	ZEND_VM_JMP(opline);
 }

-ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
+ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *val;
@@ -3175,7 +3199,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
 	ZEND_VM_JMP(opline);
 }

-ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
+ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *val;
@@ -3211,7 +3235,7 @@ ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
 	ZEND_VM_JMP(opline);
 }

-ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
+ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *val;
@@ -3280,7 +3304,7 @@ ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, LOOP_END)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMP|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -3405,7 +3429,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zend_string **rope;
@@ -3440,7 +3464,7 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zend_string **rope;
@@ -3475,7 +3499,7 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zend_string **rope;
@@ -3535,7 +3559,7 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, UNUSED|CLASS_FETCH, CONST|TMPVAR|UNUSED|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, UNUSED|CLASS_FETCH, CONST|TMP|UNUSED|CV, CACHE_SLOT)
 {
 	zval *class_name;
 	USE_OPLINE
@@ -3578,7 +3602,7 @@ ZEND_VM_C_LABEL(try_class_name):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, NUM|CACHE_SLOT)
+ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMP|UNUSED|THIS|CV, CONST|TMP|CV, NUM|CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *function_name;
@@ -3733,7 +3757,7 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, CONST|TMPVAR|UNUSED|CONSTRUCTOR|CV, NUM|CACHE_SLOT)
+ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, CONST|TMP|UNUSED|CONSTRUCTOR|CV, NUM|CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *function_name;
@@ -3894,7 +3918,7 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zval *function_name;
@@ -3947,7 +3971,7 @@ ZEND_VM_C_LABEL(try_function_name):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
+ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zval *function_name;
@@ -4263,6 +4287,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
 				? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
 			zend_verify_internal_func_info(call->func, ret);
 		}
+		ZEND_ASSERT(opline->result_type != IS_TMP_VAR || !Z_ISREF_P(ret));
 #endif
 		ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
 		ZEND_VM_FCALL_INTERRUPT_CHECK(call);
@@ -4391,6 +4416,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
 				? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
 			zend_verify_internal_func_info(call->func, ret);
 		}
+		ZEND_ASSERT(opline->result_type != IS_TMP_VAR || !Z_ISREF_P(ret));
 #endif
 		ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
 		ZEND_VM_FCALL_INTERRUPT_CHECK(call);
@@ -4500,7 +4526,7 @@ ZEND_VM_COLD_HANDLER(201, ZEND_VERIFY_NEVER_TYPE, UNUSED, UNUSED)
 	HANDLE_EXCEPTION();
 }

-ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
+ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|CV, ANY, SPEC(OBSERVER))
 {
 	USE_OPLINE
 	zval *retval_ptr;
@@ -4641,6 +4667,9 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC,

 	ZEND_OBSERVER_FCALL_END(execute_data, return_value);
 	ZEND_OBSERVER_FREE_RETVAL();
+
+	zend_return_unwrap_ref(execute_data, return_value);
+
 	ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
 }

@@ -4769,7 +4798,7 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER
 	ZEND_VM_RETURN();
 }

-ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zval *value;
@@ -5624,7 +5653,7 @@ ZEND_VM_C_LABEL(send_array):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM)
+ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|CV, NUM)
 {
 	USE_OPLINE
 	zval *arg, *param;
@@ -5834,7 +5863,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zval *val;
@@ -5879,7 +5908,7 @@ ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2)
 	ZEND_VM_SMART_BRANCH(ret == 0, 1);
 }

-ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(48, ZEND_CASE, TMP, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *op1, *op2;
@@ -5999,7 +6028,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMP|UNUSED|THIS|CV, ANY)
 {
 	USE_OPLINE
 	zval *obj;
@@ -6213,7 +6242,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, REF)
+ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|UNUSED|NEXT|CV, REF)
 {
 	USE_OPLINE
 	zval *expr_ptr, new_expr;
@@ -6462,7 +6491,7 @@ ZEND_VM_C_LABEL(add_unpack_again):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
+ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|UNUSED|NEXT|CV, ARRAY_INIT|REF)
 {
 	zval *array;
 	uint32_t size;
@@ -6484,7 +6513,7 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSE
 	}
 }

-ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
+ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|CV, ANY, TYPE)
 {
 	USE_OPLINE
 	zval *expr;
@@ -6533,7 +6562,7 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSERVER))
+ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|CV, ANY, EVAL, SPEC(OBSERVER))
 {
 	USE_OPLINE
 	zend_op_array *new_op_array;
@@ -6671,7 +6700,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 {
 	USE_OPLINE
@@ -6724,7 +6753,7 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|CV, CONST|TMP|CV)
 {
 	USE_OPLINE
 	zval *container;
@@ -6826,7 +6855,7 @@ ZEND_VM_C_LABEL(num_index_dim):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMP|CV, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *container;
@@ -6871,7 +6900,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
+ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *array_ptr, *result;
@@ -7165,7 +7194,7 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
+ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, TMP, ANY, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *array;
@@ -7234,6 +7263,10 @@ ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
 		zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
 		ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 	} else {
+		if (UNEXPECTED(Z_ISREF_P(value))) {
+			value = Z_REFVAL_P(value);
+			value_type = Z_TYPE_INFO_P(value);
+		}
 		zval *res = EX_VAR(opline->op2.var);
 		zend_refcounted *gc = Z_COUNTED_P(value);

@@ -7470,7 +7503,7 @@ ZEND_VM_HOT_HANDLER(154, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET))
 	}
 }

-ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
+ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|CV, UNUSED, VAR_FETCH|ISSET)
 {
 	USE_OPLINE
 	zval *value;
@@ -7514,7 +7547,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|
 	ZEND_VM_SMART_BRANCH(result, true);
 }

-/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|TMP) */
 ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CACHE_SLOT)
 {
 	USE_OPLINE
@@ -7535,7 +7568,7 @@ ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CAC
 	ZEND_VM_SMART_BRANCH(result, 1);
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|CV, CONST|TMPVAR|CV, ISSET)
+ZEND_VM_COLD_CONSTCONST_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|CV, CONST|TMP|CV, ISSET)
 {
 	USE_OPLINE
 	zval *container;
@@ -7614,7 +7647,7 @@ ZEND_VM_C_LABEL(isset_dim_obj_exit):
 	ZEND_VM_SMART_BRANCH(result, 1);
 }

-ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET|CACHE_SLOT)
+ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|UNUSED|THIS|CV, CONST|TMP|CV, ISSET|CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *container;
@@ -7664,7 +7697,7 @@ ZEND_VM_C_LABEL(isset_object_finish):
 	ZEND_VM_SMART_BRANCH(result, 1);
 }

-ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
+ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMP|CONST, CV|TMP|CONST)
 {
 	USE_OPLINE

@@ -7742,7 +7775,7 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
+ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *value;
@@ -7789,7 +7822,7 @@ ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
+ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *value;
@@ -7830,7 +7863,7 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|VAR|CV, JMP_ADDR)
+ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|CV, JMP_ADDR)
 {
 	USE_OPLINE
 	zval *val, *result;
@@ -8030,7 +8063,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMP|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
 {
 	USE_OPLINE
 	zval *expr;
@@ -8386,7 +8419,7 @@ ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper, ANY, ANY)
 	HANDLE_EXCEPTION();
 }

-ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED, SRC)
+ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|CV|UNUSED, SRC)
 {
 	USE_OPLINE

@@ -8507,7 +8540,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED
 	ZEND_VM_RETURN();
 }

-ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
@@ -8748,7 +8781,7 @@ ZEND_VM_C_LABEL(check_indirect):
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMP|CV, ANY)
 {
 	USE_OPLINE
 	zval *value;
@@ -8810,7 +8843,7 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMPVAR|CV, ANY, TYPE_MASK)
+ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|CV, ANY, TYPE_MASK)
 {
 	USE_OPLINE
 	zval *value;
@@ -8916,7 +8949,7 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
 	}
 }

-ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, CV|TMPVAR|UNUSED|CLASS_FETCH, ANY)
+ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, CV|TMP|UNUSED|CLASS_FETCH, ANY)
 {
 	uint32_t fetch_type;
 	zend_class_entry *called_scope, *scope;
@@ -9429,7 +9462,7 @@ ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED)
 	HANDLE_EXCEPTION();
 }

-ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
+ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|CV, CONST, NUM)
 {
 	USE_OPLINE
 	zval *op1;
@@ -9501,7 +9534,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM
 	ZEND_VM_SMART_BRANCH(0, 1);
 }

-ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
+ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|CV, UNUSED)
 {
 	USE_OPLINE
 	zval *op1;
@@ -9556,7 +9589,7 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
 	ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
 }

-ZEND_VM_TYPE_SPEC_HANDLER(ZEND_COUNT, (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_COUNT_ARRAY, CV|TMPVAR, UNUSED)
+ZEND_VM_TYPE_SPEC_HANDLER(ZEND_COUNT, (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_COUNT_ARRAY, CV|TMP, UNUSED)
 {
 	USE_OPLINE
 	zend_array *ht = Z_ARRVAL_P(GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R));
@@ -9571,7 +9604,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_COUNT, (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_B
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED)
+ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|CV, UNUSED)
 {
 	USE_OPLINE

@@ -9632,7 +9665,7 @@ ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
 	ZEND_VM_NEXT_OPCODE();
 }

-ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
+ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|CV, UNUSED)
 {
 	USE_OPLINE
 	zval *op1;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 38b869c4a4c..77edd6b7cc5 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ
diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h
index d52de1226df..6f159519545 100644
Binary files a/Zend/zend_vm_handlers.h and b/Zend/zend_vm_handlers.h differ
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index cb70e8ccd86..87cd00a6f8b 100644
Binary files a/Zend/zend_vm_opcodes.c and b/Zend/zend_vm_opcodes.c differ
diff --git a/ext/mbstring/tests/gh20836.phpt b/ext/mbstring/tests/gh20836.phpt
index 60b6a4ce8d4..0bdb3a44f3b 100644
--- a/ext/mbstring/tests/gh20836.phpt
+++ b/ext/mbstring/tests/gh20836.phpt
@@ -7,7 +7,8 @@

 $a = [];
 $b = [];
-$a[] = $b[] = &$a;
+$b[] = &$a;
+$a[] = &$b;
 var_dump(mb_convert_variables('utf-8', 'utf-8', $a));

 $c = [];
diff --git a/ext/opcache/tests/array_map_foreach_optimization_001.phpt b/ext/opcache/tests/array_map_foreach_optimization_001.phpt
index eba3d6b2955..c38265f35eb 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_001.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_001.phpt
@@ -28,16 +28,16 @@ function plus1($x) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(10) 2
-0003 V2 = DO_ICALL
-0004 ASSIGN CV0($array) V2
+0003 T2 = DO_ICALL
+0004 ASSIGN CV0($array) T2
 0005 TYPE_ASSERT 131079 string("array_map") CV0($array)
 0006 T2 = INIT_ARRAY 0 (packed) NEXT
 0007 V3 = FE_RESET_R CV0($array) 0014
 0008 T5 = FE_FETCH_R V3 T4 0014
 0009 INIT_FCALL 1 %d string("plus1")
 0010 SEND_VAL T4 1
-0011 V4 = DO_UCALL
-0012 T2 = ADD_ARRAY_ELEMENT V4 T5
+0011 T4 = DO_UCALL
+0012 T2 = ADD_ARRAY_ELEMENT T4 T5
 0013 JMP 0008
 0014 FE_FREE V3
 0015 ASSIGN CV1($foo) T2
diff --git a/ext/opcache/tests/array_map_foreach_optimization_002.phpt b/ext/opcache/tests/array_map_foreach_optimization_002.phpt
index 57e8706e90e..03fb221d7ed 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_002.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_002.phpt
@@ -31,19 +31,19 @@ function plus1($x) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(10) 2
-0003 V2 = DO_ICALL
-0004 ASSIGN CV0($array) V2
-0005 V5 = NEW 1 string("ArrayIterator")
+0003 T2 = DO_ICALL
+0004 ASSIGN CV0($array) T2
+0005 T5 = NEW 1 string("ArrayIterator")
 0006 SEND_VAR%S CV0($array) 1
 0007 DO_FCALL
-0008 TYPE_ASSERT 131079 string("array_map") V5
+0008 TYPE_ASSERT 131079 string("array_map") T5
 0009 T2 = INIT_ARRAY 0 (packed) NEXT
-0010 V3 = FE_RESET_R V5 0017
+0010 V3 = FE_RESET_R T5 0017
 0011 T5 = FE_FETCH_R V3 T4 0017
 0012 INIT_FCALL 1 %d string("plus1")
 0013 SEND_VAL T4 1
-0014 V4 = DO_UCALL
-0015 T2 = ADD_ARRAY_ELEMENT V4 T5
+0014 T4 = DO_UCALL
+0015 T2 = ADD_ARRAY_ELEMENT T4 T5
 0016 JMP 0011
 0017 FE_FREE V3
 0018 ASSIGN CV1($foo) T2
diff --git a/ext/opcache/tests/array_map_foreach_optimization_003.phpt b/ext/opcache/tests/array_map_foreach_optimization_003.phpt
index 7c8529494d2..e3a9972c124 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_003.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_003.phpt
@@ -29,8 +29,8 @@ function plus1($x) {
 0003 T4 = FE_FETCH_R V2 T3 0009
 0004 INIT_FCALL 1 %d string("plus1")
 0005 SEND_VAL T3 1
-0006 V3 = DO_UCALL
-0007 T1 = ADD_ARRAY_ELEMENT V3 T4
+0006 T3 = DO_UCALL
+0007 T1 = ADD_ARRAY_ELEMENT T3 T4
 0008 JMP 0003
 0009 FE_FREE V2
 0010 ASSIGN CV0($foo) T1
diff --git a/ext/opcache/tests/array_map_foreach_optimization_004.phpt b/ext/opcache/tests/array_map_foreach_optimization_004.phpt
index 8b55a241a69..d4ead73983b 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_004.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_004.phpt
@@ -26,16 +26,16 @@ function stdClass() {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(10) 2
-0003 V1 = DO_ICALL
-0004 ASSIGN CV0($array) V1
+0003 T1 = DO_ICALL
+0004 ASSIGN CV0($array) T1
 0005 TYPE_ASSERT 131079 string("array_map") CV0($array)
 0006 T1 = INIT_ARRAY 0 (packed) NEXT
 0007 V2 = FE_RESET_R CV0($array) 0014
 0008 T4 = FE_FETCH_R V2 T3 0014
 0009 INIT_FCALL 1 %d string("stdclass")
 0010 SEND_VAL T3 1
-0011 V3 = DO_UCALL
-0012 T1 = ADD_ARRAY_ELEMENT V3 T4
+0011 T3 = DO_UCALL
+0012 T1 = ADD_ARRAY_ELEMENT T3 T4
 0013 JMP 0008
 0014 FE_FREE V2
 0015 FREE T1
@@ -50,8 +50,8 @@ function stdClass() {
      ; (lines=3, args=0, vars=0, tmps=%d)
      ; (after optimizer)
      ; %s
-0000 V0 = NEW 0 string("stdClass")
+0000 T0 = NEW 0 string("stdClass")
 0001 DO_FCALL
-0002 RETURN V0
+0002 RETURN T0
 LIVE RANGES:
      0: 0001 - 0002 (new)
diff --git a/ext/opcache/tests/array_map_foreach_optimization_005.phpt b/ext/opcache/tests/array_map_foreach_optimization_005.phpt
index 69edf469796..33197e2c8d5 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_005.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_005.phpt
@@ -30,16 +30,16 @@ static function plus1($x) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(10) 2
-0003 V2 = DO_ICALL
-0004 ASSIGN CV0($array) V2
+0003 T2 = DO_ICALL
+0004 ASSIGN CV0($array) T2
 0005 TYPE_ASSERT 131079 string("array_map") CV0($array)
 0006 T2 = INIT_ARRAY 0 (packed) NEXT
 0007 V3 = FE_RESET_R CV0($array) 0014
 0008 T5 = FE_FETCH_R V3 T4 0014
 0009 INIT_STATIC_METHOD_CALL 1 string("Adder") string("plus1")
 0010 SEND_VAL T4 1
-0011 V4 = DO_UCALL
-0012 T2 = ADD_ARRAY_ELEMENT V4 T5
+0011 T4 = DO_UCALL
+0012 T2 = ADD_ARRAY_ELEMENT T4 T5
 0013 JMP 0008
 0014 FE_FREE V3
 0015 ASSIGN CV1($foo) T2
diff --git a/ext/opcache/tests/array_map_foreach_optimization_006.phpt b/ext/opcache/tests/array_map_foreach_optimization_006.phpt
index a3b1c534e34..889fee27b8a 100644
--- a/ext/opcache/tests/array_map_foreach_optimization_006.phpt
+++ b/ext/opcache/tests/array_map_foreach_optimization_006.phpt
@@ -29,8 +29,8 @@ function plus1($x) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(10) 2
-0003 V3 = DO_ICALL
-0004 ASSIGN CV0($array) V3
+0003 T3 = DO_ICALL
+0004 ASSIGN CV0($array) T3
 0005 ASSIGN CV1($plus1) string("plus1")
 0006 TYPE_ASSERT 131079 string("array_map") CV0($array)
 0007 T3 = INIT_ARRAY 0 (packed) NEXT
@@ -38,8 +38,8 @@ function plus1($x) {
 0009 T6 = FE_FETCH_R V4 T5 0015
 0010 INIT_DYNAMIC_CALL 1 CV1($plus1)
 0011 SEND_VAL_EX T5 1
-0012 V5 = DO_FCALL
-0013 T3 = ADD_ARRAY_ELEMENT V5 T6
+0012 T5 = DO_FCALL
+0013 T3 = ADD_ARRAY_ELEMENT T5 T6
 0014 JMP 0009
 0015 FE_FREE V4
 0016 ASSIGN CV2($foo) T3
diff --git a/ext/opcache/tests/dump_property_hooks.phpt b/ext/opcache/tests/dump_property_hooks.phpt
index 5083ad385f3..3073ca89ff9 100644
--- a/ext/opcache/tests/dump_property_hooks.phpt
+++ b/ext/opcache/tests/dump_property_hooks.phpt
@@ -39,9 +39,9 @@ class A {
      ; (lines=10, args=0, vars=1, tmps=%d)
      ; (after optimizer)
      ; %sdump_property_hooks.php:1-22
-0000 V1 = NEW 0 string("A")
+0000 T1 = NEW 0 string("A")
 0001 DO_FCALL
-0002 ASSIGN CV0($a) V1
+0002 ASSIGN CV0($a) T1
 0003 INIT_FCALL 1 %d string("var_dump")
 0004 T1 = FETCH_OBJ_R CV0($a) string("prop")
 0005 SEND_VAL T1 1
diff --git a/ext/opcache/tests/gh20628_borked_live_range_calc.phpt b/ext/opcache/tests/gh20628_borked_live_range_calc.phpt
new file mode 100644
index 00000000000..f0b6ccfc92c
--- /dev/null
+++ b/ext/opcache/tests/gh20628_borked_live_range_calc.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Broken live-range calculation with QM_ASSIGN optimization
+--EXTENSIONS--
+opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+--FILE--
+<?php
+
+function test($cond) {
+    $caller = $cond ? new \ReflectionMethod('non', 'existent') : null;
+}
+
+try {
+    test(true);
+} catch (Throwable $e) {
+    echo $e::class, $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+ReflectionExceptionClass "non" does not exist
diff --git a/ext/opcache/tests/match/001.phpt b/ext/opcache/tests/match/001.phpt
index 502400681cf..9d9ad2ac9e3 100644
--- a/ext/opcache/tests/match/001.phpt
+++ b/ext/opcache/tests/match/001.phpt
@@ -34,17 +34,17 @@ function test($char) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL string("a") 1
 0002 SEND_VAL string("i") 2
-0003 V2 = DO_ICALL
-0004 V1 = FE_RESET_R V2 0013
-0005 FE_FETCH_R V1 CV0($char) 0013
+0003 T2 = DO_ICALL
+0004 T1 = FE_RESET_R T2 0013
+0005 FE_FETCH_R T1 CV0($char) 0013
 0006 INIT_FCALL 1 %d string("var_dump")
 0007 INIT_FCALL 1 %d string("test")
 0008 SEND_VAR CV0($char) 1
-0009 V2 = DO_UCALL
-0010 SEND_VAR V2 1
+0009 T2 = DO_UCALL
+0010 SEND_VAL T2 1
 0011 DO_ICALL
 0012 JMP 0005
-0013 FE_FREE V1
+0013 FE_FREE T1
 0014 RETURN int(1)
 LIVE RANGES:
      1: 0005 - 0013 (loop)
diff --git a/ext/opcache/tests/match/003.phpt b/ext/opcache/tests/match/003.phpt
index 24f3cd26121..8bed8471788 100644
--- a/ext/opcache/tests/match/003.phpt
+++ b/ext/opcache/tests/match/003.phpt
@@ -35,17 +35,17 @@ function test($char) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(0) 1
 0002 SEND_VAL int(10) 2
-0003 V2 = DO_ICALL
-0004 V1 = FE_RESET_R V2 0013
-0005 FE_FETCH_R V1 CV0($char) 0013
+0003 T2 = DO_ICALL
+0004 T1 = FE_RESET_R T2 0013
+0005 FE_FETCH_R T1 CV0($char) 0013
 0006 INIT_FCALL 1 %d string("var_dump")
 0007 INIT_FCALL 1 %d string("test")
 0008 SEND_VAR CV0($char) 1
-0009 V2 = DO_UCALL
-0010 SEND_VAR V2 1
+0009 T2 = DO_UCALL
+0010 SEND_VAL T2 1
 0011 DO_ICALL
 0012 JMP 0005
-0013 FE_FREE V1
+0013 FE_FREE T1
 0014 RETURN int(1)
 LIVE RANGES:
      1: 0005 - 0013 (loop)
diff --git a/ext/opcache/tests/match/004.phpt b/ext/opcache/tests/match/004.phpt
index d9d4149b945..ae7b40f20f5 100644
--- a/ext/opcache/tests/match/004.phpt
+++ b/ext/opcache/tests/match/004.phpt
@@ -40,24 +40,24 @@ function test($value) {
 0000 INIT_FCALL 2 %d string("range")
 0001 SEND_VAL int(0) 1
 0002 SEND_VAL int(6) 2
-0003 V2 = DO_ICALL
-0004 V1 = FE_RESET_R V2 0020
-0005 FE_FETCH_R V1 CV0($number) 0020
+0003 T2 = DO_ICALL
+0004 T1 = FE_RESET_R T2 0020
+0005 FE_FETCH_R T1 CV0($number) 0020
 0006 INIT_FCALL 1 %d string("var_dump")
 0007 INIT_FCALL 1 %d string("test")
 0008 SEND_VAR CV0($number) 1
-0009 V2 = DO_UCALL
-0010 SEND_VAR V2 1
+0009 T2 = DO_UCALL
+0010 SEND_VAL T2 1
 0011 DO_ICALL
 0012 INIT_FCALL 1 %d string("var_dump")
 0013 INIT_FCALL 1 %d string("test")
 0014 T2 = CAST (string) CV0($number)
 0015 SEND_VAL T2 1
-0016 V2 = DO_UCALL
-0017 SEND_VAR V2 1
+0016 T2 = DO_UCALL
+0017 SEND_VAL T2 1
 0018 DO_ICALL
 0019 JMP 0005
-0020 FE_FREE V1
+0020 FE_FREE T1
 0021 RETURN int(1)
 LIVE RANGES:
      1: 0005 - 0020 (loop)
diff --git a/ext/opcache/tests/named_parameter_new.phpt b/ext/opcache/tests/named_parameter_new.phpt
index 1f6f64333c9..f8979766421 100644
--- a/ext/opcache/tests/named_parameter_new.phpt
+++ b/ext/opcache/tests/named_parameter_new.phpt
@@ -58,15 +58,15 @@ public static function new(int $bar): self
      ; (after optimizer)
      ; %s
 0000 CV0($bar) = RECV 1
-0001 V2 = NEW 1 string("Random\\Engine\\Xoshiro256StarStar")
+0001 T2 = NEW 1 string("Random\\Engine\\Xoshiro256StarStar")
 0002 SEND_VAL int(123) 1
 0003 DO_FCALL
-0004 CV1($engine) = QM_ASSIGN V2
-0005 V2 = NEW 2 (self) (exception)
+0004 CV1($engine) = QM_ASSIGN T2
+0005 T2 = NEW 2 (self) (exception)
 0006 SEND_VAR CV1($engine) 1
 0007 SEND_VAR CV0($bar) 2
 0008 DO_FCALL
-0009 RETURN V2
+0009 RETURN T2
 LIVE RANGES:
      2: 0002 - 0004 (new)
      2: 0006 - 0009 (new)
diff --git a/ext/opcache/tests/nodiscard_001.phpt b/ext/opcache/tests/nodiscard_001.phpt
index 7e232f8f44e..8f87e7877bc 100644
--- a/ext/opcache/tests/nodiscard_001.phpt
+++ b/ext/opcache/tests/nodiscard_001.phpt
@@ -33,28 +33,28 @@ function test() {
 0000 INIT_FCALL 0 %d string("zend_test_nodiscard")
 0001 DO_FCALL_BY_NAME
 0002 INIT_FCALL 0 %d string("zend_test_nodiscard")
-0003 V2 = DO_ICALL
-0004 FREE V2
+0003 T2 = DO_ICALL
+0004 FREE T2
 0005 INIT_FCALL 0 %d string("zend_test_nodiscard")
-0006 V2 = DO_ICALL
-0007 ASSIGN CV0($success) V2
+0006 T2 = DO_ICALL
+0007 ASSIGN CV0($success) T2
 0008 INIT_FCALL 0 %d string("test")
 0009 DO_FCALL_BY_NAME
 0010 INIT_FCALL 0 %d string("test")
-0011 V2 = DO_UCALL
-0012 FREE V2
+0011 T2 = DO_UCALL
+0012 FREE T2
 0013 INIT_FCALL 0 %d string("test")
-0014 V2 = DO_UCALL
-0015 ASSIGN CV1($obj) V2
+0014 T2 = DO_UCALL
+0015 ASSIGN CV1($obj) T2
 0016 RETURN int(1)

 test:
      ; (lines=3, args=0, vars=0, tmps=%d)
      ; (after optimizer)
      ; %s
-0000 V0 = NEW 0 string("stdClass")
+0000 T0 = NEW 0 string("stdClass")
 0001 DO_FCALL
-0002 RETURN V0
+0002 RETURN T0
 LIVE RANGES:
      0: 0001 - 0002 (new)

diff --git a/ext/opcache/tests/opt/block_pass_007.phpt b/ext/opcache/tests/opt/block_pass_007.phpt
index b2dca320d9b..1afecfc3e17 100644
--- a/ext/opcache/tests/opt/block_pass_007.phpt
+++ b/ext/opcache/tests/opt/block_pass_007.phpt
@@ -24,8 +24,8 @@
 0000 INIT_FCALL 2 %d string("random_int")
 0001 SEND_VAL int(1) 1
 0002 SEND_VAL int(2) 2
-0003 V1 = DO_ICALL
-0004 ASSIGN CV0($f) V1
+0003 T1 = DO_ICALL
+0004 ASSIGN CV0($f) T1
 0005 INIT_FCALL 1 %d string("var_dump")
 0006 T1 = BOOL_NOT CV0($f)
 0007 SEND_VAL T1 1
diff --git a/ext/opcache/tests/opt/dce_006.phpt b/ext/opcache/tests/opt/dce_006.phpt
index 2596651ed3e..2c1fe749ae9 100644
--- a/ext/opcache/tests/opt/dce_006.phpt
+++ b/ext/opcache/tests/opt/dce_006.phpt
@@ -31,9 +31,9 @@ function foo(int $x) {
      ; (after optimizer)
      ; %sdce_006.php:5-8
 0000 CV0($x) = RECV 1
-0001 V2 = NEW 0 string("A")
+0001 T2 = NEW 0 string("A")
 0002 DO_FCALL
-0003 CV1($a) = QM_ASSIGN V2
+0003 CV1($a) = QM_ASSIGN T2
 0004 ASSIGN_OBJ CV1($a) string("foo")
 0005 OP_DATA CV0($x)
 0006 RETURN null
diff --git a/ext/opcache/tests/opt/gh11170.phpt b/ext/opcache/tests/opt/gh11170.phpt
index 9ea733f92b1..ae26cb4081f 100644
--- a/ext/opcache/tests/opt/gh11170.phpt
+++ b/ext/opcache/tests/opt/gh11170.phpt
@@ -65,8 +65,8 @@ function test_and() {
      ; level=0
      ; children=(BB1, BB2, BB3)
 0000 INIT_FCALL 0 %d string("rand")
-0001 #2.V2 [long] = DO_ICALL
-0002 #3.T3 [long] RANGE[MIN..MAX] = MOD #2.V2 [long] int(10)
+0001 #2.T2 [long] = DO_ICALL
+0002 #3.T3 [long] RANGE[MIN..MAX] = MOD #2.T2 [long] int(10)
 0003 JMPZ #3.T3 [long] RANGE[MIN..MAX] BB2

 BB1:
@@ -111,8 +111,8 @@ function test_and() {
      ; level=0
      ; children=(BB1, BB2, BB3)
 0000 INIT_FCALL 0 %d string("rand")
-0001 #2.V2 [long] = DO_ICALL
-0002 #3.T3 [long] RANGE[MIN..MAX] = MOD #2.V2 [long] int(10)
+0001 #2.T2 [long] = DO_ICALL
+0002 #3.T3 [long] RANGE[MIN..MAX] = MOD #2.T2 [long] int(10)
 0003 JMPZ #3.T3 [long] RANGE[MIN..MAX] BB2

 BB1:
diff --git a/ext/opcache/tests/opt/gh14873.phpt b/ext/opcache/tests/opt/gh14873.phpt
index d442128d023..20428b5bcd2 100644
--- a/ext/opcache/tests/opt/gh14873.phpt
+++ b/ext/opcache/tests/opt/gh14873.phpt
@@ -62,44 +62,44 @@ function testStrstr3Third(bool $value): string {
 0000 INIT_FCALL 1 %d string("var_dump")
 0001 INIT_FCALL 1 %d string("testtrim1")
 0002 SEND_VAL string(" boo ") 1
-0003 V0 = DO_UCALL
-0004 SEND_VAR V0 1
+0003 T0 = DO_UCALL
+0004 SEND_VAL T0 1
 0005 DO_ICALL
 0006 INIT_FCALL 1 %d string("var_dump")
 0007 INIT_FCALL 1 %d string("testmin2first")
 0008 SEND_VAL int(5) 1
-0009 V0 = DO_UCALL
-0010 SEND_VAR V0 1
+0009 T0 = DO_UCALL
+0010 SEND_VAL T0 1
 0011 DO_ICALL
 0012 INIT_FCALL 1 %d string("var_dump")
 0013 INIT_FCALL 1 %d string("testmin2second")
 0014 SEND_VAL int(5) 1
-0015 V0 = DO_UCALL
-0016 SEND_VAR V0 1
+0015 T0 = DO_UCALL
+0016 SEND_VAL T0 1
 0017 DO_ICALL
 0018 INIT_FCALL 1 %d string("var_dump")
 0019 INIT_FCALL 1 %d string("testmin2_tmp")
 0020 SEND_VAL int(5) 1
-0021 V0 = DO_UCALL
-0022 SEND_VAR V0 1
+0021 T0 = DO_UCALL
+0022 SEND_VAL T0 1
 0023 DO_ICALL
 0024 INIT_FCALL 1 %d string("var_dump")
 0025 INIT_FCALL 1 %d string("teststrstr3first")
 0026 SEND_VAL string("needles") 1
-0027 V0 = DO_UCALL
-0028 SEND_VAR V0 1
+0027 T0 = DO_UCALL
+0028 SEND_VAL T0 1
 0029 DO_ICALL
 0030 INIT_FCALL 1 %d string("var_dump")
 0031 INIT_FCALL 1 %d string("teststrstr3second")
 0032 SEND_VAL string("needle") 1
-0033 V0 = DO_UCALL
-0034 SEND_VAR V0 1
+0033 T0 = DO_UCALL
+0034 SEND_VAL T0 1
 0035 DO_ICALL
 0036 INIT_FCALL 1 %d string("var_dump")
 0037 INIT_FCALL 1 %d string("teststrstr3third")
 0038 SEND_VAL bool(false) 1
-0039 V0 = DO_UCALL
-0040 SEND_VAR V0 1
+0039 T0 = DO_UCALL
+0040 SEND_VAL T0 1
 0041 DO_ICALL
 0042 RETURN int(1)

diff --git a/ext/opcache/tests/opt/gh18107_1.phpt b/ext/opcache/tests/opt/gh18107_1.phpt
index 062ccd46455..a2cf3162090 100644
--- a/ext/opcache/tests/opt/gh18107_1.phpt
+++ b/ext/opcache/tests/opt/gh18107_1.phpt
@@ -29,15 +29,15 @@
      ; %s
 0000 T1 = ISSET_ISEMPTY_CV (isset) CV0($badvar)
 0001 JMPNZ T1 0006
-0002 V3 = NEW 1 string("Exception")
+0002 T3 = NEW 1 string("Exception")
 0003 SEND_VAL%S string("Should happen") 1
 0004 DO_FCALL
-0005 THROW V3
+0005 THROW T3
 0006 JMP 0006
-0007 V6 = NEW 1 string("Exception")
+0007 T6 = NEW 1 string("Exception")
 0008 SEND_VAL%S string("Should not happen") 1
 0009 DO_FCALL
-0010 THROW V6
+0010 THROW T6
 0011 FAST_RET T5
 EXCEPTION TABLE:
      0006, -, 0007, 0011
diff --git a/ext/opcache/tests/opt/gh18107_2.phpt b/ext/opcache/tests/opt/gh18107_2.phpt
index bd34a54edf6..74a709223e5 100644
--- a/ext/opcache/tests/opt/gh18107_2.phpt
+++ b/ext/opcache/tests/opt/gh18107_2.phpt
@@ -32,18 +32,18 @@
      ; %s
 0000 T2 = ISSET_ISEMPTY_CV (isset) CV0($badvar)
 0001 JMPNZ T2 0008
-0002 V4 = NEW 1 string("Exception")
+0002 T4 = NEW 1 string("Exception")
 0003 SEND_VAL%S string("Should happen") 1
 0004 DO_FCALL
-0005 THROW V4
+0005 THROW T4
 0006 CV1($e) = CATCH string("Throwable")
 0007 ECHO string("foo")
 0008 T6 = FAST_CALL 0010
 0009 JMP 0015
-0010 V7 = NEW 1 string("Exception")
+0010 T7 = NEW 1 string("Exception")
 0011 SEND_VAL%S string("Should not happen") 1
 0012 DO_FCALL
-0013 THROW V7
+0013 THROW T7
 0014 FAST_RET T6
 0015 RETURN int(1)
 EXCEPTION TABLE:
diff --git a/ext/opcache/tests/opt/jmp_001.phpt b/ext/opcache/tests/opt/jmp_001.phpt
index 71ff73671e8..d5491dfe1ab 100644
--- a/ext/opcache/tests/opt/jmp_001.phpt
+++ b/ext/opcache/tests/opt/jmp_001.phpt
@@ -28,6 +28,6 @@ function test() {
      ; (after optimizer)
      ; %s:2-6
 0000 INIT_FCALL_BY_NAME 0 string("test2")
-0001 V1 = DO_FCALL_BY_NAME
-0002 CV0($var) = QM_ASSIGN V1
+0001 T1 = DO_FCALL_BY_NAME
+0002 CV0($var) = QM_ASSIGN T1
 0003 RETURN CV0($var)
diff --git a/ext/opcache/tests/opt/sccp_022.phpt b/ext/opcache/tests/opt/sccp_022.phpt
index ffcc48b0dcc..27d7b6d7192 100644
--- a/ext/opcache/tests/opt/sccp_022.phpt
+++ b/ext/opcache/tests/opt/sccp_022.phpt
@@ -51,14 +51,14 @@ function bar() {
      ; (lines=9, args=0, vars=3, tmps=2)
      ; (after optimizer)
      ; %s
-0000 V3 = FE_RESET_R CV0($a) 0007
-0001 FE_FETCH_R V3 CV1($v) 0007
-0002 V4 = FE_RESET_R CV1($v) 0005
-0003 FE_FETCH_R V4 CV2($v2) 0005
+0000 T3 = FE_RESET_R CV0($a) 0007
+0001 FE_FETCH_R T3 CV1($v) 0007
+0002 T4 = FE_RESET_R CV1($v) 0005
+0003 FE_FETCH_R T4 CV2($v2) 0005
 0004 JMP 0003
-0005 FE_FREE V4
+0005 FE_FREE T4
 0006 JMP 0001
-0007 FE_FREE V3
+0007 FE_FREE T3
 0008 RETURN null
 LIVE RANGES:
      3: 0001 - 0007 (loop)
diff --git a/ext/opcache/tests/opt/sccp_032.phpt b/ext/opcache/tests/opt/sccp_032.phpt
index 6ee4a837ecd..3db224845f3 100644
--- a/ext/opcache/tests/opt/sccp_032.phpt
+++ b/ext/opcache/tests/opt/sccp_032.phpt
@@ -30,27 +30,26 @@ function test(): Generator {
      ; (after optimizer)
      ; %ssccp_032.php:1-15
 0000 INIT_FCALL 0 %d string("test")
-0001 V2 = DO_UCALL
-0002 V1 = FE_RESET_R V2 0009
-0003 FE_FETCH_R V1 CV0($x) 0009
+0001 T2 = DO_UCALL
+0002 T1 = FE_RESET_R T2 0009
+0003 FE_FETCH_R T1 CV0($x) 0009
 0004 INIT_FCALL 1 %d string("var_export")
 0005 SEND_VAR CV0($x) 1
 0006 DO_ICALL
 0007 ECHO string("\n")
 0008 JMP 0003
-0009 FE_FREE V1
+0009 FE_FREE T1
 0010 RETURN int(1)
 LIVE RANGES:
      1: 0003 - 0009 (loop)

 test:
-     ; (lines=5, args=0, vars=0, tmps=1)
+     ; (lines=4, args=0, vars=0, tmps=0)
      ; (after optimizer)
      ; %ssccp_032.php:2-9
 0000 GENERATOR_CREATE
 0001 YIELD null
-0002 T0 = YIELD_FROM array(...)
-0003 FREE T0
-0004 GENERATOR_RETURN null
+0002 YIELD_FROM array(...)
+0003 GENERATOR_RETURN null
 NULL
 3
diff --git a/ext/opcache/tests/opt/type_inference_final_class.phpt b/ext/opcache/tests/opt/type_inference_final_class.phpt
index 3c4aa03d8cb..be3b584b3c6 100644
--- a/ext/opcache/tests/opt/type_inference_final_class.phpt
+++ b/ext/opcache/tests/opt/type_inference_final_class.phpt
@@ -39,5 +39,5 @@ public function getInt2(): int {
      ; (lines=2, args=0, vars=0, tmps=1)
      ; (after optimizer)
      ; %s
-0000 V0 = QM_ASSIGN int(42)
-0001 RETURN V0
+0000 T0 = VERIFY_RETURN_TYPE int(42)
+0001 RETURN T0
diff --git a/ext/opcache/tests/pipe_optimizations.phpt b/ext/opcache/tests/pipe_optimizations.phpt
index 5a8750845dd..5115eaff59a 100644
--- a/ext/opcache/tests/pipe_optimizations.phpt
+++ b/ext/opcache/tests/pipe_optimizations.phpt
@@ -35,30 +35,29 @@ public static function bar(int $a): int {
 ?>
 --EXPECTF--
 $_main:
-     ; (lines=18, args=0, vars=2, tmps=%d)
+     ; (lines=17, args=0, vars=2, tmps=%d)
      ; (after optimizer)
      ; %s:1-27
-0000 V2 = NEW 0 string("Other")
+0000 T2 = NEW 0 string("Other")
 0001 DO_FCALL
-0002 ASSIGN CV0($o) V2
+0002 ASSIGN CV0($o) T2
 0003 INIT_FCALL 1 %d string("_test1")
 0004 SEND_VAL int(5) 1
 0005 T2 = DO_UCALL
 0006 INIT_METHOD_CALL 1 CV0($o) string("foo")
 0007 SEND_VAL_EX T2 1
-0008 V3 = DO_FCALL
-0009 T2 = QM_ASSIGN V3
-0010 INIT_STATIC_METHOD_CALL 1 string("Other") string("bar")
-0011 SEND_VAL T2 1
-0012 V2 = DO_UCALL
-0013 ASSIGN CV1($res1) V2
-0014 INIT_FCALL 1 %d string("var_dump")
-0015 SEND_VAR CV1($res1) 1
-0016 DO_ICALL
-0017 RETURN int(1)
+0008 T2 = DO_FCALL
+0009 INIT_STATIC_METHOD_CALL 1 string("Other") string("bar")
+0010 SEND_VAL T2 1
+0011 T2 = DO_UCALL
+0012 ASSIGN CV1($res1) T2
+0013 INIT_FCALL 1 %d string("var_dump")
+0014 SEND_VAR CV1($res1) 1
+0015 DO_ICALL
+0016 RETURN int(1)
 LIVE RANGES:
      2: 0001 - 0002 (new)
-     2: 0010 - 0011 (tmp/var)
+     2: 0009 - 0010 (tmp/var)

 _test1:
      ; (lines=4, args=1, vars=1, tmps=%d)
diff --git a/sapi/phpdbg/tests/print_001.phpt b/sapi/phpdbg/tests/print_001.phpt
index ae1b7991973..031b4d5a961 100644
--- a/sapi/phpdbg/tests/print_001.phpt
+++ b/sapi/phpdbg/tests/print_001.phpt
@@ -19,8 +19,8 @@
 L0015 0001 INIT_FCALL %d %d string("var_dump")
 L0015 0002 INIT_FCALL %d %d string("strrev")
 L0015 0003 SEND_VAR CV0($baz) 1
-L0015 0004 V1 = DO_ICALL
-L0015 0005 SEND_VAR V1 1
+L0015 0004 T1 = DO_ICALL
+L0015 0005 SEND_VAL T1 1
 L0015 0006 DO_ICALL
 L0016 0007 RETURN null
 prompt> [User Class: Foo\Bar (2 methods)]
@@ -44,9 +44,9 @@
 $_main:
      ; (lines=9, args=0, vars=0, tmps=%d)
      ; %s:1-21
-L0018 0000 V0 = NEW 0 string("Foo\\Bar")
+L0018 0000 T0 = NEW 0 string("Foo\\Bar")
 L0018 0001 DO_FCALL
-L0018 0002 INIT_METHOD_CALL 1 V0 string("Foo")
+L0018 0002 INIT_METHOD_CALL 1 T0 string("Foo")
 L0018 0003 SEND_VAL_EX string("test \"quotes\"") 1
 L0018 0004 DO_FCALL
 L0019 0005 INIT_FCALL %d %d string("foo")
diff --git a/sapi/phpdbg/tests/print_002.phpt b/sapi/phpdbg/tests/print_002.phpt
index 3b46fe0c13c..a183939cad3 100644
--- a/sapi/phpdbg/tests/print_002.phpt
+++ b/sapi/phpdbg/tests/print_002.phpt
@@ -25,8 +25,8 @@
 L0015 0001 INIT_FCALL %d %d string("var_dump")
 L0015 0002 INIT_FCALL %d %d string("strrev")
 L0015 0003 SEND_VAR CV0($baz) 1
-L0015 0004 V1 = DO_ICALL
-L0015 0005 SEND_VAR V1 1
+L0015 0004 T1 = DO_ICALL
+L0015 0005 SEND_VAL T1 1
 L0015 0006 DO_ICALL
 L0016 0007 RETURN null
 prompt> L0015 0001 INIT_FCALL %d %d string("var_dump")