1212 * dead variable and does NOT wrtie it back to the stack.
1313 */
1414
15- #include <stdbool.h>
16-
1715#include "defs.h"
1816#include "globals.c"
1917
18+ void vreg_map_to_phys (var_t * var , int phys_reg )
19+ {
20+ if (var )
21+ var -> phys_reg = phys_reg ;
22+ }
23+
24+ int vreg_get_phys (var_t * var )
25+ {
26+ if (var )
27+ return var -> phys_reg ;
28+ return -1 ;
29+ }
30+
31+ void vreg_clear_phys (var_t * var )
32+ {
33+ if (var )
34+ var -> phys_reg = -1 ;
35+ }
36+
2037/* Aligns size to nearest multiple of 4, this meets ARMv7's alignment
2138 * requirement.
2239 *
@@ -45,6 +62,7 @@ void refresh(basic_block_t *bb, insn_t *insn)
4562 if (check_live_out (bb , REGS [i ].var ))
4663 continue ;
4764 if (REGS [i ].var -> consumed < insn -> idx ) {
65+ vreg_clear_phys (REGS [i ].var );
4866 REGS [i ].var = NULL ;
4967 REGS [i ].polluted = 0 ;
5068 }
@@ -75,6 +93,46 @@ ph2_ir_t *bb_add_ph2_ir(basic_block_t *bb, opcode_t op)
7593 return n ;
7694}
7795
96+ int calculate_spill_cost (var_t * var , basic_block_t * bb , int current_idx )
97+ {
98+ if (check_live_out (bb , var ))
99+ return 1000 ;
100+
101+ if (var -> consumed > current_idx ) {
102+ int distance = var -> consumed - current_idx ;
103+ if (distance < 10 )
104+ return 100 - distance * 10 ;
105+ }
106+
107+ return 0 ;
108+ }
109+
110+ int find_best_spill (basic_block_t * bb ,
111+ int current_idx ,
112+ int avoid_reg1 ,
113+ int avoid_reg2 )
114+ {
115+ int best_reg = -1 ;
116+ int min_cost = 99999 ;
117+
118+ for (int i = 0 ; i < REG_CNT ; i ++ ) {
119+ if (i == avoid_reg1 || i == avoid_reg2 )
120+ continue ;
121+
122+ if (!REGS [i ].var )
123+ continue ;
124+
125+ int cost = calculate_spill_cost (REGS [i ].var , bb , current_idx );
126+
127+ if (cost < min_cost ) {
128+ min_cost = cost ;
129+ best_reg = i ;
130+ }
131+ }
132+
133+ return best_reg ;
134+ }
135+
78136/* Priority of spilling:
79137 * - live_out variable
80138 * - farthest local variable
@@ -83,6 +141,7 @@ void spill_var(basic_block_t *bb, var_t *var, int idx)
83141{
84142 if (!REGS [idx ].polluted ) {
85143 REGS [idx ].var = NULL ;
144+ vreg_clear_phys (var );
86145 return ;
87146 }
88147
@@ -96,6 +155,7 @@ void spill_var(basic_block_t *bb, var_t *var, int idx)
96155 ir -> src1 = var -> offset ;
97156 REGS [idx ].var = NULL ;
98157 REGS [idx ].polluted = 0 ;
158+ vreg_clear_phys (var );
99159}
100160
101161/* Return the index of register for given variable. Otherwise, return -1. */
@@ -116,91 +176,96 @@ void load_var(basic_block_t *bb, var_t *var, int idx)
116176 ir -> dest = idx ;
117177 REGS [idx ].var = var ;
118178 REGS [idx ].polluted = 0 ;
179+ vreg_map_to_phys (var , idx );
119180}
120181
121182int prepare_operand (basic_block_t * bb , var_t * var , int operand_0 )
122183{
184+ int phys_reg = vreg_get_phys (var );
185+ if (phys_reg >= 0 && phys_reg < REG_CNT && REGS [phys_reg ].var == var )
186+ return phys_reg ;
187+
123188 int i = find_in_regs (var );
124- if (i > -1 )
189+ if (i > -1 ) {
190+ vreg_map_to_phys (var , i );
125191 return i ;
192+ }
126193
127194 for (i = 0 ; i < REG_CNT ; i ++ ) {
128195 if (!REGS [i ].var ) {
129196 load_var (bb , var , i );
197+ vreg_map_to_phys (var , i );
130198 return i ;
131199 }
132200 }
133201
134- for (i = 0 ; i < REG_CNT ; i ++ ) {
135- if (i == operand_0 )
136- continue ;
137- if (check_live_out (bb , REGS [i ].var )) {
138- spill_var (bb , REGS [i ].var , i );
139- load_var (bb , var , i );
140- return i ;
202+ int spilled = find_best_spill (
203+ bb , bb -> insn_list .tail ? bb -> insn_list .tail -> idx : 0 , operand_0 , -1 );
204+
205+ if (spilled < 0 ) {
206+ for (i = 0 ; i < REG_CNT ; i ++ ) {
207+ if (i != operand_0 && REGS [i ].var ) {
208+ spilled = i ;
209+ break ;
210+ }
141211 }
142212 }
143213
144- /* spill farthest local */
145- int spilled = 0 ;
146- for (i = 0 ; i < REG_CNT ; i ++ ) {
147- if (!REGS [i ].var )
148- continue ;
149- if (REGS [i ].var -> consumed > REGS [spilled ].var -> consumed )
150- spilled = i ;
151- }
214+ if (REGS [spilled ].var )
215+ vreg_clear_phys (REGS [spilled ].var );
152216
153217 spill_var (bb , REGS [spilled ].var , spilled );
154218 load_var (bb , var , spilled );
219+ vreg_map_to_phys (var , spilled );
155220
156221 return spilled ;
157222}
158223
159224int prepare_dest (basic_block_t * bb , var_t * var , int operand_0 , int operand_1 )
160225{
226+ int phys_reg = vreg_get_phys (var );
227+ if (phys_reg >= 0 && phys_reg < REG_CNT && REGS [phys_reg ].var == var ) {
228+ REGS [phys_reg ].polluted = 1 ;
229+ return phys_reg ;
230+ }
231+
161232 int i = find_in_regs (var );
162233 if (i > -1 ) {
163234 REGS [i ].polluted = 1 ;
235+ vreg_map_to_phys (var , i );
164236 return i ;
165237 }
166238
167239 for (i = 0 ; i < REG_CNT ; i ++ ) {
168240 if (!REGS [i ].var ) {
169241 REGS [i ].var = var ;
170242 REGS [i ].polluted = 1 ;
243+ vreg_map_to_phys (var , i );
171244 return i ;
172245 }
173246 }
174247
175- for ( i = 0 ; i < REG_CNT ; i ++ ) {
176- if ( i == operand_0 )
177- continue ;
178- if ( i == operand_1 )
179- continue ;
180- if ( check_live_out ( bb , REGS [ i ]. var ) ) {
181- spill_var ( bb , REGS [i ].var , i );
182- REGS [ i ]. var = var ;
183- REGS [ i ]. polluted = 1 ;
184- return i ;
248+ int spilled =
249+ find_best_spill ( bb , bb -> insn_list . tail ? bb -> insn_list . tail -> idx : 0 ,
250+ operand_0 , operand_1 ) ;
251+
252+ if ( spilled < 0 ) {
253+ for ( i = 0 ; i < REG_CNT ; i ++ ) {
254+ if ( i != operand_0 && i != operand_1 && REGS [i ].var ) {
255+ spilled = i ;
256+ break ;
257+ }
185258 }
186259 }
187260
188- /* spill farthest local */
189- int spilled = 0 ;
190- for (i = 0 ; i < REG_CNT ; i ++ ) {
191- if (i == operand_0 )
192- continue ;
193- if (i == operand_1 )
194- continue ;
195- if (!REGS [i ].var )
196- continue ;
197- if (REGS [i ].var -> consumed > REGS [spilled ].var -> consumed )
198- spilled = i ;
261+ if (REGS [spilled ].var ) {
262+ vreg_clear_phys (REGS [spilled ].var );
199263 }
200264
201265 spill_var (bb , REGS [spilled ].var , spilled );
202266 REGS [spilled ].var = var ;
203267 REGS [spilled ].polluted = 1 ;
268+ vreg_map_to_phys (var , spilled );
204269
205270 return spilled ;
206271}
@@ -227,11 +292,13 @@ void spill_live_out(basic_block_t *bb)
227292 if (!REGS [i ].var )
228293 continue ;
229294 if (!check_live_out (bb , REGS [i ].var )) {
295+ vreg_clear_phys (REGS [i ].var );
230296 REGS [i ].var = NULL ;
231297 REGS [i ].polluted = 0 ;
232298 continue ;
233299 }
234300 if (!var_check_killed (REGS [i ].var , bb )) {
301+ vreg_clear_phys (REGS [i ].var );
235302 REGS [i ].var = NULL ;
236303 REGS [i ].polluted = 0 ;
237304 continue ;
@@ -316,6 +383,7 @@ void reg_alloc(void)
316383 spill_var (GLOBAL_FUNC -> bbs , global_insn -> rd , dest );
317384 /* release the unused constant number in register manually */
318385 REGS [src0 ].polluted = 0 ;
386+ vreg_clear_phys (REGS [src0 ].var );
319387 REGS [src0 ].var = NULL ;
320388 break ;
321389 case OP_add : {
@@ -539,8 +607,10 @@ void reg_alloc(void)
539607 REGS [dest ].polluted = 0 ;
540608 }
541609
542- if (clear_reg )
610+ if (clear_reg ) {
611+ vreg_clear_phys (REGS [src0 ].var );
543612 REGS [src0 ].var = NULL ;
613+ }
544614
545615 break ;
546616 case OP_read :
0 commit comments