Mercurial > hg > graal-compiler
comparison src/share/vm/c1/c1_Optimizer.cpp @ 1819:f02a8bbe6ed4
6986046: C1 valuestack cleanup
Summary: fixes an historical oddity in C1 with inlining where all of the expression stacks are kept in the topmost ValueStack instead of being in their respective ValueStacks.
Reviewed-by: never
Contributed-by: Christian Wimmer <cwimmer@uci.edu>
author | roland |
---|---|
date | Tue, 29 Dec 2009 19:08:54 +0100 |
parents | d5d065957597 |
children | 42a10fc37986 |
comparison
equal
deleted
inserted
replaced
1817:c40600e85311 | 1819:f02a8bbe6ed4 |
---|---|
138 | 138 |
139 // 2) substitute conditional expression | 139 // 2) substitute conditional expression |
140 // with an IfOp followed by a Goto | 140 // with an IfOp followed by a Goto |
141 // cut if_ away and get node before | 141 // cut if_ away and get node before |
142 Instruction* cur_end = if_->prev(block); | 142 Instruction* cur_end = if_->prev(block); |
143 int bci = if_->bci(); | |
144 | 143 |
145 // append constants of true- and false-block if necessary | 144 // append constants of true- and false-block if necessary |
146 // clone constants because original block must not be destroyed | 145 // clone constants because original block must not be destroyed |
147 assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch"); | 146 assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch"); |
148 if (t_value == t_const) { | 147 if (t_value == t_const) { |
149 t_value = new Constant(t_const->type()); | 148 t_value = new Constant(t_const->type()); |
150 cur_end = cur_end->set_next(t_value, bci); | 149 NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci())); |
150 cur_end = cur_end->set_next(t_value); | |
151 } | 151 } |
152 if (f_value == f_const) { | 152 if (f_value == f_const) { |
153 f_value = new Constant(f_const->type()); | 153 f_value = new Constant(f_const->type()); |
154 cur_end = cur_end->set_next(f_value, bci); | 154 NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci())); |
155 cur_end = cur_end->set_next(f_value); | |
155 } | 156 } |
156 | 157 |
157 // it is very unlikely that the condition can be statically decided | 158 // it is very unlikely that the condition can be statically decided |
158 // (this was checked previously by the Canonicalizer), so always | 159 // (this was checked previously by the Canonicalizer), so always |
159 // append IfOp | 160 // append IfOp |
160 Value result = new IfOp(if_->x(), if_->cond(), if_->y(), t_value, f_value); | 161 Value result = new IfOp(if_->x(), if_->cond(), if_->y(), t_value, f_value); |
161 cur_end = cur_end->set_next(result, bci); | 162 NOT_PRODUCT(result->set_printable_bci(if_->printable_bci())); |
163 cur_end = cur_end->set_next(result); | |
162 | 164 |
163 // append Goto to successor | 165 // append Goto to successor |
164 ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL; | 166 ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL; |
165 Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint()); | 167 Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint()); |
166 | 168 |
167 // prepare state for Goto | 169 // prepare state for Goto |
168 ValueStack* goto_state = if_->state(); | 170 ValueStack* goto_state = if_->state(); |
169 while (sux_state->scope() != goto_state->scope()) { | 171 while (sux_state->scope() != goto_state->scope()) { |
170 goto_state = goto_state->pop_scope(); | 172 goto_state = goto_state->caller_state(); |
171 assert(goto_state != NULL, "states do not match up"); | 173 assert(goto_state != NULL, "states do not match up"); |
172 } | 174 } |
173 goto_state = goto_state->copy(); | 175 goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci()); |
174 goto_state->push(result->type(), result); | 176 goto_state->push(result->type(), result); |
175 assert(goto_state->is_same_across_scopes(sux_state), "states must match now"); | 177 assert(goto_state->is_same(sux_state), "states must match now"); |
176 goto_->set_state(goto_state); | 178 goto_->set_state(goto_state); |
177 | 179 |
178 // Steal the bci for the goto from the sux | 180 cur_end = cur_end->set_next(goto_, goto_state->bci()); |
179 cur_end = cur_end->set_next(goto_, sux->bci()); | |
180 | 181 |
181 // Adjust control flow graph | 182 // Adjust control flow graph |
182 BlockBegin::disconnect_edge(block, t_block); | 183 BlockBegin::disconnect_edge(block, t_block); |
183 BlockBegin::disconnect_edge(block, f_block); | 184 BlockBegin::disconnect_edge(block, f_block); |
184 if (t_block->number_of_preds() == 0) { | 185 if (t_block->number_of_preds() == 0) { |
249 #ifdef ASSERT | 250 #ifdef ASSERT |
250 // verify that state at the end of block and at the beginning of sux are equal | 251 // verify that state at the end of block and at the beginning of sux are equal |
251 // no phi functions must be present at beginning of sux | 252 // no phi functions must be present at beginning of sux |
252 ValueStack* sux_state = sux->state(); | 253 ValueStack* sux_state = sux->state(); |
253 ValueStack* end_state = end->state(); | 254 ValueStack* end_state = end->state(); |
254 while (end_state->scope() != sux_state->scope()) { | 255 |
255 // match up inlining level | 256 assert(end_state->scope() == sux_state->scope(), "scopes must match"); |
256 end_state = end_state->pop_scope(); | |
257 } | |
258 assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); | 257 assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal"); |
259 assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); | 258 assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal"); |
260 | 259 |
261 int index; | 260 int index; |
262 Value sux_value; | 261 Value sux_value; |
271 | 270 |
272 // find instruction before end & append first instruction of sux block | 271 // find instruction before end & append first instruction of sux block |
273 Instruction* prev = end->prev(block); | 272 Instruction* prev = end->prev(block); |
274 Instruction* next = sux->next(); | 273 Instruction* next = sux->next(); |
275 assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); | 274 assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd"); |
276 prev->set_next(next, next->bci()); | 275 prev->set_next(next); |
277 sux->disconnect_from_graph(); | 276 sux->disconnect_from_graph(); |
278 block->set_end(sux->end()); | 277 block->set_end(sux->end()); |
279 // add exception handlers of deleted block, if any | 278 // add exception handlers of deleted block, if any |
280 for (int k = 0; k < sux->number_of_exception_handlers(); k++) { | 279 for (int k = 0; k < sux->number_of_exception_handlers(); k++) { |
281 BlockBegin* xhandler = sux->exception_handler_at(k); | 280 BlockBegin* xhandler = sux->exception_handler_at(k); |
335 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), | 334 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(), |
336 tblock, fblock, if_->state_before(), if_->is_safepoint()); | 335 tblock, fblock, if_->state_before(), if_->is_safepoint()); |
337 newif->set_state(if_->state()->copy()); | 336 newif->set_state(if_->state()->copy()); |
338 | 337 |
339 assert(prev->next() == if_, "must be guaranteed by above search"); | 338 assert(prev->next() == if_, "must be guaranteed by above search"); |
340 prev->set_next(newif, if_->bci()); | 339 NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci())); |
340 prev->set_next(newif); | |
341 block->set_end(newif); | 341 block->set_end(newif); |
342 | 342 |
343 _merge_count++; | 343 _merge_count++; |
344 if (PrintBlockElimination) { | 344 if (PrintBlockElimination) { |
345 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); | 345 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id()); |
703 // Mark instructions in this block as visitable as they are seen | 703 // Mark instructions in this block as visitable as they are seen |
704 // in the instruction list. This keeps the iteration from | 704 // in the instruction list. This keeps the iteration from |
705 // visiting instructions which are references in other blocks or | 705 // visiting instructions which are references in other blocks or |
706 // visiting instructions more than once. | 706 // visiting instructions more than once. |
707 mark_visitable(instr); | 707 mark_visitable(instr); |
708 if (instr->is_root() || instr->can_trap() || (instr->as_NullCheck() != NULL)) { | 708 if (instr->is_pinned() || instr->can_trap() || (instr->as_NullCheck() != NULL)) { |
709 mark_visited(instr); | 709 mark_visited(instr); |
710 instr->input_values_do(this); | 710 instr->input_values_do(this); |
711 instr->visit(&_visitor); | 711 instr->visit(&_visitor); |
712 } | 712 } |
713 } | 713 } |