1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00
Files
archived-php-src/ext/opcache/tests/opt/gh14873.phpt
Ilija Tovilo 6173a9a109 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
2026-01-31 19:44:56 +01:00

190 lines
4.5 KiB
PHP

--TEST--
GH-14873 (PHP 8.4 min function fails on typed integer)
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=0x7FFEBFFF
opcache.opt_debug_level=0x20000
--FILE--
<?php
function testTrim1(string $value): string {
$value = trim($value);
return $value;
}
function testMin2First(int $value): int {
$value = min($value, 100);
return $value;
}
function testMin2Second(int $value): int {
$value = min(100, $value);
return $value;
}
function testMin2_TMP(int $value): int {
$value = min($value + 1, 100);
return $value;
}
function testStrstr3First(string $value): string {
$value = strstr($value, "needle", false);
return $value;
}
function testStrstr3Second(string $value): string {
$value = strstr("needles", $value, false);
return $value;
}
function testStrstr3Third(bool $value): string {
$value = strstr("needles", "needle", $value);
return $value;
}
var_dump(testTrim1(" boo "));
var_dump(testMin2First(5));
var_dump(testMin2Second(5));
var_dump(testMin2_TMP(5));
var_dump(testStrstr3First("needles"));
var_dump(testStrstr3Second("needle"));
var_dump(testStrstr3Third(false));
?>
--EXPECTF--
$_main:
; (lines=43, args=0, vars=0, tmps=%d)
; (after optimizer)
; %s
0000 INIT_FCALL 1 %d string("var_dump")
0001 INIT_FCALL 1 %d string("testtrim1")
0002 SEND_VAL string(" boo ") 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 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 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 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 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 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 T0 = DO_UCALL
0040 SEND_VAL T0 1
0041 DO_ICALL
0042 RETURN int(1)
testTrim1:
; (lines=4, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_1(trim) CV0($value)
0002 ASSIGN CV0($value) T1
0003 RETURN CV0($value)
testMin2First:
; (lines=5, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_2(min) CV0($value) int(100)
0002 CV0($value) = QM_ASSIGN T1
0003 VERIFY_RETURN_TYPE CV0($value)
0004 RETURN CV0($value)
testMin2Second:
; (lines=5, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_2(min) int(100) CV0($value)
0002 CV0($value) = QM_ASSIGN T1
0003 VERIFY_RETURN_TYPE CV0($value)
0004 RETURN CV0($value)
testMin2_TMP:
; (lines=5, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = ADD CV0($value) int(1)
0002 CV0($value) = FRAMELESS_ICALL_2(min) T1 int(100)
0003 VERIFY_RETURN_TYPE CV0($value)
0004 RETURN CV0($value)
testStrstr3First:
; (lines=6, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_3(strstr) CV0($value) string("needle")
0002 OP_DATA bool(false)
0003 ASSIGN CV0($value) T1
0004 VERIFY_RETURN_TYPE CV0($value)
0005 RETURN CV0($value)
LIVE RANGES:
1: 0002 - 0003 (tmp/var)
testStrstr3Second:
; (lines=6, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_3(strstr) string("needles") CV0($value)
0002 OP_DATA bool(false)
0003 ASSIGN CV0($value) T1
0004 VERIFY_RETURN_TYPE CV0($value)
0005 RETURN CV0($value)
LIVE RANGES:
1: 0002 - 0003 (tmp/var)
testStrstr3Third:
; (lines=6, args=1, vars=1, tmps=%d)
; (after optimizer)
; %s
0000 CV0($value) = RECV 1
0001 T1 = FRAMELESS_ICALL_3(strstr) string("needles") string("needle")
0002 OP_DATA CV0($value)
0003 CV0($value) = QM_ASSIGN T1
0004 VERIFY_RETURN_TYPE CV0($value)
0005 RETURN CV0($value)
LIVE RANGES:
1: 0002 - 0003 (tmp/var)
string(3) "boo"
int(5)
int(5)
int(6)
string(7) "needles"
string(7) "needles"
string(7) "needles"