2 * liveness.c: liveness analysis
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2002 Ximian, Inc.
13 //#define DEBUG_LIVENESS
16 extern guint8 mono_burg_arity [];
18 /* mono_bitset_mp_new:
20 * allocates a MonoBitSet inside a memory pool
23 mono_bitset_mp_new (MonoMemPool *mp, guint32 max_size)
25 int size = mono_bitset_alloc_size (max_size, 0);
28 mem = mono_mempool_alloc0 (mp, size);
29 return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE);
34 mono_bitset_print (MonoBitSet *set)
39 for (i = 0; i < mono_bitset_size (set); i++) {
41 if (mono_bitset_test (set, i))
50 update_live_range (MonoCompile *cfg, int idx, int block_dfn, int tree_pos)
52 MonoLiveRange *range = &MONO_VARINFO (cfg, idx)->range;
53 guint32 abs_pos = (block_dfn << 16) | tree_pos;
55 if (range->first_use.abs_pos > abs_pos)
56 range->first_use.abs_pos = abs_pos;
58 if (range->last_use.abs_pos < abs_pos)
59 range->last_use.abs_pos = abs_pos;
63 update_gen_kill_set (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, int inst_num)
65 int arity = mono_burg_arity [inst->opcode];
66 int max_vars = cfg->num_varinfo;
69 update_gen_kill_set (cfg, bb, inst->inst_i0, inst_num);
72 update_gen_kill_set (cfg, bb, inst->inst_i1, inst_num);
74 if (inst->ssa_op == MONO_SSA_LOAD) {
75 int idx = inst->inst_i0->inst_c0;
76 MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
77 g_assert (idx < max_vars);
78 update_live_range (cfg, idx, bb->dfn, inst_num);
79 if (!mono_bitset_test (bb->kill_set, idx))
80 mono_bitset_set (bb->gen_set, idx);
81 vi->spill_costs += 1 + (bb->nesting * 2);
82 } else if (inst->ssa_op == MONO_SSA_STORE) {
83 int idx = inst->inst_i0->inst_c0;
84 MonoMethodVar *vi = MONO_VARINFO (cfg, idx);
85 g_assert (idx < max_vars);
86 g_assert (inst->inst_i1->opcode != OP_PHI);
88 update_live_range (cfg, idx, bb->dfn, inst_num);
89 mono_bitset_set (bb->kill_set, idx);
90 vi->spill_costs += 1 + (bb->nesting * 2);
94 /* generic liveness analysis code. CFG specific parts are
95 * in update_gen_kill_set()
98 mono_analyze_liveness (MonoCompile *cfg)
100 MonoBitSet *old_live_in_set, *old_live_out_set;
102 int i, j, max_vars = cfg->num_varinfo;
104 #ifdef DEBUG_LIVENESS
105 printf ("LIVENLESS %s\n", mono_method_full_name (cfg->method, TRUE));
108 g_assert (!(cfg->comp_done & MONO_COMP_LIVENESS));
110 cfg->comp_done |= MONO_COMP_LIVENESS;
115 for (i = 0; i < cfg->num_bblocks; ++i) {
116 MonoBasicBlock *bb = cfg->bblocks [i];
118 bb->gen_set = mono_bitset_mp_new (cfg->mempool, max_vars);
119 bb->kill_set = mono_bitset_mp_new (cfg->mempool, max_vars);
120 bb->live_in_set = mono_bitset_mp_new (cfg->mempool, max_vars);
121 bb->live_out_set = mono_bitset_mp_new (cfg->mempool, max_vars);
124 for (i = 0; i < cfg->num_bblocks; ++i) {
125 MonoBasicBlock *bb = cfg->bblocks [i];
129 for (tree_num = 0, inst = bb->code; inst; inst = inst->next, tree_num++) {
130 //mono_print_tree (inst); printf ("\n");
131 update_gen_kill_set (cfg, bb, inst, tree_num);
134 #ifdef DEBUG_LIVENESS
135 printf ("BLOCK BB%d (", bb->block_num);
136 for (j = 0; j < bb->out_count; j++)
137 printf ("BB%d, ", bb->out_bb [j]->block_num);
140 printf ("GEN BB%d: ", bb->block_num); mono_bitset_print (bb->gen_set); printf ("\n");
141 printf ("KILL BB%d: ", bb->block_num); mono_bitset_print (bb->kill_set); printf ("\n");
145 old_live_in_set = mono_bitset_new (max_vars, 0);
146 old_live_out_set = mono_bitset_new (max_vars, 0);
151 for (i = cfg->num_bblocks - 1; i >= 0; i--) {
152 MonoBasicBlock *bb = cfg->bblocks [i];
154 mono_bitset_copyto (bb->live_in_set, old_live_in_set);
155 mono_bitset_copyto (bb->live_out_set, old_live_out_set);
157 mono_bitset_copyto (bb->live_out_set, bb->live_in_set);
158 mono_bitset_sub (bb->live_in_set, bb->kill_set);
159 mono_bitset_union (bb->live_in_set, bb->gen_set);
161 mono_bitset_clear_all (bb->live_out_set);
163 for (j = 0; j < bb->out_count; j++)
164 mono_bitset_union (bb->live_out_set, bb->out_bb [j]->live_in_set);
166 if (!(mono_bitset_equal (old_live_in_set, bb->live_in_set) &&
167 mono_bitset_equal (old_live_out_set, bb->live_out_set)))
173 mono_bitset_free (old_live_in_set);
174 mono_bitset_free (old_live_out_set);
176 for (i = 0; i < cfg->num_bblocks; ++i) {
177 MonoBasicBlock *bb = cfg->bblocks [i];
179 for (j = max_vars - 1; j >= 0; j--) {
181 if (mono_bitset_test (bb->live_in_set, j))
182 update_live_range (cfg, j, bb->dfn, 0);
184 if (mono_bitset_test (bb->live_out_set, j))
185 update_live_range (cfg, j, bb->dfn, 0xffff);
189 #ifdef DEBUG_LIVENESS
190 for (i = cfg->num_bblocks - 1; i >= 0; i--) {
191 MonoBasicBlock *bb = cfg->bblocks [i];
193 printf ("LIVE IN BB%d: ", bb->block_num);
194 mono_bitset_print (bb->live_in_set);
196 printf ("LIVE OUT BB%d: ", bb->block_num);
197 mono_bitset_print (bb->live_out_set);