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. */
@@ -125,92 +185,98 @@ void load_var(basic_block_t *bb, var_t *var, int idx)
125185 ir -> dest = idx ;
126186 REGS [idx ].var = var ;
127187 REGS [idx ].polluted = 0 ;
188+ vreg_map_to_phys (var , idx );
128189}
129190
130191int prepare_operand (basic_block_t * bb , var_t * var , int operand_0 )
131192{
193+ /* Check VReg mapping first for O(1) lookup */
194+ int phys_reg = vreg_get_phys (var );
195+ if (phys_reg >= 0 && phys_reg < REG_CNT && REGS [phys_reg ].var == var )
196+ return phys_reg ;
197+
132198 /* Force reload for address-taken variables (may be modified via pointer) */
133199 int i = find_in_regs (var );
134- if (i > -1 && !var -> address_taken )
200+ if (i > -1 && !var -> address_taken ) {
201+ vreg_map_to_phys (var , i );
135202 return i ;
203+ }
136204
137205 for (i = 0 ; i < REG_CNT ; i ++ ) {
138206 if (!REGS [i ].var ) {
139207 load_var (bb , var , i );
208+ vreg_map_to_phys (var , i );
140209 return i ;
141210 }
142211 }
143212
144- for (i = 0 ; i < REG_CNT ; i ++ ) {
145- if (i == operand_0 )
146- continue ;
147- if (check_live_out (bb , REGS [i ].var )) {
148- spill_var (bb , REGS [i ].var , i );
149- load_var (bb , var , i );
150- return i ;
213+ int spilled = find_best_spill (
214+ bb , bb -> insn_list .tail ? bb -> insn_list .tail -> idx : 0 , operand_0 , -1 );
215+
216+ if (spilled < 0 ) {
217+ for (i = 0 ; i < REG_CNT ; i ++ ) {
218+ if (i != operand_0 && REGS [i ].var ) {
219+ spilled = i ;
220+ break ;
221+ }
151222 }
152223 }
153224
154- /* spill farthest local */
155- int spilled = 0 ;
156- for (i = 0 ; i < REG_CNT ; i ++ ) {
157- if (!REGS [i ].var )
158- continue ;
159- if (REGS [i ].var -> consumed > REGS [spilled ].var -> consumed )
160- spilled = i ;
161- }
225+ if (REGS [spilled ].var )
226+ vreg_clear_phys (REGS [spilled ].var );
162227
163228 spill_var (bb , REGS [spilled ].var , spilled );
164229 load_var (bb , var , spilled );
230+ vreg_map_to_phys (var , spilled );
165231
166232 return spilled ;
167233}
168234
169235int prepare_dest (basic_block_t * bb , var_t * var , int operand_0 , int operand_1 )
170236{
237+ int phys_reg = vreg_get_phys (var );
238+ if (phys_reg >= 0 && phys_reg < REG_CNT && REGS [phys_reg ].var == var ) {
239+ REGS [phys_reg ].polluted = 1 ;
240+ return phys_reg ;
241+ }
242+
171243 int i = find_in_regs (var );
172244 if (i > -1 ) {
173245 REGS [i ].polluted = 1 ;
246+ vreg_map_to_phys (var , i );
174247 return i ;
175248 }
176249
177250 for (i = 0 ; i < REG_CNT ; i ++ ) {
178251 if (!REGS [i ].var ) {
179252 REGS [i ].var = var ;
180253 REGS [i ].polluted = 1 ;
254+ vreg_map_to_phys (var , i );
181255 return i ;
182256 }
183257 }
184258
185- for ( i = 0 ; i < REG_CNT ; i ++ ) {
186- if ( i == operand_0 )
187- continue ;
188- if ( i == operand_1 )
189- continue ;
190- if ( check_live_out ( bb , REGS [ i ]. var ) ) {
191- spill_var ( bb , REGS [i ].var , i );
192- REGS [ i ]. var = var ;
193- REGS [ i ]. polluted = 1 ;
194- return i ;
259+ int spilled =
260+ find_best_spill ( bb , bb -> insn_list . tail ? bb -> insn_list . tail -> idx : 0 ,
261+ operand_0 , operand_1 ) ;
262+
263+ if ( spilled < 0 ) {
264+ for ( i = 0 ; i < REG_CNT ; i ++ ) {
265+ if ( i != operand_0 && i != operand_1 && REGS [i ].var ) {
266+ spilled = i ;
267+ break ;
268+ }
195269 }
196270 }
197271
198- /* spill farthest local */
199- int spilled = 0 ;
200- for (i = 0 ; i < REG_CNT ; i ++ ) {
201- if (i == operand_0 )
202- continue ;
203- if (i == operand_1 )
204- continue ;
205- if (!REGS [i ].var )
206- continue ;
207- if (REGS [i ].var -> consumed > REGS [spilled ].var -> consumed )
208- spilled = i ;
272+ if (REGS [spilled ].var ) {
273+ vreg_clear_phys (REGS [spilled ].var );
209274 }
210275
211276 spill_var (bb , REGS [spilled ].var , spilled );
212277 REGS [spilled ].var = var ;
213278 REGS [spilled ].polluted = 1 ;
279+ vreg_map_to_phys (var , spilled );
214280
215281 return spilled ;
216282}
@@ -247,11 +313,13 @@ void spill_live_out(basic_block_t *bb)
247313 if (!REGS [i ].var )
248314 continue ;
249315 if (!check_live_out (bb , REGS [i ].var )) {
316+ vreg_clear_phys (REGS [i ].var );
250317 REGS [i ].var = NULL ;
251318 REGS [i ].polluted = 0 ;
252319 continue ;
253320 }
254321 if (!var_check_killed (REGS [i ].var , bb )) {
322+ vreg_clear_phys (REGS [i ].var );
255323 REGS [i ].var = NULL ;
256324 REGS [i ].polluted = 0 ;
257325 continue ;
@@ -336,6 +404,7 @@ void reg_alloc(void)
336404 spill_var (GLOBAL_FUNC -> bbs , global_insn -> rd , dest );
337405 /* release the unused constant number in register manually */
338406 REGS [src0 ].polluted = 0 ;
407+ vreg_clear_phys (REGS [src0 ].var );
339408 REGS [src0 ].var = NULL ;
340409 break ;
341410 case OP_add : {
@@ -565,8 +634,10 @@ void reg_alloc(void)
565634 REGS [dest ].polluted = 0 ;
566635 }
567636
568- if (clear_reg )
637+ if (clear_reg ) {
638+ vreg_clear_phys (REGS [src0 ].var );
569639 REGS [src0 ].var = NULL ;
640+ }
570641
571642 break ;
572643 case OP_read :
0 commit comments