@@ -403,7 +403,136 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
403
403
goto optimize_bool ;
404
404
}
405
405
break ;
406
-
406
+ case ZEND_TYPE_CHECK :
407
+ /* Optimize checks such as e === true, e !== true, e !== false, etc. when e is from an opcode that only results in booleans */
408
+ /* If opcache combines ZEND_TYPE_CHECKs into is_true_or_string($x) in the future, this is designed to properly handle that. */
409
+ if ((opline -> extended_value & MAY_BE_FALSE ) ^ (opline -> extended_value & MAY_BE_TRUE )) {
410
+ if (opline -> op1_type == IS_TMP_VAR &&
411
+ !zend_bitset_in (used_ext , VAR_NUM (opline -> op1 .var ))) {
412
+ src = VAR_SOURCE (opline -> op1 );
413
+ if (src ) {
414
+ switch (src -> opcode ) {
415
+ case ZEND_BOOL_NOT :
416
+ VAR_SOURCE (opline -> op1 ) = NULL ;
417
+ COPY_NODE (opline -> op1 , src -> op1 );
418
+ opline -> opcode = (opline -> extended_value & MAY_BE_FALSE ) ? ZEND_BOOL : ZEND_BOOL_NOT ;
419
+ MAKE_NOP (src );
420
+ ++ (* opt_count );
421
+ goto optimize_bool ;
422
+ case ZEND_BOOL :
423
+ VAR_SOURCE (opline -> op1 ) = NULL ;
424
+ COPY_NODE (opline -> op1 , src -> op1 );
425
+ opline -> opcode = (opline -> extended_value & MAY_BE_FALSE ) ? ZEND_BOOL_NOT : ZEND_BOOL ;
426
+ MAKE_NOP (src );
427
+ ++ (* opt_count );
428
+ goto optimize_bool ;
429
+ case ZEND_IS_EQUAL :
430
+ if (opline -> extended_value & MAY_BE_FALSE ) {
431
+ src -> opcode = ZEND_IS_NOT_EQUAL ;
432
+ }
433
+ COPY_NODE (src -> result , opline -> result );
434
+ SET_VAR_SOURCE (src );
435
+ MAKE_NOP (opline );
436
+ ++ (* opt_count );
437
+ break ;
438
+ case ZEND_IS_NOT_EQUAL :
439
+ if (opline -> extended_value & MAY_BE_FALSE ) {
440
+ src -> opcode = ZEND_IS_EQUAL ;
441
+ }
442
+ COPY_NODE (src -> result , opline -> result );
443
+ SET_VAR_SOURCE (src );
444
+ MAKE_NOP (opline );
445
+ ++ (* opt_count );
446
+ break ;
447
+ case ZEND_IS_IDENTICAL :
448
+ if (opline -> extended_value & MAY_BE_FALSE ) {
449
+ src -> opcode = ZEND_IS_NOT_IDENTICAL ;
450
+ }
451
+ COPY_NODE (src -> result , opline -> result );
452
+ SET_VAR_SOURCE (src );
453
+ MAKE_NOP (opline );
454
+ ++ (* opt_count );
455
+ break ;
456
+ case ZEND_IS_NOT_IDENTICAL :
457
+ if (opline -> extended_value & MAY_BE_FALSE ) {
458
+ src -> opcode = ZEND_IS_IDENTICAL ;
459
+ }
460
+ COPY_NODE (src -> result , opline -> result );
461
+ SET_VAR_SOURCE (src );
462
+ MAKE_NOP (opline );
463
+ ++ (* opt_count );
464
+ break ;
465
+ case ZEND_TYPE_CHECK :
466
+ if (opline -> extended_value & MAY_BE_FALSE ) {
467
+ if (src -> extended_value == MAY_BE_RESOURCE || src -> extended_value == (MAY_BE_ANY - MAY_BE_RESOURCE )) {
468
+ /* is_resource() is a special case - it returns false if the resource is closed. Don't convert to/from it. */
469
+ break ;
470
+ }
471
+ src -> extended_value = MAY_BE_ANY - src -> extended_value ;
472
+ }
473
+ COPY_NODE (src -> result , opline -> result );
474
+ SET_VAR_SOURCE (src );
475
+ MAKE_NOP (opline );
476
+ ++ (* opt_count );
477
+ break ;
478
+ case ZEND_IS_SMALLER :
479
+ if (opline -> extended_value & MAY_BE_FALSE ) {
480
+ zend_uchar tmp_type ;
481
+ uint32_t tmp ;
482
+
483
+ src -> opcode = ZEND_IS_SMALLER_OR_EQUAL ;
484
+ tmp_type = src -> op1_type ;
485
+ src -> op1_type = src -> op2_type ;
486
+ src -> op2_type = tmp_type ;
487
+ tmp = src -> op1 .num ;
488
+ src -> op1 .num = src -> op2 .num ;
489
+ src -> op2 .num = tmp ;
490
+ }
491
+ COPY_NODE (src -> result , opline -> result );
492
+ SET_VAR_SOURCE (src );
493
+ MAKE_NOP (opline );
494
+ ++ (* opt_count );
495
+ break ;
496
+ case ZEND_IS_SMALLER_OR_EQUAL :
497
+ if (opline -> extended_value & MAY_BE_FALSE ) {
498
+ zend_uchar tmp_type ;
499
+ uint32_t tmp ;
500
+
501
+ src -> opcode = ZEND_IS_SMALLER ;
502
+ tmp_type = src -> op1_type ;
503
+ src -> op1_type = src -> op2_type ;
504
+ src -> op2_type = tmp_type ;
505
+ tmp = src -> op1 .num ;
506
+ src -> op1 .num = src -> op2 .num ;
507
+ src -> op2 .num = tmp ;
508
+ }
509
+ COPY_NODE (src -> result , opline -> result );
510
+ SET_VAR_SOURCE (src );
511
+ MAKE_NOP (opline );
512
+ ++ (* opt_count );
513
+ break ;
514
+ case ZEND_ISSET_ISEMPTY_CV :
515
+ case ZEND_ISSET_ISEMPTY_VAR :
516
+ case ZEND_ISSET_ISEMPTY_DIM_OBJ :
517
+ case ZEND_ISSET_ISEMPTY_PROP_OBJ :
518
+ case ZEND_ISSET_ISEMPTY_STATIC_PROP :
519
+ case ZEND_INSTANCEOF :
520
+ case ZEND_DEFINED :
521
+ case ZEND_IN_ARRAY :
522
+ case ZEND_ARRAY_KEY_EXISTS :
523
+ if (opline -> extended_value & MAY_BE_FALSE ) {
524
+ break ;
525
+ }
526
+ COPY_NODE (src -> result , opline -> result );
527
+ SET_VAR_SOURCE (src );
528
+ MAKE_NOP (opline );
529
+ ++ (* opt_count );
530
+ break ;
531
+ }
532
+ }
533
+ }
534
+ }
535
+ break ;
407
536
case ZEND_BOOL :
408
537
case ZEND_BOOL_NOT :
409
538
optimize_bool :
0 commit comments