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
25 optimize_initlocals (MonoCompile *cfg);
27 /* mono_bitset_mp_new:
29 * allocates a MonoBitSet inside a memory pool
31 static inline MonoBitSet*
32 mono_bitset_mp_new (MonoMemPool *mp, guint32 max_size)
34 int size = mono_bitset_alloc_size (max_size, 0);
37 mem = mono_mempool_alloc0 (mp, size);
38 return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE);
41 static inline MonoBitSet*
42 mono_bitset_mp_new_noinit (MonoMemPool *mp, guint32 max_size)
44 int size = mono_bitset_alloc_size (max_size, 0);
47 mem = mono_mempool_alloc (mp, size);
48 return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE);
51 G_GNUC_UNUSED static void
52 mono_bitset_print (MonoBitSet *set)
57 for (i = 0; i < mono_bitset_size (set); i++) {
59 if (mono_bitset_test (set, i))
67 update_live_range (MonoCompile *cfg, int idx, int block_dfn, int tree_pos)
69 MonoLiveRange *range = &MONO_VARINFO (cfg, idx)->range;
70 guint32 abs_pos = (block_dfn << 16) | tree_pos;
72 if (range->first_use.abs_pos > abs_pos)
73 range->first_use.abs_pos = abs_pos;
75 if (range->last_use.abs_pos < abs_pos)
76 range->last_use.abs_pos = abs_pos;
80 update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int inst_num)
82 int arity = mono_burg_arity [inst->opcode];
83 int max_vars = cfg->num_varinfo;
86 update_gen_kill_set (cfg, bb, inst->inst_i0, inst_num);
89 update_gen_kill_set (cfg, bb, inst->inst_i1, inst_num);
91 if ((inst->ssa_op & MONO_SSA_LOAD_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
92 MonoLocalVariableList* affected_variables;
93 MonoLocalVariableList local_affected_variable;
95 if (cfg->aliasing_info == NULL) {
96 if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
97 local_affected_variable.variable_index = inst->inst_i0->inst_c0;
98 local_affected_variable.next = NULL;
99 affected_variables = &local_affected_variable;
101 affected_variables = NULL;
104 affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg->aliasing_info, inst);
107 if (inst->ssa_op & MONO_SSA_LOAD) {
108 MonoLocalVariableList* affected_variable = affected_variables;
109 while (affected_variable != NULL) {
110 int idx = affected_variable->variable_index;
111 MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
112 g_assert (idx < max_vars);
113 if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
115 * Variables used in exception regions can't be allocated to
118 cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
120 update_live_range (cfg, idx, bb->dfn, inst_num);
121 if (!mono_bitset_test_fast (bb->kill_set, idx))
122 mono_bitset_set_fast (bb->gen_set, idx);
123 if (inst->ssa_op == MONO_SSA_LOAD)
124 vi->spill_costs += SPILL_COST_INCREMENT;
126 affected_variable = affected_variable->next;
128 } else if ((inst->ssa_op == MONO_SSA_STORE) || (inst->opcode == OP_DUMMY_STORE)) {
129 MonoLocalVariableList* affected_variable = affected_variables;
130 while (affected_variable != NULL) {
131 int idx = affected_variable->variable_index;
132 MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
133 g_assert (idx < max_vars);
135 //g_assert (inst->inst_i1->opcode != OP_PHI);
136 if ((bb->region != -1) && !MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY)) {
138 * Variables used in exception regions can't be allocated to
141 cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
143 update_live_range (cfg, idx, bb->dfn, inst_num);
144 mono_bitset_set_fast (bb->kill_set, idx);
145 if (inst->ssa_op == MONO_SSA_STORE)
146 vi->spill_costs += SPILL_COST_INCREMENT;
148 affected_variable = affected_variable->next;
151 } else if (inst->opcode == CEE_JMP) {
152 /* Keep arguments live! */
154 for (i = 0; i < cfg->num_varinfo; i++) {
155 if (cfg->varinfo [i]->opcode == OP_ARG) {
156 if (!mono_bitset_test_fast (bb->kill_set, i))
157 mono_bitset_set_fast (bb->gen_set, i);
164 update_volatile (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int inst_num)
166 int arity = mono_burg_arity [inst->opcode];
167 int max_vars = cfg->num_varinfo;
170 update_volatile (cfg, bb, inst->inst_i0, inst_num);
173 update_volatile (cfg, bb, inst->inst_i1, inst_num);
175 if (inst->ssa_op & MONO_SSA_LOAD_STORE) {
176 MonoLocalVariableList* affected_variables;
177 MonoLocalVariableList local_affected_variable;
179 if (cfg->aliasing_info == NULL) {
180 if ((inst->ssa_op == MONO_SSA_LOAD) || (inst->ssa_op == MONO_SSA_STORE)) {
181 local_affected_variable.variable_index = inst->inst_i0->inst_c0;
182 local_affected_variable.next = NULL;
183 affected_variables = &local_affected_variable;
185 affected_variables = NULL;
188 affected_variables = mono_aliasing_get_affected_variables_for_inst_traversing_code (cfg->aliasing_info, inst);
191 while (affected_variables != NULL) {
192 int idx = affected_variables->variable_index;
193 MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
194 g_assert (idx < max_vars);
195 cfg->varinfo [vi->idx]->flags |= MONO_INST_VOLATILE;
197 affected_variables = affected_variables->next;
203 visit_bb (MonoCompile *cfg, MonoBasicBlock *bb, GSList **visited)
208 if (g_slist_find (*visited, bb))
211 if (cfg->aliasing_info != NULL)
212 mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
214 for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
215 update_volatile (cfg, bb, inst, tree_num);
218 *visited = g_slist_append (*visited, bb);
221 * Need to visit all bblocks reachable from this one since they can be
222 * reached during exception handling.
224 for (i = 0; i < bb->out_count; ++i) {
225 visit_bb (cfg, bb->out_bb [i], visited);
230 mono_liveness_handle_exception_clauses (MonoCompile *cfg)
233 GSList *visited = NULL;
236 * Variables in exception handler register cannot be allocated to registers
237 * so make them volatile. See bug #42136. This will not be neccessary when
238 * the back ends could guarantee that the variables will be in the
239 * correct registers when a handler is called.
240 * This includes try blocks too, since a variable in a try block might be
241 * accessed after an exception handler has been run.
243 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
245 if (bb->region == -1 || MONO_BBLOCK_IS_IN_REGION (bb, MONO_REGION_TRY))
248 visit_bb (cfg, bb, &visited);
250 g_slist_free (visited);
253 /* generic liveness analysis code. CFG specific parts are
254 * in update_gen_kill_set()
257 mono_analyze_liveness (MonoCompile *cfg)
259 MonoBitSet *old_live_out_set;
260 int i, j, max_vars = cfg->num_varinfo;
262 gboolean *in_worklist;
263 MonoBasicBlock **worklist;
268 #ifdef DEBUG_LIVENESS
269 printf ("LIVENESS %s\n", mono_method_full_name (cfg->method, TRUE));
272 g_assert (!(cfg->comp_done & MONO_COMP_LIVENESS));
274 cfg->comp_done |= MONO_COMP_LIVENESS;
279 bitsize = mono_bitset_alloc_size (max_vars, 0);
280 mem = mono_mempool_alloc0 (cfg->mempool, cfg->num_bblocks * bitsize * 4);
282 for (i = 0; i < cfg->num_bblocks; ++i) {
283 MonoBasicBlock *bb = cfg->bblocks [i];
285 bb->gen_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
287 bb->kill_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
289 /* Initialized later */
290 bb->live_in_set = NULL;
291 bb->live_out_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
294 for (i = 0; i < max_vars; i ++) {
295 MONO_VARINFO (cfg, i)->range.first_use.abs_pos = ~ 0;
296 MONO_VARINFO (cfg, i)->range.last_use .abs_pos = 0;
297 MONO_VARINFO (cfg, i)->spill_costs = 0;
300 for (i = 0; i < cfg->num_bblocks; ++i) {
301 MonoBasicBlock *bb = cfg->bblocks [i];
305 if (cfg->aliasing_info != NULL)
306 mono_aliasing_initialize_code_traversal (cfg->aliasing_info, bb);
308 for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
309 #ifdef DEBUG_LIVENESS
310 mono_print_tree (inst); printf ("\n");
312 update_gen_kill_set (cfg, bb, inst, tree_num);
315 #ifdef DEBUG_LIVENESS
316 printf ("BLOCK BB%d (", bb->block_num);
317 for (j = 0; j < bb->out_count; j++)
318 printf ("BB%d, ", bb->out_bb [j]->block_num);
321 printf ("GEN BB%d: ", bb->block_num); mono_bitset_print (bb->gen_set);
322 printf ("KILL BB%d: ", bb->block_num); mono_bitset_print (bb->kill_set);
326 old_live_out_set = mono_bitset_new (max_vars, 0);
327 in_worklist = g_new0 (gboolean, cfg->num_bblocks + 1);
329 worklist = g_new (MonoBasicBlock *, cfg->num_bblocks + 1);
333 * This is a backward dataflow analysis problem, so we process blocks in
334 * decreasing dfn order, this speeds up the iteration.
336 for (i = 0; i < cfg->num_bblocks; i ++) {
337 MonoBasicBlock *bb = cfg->bblocks [i];
339 worklist [l_end ++] = bb;
340 in_worklist [bb->dfn] = TRUE;
346 MonoBasicBlock *bb = worklist [--l_end];
347 MonoBasicBlock *out_bb;
350 in_worklist [bb->dfn] = FALSE;
352 #ifdef DEBUG_LIVENESS
353 printf ("P: %d(%d): IN: ", bb->block_num, bb->dfn);
354 for (j = 0; j < bb->in_count; ++j)
355 printf ("BB%d ", bb->in_bb [j]->block_num);
357 for (j = 0; j < bb->out_count; ++j)
358 printf ("BB%d ", bb->out_bb [j]->block_num);
362 if (bb->out_count == 0)
367 if (!bb->live_in_set) {
368 /* First pass over this bblock */
373 mono_bitset_copyto (bb->live_out_set, old_live_out_set);
376 for (j = 0; j < bb->out_count; j++) {
377 out_bb = bb->out_bb [j];
379 if (!out_bb->live_in_set) {
380 out_bb->live_in_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
383 mono_bitset_copyto (out_bb->live_out_set, out_bb->live_in_set);
384 mono_bitset_sub (out_bb->live_in_set, out_bb->kill_set);
385 mono_bitset_union (out_bb->live_in_set, out_bb->gen_set);
388 mono_bitset_union (bb->live_out_set, out_bb->live_in_set);
391 if (changed || !mono_bitset_equal (old_live_out_set, bb->live_out_set)) {
392 if (!bb->live_in_set) {
393 bb->live_in_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
396 mono_bitset_copyto (bb->live_out_set, bb->live_in_set);
397 mono_bitset_sub (bb->live_in_set, bb->kill_set);
398 mono_bitset_union (bb->live_in_set, bb->gen_set);
400 for (j = 0; j < bb->in_count; j++) {
401 MonoBasicBlock *in_bb = bb->in_bb [j];
403 * Some basic blocks do not seem to be in the
404 * cfg->bblocks array...
406 if (in_bb->gen_set && !in_worklist [in_bb->dfn]) {
407 #ifdef DEBUG_LIVENESS
408 printf ("\tADD: %d\n", in_bb->block_num);
411 * Put the block at the top of the stack, so it
412 * will be processed right away.
414 worklist [l_end ++] = in_bb;
415 in_worklist [in_bb->dfn] = TRUE;
421 //printf ("IT: %d %d %d.\n", iterations, in_iter, out_iter);
423 mono_bitset_free (old_live_out_set);
426 g_free (in_worklist);
428 /* Compute live_in_set for bblocks skipped earlier */
429 for (i = 0; i < cfg->num_bblocks; ++i) {
430 MonoBasicBlock *bb = cfg->bblocks [i];
432 if (!bb->live_in_set) {
433 bb->live_in_set = mono_bitset_mem_new (mem, max_vars, MONO_BITSET_DONT_FREE);
436 mono_bitset_copyto (bb->live_out_set, bb->live_in_set);
437 mono_bitset_sub (bb->live_in_set, bb->kill_set);
438 mono_bitset_union (bb->live_in_set, bb->gen_set);
443 * This code can be slow for large methods so inline the calls to
446 for (i = 0; i < cfg->num_bblocks; ++i) {
447 MonoBasicBlock *bb = cfg->bblocks [i];
450 if (!bb->live_out_set)
453 rem = max_vars % BITS_PER_CHUNK;
454 max = ((max_vars + (BITS_PER_CHUNK -1)) / BITS_PER_CHUNK);
455 for (j = 0; j < max; ++j) {
460 bits_in = mono_bitset_get_fast (bb->live_in_set, j);
461 bits_out = mono_bitset_get_fast (bb->live_out_set, j);
464 end = (j * BITS_PER_CHUNK) + rem;
466 end = (j * BITS_PER_CHUNK) + BITS_PER_CHUNK;
468 k = (j * BITS_PER_CHUNK);
469 while ((bits_in || bits_out)) {
471 update_live_range (cfg, k, bb->dfn, 0);
473 update_live_range (cfg, k, bb->dfn, 0xffff);
482 * Arguments need to have their live ranges extended to the beginning of
483 * the method to account for the arg reg/memory -> global register copies
484 * in the prolog (bug #74992).
487 for (i = 0; i < max_vars; i ++) {
488 MonoMethodVar *vi = MONO_VARINFO (cfg, i);
489 if (cfg->varinfo [vi->idx]->opcode == OP_ARG)
490 vi->range.first_use.abs_pos = 0;
493 #ifdef DEBUG_LIVENESS
494 for (i = cfg->num_bblocks - 1; i >= 0; i--) {
495 MonoBasicBlock *bb = cfg->bblocks [i];
497 printf ("LIVE IN BB%d: ", bb->block_num);
498 mono_bitset_print (bb->live_in_set);
499 printf ("LIVE OUT BB%d: ", bb->block_num);
500 mono_bitset_print (bb->live_out_set);
504 optimize_initlocals (cfg);
508 update_used (MonoCompile *cfg, MonoInst *inst, MonoBitSet *used)
510 int arity = mono_burg_arity [inst->opcode];
513 update_used (cfg, inst->inst_i0, used);
516 update_used (cfg, inst->inst_i1, used);
518 if (inst->ssa_op & MONO_SSA_LOAD_STORE) {
519 if (inst->ssa_op == MONO_SSA_LOAD) {
520 int idx = inst->inst_i0->inst_c0;
522 mono_bitset_set_fast (used, idx);
528 * optimize_initlocals:
530 * Try to optimize away some of the redundant initialization code inserted because of
531 * 'locals init' using the liveness information.
534 optimize_initlocals (MonoCompile *cfg)
538 MonoBasicBlock *initlocals_bb;
540 used = mono_bitset_new (cfg->num_varinfo, 0);
542 mono_bitset_clear_all (used);
543 initlocals_bb = cfg->bb_entry->next_bb;
544 for (ins = initlocals_bb->code; ins; ins = ins->next) {
545 update_used (cfg, ins, used);
548 for (ins = initlocals_bb->code; ins; ins = ins->next) {
549 if (ins->ssa_op == MONO_SSA_STORE) {
550 int idx = ins->inst_i0->inst_c0;
551 MonoInst *var = cfg->varinfo [idx];
553 if (var && !mono_bitset_test_fast (used, idx) && !mono_bitset_test_fast (initlocals_bb->live_out_set, var->inst_c0) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) {
554 if (ins->inst_i1 && ((ins->inst_i1->opcode == OP_ICONST) || (ins->inst_i1->opcode == OP_I8CONST))) {
556 ins->ssa_op = MONO_SSA_NOP;
557 MONO_VARINFO (cfg, var->inst_c0)->spill_costs -= 1;