@@ -1754,28 +1754,28 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
17541754 uint8_t * flags ;
17551755 const zend_op_array * * vars_op_array ;
17561756 zend_lifetime_interval * * intervals , * list , * ival ;
1757- zend_lifetime_interval * hints = NULL ;
17581757 void * checkpoint ;
17591758 zend_jit_trace_stack_frame * frame ;
17601759 zend_jit_trace_stack * stack ;
17611760 uint32_t parent_vars_count = parent_trace ?
17621761 zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_size : 0 ;
1762+ zend_jit_trace_stack * parent_stack = parent_trace ?
1763+ zend_jit_traces [parent_trace ].stack_map +
1764+ zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_offset : NULL ;
17631765 ALLOCA_FLAG (use_heap );
17641766
17651767 ZEND_ASSERT (ssa -> var_info != NULL );
17661768
17671769 start = do_alloca (sizeof (int ) * ssa -> vars_count * 2 +
17681770 ZEND_MM_ALIGNED_SIZE (sizeof (uint8_t ) * ssa -> vars_count ) +
1769- ZEND_MM_ALIGNED_SIZE (sizeof (zend_op_array * ) * ssa -> vars_count ) +
1770- ZEND_MM_ALIGNED_SIZE (sizeof (zend_lifetime_interval ) * parent_vars_count ),
1771+ ZEND_MM_ALIGNED_SIZE (sizeof (zend_op_array * ) * ssa -> vars_count ),
17711772 use_heap );
17721773 if (!start ) {
17731774 return NULL ;
17741775 }
17751776 end = start + ssa -> vars_count ;
17761777 flags = (uint8_t * )(end + ssa -> vars_count );
17771778 vars_op_array = (const zend_op_array * * )(flags + ZEND_MM_ALIGNED_SIZE (sizeof (uint8_t ) * ssa -> vars_count ));
1778- hints = (zend_lifetime_interval * )((char * )vars_op_array + ZEND_MM_ALIGNED_SIZE (sizeof (zend_op_array * ) * ssa -> vars_count ));
17791779
17801780 memset (start , -1 , sizeof (int ) * ssa -> vars_count * 2 );
17811781 memset (flags , 0 , sizeof (uint8_t ) * ssa -> vars_count );
@@ -1802,8 +1802,13 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
18021802 if ((ssa -> vars [i ].use_chain >= 0 /*|| ssa->vars[i].phi_use_chain*/ )
18031803 && zend_jit_var_supports_reg (ssa , i )) {
18041804 start [i ] = 0 ;
1805- flags [i ] = ZREG_LOAD ;
1806- count ++ ;
1805+ if (i < parent_vars_count && STACK_REG (parent_stack , i ) != ZREG_NONE ) {
1806+ /* We will try to reuse register from parent trace */
1807+ count += 2 ;
1808+ } else {
1809+ flags [i ] = ZREG_LOAD ;
1810+ count ++ ;
1811+ }
18071812 }
18081813 i ++ ;
18091814 }
@@ -2086,10 +2091,8 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
20862091 memset (intervals , 0 , sizeof (zend_lifetime_interval * ) * ssa -> vars_count );
20872092 list = zend_arena_alloc (& CG (arena ), sizeof (zend_lifetime_interval ) * count );
20882093 j = 0 ;
2089- //fprintf(stderr, "(%d)\n", count);
20902094 for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
20912095 if (start [i ] >= 0 && end [i ] >= 0 ) {
2092- //fprintf(stderr, "#%d: %d..%d\n", i, start[i], end[i]);
20932096 ZEND_ASSERT (j < count );
20942097 intervals [i ] = & list [j ];
20952098 list [j ].ssa_var = i ;
@@ -2115,25 +2118,27 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
21152118
21162119 /* Add hints */
21172120 if (parent_vars_count ) {
2118- zend_jit_trace_stack * parent_stack =
2119- zend_jit_traces [parent_trace ].stack_map +
2120- zend_jit_traces [parent_trace ].exit_info [exit_num ].stack_offset ;
2121-
2122- j = trace_buffer -> op_array -> last_var ;
2121+ i = trace_buffer -> op_array -> last_var ;
21232122 if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2124- j += trace_buffer -> op_array -> T ;
2123+ i += trace_buffer -> op_array -> T ;
21252124 }
2126- if (parent_vars_count < (uint32_t )j ) {
2127- j = parent_vars_count ;
2125+ if ((uint32_t )i > parent_vars_count ) {
2126+ i = parent_vars_count ;
21282127 }
2129- if (j ) {
2130- memset (hints , 0 , sizeof (zend_lifetime_interval ) * j );
2131- for (i = 0 ; i < j ; i ++ ) {
2132- if (intervals [i ] && STACK_REG (parent_stack , i ) != ZREG_NONE ) {
2133- intervals [i ]-> hint = hints + i ;
2134- hints [i ].ssa_var = - 1 ;
2135- hints [i ].reg = STACK_REG (parent_stack , i );
2136- }
2128+ while (i > 0 ) {
2129+ i -- ;
2130+ if (intervals [i ] && STACK_REG (parent_stack , i ) != ZREG_NONE ) {
2131+ list [j ].ssa_var = - 1 ;
2132+ list [j ].reg = STACK_REG (parent_stack , i );
2133+ list [j ].flags = 0 ;
2134+ list [j ].range .start = -1 ;
2135+ list [j ].range .end = -1 ;
2136+ list [j ].range .next = NULL ;
2137+ list [j ].hint = NULL ;
2138+ list [j ].used_as_hint = NULL ;
2139+ list [j ].list_next = NULL ;
2140+ intervals [i ]-> hint = & list [j ];
2141+ j ++ ;
21372142 }
21382143 }
21392144 }
@@ -2246,6 +2251,23 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
22462251 return NULL ;
22472252 }
22482253
2254+ /* Add LOAD flag to registers that can't reuse register from parent trace */
2255+ if (parent_vars_count ) {
2256+ i = trace_buffer -> op_array -> last_var ;
2257+ if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2258+ i += trace_buffer -> op_array -> T ;
2259+ }
2260+ if ((uint32_t )i > parent_vars_count ) {
2261+ i = parent_vars_count ;
2262+ }
2263+ while (i > 0 ) {
2264+ i -- ;
2265+ if (intervals [i ] && intervals [i ]-> reg != STACK_REG (parent_stack , i )) {
2266+ intervals [i ]-> flags |= ZREG_LOAD ;
2267+ }
2268+ }
2269+ }
2270+
22492271 /* SSA resolution */
22502272 if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
22512273 zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
@@ -2259,7 +2281,12 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
22592281 intervals [def ]-> flags |= ZREG_LOAD ;
22602282 } else if (intervals [def ]-> reg != intervals [use ]-> reg ) {
22612283 intervals [def ]-> flags |= ZREG_LOAD ;
2262- intervals [use ]-> flags |= ZREG_STORE ;
2284+ if (ssa -> vars [use ].use_chain >= 0 ) {
2285+ intervals [use ]-> flags |= ZREG_STORE ;
2286+ } else {
2287+ intervals [use ] = NULL ;
2288+ count -- ;
2289+ }
22632290 } else {
22642291 use = phi -> sources [0 ];
22652292 ZEND_ASSERT (!intervals [use ]);
@@ -2275,57 +2302,17 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
22752302 intervals [use ]-> list_next = NULL ;
22762303 }
22772304 } else if (intervals [use ] && !ssa -> vars [phi -> ssa_var ].no_val ) {
2278- intervals [use ]-> flags |= ZREG_STORE ;
2279- }
2280- phi = phi -> next ;
2281- }
2282- }
2283-
2284- if (parent_vars_count ) {
2285- /* Variables that reuse registers from parent trace don't have to be loaded */
2286- j = op_array -> last_var ;
2287- if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2288- j += op_array -> T ;
2289- }
2290- if (parent_vars_count < (uint32_t )j ) {
2291- j = parent_vars_count ;
2292- }
2293- for (i = 0 ; i < j ; i ++ ) {
2294- if (intervals [i ]
2295- && intervals [i ]-> hint
2296- && intervals [i ]-> reg == intervals [i ]-> hint -> reg
2297- && intervals [i ]-> hint -> ssa_var == -1 ) {
2298- intervals [i ]-> flags &= ~ZREG_LOAD ;
2299- }
2300- }
2301- }
2302-
2303- /* Remove useless register allocation */
2304- for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
2305- if (intervals [i ] &&
2306- ((intervals [i ]-> flags & ZREG_LOAD ) ||
2307- ((intervals [i ]-> flags & ZREG_STORE ) && ssa -> vars [i ].definition >= 0 )) &&
2308- ssa -> vars [i ].use_chain < 0 ) {
2309- zend_bool may_remove = 1 ;
2310- zend_ssa_phi * phi = ssa -> vars [i ].phi_use_chain ;
2311-
2312- while (phi ) {
2313- if (intervals [phi -> ssa_var ] &&
2314- !(intervals [phi -> ssa_var ]-> flags & ZREG_LOAD )) {
2315- may_remove = 0 ;
2316- break ;
2305+ if (ssa -> vars [use ].use_chain >= 0 ) {
2306+ intervals [use ]-> flags |= ZREG_STORE ;
2307+ } else {
2308+ intervals [use ] = NULL ;
2309+ count -- ;
23172310 }
2318- phi = zend_ssa_next_use_phi (ssa , i , phi );
2319- }
2320- if (may_remove ) {
2321- intervals [i ] = NULL ;
2322- count -- ;
23232311 }
2312+ phi = phi -> next ;
23242313 }
23252314 }
23262315
2327- // Remove intervals used once ????
2328-
23292316 if (!count ) {
23302317 zend_arena_release (& CG (arena ), checkpoint );
23312318 return NULL ;
0 commit comments