@@ -805,7 +805,12 @@ static bool zend_jit_trace_is_false_loop(const zend_op_array *op_array, const ze
805
805
}
806
806
}
807
807
808
- static int zend_jit_trace_copy_ssa_var_info (const zend_op_array * op_array , const zend_ssa * ssa , const zend_op * * tssa_opcodes , zend_ssa * tssa , int ssa_var )
808
+ static int zend_jit_trace_copy_ssa_var_info (const zend_op_array * op_array ,
809
+ const zend_ssa * ssa ,
810
+ const zend_op * * tssa_opcodes ,
811
+ zend_ssa * tssa ,
812
+ int ssa_var ,
813
+ const zend_op * opline )
809
814
{
810
815
int var , use , def , src ;
811
816
zend_ssa_op * op ;
@@ -913,6 +918,54 @@ static int zend_jit_trace_copy_ssa_var_info(const zend_op_array *op_array, const
913
918
assert (0 );
914
919
return 0 ;
915
920
}
921
+ if (opline ) {
922
+ /* Try to find a difinition in SSA dominators tree */
923
+ var = tssa -> vars [ssa_var ].var ;
924
+ uint32_t op_num = opline - op_array -> opcodes ;
925
+ uint32_t b = ssa -> cfg .map [op_num ];
926
+ zend_basic_block * bb = ssa -> cfg .blocks + b ;
927
+ zend_ssa_phi * pi , * phi ;
928
+
929
+ while (1 ) {
930
+ while (op_num > bb -> start ) {
931
+ op_num -- ;
932
+ op = ssa -> ops + op_num ;
933
+ if (op -> result_def >= 0 && ssa -> vars [op -> result_def ].var == var ) {
934
+ src = op -> result_def ;
935
+ goto copy_info ;
936
+ } else if (op -> op2_def >= 0 && ssa -> vars [op -> op2_def ].var == var ) {
937
+ src = op -> op2_def ;
938
+ goto copy_info ;
939
+ } else if (op -> op1_def >= 0 && ssa -> vars [op -> op1_def ].var == var ) {
940
+ src = op -> op1_def ;
941
+ goto copy_info ;
942
+ }
943
+ }
944
+ phi = ssa -> blocks [b ].phis ;
945
+ pi = NULL ;
946
+ while (phi ) {
947
+ if (ssa -> vars [phi -> ssa_var ].var == var ) {
948
+ if (phi -> pi >= 0 ) {
949
+ pi = phi ;
950
+ } else {
951
+ src = phi -> ssa_var ;
952
+ goto copy_info ;
953
+ }
954
+ }
955
+ phi = phi -> next ;
956
+ }
957
+ if (pi ) {
958
+ src = pi -> ssa_var ;
959
+ goto copy_info ;
960
+ }
961
+ if (bb -> idom < 0 ) {
962
+ break ;
963
+ }
964
+ b = bb -> idom ;
965
+ bb = ssa -> cfg .blocks + b ;
966
+ op_num = bb -> start + bb -> len ;
967
+ }
968
+ }
916
969
goto copy_info ;
917
970
}
918
971
return 0 ;
@@ -1586,6 +1639,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1586
1639
1587
1640
/* 4. Type inference */
1588
1641
op_array = trace_buffer -> op_array ;
1642
+ opline = trace_buffer [1 ].opline ;
1589
1643
jit_extension =
1590
1644
(zend_jit_op_array_trace_extension * )ZEND_FUNC_INFO (op_array );
1591
1645
ssa = & jit_extension -> func_info .ssa ;
@@ -1597,7 +1651,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1597
1651
while (i < op_array -> last_var ) {
1598
1652
if (i < op_array -> num_args ) {
1599
1653
if (ssa -> var_info
1600
- && zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , i )) {
1654
+ && zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , i , NULL )) {
1601
1655
/* pass */
1602
1656
} else {
1603
1657
if (ssa -> vars ) {
@@ -1652,7 +1706,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1652
1706
}
1653
1707
while (i < op_array -> last_var + op_array -> T ) {
1654
1708
if (!ssa -> var_info
1655
- || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , i )) {
1709
+ || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , i , opline )) {
1656
1710
if (ssa -> vars && i < ssa -> vars_count ) {
1657
1711
ssa_vars [i ].alias = ssa -> vars [i ].alias ;
1658
1712
} else {
@@ -1690,7 +1744,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1690
1744
1691
1745
while (phi ) {
1692
1746
if (!ssa -> var_info
1693
- || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , phi -> ssa_var )) {
1747
+ || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , phi -> ssa_var , NULL )) {
1694
1748
ssa_vars [phi -> ssa_var ].alias = ssa_vars [phi -> sources [0 ]].alias ;
1695
1749
ssa_var_info [phi -> ssa_var ].type = ssa_var_info [phi -> sources [0 ]].type ;
1696
1750
}
@@ -2409,7 +2463,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2409
2463
ssa_vars [v ].var = i ;
2410
2464
if (i < op_array -> num_args ) {
2411
2465
if (ssa -> var_info
2412
- && zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v )) {
2466
+ && zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v , NULL )) {
2413
2467
/* pass */
2414
2468
} else {
2415
2469
ssa_vars [v ].alias = zend_jit_var_may_alias (op_array , ssa , i );
@@ -2460,7 +2514,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2460
2514
while (i < op_array -> last_var ) {
2461
2515
ssa_vars [v ].var = i ;
2462
2516
if (!ssa -> var_info
2463
- || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v )) {
2517
+ || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v , NULL )) {
2464
2518
ssa_var_info [v ].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2465
2519
}
2466
2520
i ++ ;
@@ -2469,7 +2523,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2469
2523
while (i < op_array -> last_var + op_array -> T ) {
2470
2524
ssa_vars [v ].var = i ;
2471
2525
if (!ssa -> var_info
2472
- || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v )) {
2526
+ || !zend_jit_trace_copy_ssa_var_info (op_array , ssa , ssa_opcodes , tssa , v , NULL )) {
2473
2527
ssa_var_info [v ].type = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2474
2528
}
2475
2529
i ++ ;
@@ -3308,13 +3362,16 @@ static void zend_jit_trace_cleanup_stack(zend_jit_ctx *jit, zend_jit_trace_stack
3308
3362
CLEAR_STACK_REF (stack , EX_VAR_TO_NUM (opline -> op1 .var ));
3309
3363
}
3310
3364
if (ssa_op -> op2_use >= 0
3365
+ && ssa_op -> op2_use != ssa_op -> op1_use
3311
3366
&& jit -> ra [ssa_op -> op2_use ].ref
3312
3367
&& (jit -> ra [ssa_op -> op2_use ].flags & ZREG_LAST_USE )
3313
3368
&& (ssa_op -> op2_use_chain == -1
3314
3369
|| zend_ssa_is_no_val_use (ssa_opcodes [ssa_op -> op2_use_chain ], ssa -> ops + ssa_op -> op2_use_chain , ssa_op -> op2_use ))) {
3315
3370
CLEAR_STACK_REF (stack , EX_VAR_TO_NUM (opline -> op2 .var ));
3316
3371
}
3317
3372
if (ssa_op -> result_use >= 0
3373
+ && ssa_op -> result_use != ssa_op -> op1_use
3374
+ && ssa_op -> result_use != ssa_op -> op2_use
3318
3375
&& jit -> ra [ssa_op -> result_use ].ref
3319
3376
&& (jit -> ra [ssa_op -> result_use ].flags & ZREG_LAST_USE )
3320
3377
&& (ssa_op -> res_use_chain == -1
@@ -4143,8 +4200,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4143
4200
} else if (i < parent_vars_count
4144
4201
&& STACK_TYPE (parent_stack , i ) != IS_UNKNOWN ) {
4145
4202
/* This must be already handled by trace type inference */
4146
- ZEND_UNREACHABLE ( );
4147
- // SET_STACK_TYPE(stack, i, STACK_TYPE(parent_stack, i));
4203
+ ZEND_ASSERT ( ssa -> vars [ i ]. use_chain < 0 && ! ssa -> vars [ i ]. phi_use_chain );
4204
+ SET_STACK_TYPE (stack , i , STACK_TYPE (parent_stack , i ), 1 );
4148
4205
} else if ((info & MAY_BE_GUARD ) != 0
4149
4206
&& (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
4150
4207
|| trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
0 commit comments