< prev index next >

src/hotspot/share/c1/c1_Optimizer.cpp

Print this page
   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;


< prev index next >