1 /*
2 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
72 void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
73 int e = sux->number_of_exception_handlers();
74 for (int i = 0; i < e; i++) {
75 BlockBegin* xhandler = sux->exception_handler_at(i);
76 block->add_exception_handler(xhandler);
77
78 assert(xhandler->is_predecessor(sux), "missing predecessor");
79 if (sux->number_of_preds() == 0) {
80 // sux is disconnected from graph so disconnect from exception handlers
81 xhandler->remove_predecessor(sux);
82 }
83 if (!xhandler->is_predecessor(block)) {
84 xhandler->add_predecessor(block);
85 }
86 }
87 }
88
89 virtual void block_do(BlockBegin* block);
90
91 private:
92 Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval);
93 };
94
95 void CE_Eliminator::block_do(BlockBegin* block) {
96 // 1) find conditional expression
97 // check if block ends with an If
98 If* if_ = block->end()->as_If();
99 if (if_ == NULL) return;
100
101 // check if If works on int or object types
102 // (we cannot handle If's working on long, float or doubles yet,
103 // since IfOp doesn't support them - these If's show up if cmp
104 // operations followed by If's are eliminated)
105 ValueType* if_type = if_->x()->type();
106 if (!if_type->is_int() && !if_type->is_object()) return;
107
108 BlockBegin* t_block = if_->tsux();
109 BlockBegin* f_block = if_->fsux();
110 Instruction* t_cur = t_block->next();
111 Instruction* f_cur = f_block->next();
112
182
183 // 2) substitute conditional expression
184 // with an IfOp followed by a Goto
185 // cut if_ away and get node before
186 Instruction* cur_end = if_->prev();
187
188 // append constants of true- and false-block if necessary
189 // clone constants because original block must not be destroyed
190 assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
191 if (t_value == t_const) {
192 t_value = new Constant(t_const->type());
193 NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
194 cur_end = cur_end->set_next(t_value);
195 }
196 if (f_value == f_const) {
197 f_value = new Constant(f_const->type());
198 NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
199 cur_end = cur_end->set_next(f_value);
200 }
201
202 Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
203 assert(result != NULL, "make_ifop must return a non-null instruction");
204 if (!result->is_linked() && result->can_be_linked()) {
205 NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
206 cur_end = cur_end->set_next(result);
207 }
208
209 // append Goto to successor
210 ValueStack* state_before = if_->state_before();
211 Goto* goto_ = new Goto(sux, state_before, is_safepoint);
212
213 // prepare state for Goto
214 ValueStack* goto_state = if_state;
215 goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
216 goto_state->push(result->type(), result);
217 assert(goto_state->is_same(sux_state), "states must match now");
218 goto_->set_state(goto_state);
219
220 cur_end = cur_end->set_next(goto_, goto_state->bci());
221
222 // Adjust control flow graph
234 // update block end
235 block->set_end(goto_);
236
237 // substitute the phi if possible
238 if (sux_phi->as_Phi()->operand_count() == 1) {
239 assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
240 sux_phi->set_subst(result);
241 _has_substitution = true;
242 }
243
244 // 3) successfully eliminated a conditional expression
245 _cee_count++;
246 if (PrintCEE) {
247 tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id());
248 tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id());
249 }
250
251 _hir->verify();
252 }
253
254 Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) {
255 if (!OptimizeIfOps) {
256 return new IfOp(x, cond, y, tval, fval);
257 }
258
259 tval = tval->subst();
260 fval = fval->subst();
261 if (tval == fval) {
262 _ifop_count++;
263 return tval;
264 }
265
266 x = x->subst();
267 y = y->subst();
268
269 Constant* y_const = y->as_Constant();
270 if (y_const != NULL) {
271 IfOp* x_ifop = x->as_IfOp();
272 if (x_ifop != NULL) { // x is an ifop, y is a constant
273 Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant();
274 Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant();
275
276 if (x_tval_const != NULL && x_fval_const != NULL) {
277 Instruction::Condition x_ifop_cond = x_ifop->cond();
278
279 Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const);
280 Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const);
281
282 // not_comparable here is a valid return in case we're comparing unloaded oop constants
283 if (t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable) {
284 Value new_tval = t_compare_res == Constant::cond_true ? tval : fval;
285 Value new_fval = f_compare_res == Constant::cond_true ? tval : fval;
286
287 _ifop_count++;
288 if (new_tval == new_fval) {
289 return new_tval;
290 } else {
291 return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval);
292 }
293 }
294 }
295 } else {
296 Constant* x_const = x->as_Constant();
297 if (x_const != NULL) { // x and y are constants
298 Constant::CompareResult x_compare_res = x_const->compare(cond, y_const);
299 // not_comparable here is a valid return in case we're comparing unloaded oop constants
300 if (x_compare_res != Constant::not_comparable) {
301 _ifop_count++;
302 return x_compare_res == Constant::cond_true ? tval : fval;
303 }
304 }
305 }
306 }
307 return new IfOp(x, cond, y, tval, fval);
308 }
309
310 void Optimizer::eliminate_conditional_expressions() {
311 // find conditional expressions & replace them with IfOps
312 CE_Eliminator ce(ir());
313 }
314
315 class BlockMerger: public BlockClosure {
316 private:
317 IR* _hir;
318 int _merge_count; // the number of block pairs successfully merged
319
320 public:
321 BlockMerger(IR* hir)
322 : _hir(hir)
323 , _merge_count(0)
324 {
325 _hir->iterate_preorder(this);
326 CompileLog* log = _hir->compilation()->log();
327 if (log != NULL)
419 // When if_ and ifop are not in the same block, prev
420 // becomes NULL In such (rare) cases it is not
421 // profitable to perform the optimization.
422 Value prev = ifop;
423 while (prev != NULL && prev->next() != if_) {
424 prev = prev->next();
425 }
426
427 if (prev != NULL) {
428 Instruction::Condition cond = if_->cond();
429 BlockBegin* tsux = if_->tsux();
430 BlockBegin* fsux = if_->fsux();
431 if (swapped) {
432 cond = Instruction::mirror(cond);
433 }
434
435 BlockBegin* tblock = tval->compare(cond, con, tsux, fsux);
436 BlockBegin* fblock = fval->compare(cond, con, tsux, fsux);
437 if (tblock != fblock && !if_->is_safepoint()) {
438 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(),
439 tblock, fblock, if_->state_before(), if_->is_safepoint());
440 newif->set_state(if_->state()->copy());
441
442 assert(prev->next() == if_, "must be guaranteed by above search");
443 NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci()));
444 prev->set_next(newif);
445 block->set_end(newif);
446
447 _merge_count++;
448 if (PrintBlockElimination) {
449 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id());
450 }
451
452 _hir->verify();
453 }
454 }
455 }
456 }
457 }
458
459 return true;
|
1 /*
2 * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
72 void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
73 int e = sux->number_of_exception_handlers();
74 for (int i = 0; i < e; i++) {
75 BlockBegin* xhandler = sux->exception_handler_at(i);
76 block->add_exception_handler(xhandler);
77
78 assert(xhandler->is_predecessor(sux), "missing predecessor");
79 if (sux->number_of_preds() == 0) {
80 // sux is disconnected from graph so disconnect from exception handlers
81 xhandler->remove_predecessor(sux);
82 }
83 if (!xhandler->is_predecessor(block)) {
84 xhandler->add_predecessor(block);
85 }
86 }
87 }
88
89 virtual void block_do(BlockBegin* block);
90
91 private:
92 Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval,
93 ValueStack* state_before, bool substituability_check);
94 };
95
96 void CE_Eliminator::block_do(BlockBegin* block) {
97 // 1) find conditional expression
98 // check if block ends with an If
99 If* if_ = block->end()->as_If();
100 if (if_ == NULL) return;
101
102 // check if If works on int or object types
103 // (we cannot handle If's working on long, float or doubles yet,
104 // since IfOp doesn't support them - these If's show up if cmp
105 // operations followed by If's are eliminated)
106 ValueType* if_type = if_->x()->type();
107 if (!if_type->is_int() && !if_type->is_object()) return;
108
109 BlockBegin* t_block = if_->tsux();
110 BlockBegin* f_block = if_->fsux();
111 Instruction* t_cur = t_block->next();
112 Instruction* f_cur = f_block->next();
113
183
184 // 2) substitute conditional expression
185 // with an IfOp followed by a Goto
186 // cut if_ away and get node before
187 Instruction* cur_end = if_->prev();
188
189 // append constants of true- and false-block if necessary
190 // clone constants because original block must not be destroyed
191 assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
192 if (t_value == t_const) {
193 t_value = new Constant(t_const->type());
194 NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
195 cur_end = cur_end->set_next(t_value);
196 }
197 if (f_value == f_const) {
198 f_value = new Constant(f_const->type());
199 NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
200 cur_end = cur_end->set_next(f_value);
201 }
202
203 Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value,
204 if_->state_before(), if_->substituability_check());
205 assert(result != NULL, "make_ifop must return a non-null instruction");
206 if (!result->is_linked() && result->can_be_linked()) {
207 NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
208 cur_end = cur_end->set_next(result);
209 }
210
211 // append Goto to successor
212 ValueStack* state_before = if_->state_before();
213 Goto* goto_ = new Goto(sux, state_before, is_safepoint);
214
215 // prepare state for Goto
216 ValueStack* goto_state = if_state;
217 goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
218 goto_state->push(result->type(), result);
219 assert(goto_state->is_same(sux_state), "states must match now");
220 goto_->set_state(goto_state);
221
222 cur_end = cur_end->set_next(goto_, goto_state->bci());
223
224 // Adjust control flow graph
236 // update block end
237 block->set_end(goto_);
238
239 // substitute the phi if possible
240 if (sux_phi->as_Phi()->operand_count() == 1) {
241 assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
242 sux_phi->set_subst(result);
243 _has_substitution = true;
244 }
245
246 // 3) successfully eliminated a conditional expression
247 _cee_count++;
248 if (PrintCEE) {
249 tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id());
250 tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id());
251 }
252
253 _hir->verify();
254 }
255
256 Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval,
257 ValueStack* state_before, bool substituability_check) {
258 if (!OptimizeIfOps) {
259 return new IfOp(x, cond, y, tval, fval, state_before, substituability_check);
260 }
261
262 tval = tval->subst();
263 fval = fval->subst();
264 if (tval == fval) {
265 _ifop_count++;
266 return tval;
267 }
268
269 x = x->subst();
270 y = y->subst();
271
272 Constant* y_const = y->as_Constant();
273 if (y_const != NULL) {
274 IfOp* x_ifop = x->as_IfOp();
275 if (x_ifop != NULL) { // x is an ifop, y is a constant
276 Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant();
277 Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant();
278
279 if (x_tval_const != NULL && x_fval_const != NULL) {
280 Instruction::Condition x_ifop_cond = x_ifop->cond();
281
282 Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const);
283 Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const);
284
285 // not_comparable here is a valid return in case we're comparing unloaded oop constants
286 if (t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable) {
287 Value new_tval = t_compare_res == Constant::cond_true ? tval : fval;
288 Value new_fval = f_compare_res == Constant::cond_true ? tval : fval;
289
290 _ifop_count++;
291 if (new_tval == new_fval) {
292 return new_tval;
293 } else {
294 return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval, state_before, substituability_check);
295 }
296 }
297 }
298 } else {
299 Constant* x_const = x->as_Constant();
300 if (x_const != NULL) { // x and y are constants
301 Constant::CompareResult x_compare_res = x_const->compare(cond, y_const);
302 // not_comparable here is a valid return in case we're comparing unloaded oop constants
303 if (x_compare_res != Constant::not_comparable) {
304 _ifop_count++;
305 return x_compare_res == Constant::cond_true ? tval : fval;
306 }
307 }
308 }
309 }
310 return new IfOp(x, cond, y, tval, fval, state_before, substituability_check);
311 }
312
313 void Optimizer::eliminate_conditional_expressions() {
314 // find conditional expressions & replace them with IfOps
315 CE_Eliminator ce(ir());
316 }
317
318 class BlockMerger: public BlockClosure {
319 private:
320 IR* _hir;
321 int _merge_count; // the number of block pairs successfully merged
322
323 public:
324 BlockMerger(IR* hir)
325 : _hir(hir)
326 , _merge_count(0)
327 {
328 _hir->iterate_preorder(this);
329 CompileLog* log = _hir->compilation()->log();
330 if (log != NULL)
422 // When if_ and ifop are not in the same block, prev
423 // becomes NULL In such (rare) cases it is not
424 // profitable to perform the optimization.
425 Value prev = ifop;
426 while (prev != NULL && prev->next() != if_) {
427 prev = prev->next();
428 }
429
430 if (prev != NULL) {
431 Instruction::Condition cond = if_->cond();
432 BlockBegin* tsux = if_->tsux();
433 BlockBegin* fsux = if_->fsux();
434 if (swapped) {
435 cond = Instruction::mirror(cond);
436 }
437
438 BlockBegin* tblock = tval->compare(cond, con, tsux, fsux);
439 BlockBegin* fblock = fval->compare(cond, con, tsux, fsux);
440 if (tblock != fblock && !if_->is_safepoint()) {
441 If* newif = new If(ifop->x(), ifop->cond(), false, ifop->y(),
442 tblock, fblock, if_->state_before(), if_->is_safepoint(), if_->substituability_check());
443 newif->set_state(if_->state()->copy());
444
445 assert(prev->next() == if_, "must be guaranteed by above search");
446 NOT_PRODUCT(newif->set_printable_bci(if_->printable_bci()));
447 prev->set_next(newif);
448 block->set_end(newif);
449
450 _merge_count++;
451 if (PrintBlockElimination) {
452 tty->print_cr("%d. replaced If and IfOp at end of B%d with single If", _merge_count, block->block_id());
453 }
454
455 _hir->verify();
456 }
457 }
458 }
459 }
460 }
461
462 return true;
|