src/share/vm/c1/c1_Optimizer.cpp

Print this page
rev 4136 : 7153771: array bound check elimination for c1
Summary: when possible optimize out array bound checks, inserting predicates when needed.
Reviewed-by:


 161   Value t_value = t_goto->state()->stack_at(if_state->stack_size());
 162   Value f_value = f_goto->state()->stack_at(if_state->stack_size());
 163 
 164   // backend does not support floats
 165   assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
 166   if (t_value->type()->is_float_kind()) return;
 167 
 168   // check that successor has no other phi functions but sux_phi
 169   // this can happen when t_block or f_block contained additonal stores to local variables
 170   // that are no longer represented by explicit instructions
 171   for_each_phi_fun(sux, phi,
 172                    if (phi != sux_phi) return;
 173                    );
 174   // true and false blocks can't have phis
 175   for_each_phi_fun(t_block, phi, return; );
 176   for_each_phi_fun(f_block, phi, return; );
 177 
 178   // 2) substitute conditional expression
 179   //    with an IfOp followed by a Goto
 180   // cut if_ away and get node before
 181   Instruction* cur_end = if_->prev(block);
 182 
 183   // append constants of true- and false-block if necessary
 184   // clone constants because original block must not be destroyed
 185   assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
 186   if (t_value == t_const) {
 187     t_value = new Constant(t_const->type());
 188     NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
 189     cur_end = cur_end->set_next(t_value);
 190   }
 191   if (f_value == f_const) {
 192     f_value = new Constant(f_const->type());
 193     NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
 194     cur_end = cur_end->set_next(f_value);
 195   }
 196 
 197   Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
 198   assert(result != NULL, "make_ifop must return a non-null instruction");
 199   if (!result->is_linked() && result->can_be_linked()) {
 200     NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
 201     cur_end = cur_end->set_next(result);
 202   }
 203 
 204   // append Goto to successor
 205   ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
 206   Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
 207 
 208   // prepare state for Goto
 209   ValueStack* goto_state = if_state;
 210   goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
 211   goto_state->push(result->type(), result);
 212   assert(goto_state->is_same(sux_state), "states must match now");
 213   goto_->set_state(goto_state);
 214 
 215   cur_end = cur_end->set_next(goto_, goto_state->bci());
 216 
 217   // Adjust control flow graph
 218   BlockBegin::disconnect_edge(block, t_block);
 219   BlockBegin::disconnect_edge(block, f_block);
 220   if (t_block->number_of_preds() == 0) {
 221     BlockBegin::disconnect_edge(t_block, sux);
 222   }
 223   adjust_exception_edges(block, t_block);
 224   if (f_block->number_of_preds() == 0) {
 225     BlockBegin::disconnect_edge(f_block, sux);


 350         // no phi functions must be present at beginning of sux
 351         ValueStack* sux_state = sux->state();
 352         ValueStack* end_state = end->state();
 353 
 354         assert(end_state->scope() == sux_state->scope(), "scopes must match");
 355         assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal");
 356         assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal");
 357 
 358         int index;
 359         Value sux_value;
 360         for_each_stack_value(sux_state, index, sux_value) {
 361           assert(sux_value == end_state->stack_at(index), "stack not equal");
 362         }
 363         for_each_local_value(sux_state, index, sux_value) {
 364           assert(sux_value == end_state->local_at(index), "locals not equal");
 365         }
 366         assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal");
 367 #endif
 368 
 369         // find instruction before end & append first instruction of sux block
 370         Instruction* prev = end->prev(block);
 371         Instruction* next = sux->next();
 372         assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd");
 373         prev->set_next(next);

 374         sux->disconnect_from_graph();
 375         block->set_end(sux->end());
 376         // add exception handlers of deleted block, if any
 377         for (int k = 0; k < sux->number_of_exception_handlers(); k++) {
 378           BlockBegin* xhandler = sux->exception_handler_at(k);
 379           block->add_exception_handler(xhandler);
 380 
 381           // also substitute predecessor of exception handler
 382           assert(xhandler->is_predecessor(sux), "missing predecessor");
 383           xhandler->remove_predecessor(sux);
 384           if (!xhandler->is_predecessor(block)) {
 385             xhandler->add_predecessor(block);
 386           }
 387         }
 388 
 389         // debugging output
 390         _merge_count++;
 391         if (PrintBlockElimination) {
 392           tty->print_cr("%d. merged B%d & B%d (stack size = %d)",
 393                         _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size());


 516   void do_IfInstanceOf   (IfInstanceOf*    x);
 517   void do_TableSwitch    (TableSwitch*     x);
 518   void do_LookupSwitch   (LookupSwitch*    x);
 519   void do_Return         (Return*          x);
 520   void do_Throw          (Throw*           x);
 521   void do_Base           (Base*            x);
 522   void do_OsrEntry       (OsrEntry*        x);
 523   void do_ExceptionObject(ExceptionObject* x);
 524   void do_RoundFP        (RoundFP*         x);
 525   void do_UnsafeGetRaw   (UnsafeGetRaw*    x);
 526   void do_UnsafePutRaw   (UnsafePutRaw*    x);
 527   void do_UnsafeGetObject(UnsafeGetObject* x);
 528   void do_UnsafePutObject(UnsafePutObject* x);
 529   void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x);
 530   void do_UnsafePrefetchRead (UnsafePrefetchRead*  x);
 531   void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
 532   void do_ProfileCall    (ProfileCall*     x);
 533   void do_ProfileInvoke  (ProfileInvoke*   x);
 534   void do_RuntimeCall    (RuntimeCall*     x);
 535   void do_MemBar         (MemBar*          x);


 536 };
 537 
 538 
 539 // Because of a static contained within (for the purpose of iteration
 540 // over instructions), it is only valid to have one of these active at
 541 // a time
 542 class NullCheckEliminator: public ValueVisitor {
 543  private:
 544   Optimizer*        _opt;
 545 
 546   ValueSet*         _visitable_instructions;        // Visit each instruction only once per basic block
 547   BlockList*        _work_list;                   // Basic blocks to visit
 548 
 549   bool visitable(Value x) {
 550     assert(_visitable_instructions != NULL, "check");
 551     return _visitable_instructions->contains(x);
 552   }
 553   void mark_visited(Value x) {
 554     assert(_visitable_instructions != NULL, "check");
 555     _visitable_instructions->remove(x);


 697 void NullCheckVisitor::do_IfInstanceOf   (IfInstanceOf*    x) {}
 698 void NullCheckVisitor::do_TableSwitch    (TableSwitch*     x) {}
 699 void NullCheckVisitor::do_LookupSwitch   (LookupSwitch*    x) {}
 700 void NullCheckVisitor::do_Return         (Return*          x) {}
 701 void NullCheckVisitor::do_Throw          (Throw*           x) { nce()->clear_last_explicit_null_check(); }
 702 void NullCheckVisitor::do_Base           (Base*            x) {}
 703 void NullCheckVisitor::do_OsrEntry       (OsrEntry*        x) {}
 704 void NullCheckVisitor::do_ExceptionObject(ExceptionObject* x) { nce()->handle_ExceptionObject(x); }
 705 void NullCheckVisitor::do_RoundFP        (RoundFP*         x) {}
 706 void NullCheckVisitor::do_UnsafeGetRaw   (UnsafeGetRaw*    x) {}
 707 void NullCheckVisitor::do_UnsafePutRaw   (UnsafePutRaw*    x) {}
 708 void NullCheckVisitor::do_UnsafeGetObject(UnsafeGetObject* x) {}
 709 void NullCheckVisitor::do_UnsafePutObject(UnsafePutObject* x) {}
 710 void NullCheckVisitor::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {}
 711 void NullCheckVisitor::do_UnsafePrefetchRead (UnsafePrefetchRead*  x) {}
 712 void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {}
 713 void NullCheckVisitor::do_ProfileCall    (ProfileCall*     x) { nce()->clear_last_explicit_null_check(); }
 714 void NullCheckVisitor::do_ProfileInvoke  (ProfileInvoke*   x) {}
 715 void NullCheckVisitor::do_RuntimeCall    (RuntimeCall*     x) {}
 716 void NullCheckVisitor::do_MemBar         (MemBar*          x) {}


 717 
 718 
 719 void NullCheckEliminator::visit(Value* p) {
 720   assert(*p != NULL, "should not find NULL instructions");
 721   if (visitable(*p)) {
 722     mark_visited(*p);
 723     (*p)->visit(&_visitor);
 724   }
 725 }
 726 
 727 bool NullCheckEliminator::merge_state_for(BlockBegin* block, ValueSet* incoming_state) {
 728   ValueSet* state = state_for(block);
 729   if (state == NULL) {
 730     state = incoming_state->copy();
 731     set_state_for(block, state);
 732     return true;
 733   } else {
 734     bool changed = state->set_intersect(incoming_state);
 735     if (PrintNullCheckElimination && changed) {
 736       tty->print_cr("Block %d's null check state changed", block->block_id());




 161   Value t_value = t_goto->state()->stack_at(if_state->stack_size());
 162   Value f_value = f_goto->state()->stack_at(if_state->stack_size());
 163 
 164   // backend does not support floats
 165   assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
 166   if (t_value->type()->is_float_kind()) return;
 167 
 168   // check that successor has no other phi functions but sux_phi
 169   // this can happen when t_block or f_block contained additonal stores to local variables
 170   // that are no longer represented by explicit instructions
 171   for_each_phi_fun(sux, phi,
 172                    if (phi != sux_phi) return;
 173                    );
 174   // true and false blocks can't have phis
 175   for_each_phi_fun(t_block, phi, return; );
 176   for_each_phi_fun(f_block, phi, return; );
 177 
 178   // 2) substitute conditional expression
 179   //    with an IfOp followed by a Goto
 180   // cut if_ away and get node before
 181   Instruction* cur_end = if_->prev();
 182 
 183   // append constants of true- and false-block if necessary
 184   // clone constants because original block must not be destroyed
 185   assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
 186   if (t_value == t_const) {
 187     t_value = new Constant(t_const->type());
 188     NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
 189     cur_end = cur_end->set_next(t_value);
 190   }
 191   if (f_value == f_const) {
 192     f_value = new Constant(f_const->type());
 193     NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
 194     cur_end = cur_end->set_next(f_value);
 195   }
 196 
 197   Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
 198   assert(result != NULL, "make_ifop must return a non-null instruction");
 199   if (!result->is_linked() && result->can_be_linked()) {
 200     NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
 201     cur_end = cur_end->set_next(result);
 202   }
 203 
 204   // append Goto to successor
 205   ValueStack* state_before = if_->state_before();
 206   Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
 207 
 208   // prepare state for Goto
 209   ValueStack* goto_state = if_state;
 210   goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
 211   goto_state->push(result->type(), result);
 212   assert(goto_state->is_same(sux_state), "states must match now");
 213   goto_->set_state(goto_state);
 214 
 215   cur_end = cur_end->set_next(goto_, goto_state->bci());
 216 
 217   // Adjust control flow graph
 218   BlockBegin::disconnect_edge(block, t_block);
 219   BlockBegin::disconnect_edge(block, f_block);
 220   if (t_block->number_of_preds() == 0) {
 221     BlockBegin::disconnect_edge(t_block, sux);
 222   }
 223   adjust_exception_edges(block, t_block);
 224   if (f_block->number_of_preds() == 0) {
 225     BlockBegin::disconnect_edge(f_block, sux);


 350         // no phi functions must be present at beginning of sux
 351         ValueStack* sux_state = sux->state();
 352         ValueStack* end_state = end->state();
 353 
 354         assert(end_state->scope() == sux_state->scope(), "scopes must match");
 355         assert(end_state->stack_size() == sux_state->stack_size(), "stack not equal");
 356         assert(end_state->locals_size() == sux_state->locals_size(), "locals not equal");
 357 
 358         int index;
 359         Value sux_value;
 360         for_each_stack_value(sux_state, index, sux_value) {
 361           assert(sux_value == end_state->stack_at(index), "stack not equal");
 362         }
 363         for_each_local_value(sux_state, index, sux_value) {
 364           assert(sux_value == end_state->local_at(index), "locals not equal");
 365         }
 366         assert(sux_state->caller_state() == end_state->caller_state(), "caller not equal");
 367 #endif
 368 
 369         // find instruction before end & append first instruction of sux block
 370         Instruction* prev = end->prev();
 371         Instruction* next = sux->next();
 372         assert(prev->as_BlockEnd() == NULL, "must not be a BlockEnd");
 373         prev->set_next(next);
 374         prev->fixup_block_pointers();
 375         sux->disconnect_from_graph();
 376         block->set_end(sux->end());
 377         // add exception handlers of deleted block, if any
 378         for (int k = 0; k < sux->number_of_exception_handlers(); k++) {
 379           BlockBegin* xhandler = sux->exception_handler_at(k);
 380           block->add_exception_handler(xhandler);
 381 
 382           // also substitute predecessor of exception handler
 383           assert(xhandler->is_predecessor(sux), "missing predecessor");
 384           xhandler->remove_predecessor(sux);
 385           if (!xhandler->is_predecessor(block)) {
 386             xhandler->add_predecessor(block);
 387           }
 388         }
 389 
 390         // debugging output
 391         _merge_count++;
 392         if (PrintBlockElimination) {
 393           tty->print_cr("%d. merged B%d & B%d (stack size = %d)",
 394                         _merge_count, block->block_id(), sux->block_id(), sux->state()->stack_size());


 517   void do_IfInstanceOf   (IfInstanceOf*    x);
 518   void do_TableSwitch    (TableSwitch*     x);
 519   void do_LookupSwitch   (LookupSwitch*    x);
 520   void do_Return         (Return*          x);
 521   void do_Throw          (Throw*           x);
 522   void do_Base           (Base*            x);
 523   void do_OsrEntry       (OsrEntry*        x);
 524   void do_ExceptionObject(ExceptionObject* x);
 525   void do_RoundFP        (RoundFP*         x);
 526   void do_UnsafeGetRaw   (UnsafeGetRaw*    x);
 527   void do_UnsafePutRaw   (UnsafePutRaw*    x);
 528   void do_UnsafeGetObject(UnsafeGetObject* x);
 529   void do_UnsafePutObject(UnsafePutObject* x);
 530   void do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x);
 531   void do_UnsafePrefetchRead (UnsafePrefetchRead*  x);
 532   void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x);
 533   void do_ProfileCall    (ProfileCall*     x);
 534   void do_ProfileInvoke  (ProfileInvoke*   x);
 535   void do_RuntimeCall    (RuntimeCall*     x);
 536   void do_MemBar         (MemBar*          x);
 537   void do_RangeCheckPredicate(RangeCheckPredicate* x);
 538   void do_Assert         (Assert*          x);
 539 };
 540 
 541 
 542 // Because of a static contained within (for the purpose of iteration
 543 // over instructions), it is only valid to have one of these active at
 544 // a time
 545 class NullCheckEliminator: public ValueVisitor {
 546  private:
 547   Optimizer*        _opt;
 548 
 549   ValueSet*         _visitable_instructions;        // Visit each instruction only once per basic block
 550   BlockList*        _work_list;                   // Basic blocks to visit
 551 
 552   bool visitable(Value x) {
 553     assert(_visitable_instructions != NULL, "check");
 554     return _visitable_instructions->contains(x);
 555   }
 556   void mark_visited(Value x) {
 557     assert(_visitable_instructions != NULL, "check");
 558     _visitable_instructions->remove(x);


 700 void NullCheckVisitor::do_IfInstanceOf   (IfInstanceOf*    x) {}
 701 void NullCheckVisitor::do_TableSwitch    (TableSwitch*     x) {}
 702 void NullCheckVisitor::do_LookupSwitch   (LookupSwitch*    x) {}
 703 void NullCheckVisitor::do_Return         (Return*          x) {}
 704 void NullCheckVisitor::do_Throw          (Throw*           x) { nce()->clear_last_explicit_null_check(); }
 705 void NullCheckVisitor::do_Base           (Base*            x) {}
 706 void NullCheckVisitor::do_OsrEntry       (OsrEntry*        x) {}
 707 void NullCheckVisitor::do_ExceptionObject(ExceptionObject* x) { nce()->handle_ExceptionObject(x); }
 708 void NullCheckVisitor::do_RoundFP        (RoundFP*         x) {}
 709 void NullCheckVisitor::do_UnsafeGetRaw   (UnsafeGetRaw*    x) {}
 710 void NullCheckVisitor::do_UnsafePutRaw   (UnsafePutRaw*    x) {}
 711 void NullCheckVisitor::do_UnsafeGetObject(UnsafeGetObject* x) {}
 712 void NullCheckVisitor::do_UnsafePutObject(UnsafePutObject* x) {}
 713 void NullCheckVisitor::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {}
 714 void NullCheckVisitor::do_UnsafePrefetchRead (UnsafePrefetchRead*  x) {}
 715 void NullCheckVisitor::do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) {}
 716 void NullCheckVisitor::do_ProfileCall    (ProfileCall*     x) { nce()->clear_last_explicit_null_check(); }
 717 void NullCheckVisitor::do_ProfileInvoke  (ProfileInvoke*   x) {}
 718 void NullCheckVisitor::do_RuntimeCall    (RuntimeCall*     x) {}
 719 void NullCheckVisitor::do_MemBar         (MemBar*          x) {}
 720 void NullCheckVisitor::do_RangeCheckPredicate(RangeCheckPredicate* x) {}
 721 void NullCheckVisitor::do_Assert         (Assert*          x) {}
 722 
 723 
 724 void NullCheckEliminator::visit(Value* p) {
 725   assert(*p != NULL, "should not find NULL instructions");
 726   if (visitable(*p)) {
 727     mark_visited(*p);
 728     (*p)->visit(&_visitor);
 729   }
 730 }
 731 
 732 bool NullCheckEliminator::merge_state_for(BlockBegin* block, ValueSet* incoming_state) {
 733   ValueSet* state = state_for(block);
 734   if (state == NULL) {
 735     state = incoming_state->copy();
 736     set_state_for(block, state);
 737     return true;
 738   } else {
 739     bool changed = state->set_intersect(incoming_state);
 740     if (PrintNullCheckElimination && changed) {
 741       tty->print_cr("Block %d's null check state changed", block->block_id());