@@ -1738,7 +1738,7 @@ static void zend_jit_close_var(zend_jit_trace_stack *stack, uint32_t n, const ze
17381738 }
17391739}
17401740
1741- static zend_lifetime_interval * * zend_jit_trace_allocate_registers (zend_jit_trace_rec * trace_buffer , zend_ssa * ssa )
1741+ static zend_lifetime_interval * * zend_jit_trace_allocate_registers (zend_jit_trace_rec * trace_buffer , zend_ssa * ssa , uint32_t parent_trace , uint32_t exit_num )
17421742{
17431743 const zend_op * * ssa_opcodes = ((zend_tssa * )ssa )-> tssa_opcodes ;
17441744 zend_jit_trace_rec * p ;
@@ -1751,22 +1751,28 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
17511751 uint8_t * flags ;
17521752 const zend_op_array * * vars_op_array ;
17531753 zend_lifetime_interval * * intervals , * list , * ival ;
1754+ zend_lifetime_interval * hints = NULL ;
17541755 void * checkpoint ;
17551756 zend_jit_trace_stack_frame * frame ;
17561757 zend_jit_trace_stack * stack ;
1758+ uint32_t parent_vars_count = parent_trace ?
1759+ zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_size : 0 ;
17571760 ALLOCA_FLAG (use_heap );
17581761
17591762 ZEND_ASSERT (ssa -> var_info != NULL );
17601763
17611764 start = do_alloca (sizeof (int ) * ssa -> vars_count * 2 +
17621765 ZEND_MM_ALIGNED_SIZE (sizeof (uint8_t ) * ssa -> vars_count ) +
1763- sizeof (zend_op_array * ) * ssa -> vars_count , use_heap );
1766+ ZEND_MM_ALIGNED_SIZE (sizeof (zend_op_array * ) * ssa -> vars_count ) +
1767+ ZEND_MM_ALIGNED_SIZE (sizeof (zend_lifetime_interval ) * parent_vars_count ),
1768+ use_heap );
17641769 if (!start ) {
17651770 return NULL ;
17661771 }
17671772 end = start + ssa -> vars_count ;
17681773 flags = (uint8_t * )(end + ssa -> vars_count );
17691774 vars_op_array = (const zend_op_array * * )(flags + ZEND_MM_ALIGNED_SIZE (sizeof (uint8_t ) * ssa -> vars_count ));
1775+ hints = (zend_lifetime_interval * )((char * )vars_op_array + ZEND_MM_ALIGNED_SIZE (sizeof (zend_op_array * ) * ssa -> vars_count ));
17701776
17711777 memset (start , -1 , sizeof (int ) * ssa -> vars_count * 2 );
17721778 memset (flags , 0 , sizeof (uint8_t ) * ssa -> vars_count );
@@ -2105,6 +2111,30 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
21052111 start = end = NULL ;
21062112
21072113 /* Add hints */
2114+ if (parent_vars_count ) {
2115+ zend_jit_trace_stack * parent_stack =
2116+ zend_jit_traces [parent_trace ].stack_map +
2117+ zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_offset ;
2118+
2119+ j = trace_buffer -> op_array -> last_var ;
2120+ if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2121+ j += trace_buffer -> op_array -> T ;
2122+ }
2123+ if (parent_vars_count < (uint32_t )j ) {
2124+ j = parent_vars_count ;
2125+ }
2126+ if (j ) {
2127+ memset (hints , 0 , sizeof (zend_lifetime_interval ) * j );
2128+ for (i = 0 ; i < j ; i ++ ) {
2129+ if (intervals [i ] && STACK_REG (parent_stack , i ) != ZREG_NONE ) {
2130+ intervals [i ]-> hint = hints + i ;
2131+ hints [i ].ssa_var = - 1 ;
2132+ hints [i ].reg = STACK_REG (parent_stack , i );
2133+ }
2134+ }
2135+ }
2136+ }
2137+
21082138 if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
21092139 zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
21102140
@@ -2241,6 +2271,25 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
22412271 }
22422272 }
22432273
2274+ if (parent_vars_count ) {
2275+ /* Variables that reuse registers from parent trace don't have to be loaded */
2276+ j = op_array -> last_var ;
2277+ if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2278+ j += op_array -> T ;
2279+ }
2280+ if (parent_vars_count < (uint32_t )j ) {
2281+ j = parent_vars_count ;
2282+ }
2283+ for (i = 0 ; i < j ; i ++ ) {
2284+ if (intervals [i ]
2285+ && intervals [i ]-> hint
2286+ && intervals [i ]-> reg == intervals [i ]-> hint -> reg
2287+ && intervals [i ]-> hint -> ssa_var == -1 ) {
2288+ intervals [i ]-> flags &= ~ZREG_LOAD ;
2289+ }
2290+ }
2291+ }
2292+
22442293 /* Remove useless register allocation */
22452294 for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
22462295 if (intervals [i ] &&
@@ -2333,7 +2382,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
23332382
23342383 /* Register allocation */
23352384 if (zend_jit_reg_alloc && zend_jit_level >= ZEND_JIT_LEVEL_INLINE ) {
2336- ra = zend_jit_trace_allocate_registers (trace_buffer , ssa );
2385+ ra = zend_jit_trace_allocate_registers (trace_buffer , ssa , parent_trace , exit_num );
23372386 }
23382387
23392388 p = trace_buffer ;
0 commit comments