Skip to content

Commit aace896

Browse files
committed
Optimizer: Optimize T = BOOL(X) + TYPE_CHECK(T, true) to just BOOL
Resolves php#18411
1 parent 6048afe commit aace896

File tree

3 files changed

+98
-27
lines changed

3 files changed

+98
-27
lines changed

Zend/Optimizer/block_pass.c

+30
Original file line numberDiff line numberDiff line change
@@ -482,12 +482,42 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
482482
opline->extended_value = (1 << Z_TYPE(ZEND_OP1_LITERAL(opline)));
483483
COPY_NODE(opline->op1, opline->op2);
484484
SET_UNUSED(opline->op2);
485+
goto optimize_type_check;
485486
}
486487
if (opline->op2_type == IS_CONST &&
487488
(Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_TRUE && Z_TYPE(ZEND_OP2_LITERAL(opline)) >= IS_NULL)) {
488489
opline->opcode = ZEND_TYPE_CHECK;
489490
opline->extended_value = (1 << Z_TYPE(ZEND_OP2_LITERAL(opline)));
490491
SET_UNUSED(opline->op2);
492+
goto optimize_type_check;
493+
}
494+
break;
495+
case ZEND_TYPE_CHECK:
496+
optimize_type_check:
497+
if (opline->extended_value == (1 << IS_TRUE) || opline->extended_value == (1 << IS_FALSE)) {
498+
if (opline->op1_type == IS_TMP_VAR &&
499+
!zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) {
500+
src = VAR_SOURCE(opline->op1);
501+
502+
if (src) {
503+
switch (src->opcode) {
504+
case ZEND_BOOL:
505+
case ZEND_BOOL_NOT:
506+
/* T = BOOL(X) + TYPE_CHECK(T, true) -> BOOL(X), NOP */
507+
/* T = BOOL(X) + TYPE_CHECK(T, false) -> BOOL_NOT(X), NOP */
508+
/* T = BOOL_NOT(X) + IS_IDENTICAL(T, true) -> BOOL_NOT(X), NOP */
509+
/* T = BOOL_NOT(X) + IS_IDENTICAL(T, false) -> BOOL(X), NOP */
510+
src->opcode =
511+
((src->opcode == ZEND_BOOL) == (opline->extended_value == (1 << IS_TRUE))) ?
512+
ZEND_BOOL : ZEND_BOOL_NOT;
513+
COPY_NODE(src->result, opline->result);
514+
SET_VAR_SOURCE(src);
515+
MAKE_NOP(opline);
516+
++(*opt_count);
517+
break;
518+
}
519+
}
520+
}
491521
}
492522
break;
493523

ext/opcache/tests/match/005.phpt

+19-27
Original file line numberDiff line numberDiff line change
@@ -23,35 +23,27 @@ var_dump($result);
2323
?>
2424
--EXPECTF--
2525
$_main:
26-
; (lines=28, args=0, vars=2, tmps=3)
26+
; (lines=20, args=0, vars=2, tmps=1)
2727
; (after optimizer)
2828
; %s
2929
0000 ASSIGN CV0($text) string("Bienvenue chez nous")
3030
0001 T2 = FRAMELESS_ICALL_2(preg_match) string("/Welcome/") CV0($text)
31-
0002 T3 = BOOL T2
32-
0003 T2 = TYPE_CHECK (true) T3
33-
0004 JMPNZ T2 0018
34-
0005 T4 = FRAMELESS_ICALL_2(preg_match) string("/Hello/") CV0($text)
35-
0006 T3 = BOOL T4
36-
0007 T2 = TYPE_CHECK (true) T3
37-
0008 JMPNZ T2 0018
38-
0009 T4 = FRAMELESS_ICALL_2(preg_match) string("/Bienvenue/") CV0($text)
39-
0010 T3 = BOOL T4
40-
0011 T2 = TYPE_CHECK (true) T3
41-
0012 JMPNZ T2 0020
42-
0013 T4 = FRAMELESS_ICALL_2(preg_match) string("/Bonjour/") CV0($text)
43-
0014 T3 = BOOL T4
44-
0015 T2 = TYPE_CHECK (true) T3
45-
0016 JMPNZ T2 0020
46-
0017 JMP 0022
47-
0018 T2 = QM_ASSIGN string("en")
48-
0019 JMP 0023
49-
0020 T2 = QM_ASSIGN string("fr")
50-
0021 JMP 0023
51-
0022 T2 = QM_ASSIGN string("other")
52-
0023 ASSIGN CV1($result) T2
53-
0024 INIT_FCALL 1 %d string("var_dump")
54-
0025 SEND_VAR CV1($result) 1
55-
0026 DO_ICALL
56-
0027 RETURN int(1)
31+
0002 JMPNZ T2 0010
32+
0003 T2 = FRAMELESS_ICALL_2(preg_match) string("/Hello/") CV0($text)
33+
0004 JMPNZ T2 0010
34+
0005 T2 = FRAMELESS_ICALL_2(preg_match) string("/Bienvenue/") CV0($text)
35+
0006 JMPNZ T2 0012
36+
0007 T2 = FRAMELESS_ICALL_2(preg_match) string("/Bonjour/") CV0($text)
37+
0008 JMPNZ T2 0012
38+
0009 JMP 0014
39+
0010 T2 = QM_ASSIGN string("en")
40+
0011 JMP 0015
41+
0012 T2 = QM_ASSIGN string("fr")
42+
0013 JMP 0015
43+
0014 T2 = QM_ASSIGN string("other")
44+
0015 ASSIGN CV1($result) T2
45+
0016 INIT_FCALL 1 %d string("var_dump")
46+
0017 SEND_VAR CV1($result) 1
47+
0018 DO_ICALL
48+
0019 RETURN int(1)
5749
string(2) "fr"
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
Block Pass 007: BOOL + TYPE_CHECK
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.opt_debug_level=0x20000
8+
--EXTENSIONS--
9+
opcache
10+
--FILE--
11+
<?php
12+
$f = random_int(1, 2);
13+
14+
var_dump(!$f === true);
15+
var_dump(!$f === false);
16+
var_dump(!!$f === true);
17+
var_dump(!!$f === false);
18+
?>
19+
--EXPECTF--
20+
$_main:
21+
; (lines=22, args=0, vars=1, tmps=1)
22+
; (after optimizer)
23+
; %s
24+
0000 INIT_FCALL 2 %d string("random_int")
25+
0001 SEND_VAL int(1) 1
26+
0002 SEND_VAL int(2) 2
27+
0003 V1 = DO_ICALL
28+
0004 ASSIGN CV0($f) V1
29+
0005 INIT_FCALL 1 %d string("var_dump")
30+
0006 T1 = BOOL_NOT CV0($f)
31+
0007 SEND_VAL T1 1
32+
0008 DO_ICALL
33+
0009 INIT_FCALL 1 %d string("var_dump")
34+
0010 T1 = BOOL CV0($f)
35+
0011 SEND_VAL T1 1
36+
0012 DO_ICALL
37+
0013 INIT_FCALL 1 %d string("var_dump")
38+
0014 T1 = BOOL CV0($f)
39+
0015 SEND_VAL T1 1
40+
0016 DO_ICALL
41+
0017 INIT_FCALL 1 %d string("var_dump")
42+
0018 T1 = BOOL_NOT CV0($f)
43+
0019 SEND_VAL T1 1
44+
0020 DO_ICALL
45+
0021 RETURN int(1)
46+
bool(false)
47+
bool(true)
48+
bool(true)
49+
bool(false)

0 commit comments

Comments
 (0)