hotspot/src/share/vm/c1/c1_Optimizer.cpp
changeset 7100 6bcf9255d470
parent 6745 a34ef8968a84
child 7397 5b173b4ca846
equal deleted inserted replaced
6778:e1b7673b2435 7100:6bcf9255d470
    36 
    36 
    37 class CE_Eliminator: public BlockClosure {
    37 class CE_Eliminator: public BlockClosure {
    38  private:
    38  private:
    39   IR* _hir;
    39   IR* _hir;
    40   int _cee_count;                                // the number of CEs successfully eliminated
    40   int _cee_count;                                // the number of CEs successfully eliminated
       
    41   int _ifop_count;                               // the number of IfOps successfully simplified
    41   int _has_substitution;
    42   int _has_substitution;
    42 
    43 
    43  public:
    44  public:
    44   CE_Eliminator(IR* hir) : _cee_count(0), _hir(hir) {
    45   CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) {
    45     _has_substitution = false;
    46     _has_substitution = false;
    46     _hir->iterate_preorder(this);
    47     _hir->iterate_preorder(this);
    47     if (_has_substitution) {
    48     if (_has_substitution) {
    48       // substituted some phis so resolve the substitution
    49       // substituted some ifops/phis, so resolve the substitution
    49       SubstitutionResolver sr(_hir);
    50       SubstitutionResolver sr(_hir);
    50     }
    51     }
    51   }
    52   }
    52   int cee_count() const                          { return _cee_count; }
    53   int cee_count() const                          { return _cee_count; }
       
    54   int ifop_count() const                         { return _ifop_count; }
    53 
    55 
    54   void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
    56   void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
    55     int e = sux->number_of_exception_handlers();
    57     int e = sux->number_of_exception_handlers();
    56     for (int i = 0; i < e; i++) {
    58     for (int i = 0; i < e; i++) {
    57       BlockBegin* xhandler = sux->exception_handler_at(i);
    59       BlockBegin* xhandler = sux->exception_handler_at(i);
    66         xhandler->add_predecessor(block);
    68         xhandler->add_predecessor(block);
    67       }
    69       }
    68     }
    70     }
    69   }
    71   }
    70 
    72 
    71   virtual void block_do(BlockBegin* block) {
    73   virtual void block_do(BlockBegin* block);
    72     // 1) find conditional expression
    74 
    73     // check if block ends with an If
    75  private:
    74     If* if_ = block->end()->as_If();
    76   Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval);
    75     if (if_ == NULL) return;
    77 };
    76 
    78 
    77     // check if If works on int or object types
    79 void CE_Eliminator::block_do(BlockBegin* block) {
    78     // (we cannot handle If's working on long, float or doubles yet,
    80   // 1) find conditional expression
    79     // since IfOp doesn't support them - these If's show up if cmp
    81   // check if block ends with an If
    80     // operations followed by If's are eliminated)
    82   If* if_ = block->end()->as_If();
    81     ValueType* if_type = if_->x()->type();
    83   if (if_ == NULL) return;
    82     if (!if_type->is_int() && !if_type->is_object()) return;
    84 
    83 
    85   // check if If works on int or object types
    84     BlockBegin* t_block = if_->tsux();
    86   // (we cannot handle If's working on long, float or doubles yet,
    85     BlockBegin* f_block = if_->fsux();
    87   // since IfOp doesn't support them - these If's show up if cmp
    86     Instruction* t_cur = t_block->next();
    88   // operations followed by If's are eliminated)
    87     Instruction* f_cur = f_block->next();
    89   ValueType* if_type = if_->x()->type();
    88 
    90   if (!if_type->is_int() && !if_type->is_object()) return;
    89     // one Constant may be present between BlockBegin and BlockEnd
    91 
    90     Value t_const = NULL;
    92   BlockBegin* t_block = if_->tsux();
    91     Value f_const = NULL;
    93   BlockBegin* f_block = if_->fsux();
    92     if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
    94   Instruction* t_cur = t_block->next();
    93       t_const = t_cur;
    95   Instruction* f_cur = f_block->next();
    94       t_cur = t_cur->next();
    96 
    95     }
    97   // one Constant may be present between BlockBegin and BlockEnd
    96     if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
    98   Value t_const = NULL;
    97       f_const = f_cur;
    99   Value f_const = NULL;
    98       f_cur = f_cur->next();
   100   if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
    99     }
   101     t_const = t_cur;
   100 
   102     t_cur = t_cur->next();
   101     // check if both branches end with a goto
   103   }
   102     Goto* t_goto = t_cur->as_Goto();
   104   if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
   103     if (t_goto == NULL) return;
   105     f_const = f_cur;
   104     Goto* f_goto = f_cur->as_Goto();
   106     f_cur = f_cur->next();
   105     if (f_goto == NULL) return;
   107   }
   106 
   108 
   107     // check if both gotos merge into the same block
   109   // check if both branches end with a goto
   108     BlockBegin* sux = t_goto->default_sux();
   110   Goto* t_goto = t_cur->as_Goto();
   109     if (sux != f_goto->default_sux()) return;
   111   if (t_goto == NULL) return;
   110 
   112   Goto* f_goto = f_cur->as_Goto();
   111     // check if at least one word was pushed on sux_state
   113   if (f_goto == NULL) return;
   112     ValueStack* sux_state = sux->state();
   114 
   113     if (sux_state->stack_size() <= if_->state()->stack_size()) return;
   115   // check if both gotos merge into the same block
   114 
   116   BlockBegin* sux = t_goto->default_sux();
   115     // check if phi function is present at end of successor stack and that
   117   if (sux != f_goto->default_sux()) return;
   116     // only this phi was pushed on the stack
   118 
   117     Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
   119   // check if at least one word was pushed on sux_state
   118     if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
   120   ValueStack* sux_state = sux->state();
   119     if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return;
   121   if (sux_state->stack_size() <= if_->state()->stack_size()) return;
   120 
   122 
   121     // get the values that were pushed in the true- and false-branch
   123   // check if phi function is present at end of successor stack and that
   122     Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
   124   // only this phi was pushed on the stack
   123     Value f_value = f_goto->state()->stack_at(if_->state()->stack_size());
   125   Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
   124 
   126   if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
   125     // backend does not support floats
   127   if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return;
   126     assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
   128 
   127     if (t_value->type()->is_float_kind()) return;
   129   // get the values that were pushed in the true- and false-branch
   128 
   130   Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
   129     // check that successor has no other phi functions but sux_phi
   131   Value f_value = f_goto->state()->stack_at(if_->state()->stack_size());
   130     // this can happen when t_block or f_block contained additonal stores to local variables
   132 
   131     // that are no longer represented by explicit instructions
   133   // backend does not support floats
   132     for_each_phi_fun(sux, phi,
   134   assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
   133                      if (phi != sux_phi) return;
   135   if (t_value->type()->is_float_kind()) return;
   134                      );
   136 
   135     // true and false blocks can't have phis
   137   // check that successor has no other phi functions but sux_phi
   136     for_each_phi_fun(t_block, phi, return; );
   138   // this can happen when t_block or f_block contained additonal stores to local variables
   137     for_each_phi_fun(f_block, phi, return; );
   139   // that are no longer represented by explicit instructions
   138 
   140   for_each_phi_fun(sux, phi,
   139     // 2) substitute conditional expression
   141                    if (phi != sux_phi) return;
   140     //    with an IfOp followed by a Goto
   142                    );
   141     // cut if_ away and get node before
   143   // true and false blocks can't have phis
   142     Instruction* cur_end = if_->prev(block);
   144   for_each_phi_fun(t_block, phi, return; );
   143 
   145   for_each_phi_fun(f_block, phi, return; );
   144     // append constants of true- and false-block if necessary
   146 
   145     // clone constants because original block must not be destroyed
   147   // 2) substitute conditional expression
   146     assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
   148   //    with an IfOp followed by a Goto
   147     if (t_value == t_const) {
   149   // cut if_ away and get node before
   148       t_value = new Constant(t_const->type());
   150   Instruction* cur_end = if_->prev(block);
   149       NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
   151 
   150       cur_end = cur_end->set_next(t_value);
   152   // append constants of true- and false-block if necessary
   151     }
   153   // clone constants because original block must not be destroyed
   152     if (f_value == f_const) {
   154   assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
   153       f_value = new Constant(f_const->type());
   155   if (t_value == t_const) {
   154       NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
   156     t_value = new Constant(t_const->type());
   155       cur_end = cur_end->set_next(f_value);
   157     NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
   156     }
   158     cur_end = cur_end->set_next(t_value);
   157 
   159   }
   158     // it is very unlikely that the condition can be statically decided
   160   if (f_value == f_const) {
   159     // (this was checked previously by the Canonicalizer), so always
   161     f_value = new Constant(f_const->type());
   160     // append IfOp
   162     NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
   161     Value result = new IfOp(if_->x(), if_->cond(), if_->y(), t_value, f_value);
   163     cur_end = cur_end->set_next(f_value);
       
   164   }
       
   165 
       
   166   Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
       
   167   assert(result != NULL, "make_ifop must return a non-null instruction");
       
   168   if (!result->is_linked() && result->can_be_linked()) {
   162     NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
   169     NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
   163     cur_end = cur_end->set_next(result);
   170     cur_end = cur_end->set_next(result);
   164 
   171   }
   165     // append Goto to successor
   172 
   166     ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
   173   // append Goto to successor
   167     Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
   174   ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
   168 
   175   Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
   169     // prepare state for Goto
   176 
   170     ValueStack* goto_state = if_->state();
   177   // prepare state for Goto
   171     while (sux_state->scope() != goto_state->scope()) {
   178   ValueStack* goto_state = if_->state();
   172       goto_state = goto_state->caller_state();
   179   while (sux_state->scope() != goto_state->scope()) {
   173       assert(goto_state != NULL, "states do not match up");
   180     goto_state = goto_state->caller_state();
   174     }
   181     assert(goto_state != NULL, "states do not match up");
   175     goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
   182   }
   176     goto_state->push(result->type(), result);
   183   goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
   177     assert(goto_state->is_same(sux_state), "states must match now");
   184   goto_state->push(result->type(), result);
   178     goto_->set_state(goto_state);
   185   assert(goto_state->is_same(sux_state), "states must match now");
   179 
   186   goto_->set_state(goto_state);
   180     cur_end = cur_end->set_next(goto_, goto_state->bci());
   187 
   181 
   188   cur_end = cur_end->set_next(goto_, goto_state->bci());
   182     // Adjust control flow graph
   189 
   183     BlockBegin::disconnect_edge(block, t_block);
   190   // Adjust control flow graph
   184     BlockBegin::disconnect_edge(block, f_block);
   191   BlockBegin::disconnect_edge(block, t_block);
   185     if (t_block->number_of_preds() == 0) {
   192   BlockBegin::disconnect_edge(block, f_block);
   186       BlockBegin::disconnect_edge(t_block, sux);
   193   if (t_block->number_of_preds() == 0) {
   187     }
   194     BlockBegin::disconnect_edge(t_block, sux);
   188     adjust_exception_edges(block, t_block);
   195   }
   189     if (f_block->number_of_preds() == 0) {
   196   adjust_exception_edges(block, t_block);
   190       BlockBegin::disconnect_edge(f_block, sux);
   197   if (f_block->number_of_preds() == 0) {
   191     }
   198     BlockBegin::disconnect_edge(f_block, sux);
   192     adjust_exception_edges(block, f_block);
   199   }
   193 
   200   adjust_exception_edges(block, f_block);
   194     // update block end
   201 
   195     block->set_end(goto_);
   202   // update block end
   196 
   203   block->set_end(goto_);
   197     // substitute the phi if possible
   204 
   198     if (sux_phi->as_Phi()->operand_count() == 1) {
   205   // substitute the phi if possible
   199       assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
   206   if (sux_phi->as_Phi()->operand_count() == 1) {
   200       sux_phi->set_subst(result);
   207     assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
   201       _has_substitution = true;
   208     sux_phi->set_subst(result);
   202     }
   209     _has_substitution = true;
   203 
   210   }
   204     // 3) successfully eliminated a conditional expression
   211 
   205     _cee_count++;
   212   // 3) successfully eliminated a conditional expression
   206     if (PrintCEE) {
   213   _cee_count++;
   207       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());
   214   if (PrintCEE) {
   208     }
   215     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());
   209 
   216     tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id());
   210     _hir->verify();
   217   }
   211   }
   218 
   212 };
   219   _hir->verify();
   213 
   220 }
       
   221 
       
   222 Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) {
       
   223   if (!OptimizeIfOps) {
       
   224     return new IfOp(x, cond, y, tval, fval);
       
   225   }
       
   226 
       
   227   tval = tval->subst();
       
   228   fval = fval->subst();
       
   229   if (tval == fval) {
       
   230     _ifop_count++;
       
   231     return tval;
       
   232   }
       
   233 
       
   234   x = x->subst();
       
   235   y = y->subst();
       
   236 
       
   237   Constant* y_const = y->as_Constant();
       
   238   if (y_const != NULL) {
       
   239     IfOp* x_ifop = x->as_IfOp();
       
   240     if (x_ifop != NULL) {                 // x is an ifop, y is a constant
       
   241       Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant();
       
   242       Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant();
       
   243 
       
   244       if (x_tval_const != NULL && x_fval_const != NULL) {
       
   245         Instruction::Condition x_ifop_cond = x_ifop->cond();
       
   246 
       
   247         Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const);
       
   248         Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const);
       
   249 
       
   250         guarantee(t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
       
   251 
       
   252         Value new_tval = t_compare_res == Constant::cond_true ? tval : fval;
       
   253         Value new_fval = f_compare_res == Constant::cond_true ? tval : fval;
       
   254 
       
   255         _ifop_count++;
       
   256         if (new_tval == new_fval) {
       
   257           return new_tval;
       
   258         } else {
       
   259           return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval);
       
   260         }
       
   261       }
       
   262     } else {
       
   263       Constant* x_const = x->as_Constant();
       
   264       if (x_const != NULL) {         // x and y are constants
       
   265         Constant::CompareResult x_compare_res = x_const->compare(cond, y_const);
       
   266         guarantee(x_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
       
   267 
       
   268         _ifop_count++;
       
   269         return x_compare_res == Constant::cond_true ? tval : fval;
       
   270       }
       
   271     }
       
   272   }
       
   273   return new IfOp(x, cond, y, tval, fval);
       
   274 }
   214 
   275 
   215 void Optimizer::eliminate_conditional_expressions() {
   276 void Optimizer::eliminate_conditional_expressions() {
   216   // find conditional expressions & replace them with IfOps
   277   // find conditional expressions & replace them with IfOps
   217   CE_Eliminator ce(ir());
   278   CE_Eliminator ce(ir());
   218 }
   279 }
   219 
       
   220 
   280 
   221 class BlockMerger: public BlockClosure {
   281 class BlockMerger: public BlockClosure {
   222  private:
   282  private:
   223   IR* _hir;
   283   IR* _hir;
   224   int _merge_count;              // the number of block pairs successfully merged
   284   int _merge_count;              // the number of block pairs successfully merged