2 * liveness.c: liveness analysis
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2002 Ximian, Inc.
14 #define SPILL_COST_INCREMENT (1 << (bb->nesting << 1))
16 //#define DEBUG_LIVENESS
18 #if SIZEOF_VOID_P == 8
19 #define BITS_PER_CHUNK 64
21 #define BITS_PER_CHUNK 32
24 /* mono_bitset_mp_new:
26 * allocates a MonoBitSet inside a memory pool
28 static inline MonoBitSet
*
29 mono_bitset_mp_new (MonoMemPool
*mp
, guint32 max_size
)
31 int size
= mono_bitset_alloc_size (max_size
, 0);
34 mem
= mono_mempool_alloc0 (mp
, size
);
35 return mono_bitset_mem_new (mem
, max_size
, MONO_BITSET_DONT_FREE
);
38 static inline MonoBitSet
*
39 mono_bitset_mp_new_noinit (MonoMemPool
*mp
, guint32 max_size
)
41 int size
= mono_bitset_alloc_size (max_size
, 0);
44 mem
= mono_mempool_alloc (mp
, size
);
45 return mono_bitset_mem_new (mem
, max_size
, MONO_BITSET_DONT_FREE
);
48 G_GNUC_UNUSED
static void
49 mono_bitset_print (MonoBitSet
*set
)
54 for (i
= 0; i
< mono_bitset_size (set
); i
++) {
56 if (mono_bitset_test (set
, i
))
64 update_live_range (MonoCompile
*cfg
, int idx
, int block_dfn
, int tree_pos
)
66 MonoLiveRange
*range
= &MONO_VARINFO (cfg
, idx
)->range
;
67 guint32 abs_pos
= (block_dfn
<< 16) | tree_pos
;
69 if (range
->first_use
.abs_pos
> abs_pos
)
70 range
->first_use
.abs_pos
= abs_pos
;
72 if (range
->last_use
.abs_pos
< abs_pos
)
73 range
->last_use
.abs_pos
= abs_pos
;
77 update_gen_kill_set (MonoCompile
*cfg
, MonoBasicBlock
*bb
, MonoInst
*inst
, int inst_num
)
79 int arity
= mono_burg_arity
[inst
->opcode
];
80 int max_vars
= cfg
->num_varinfo
;
83 update_gen_kill_set (cfg
, bb
, inst
->inst_i0
, inst_num
);
86 update_gen_kill_set (cfg
, bb
, inst
->inst_i1
, inst_num
);
88 if ((inst
->ssa_op
& MONO_SSA_LOAD_STORE
) || (inst
->opcode
== OP_DUMMY_STORE
)) {
89 MonoLocalVariableList
* affected_variables
;
90 MonoLocalVariableList local_affected_variable
;
92 if (cfg
->aliasing_info
== NULL
) {
93 if ((inst
->ssa_op
== MONO_SSA_LOAD
) || (inst
->ssa_op
== MONO_SSA_STORE
) || (inst
->opcode
== OP_DUMMY_STORE
)) {
94 local_affected_variable
.variable_index
= inst
->inst_i0
->inst_c0
;
95 local_affected_variable
.next
= NULL
;
96 affected_variables
= &local_affected_variable
;
98 affected_variables
= NULL
;
101 affected_variables
= mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg
->aliasing_info
, inst
);
104 if (inst
->ssa_op
& MONO_SSA_LOAD
) {
105 MonoLocalVariableList
* affected_variable
= affected_variables
;
106 while (affected_variable
!= NULL
) {
107 int idx
= affected_variable
->variable_index
;
108 MonoMethodVar
*vi
= MONO_VARINFO (cfg
, idx
);
109 g_assert (idx
< max_vars
);
110 if ((bb
->region
!= -1) && !MONO_BBLOCK_IS_IN_REGION (bb
, MONO_REGION_TRY
)) {
112 * Variables used in exception regions can't be allocated to
115 cfg
->varinfo
[vi
->idx
]->flags
|= MONO_INST_VOLATILE
;
117 update_live_range (cfg
, idx
, bb
->dfn
, inst_num
);
118 if (!mono_bitset_test_fast (bb
->kill_set
, idx
))
119 mono_bitset_set_fast (bb
->gen_set
, idx
);
120 if (inst
->ssa_op
== MONO_SSA_LOAD
)
121 vi
->spill_costs
+= SPILL_COST_INCREMENT
;
123 affected_variable
= affected_variable
->next
;
125 } else if ((inst
->ssa_op
== MONO_SSA_STORE
) || (inst
->opcode
== OP_DUMMY_STORE
)) {
126 MonoLocalVariableList
* affected_variable
= affected_variables
;
127 while (affected_variable
!= NULL
) {
128 int idx
= affected_variable
->variable_index
;
129 MonoMethodVar
*vi
= MONO_VARINFO (cfg
, idx
);
130 g_assert (idx
< max_vars
);
132 //g_assert (inst->inst_i1->opcode != OP_PHI);
133 if ((bb
->region
!= -1) && !MONO_BBLOCK_IS_IN_REGION (bb
, MONO_REGION_TRY
)) {
135 * Variables used in exception regions can't be allocated to
138 cfg
->varinfo
[vi
->idx
]->flags
|= MONO_INST_VOLATILE
;
140 update_live_range (cfg
, idx
, bb
->dfn
, inst_num
);
141 mono_bitset_set_fast (bb
->kill_set
, idx
);
142 if (inst
->ssa_op
== MONO_SSA_STORE
)
143 vi
->spill_costs
+= SPILL_COST_INCREMENT
;
145 affected_variable
= affected_variable
->next
;
148 } else if (inst
->opcode
== CEE_JMP
) {
149 /* Keep arguments live! */
151 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
152 if (cfg
->varinfo
[i
]->opcode
== OP_ARG
) {
153 if (!mono_bitset_test_fast (bb
->kill_set
, i
))
154 mono_bitset_set_fast (bb
->gen_set
, i
);
161 update_volatile (MonoCompile
*cfg
, MonoBasicBlock
*bb
, MonoInst
*inst
, int inst_num
)
163 int arity
= mono_burg_arity
[inst
->opcode
];
164 int max_vars
= cfg
->num_varinfo
;
167 update_volatile (cfg
, bb
, inst
->inst_i0
, inst_num
);
170 update_volatile (cfg
, bb
, inst
->inst_i1
, inst_num
);
172 if (inst
->ssa_op
& MONO_SSA_LOAD_STORE
) {
173 MonoLocalVariableList
* affected_variables
;
174 MonoLocalVariableList local_affected_variable
;
176 if (cfg
->aliasing_info
== NULL
) {
177 if ((inst
->ssa_op
== MONO_SSA_LOAD
) || (inst
->ssa_op
== MONO_SSA_STORE
)) {
178 local_affected_variable
.variable_index
= inst
->inst_i0
->inst_c0
;
179 local_affected_variable
.next
= NULL
;
180 affected_variables
= &local_affected_variable
;
182 affected_variables
= NULL
;
185 affected_variables
= mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg
->aliasing_info
, inst
);
188 while (affected_variables
!= NULL
) {
189 int idx
= affected_variables
->variable_index
;
190 MonoMethodVar
*vi
= MONO_VARINFO (cfg
, idx
);
191 g_assert (idx
< max_vars
);
192 cfg
->varinfo
[vi
->idx
]->flags
|= MONO_INST_VOLATILE
;
194 affected_variables
= affected_variables
->next
;
200 visit_bb (MonoCompile
*cfg
, MonoBasicBlock
*bb
, GSList
**visited
)
205 if (g_slist_find (*visited
, bb
))
208 if (cfg
->aliasing_info
!= NULL
)
209 mono_aliasing_initialize_code_traversal (cfg
->aliasing_info
, bb
);
211 for (tree_num
= 0, inst
= bb
->code
; inst
; inst
= inst
->next
, tree_num
++) {
212 update_volatile (cfg
, bb
, inst
, tree_num
);
215 *visited
= g_slist_append (*visited
, bb
);
218 * Need to visit all bblocks reachable from this one since they can be
219 * reached during exception handling.
221 for (i
= 0; i
< bb
->out_count
; ++i
) {
222 visit_bb (cfg
, bb
->out_bb
[i
], visited
);
227 handle_exception_clauses (MonoCompile
*cfg
)
230 GSList
*visited
= NULL
;
233 * Variables in exception handler register cannot be allocated to registers
234 * so make them volatile. See bug #42136. This will not be neccessary when
235 * the back ends could guarantee that the variables will be in the
236 * correct registers when a handler is called.
237 * This includes try blocks too, since a variable in a try block might be
238 * accessed after an exception handler has been run.
240 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
242 if (bb
->region
== -1 || MONO_BBLOCK_IS_IN_REGION (bb
, MONO_REGION_TRY
))
245 visit_bb (cfg
, bb
, &visited
);
247 g_slist_free (visited
);
250 /* generic liveness analysis code. CFG specific parts are
251 * in update_gen_kill_set()
254 mono_analyze_liveness (MonoCompile
*cfg
)
256 MonoBitSet
*old_live_out_set
;
257 int i
, j
, max_vars
= cfg
->num_varinfo
;
259 gboolean
*in_worklist
;
260 MonoBasicBlock
**worklist
;
265 #ifdef DEBUG_LIVENESS
266 printf ("LIVENESS %s\n", mono_method_full_name (cfg
->method
, TRUE
));
269 g_assert (!(cfg
->comp_done
& MONO_COMP_LIVENESS
));
271 cfg
->comp_done
|= MONO_COMP_LIVENESS
;
276 bitsize
= mono_bitset_alloc_size (max_vars
, 0);
277 mem
= mono_mempool_alloc0 (cfg
->mempool
, cfg
->num_bblocks
* bitsize
* 4);
279 for (i
= 0; i
< cfg
->num_bblocks
; ++i
) {
280 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
282 bb
->gen_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
284 bb
->kill_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
286 /* Initialized later */
287 bb
->live_in_set
= NULL
;
288 bb
->live_out_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
291 for (i
= 0; i
< max_vars
; i
++) {
292 MONO_VARINFO (cfg
, i
)->range
.first_use
.abs_pos
= ~ 0;
293 MONO_VARINFO (cfg
, i
)->range
.last_use
.abs_pos
= 0;
294 MONO_VARINFO (cfg
, i
)->spill_costs
= 0;
297 for (i
= 0; i
< cfg
->num_bblocks
; ++i
) {
298 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
302 if (cfg
->aliasing_info
!= NULL
)
303 mono_aliasing_initialize_code_traversal (cfg
->aliasing_info
, bb
);
305 for (tree_num
= 0, inst
= bb
->code
; inst
; inst
= inst
->next
, tree_num
++) {
306 #ifdef DEBUG_LIVENESS
307 mono_print_tree (inst
); printf ("\n");
309 update_gen_kill_set (cfg
, bb
, inst
, tree_num
);
312 #ifdef DEBUG_LIVENESS
313 printf ("BLOCK BB%d (", bb
->block_num
);
314 for (j
= 0; j
< bb
->out_count
; j
++)
315 printf ("BB%d, ", bb
->out_bb
[j
]->block_num
);
318 printf ("GEN BB%d: ", bb
->block_num
); mono_bitset_print (bb
->gen_set
);
319 printf ("KILL BB%d: ", bb
->block_num
); mono_bitset_print (bb
->kill_set
);
323 old_live_out_set
= mono_bitset_new (max_vars
, 0);
324 in_worklist
= g_new0 (gboolean
, cfg
->num_bblocks
+ 1);
326 worklist
= g_new (MonoBasicBlock
*, cfg
->num_bblocks
+ 1);
330 * This is a backward dataflow analysis problem, so we process blocks in
331 * decreasing dfn order, this speeds up the iteration.
333 for (i
= 0; i
< cfg
->num_bblocks
; i
++) {
334 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
336 worklist
[l_end
++] = bb
;
337 in_worklist
[bb
->dfn
] = TRUE
;
343 MonoBasicBlock
*bb
= worklist
[--l_end
];
344 MonoBasicBlock
*out_bb
;
347 in_worklist
[bb
->dfn
] = FALSE
;
349 #ifdef DEBUG_LIVENESS
350 printf ("P: %d(%d): IN: ", bb
->block_num
, bb
->dfn
);
351 for (j
= 0; j
< bb
->in_count
; ++j
)
352 printf ("BB%d ", bb
->in_bb
[j
]->block_num
);
354 for (j
= 0; j
< bb
->out_count
; ++j
)
355 printf ("BB%d ", bb
->out_bb
[j
]->block_num
);
359 if (bb
->out_count
== 0)
364 if (!bb
->live_in_set
) {
365 /* First pass over this bblock */
370 mono_bitset_copyto (bb
->live_out_set
, old_live_out_set
);
373 for (j
= 0; j
< bb
->out_count
; j
++) {
374 out_bb
= bb
->out_bb
[j
];
376 if (!out_bb
->live_in_set
) {
377 out_bb
->live_in_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
380 mono_bitset_copyto (out_bb
->live_out_set
, out_bb
->live_in_set
);
381 mono_bitset_sub (out_bb
->live_in_set
, out_bb
->kill_set
);
382 mono_bitset_union (out_bb
->live_in_set
, out_bb
->gen_set
);
385 mono_bitset_union (bb
->live_out_set
, out_bb
->live_in_set
);
388 if (changed
|| !mono_bitset_equal (old_live_out_set
, bb
->live_out_set
)) {
389 if (!bb
->live_in_set
) {
390 bb
->live_in_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
393 mono_bitset_copyto (bb
->live_out_set
, bb
->live_in_set
);
394 mono_bitset_sub (bb
->live_in_set
, bb
->kill_set
);
395 mono_bitset_union (bb
->live_in_set
, bb
->gen_set
);
397 for (j
= 0; j
< bb
->in_count
; j
++) {
398 MonoBasicBlock
*in_bb
= bb
->in_bb
[j
];
400 * Some basic blocks do not seem to be in the
401 * cfg->bblocks array...
403 if (in_bb
->gen_set
&& !in_worklist
[in_bb
->dfn
]) {
404 #ifdef DEBUG_LIVENESS
405 printf ("\tADD: %d\n", in_bb
->block_num
);
408 * Put the block at the top of the stack, so it
409 * will be processed right away.
411 worklist
[l_end
++] = in_bb
;
412 in_worklist
[in_bb
->dfn
] = TRUE
;
418 //printf ("IT: %d %d %d.\n", iterations, in_iter, out_iter);
420 mono_bitset_free (old_live_out_set
);
423 g_free (in_worklist
);
425 /* Compute live_in_set for bblocks skipped earlier */
426 for (i
= 0; i
< cfg
->num_bblocks
; ++i
) {
427 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
429 if (!bb
->live_in_set
) {
430 bb
->live_in_set
= mono_bitset_mem_new (mem
, max_vars
, MONO_BITSET_DONT_FREE
);
433 mono_bitset_copyto (bb
->live_out_set
, bb
->live_in_set
);
434 mono_bitset_sub (bb
->live_in_set
, bb
->kill_set
);
435 mono_bitset_union (bb
->live_in_set
, bb
->gen_set
);
440 * This code can be slow for large methods so inline the calls to
443 for (i
= 0; i
< cfg
->num_bblocks
; ++i
) {
444 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
447 if (!bb
->live_out_set
)
450 rem
= max_vars
% BITS_PER_CHUNK
;
451 max
= ((max_vars
+ (BITS_PER_CHUNK
-1)) / BITS_PER_CHUNK
);
452 for (j
= 0; j
< max
; ++j
) {
457 bits_in
= mono_bitset_get_fast (bb
->live_in_set
, j
);
458 bits_out
= mono_bitset_get_fast (bb
->live_out_set
, j
);
461 end
= (j
* BITS_PER_CHUNK
) + rem
;
463 end
= (j
* BITS_PER_CHUNK
) + BITS_PER_CHUNK
;
465 k
= (j
* BITS_PER_CHUNK
);
466 while ((bits_in
|| bits_out
)) {
468 update_live_range (cfg
, k
, bb
->dfn
, 0);
470 update_live_range (cfg
, k
, bb
->dfn
, 0xffff);
478 /* todo: remove code when we have verified that the liveness for try/catch blocks
482 * Currently, this can't be commented out since exception blocks are not
483 * processed during liveness analysis.
485 handle_exception_clauses (cfg
);
488 * Arguments need to have their live ranges extended to the beginning of
489 * the method to account for the arg reg/memory -> global register copies
490 * in the prolog (bug #74992).
493 for (i
= 0; i
< max_vars
; i
++) {
494 MonoMethodVar
*vi
= MONO_VARINFO (cfg
, i
);
495 if (cfg
->varinfo
[vi
->idx
]->opcode
== OP_ARG
)
496 vi
->range
.first_use
.abs_pos
= 0;
499 #ifdef DEBUG_LIVENESS
500 for (i
= cfg
->num_bblocks
- 1; i
>= 0; i
--) {
501 MonoBasicBlock
*bb
= cfg
->bblocks
[i
];
503 printf ("LIVE IN BB%d: ", bb
->block_num
);
504 mono_bitset_print (bb
->live_in_set
);
505 printf ("LIVE OUT BB%d: ", bb
->block_num
);
506 mono_bitset_print (bb
->live_out_set
);