@@ -3431,6 +3431,89 @@ static void zend_jit_trace_update_condition_ranges(const zend_op *opline, const
3431
3431
}
3432
3432
}
3433
3433
3434
+ static zend_bool zend_jit_may_skip_comparison (const zend_op * opline , const zend_ssa_op * ssa_op , const zend_ssa * ssa , const zend_op * * ssa_opcodes )
3435
+ {
3436
+ zend_uchar prev_opcode ;
3437
+
3438
+ if (opline -> op1_type == IS_CONST
3439
+ && Z_TYPE_P (RT_CONSTANT (opline , opline -> op1 )) == IS_LONG
3440
+ && Z_LVAL_P (RT_CONSTANT (opline , opline -> op1 )) == 0 ) {
3441
+ if (ssa_op -> op2_use >= 0 ) {
3442
+ if ((ssa_op - 1 )-> op1_def == ssa_op -> op2_use ) {
3443
+ prev_opcode = ssa_opcodes [(ssa_op - ssa -> ops ) - 1 ]-> opcode ;
3444
+ if (prev_opcode == ZEND_PRE_INC
3445
+ || prev_opcode == ZEND_PRE_DEC
3446
+ || prev_opcode == ZEND_POST_INC
3447
+ || prev_opcode == ZEND_POST_DEC ) {
3448
+ return 1 ;
3449
+ }
3450
+ } else if ((ssa_op - 1 )-> result_def == ssa_op -> op2_use ) {
3451
+ prev_opcode = ssa_opcodes [(ssa_op - ssa -> ops ) - 1 ]-> opcode ;
3452
+ if (prev_opcode == ZEND_ADD
3453
+ || prev_opcode == ZEND_SUB ) {
3454
+ return 1 ;
3455
+ }
3456
+ }
3457
+ }
3458
+ } else if (opline -> op2_type == IS_CONST
3459
+ && Z_TYPE_P (RT_CONSTANT (opline , opline -> op2 )) == IS_LONG
3460
+ && Z_LVAL_P (RT_CONSTANT (opline , opline -> op2 )) == 0 ) {
3461
+ if (ssa_op -> op1_use >= 0 ) {
3462
+ if ((ssa_op - 1 )-> op1_def == ssa_op -> op1_use ) {
3463
+ prev_opcode = ssa_opcodes [(ssa_op - ssa -> ops ) - 1 ]-> opcode ;
3464
+ if (prev_opcode == ZEND_PRE_INC
3465
+ || prev_opcode == ZEND_PRE_DEC
3466
+ || prev_opcode == ZEND_POST_INC
3467
+ || prev_opcode == ZEND_POST_DEC ) {
3468
+ return 1 ;
3469
+ }
3470
+ } else if ((ssa_op - 1 )-> result_def == ssa_op -> op1_use ) {
3471
+ prev_opcode = ssa_opcodes [(ssa_op - ssa -> ops ) - 1 ]-> opcode ;
3472
+ if (prev_opcode == ZEND_ADD
3473
+ || prev_opcode == ZEND_SUB ) {
3474
+ return 1 ;
3475
+ }
3476
+ }
3477
+ }
3478
+ } else {
3479
+ const zend_ssa_op * prev_ssa_op = ssa_op - 1 ;
3480
+ prev_opcode = ssa_opcodes [prev_ssa_op - ssa -> ops ]-> opcode ;
3481
+
3482
+ if ((prev_opcode == ZEND_JMPZ || prev_opcode == ZEND_JMPNZ )
3483
+ && prev_ssa_op != ssa -> ops
3484
+ && prev_ssa_op -> op1_use >= 0
3485
+ && prev_ssa_op -> op1_use == (prev_ssa_op - 1 )-> result_def ) {
3486
+ prev_ssa_op -- ;
3487
+ prev_opcode = ssa_opcodes [prev_ssa_op - ssa -> ops ]-> opcode ;
3488
+ }
3489
+
3490
+ if (ssa_op -> op1_use == prev_ssa_op -> op1_use
3491
+ && ssa_op -> op2_use == prev_ssa_op -> op2_use ) {
3492
+ if (prev_opcode == ZEND_IS_EQUAL
3493
+ || prev_opcode == ZEND_IS_NOT_EQUAL
3494
+ || prev_opcode == ZEND_IS_SMALLER
3495
+ || prev_opcode == ZEND_IS_SMALLER_OR_EQUAL
3496
+ || prev_opcode == ZEND_CASE
3497
+ || prev_opcode == ZEND_IS_IDENTICAL
3498
+ || prev_opcode == ZEND_IS_NOT_IDENTICAL
3499
+ || prev_opcode == ZEND_CASE_STRICT ) {
3500
+ if (ssa_op -> op1_use < 0 ) {
3501
+ if (opline -> op1 .constant != ssa_opcodes [prev_ssa_op - ssa -> ops ]-> op1 .constant ) {
3502
+ return 0 ;
3503
+ }
3504
+ }
3505
+ if (ssa_op -> op2_use < 0 ) {
3506
+ if (opline -> op2 .constant != ssa_opcodes [prev_ssa_op - ssa -> ops ]-> op2 .constant ) {
3507
+ return 0 ;
3508
+ }
3509
+ }
3510
+ return 1 ;
3511
+ }
3512
+ }
3513
+ }
3514
+ return 0 ;
3515
+ }
3516
+
3434
3517
static const void * zend_jit_trace (zend_jit_trace_rec * trace_buffer , uint32_t parent_trace , uint32_t exit_num )
3435
3518
{
3436
3519
const void * handler = NULL ;
@@ -3451,6 +3534,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3451
3534
const void * exit_addr ;
3452
3535
uint32_t op1_info , op1_def_info , op2_info , res_info , res_use_info , op1_data_info ;
3453
3536
zend_bool send_result = 0 ;
3537
+ zend_bool skip_comparison ;
3454
3538
zend_jit_addr op1_addr , op1_def_addr , op2_addr , op2_def_addr , res_addr ;
3455
3539
zend_class_entry * ce ;
3456
3540
zend_bool ce_is_instanceof ;
@@ -4675,8 +4759,13 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4675
4759
case ZEND_IS_SMALLER_OR_EQUAL :
4676
4760
case ZEND_CASE :
4677
4761
op1_info = OP1_INFO ();
4678
- CHECK_OP1_TRACE_TYPE ();
4679
4762
op2_info = OP2_INFO ();
4763
+ skip_comparison =
4764
+ ssa_op != ssa -> ops &&
4765
+ (op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG &&
4766
+ (op2_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG &&
4767
+ zend_jit_may_skip_comparison (opline , ssa_op , ssa , ssa_opcodes );
4768
+ CHECK_OP1_TRACE_TYPE ();
4680
4769
CHECK_OP2_TRACE_TYPE ();
4681
4770
if ((opline -> result_type & (IS_SMART_BRANCH_JMPZ |IS_SMART_BRANCH_JMPNZ )) != 0 ) {
4682
4771
zend_bool exit_if_true = 0 ;
@@ -4697,7 +4786,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4697
4786
op2_info , OP2_RANGE (), OP2_REG_ADDR (),
4698
4787
RES_REG_ADDR (),
4699
4788
zend_may_throw (opline , ssa_op , op_array , ssa ),
4700
- smart_branch_opcode , -1 , -1 , exit_addr )) {
4789
+ smart_branch_opcode , -1 , -1 , exit_addr , skip_comparison )) {
4701
4790
goto jit_failure ;
4702
4791
}
4703
4792
zend_jit_trace_update_condition_ranges (opline , ssa_op , op_array , ssa , exit_if_true );
@@ -4709,7 +4798,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4709
4798
op2_info , OP2_RANGE (), OP2_REG_ADDR (),
4710
4799
RES_REG_ADDR (),
4711
4800
zend_may_throw (opline , ssa_op , op_array , ssa ),
4712
- smart_branch_opcode , -1 , -1 , exit_addr )) {
4801
+ smart_branch_opcode , -1 , -1 , exit_addr , skip_comparison )) {
4713
4802
goto jit_failure ;
4714
4803
}
4715
4804
}
@@ -4718,8 +4807,13 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4718
4807
case ZEND_IS_NOT_IDENTICAL :
4719
4808
case ZEND_CASE_STRICT :
4720
4809
op1_info = OP1_INFO ();
4721
- CHECK_OP1_TRACE_TYPE ();
4722
4810
op2_info = OP2_INFO ();
4811
+ skip_comparison =
4812
+ ssa_op != ssa -> ops &&
4813
+ (op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG &&
4814
+ (op2_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG &&
4815
+ zend_jit_may_skip_comparison (opline , ssa_op , ssa , ssa_opcodes );
4816
+ CHECK_OP1_TRACE_TYPE ();
4723
4817
CHECK_OP2_TRACE_TYPE ();
4724
4818
if ((opline -> result_type & (IS_SMART_BRANCH_JMPZ |IS_SMART_BRANCH_JMPNZ )) != 0 ) {
4725
4819
zend_bool exit_if_true = 0 ;
@@ -4743,7 +4837,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4743
4837
op2_info , OP2_RANGE (), OP2_REG_ADDR (),
4744
4838
RES_REG_ADDR (),
4745
4839
zend_may_throw (opline , ssa_op , op_array , ssa ),
4746
- smart_branch_opcode , -1 , -1 , exit_addr )) {
4840
+ smart_branch_opcode , -1 , -1 , exit_addr , skip_comparison )) {
4747
4841
goto jit_failure ;
4748
4842
}
4749
4843
zend_jit_trace_update_condition_ranges (opline , ssa_op , op_array , ssa , exit_if_true );
@@ -4755,7 +4849,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4755
4849
op2_info , OP2_RANGE (), OP2_REG_ADDR (),
4756
4850
RES_REG_ADDR (),
4757
4851
zend_may_throw (opline , ssa_op , op_array , ssa ),
4758
- smart_branch_opcode , -1 , -1 , exit_addr )) {
4852
+ smart_branch_opcode , -1 , -1 , exit_addr , skip_comparison )) {
4759
4853
goto jit_failure ;
4760
4854
}
4761
4855
}
0 commit comments