@@ -1754,28 +1754,28 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
1754
1754
uint8_t * flags ;
1755
1755
const zend_op_array * * vars_op_array ;
1756
1756
zend_lifetime_interval * * intervals , * list , * ival ;
1757
- zend_lifetime_interval * hints = NULL ;
1758
1757
void * checkpoint ;
1759
1758
zend_jit_trace_stack_frame * frame ;
1760
1759
zend_jit_trace_stack * stack ;
1761
1760
uint32_t parent_vars_count = parent_trace ?
1762
1761
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 ;
1763
1765
ALLOCA_FLAG (use_heap );
1764
1766
1765
1767
ZEND_ASSERT (ssa -> var_info != NULL );
1766
1768
1767
1769
start = do_alloca (sizeof (int ) * ssa -> vars_count * 2 +
1768
1770
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 ),
1771
1772
use_heap );
1772
1773
if (!start ) {
1773
1774
return NULL ;
1774
1775
}
1775
1776
end = start + ssa -> vars_count ;
1776
1777
flags = (uint8_t * )(end + ssa -> vars_count );
1777
1778
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 ));
1779
1779
1780
1780
memset (start , -1 , sizeof (int ) * ssa -> vars_count * 2 );
1781
1781
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
1802
1802
if ((ssa -> vars [i ].use_chain >= 0 /*|| ssa->vars[i].phi_use_chain*/ )
1803
1803
&& zend_jit_var_supports_reg (ssa , i )) {
1804
1804
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
+ }
1807
1812
}
1808
1813
i ++ ;
1809
1814
}
@@ -2086,10 +2091,8 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2086
2091
memset (intervals , 0 , sizeof (zend_lifetime_interval * ) * ssa -> vars_count );
2087
2092
list = zend_arena_alloc (& CG (arena ), sizeof (zend_lifetime_interval ) * count );
2088
2093
j = 0 ;
2089
- //fprintf(stderr, "(%d)\n", count);
2090
2094
for (i = 0 ; i < ssa -> vars_count ; i ++ ) {
2091
2095
if (start [i ] >= 0 && end [i ] >= 0 ) {
2092
- //fprintf(stderr, "#%d: %d..%d\n", i, start[i], end[i]);
2093
2096
ZEND_ASSERT (j < count );
2094
2097
intervals [i ] = & list [j ];
2095
2098
list [j ].ssa_var = i ;
@@ -2115,25 +2118,27 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2115
2118
2116
2119
/* Add hints */
2117
2120
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 ;
2123
2122
if (trace_buffer -> start != ZEND_JIT_TRACE_START_ENTER ) {
2124
- j += trace_buffer -> op_array -> T ;
2123
+ i += trace_buffer -> op_array -> T ;
2125
2124
}
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 ;
2128
2127
}
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 ++ ;
2137
2142
}
2138
2143
}
2139
2144
}
@@ -2246,6 +2251,23 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2246
2251
return NULL ;
2247
2252
}
2248
2253
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
+
2249
2271
/* SSA resolution */
2250
2272
if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2251
2273
zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
@@ -2259,7 +2281,12 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2259
2281
intervals [def ]-> flags |= ZREG_LOAD ;
2260
2282
} else if (intervals [def ]-> reg != intervals [use ]-> reg ) {
2261
2283
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
+ }
2263
2290
} else {
2264
2291
use = phi -> sources [0 ];
2265
2292
ZEND_ASSERT (!intervals [use ]);
@@ -2275,57 +2302,17 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2275
2302
intervals [use ]-> list_next = NULL ;
2276
2303
}
2277
2304
} 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 -- ;
2317
2310
}
2318
- phi = zend_ssa_next_use_phi (ssa , i , phi );
2319
- }
2320
- if (may_remove ) {
2321
- intervals [i ] = NULL ;
2322
- count -- ;
2323
2311
}
2312
+ phi = phi -> next ;
2324
2313
}
2325
2314
}
2326
2315
2327
- // Remove intervals used once ????
2328
-
2329
2316
if (!count ) {
2330
2317
zend_arena_release (& CG (arena ), checkpoint );
2331
2318
return NULL ;
0 commit comments