@@ -805,7 +805,12 @@ static bool zend_jit_trace_is_false_loop(const zend_op_array *op_array, const ze
805805 }
806806}
807807
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 )
809814{
810815 int var , use , def , src ;
811816 zend_ssa_op * op ;
@@ -913,6 +918,54 @@ static int zend_jit_trace_copy_ssa_var_info(const zend_op_array *op_array, const
913918 assert (0 );
914919 return 0 ;
915920 }
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+ }
916969 goto copy_info ;
917970 }
918971 return 0 ;
@@ -1586,6 +1639,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15861639
15871640 /* 4. Type inference */
15881641 op_array = trace_buffer -> op_array ;
1642+ opline = trace_buffer [1 ].opline ;
15891643 jit_extension =
15901644 (zend_jit_op_array_trace_extension * )ZEND_FUNC_INFO (op_array );
15911645 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
15971651 while (i < op_array -> last_var ) {
15981652 if (i < op_array -> num_args ) {
15991653 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 )) {
16011655 /* pass */
16021656 } else {
16031657 if (ssa -> vars ) {
@@ -1652,7 +1706,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
16521706 }
16531707 while (i < op_array -> last_var + op_array -> T ) {
16541708 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 )) {
16561710 if (ssa -> vars && i < ssa -> vars_count ) {
16571711 ssa_vars [i ].alias = ssa -> vars [i ].alias ;
16581712 } else {
@@ -1690,7 +1744,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
16901744
16911745 while (phi ) {
16921746 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 )) {
16941748 ssa_vars [phi -> ssa_var ].alias = ssa_vars [phi -> sources [0 ]].alias ;
16951749 ssa_var_info [phi -> ssa_var ].type = ssa_var_info [phi -> sources [0 ]].type ;
16961750 }
@@ -2409,7 +2463,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
24092463 ssa_vars [v ].var = i ;
24102464 if (i < op_array -> num_args ) {
24112465 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 )) {
24132467 /* pass */
24142468 } else {
24152469 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
24602514 while (i < op_array -> last_var ) {
24612515 ssa_vars [v ].var = i ;
24622516 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 )) {
24642518 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 ;
24652519 }
24662520 i ++ ;
@@ -2469,7 +2523,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
24692523 while (i < op_array -> last_var + op_array -> T ) {
24702524 ssa_vars [v ].var = i ;
24712525 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 )) {
24732527 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 ;
24742528 }
24752529 i ++ ;
@@ -3308,13 +3362,16 @@ static void zend_jit_trace_cleanup_stack(zend_jit_ctx *jit, zend_jit_trace_stack
33083362 CLEAR_STACK_REF (stack , EX_VAR_TO_NUM (opline -> op1 .var ));
33093363 }
33103364 if (ssa_op -> op2_use >= 0
3365+ && ssa_op -> op2_use != ssa_op -> op1_use
33113366 && jit -> ra [ssa_op -> op2_use ].ref
33123367 && (jit -> ra [ssa_op -> op2_use ].flags & ZREG_LAST_USE )
33133368 && (ssa_op -> op2_use_chain == -1
33143369 || zend_ssa_is_no_val_use (ssa_opcodes [ssa_op -> op2_use_chain ], ssa -> ops + ssa_op -> op2_use_chain , ssa_op -> op2_use ))) {
33153370 CLEAR_STACK_REF (stack , EX_VAR_TO_NUM (opline -> op2 .var ));
33163371 }
33173372 if (ssa_op -> result_use >= 0
3373+ && ssa_op -> result_use != ssa_op -> op1_use
3374+ && ssa_op -> result_use != ssa_op -> op2_use
33183375 && jit -> ra [ssa_op -> result_use ].ref
33193376 && (jit -> ra [ssa_op -> result_use ].flags & ZREG_LAST_USE )
33203377 && (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
41434200 } else if (i < parent_vars_count
41444201 && STACK_TYPE (parent_stack , i ) != IS_UNKNOWN ) {
41454202 /* 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 );
41484205 } else if ((info & MAY_BE_GUARD ) != 0
41494206 && (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
41504207 || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
0 commit comments