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