src/share/vm/opto/loopUnswitch.cpp

changeset 435
a61af66fc99e
child 543
a761c2d3b76a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/opto/loopUnswitch.cpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,237 @@
     1.4 +/*
     1.5 + * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "incls/_precompiled.incl"
    1.29 +#include "incls/_loopUnswitch.cpp.incl"
    1.30 +
    1.31 +//================= Loop Unswitching =====================
    1.32 +//
    1.33 +// orig:                       transformed:
    1.34 +//                               if (invariant-test) then
    1.35 +//  loop                           loop
    1.36 +//    stmt1                          stmt1
    1.37 +//    if (invariant-test) then       stmt2
    1.38 +//      stmt2                        stmt4
    1.39 +//    else                         endloop
    1.40 +//      stmt3                    else
    1.41 +//    endif                        loop [clone]
    1.42 +//    stmt4                          stmt1 [clone]
    1.43 +//  endloop                          stmt3
    1.44 +//                                   stmt4 [clone]
    1.45 +//                                 endloop
    1.46 +//                               endif
    1.47 +//
    1.48 +// Note: the "else" clause may be empty
    1.49 +
    1.50 +//------------------------------policy_unswitching-----------------------------
    1.51 +// Return TRUE or FALSE if the loop should be unswitched
    1.52 +// (ie. clone loop with an invariant test that does not exit the loop)
    1.53 +bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
    1.54 +  if( !LoopUnswitching ) {
    1.55 +    return false;
    1.56 +  }
    1.57 +  uint nodes_left = MaxNodeLimit - phase->C->unique();
    1.58 +  if (2 * _body.size() > nodes_left) {
    1.59 +    return false; // Too speculative if running low on nodes.
    1.60 +  }
    1.61 +  LoopNode* head = _head->as_Loop();
    1.62 +  if (head->unswitch_count() + 1 > head->unswitch_max()) {
    1.63 +    return false;
    1.64 +  }
    1.65 +  return phase->find_unswitching_candidate(this) != NULL;
    1.66 +}
    1.67 +
    1.68 +//------------------------------find_unswitching_candidate-----------------------------
    1.69 +// Find candidate "if" for unswitching
    1.70 +IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const {
    1.71 +
    1.72 +  // Find first invariant test that doesn't exit the loop
    1.73 +  LoopNode *head = loop->_head->as_Loop();
    1.74 +  IfNode* unswitch_iff = NULL;
    1.75 +  Node* n = head->in(LoopNode::LoopBackControl);
    1.76 +  while (n != head) {
    1.77 +    Node* n_dom = idom(n);
    1.78 +    if (n->is_Region()) {
    1.79 +      if (n_dom->is_If()) {
    1.80 +        IfNode* iff = n_dom->as_If();
    1.81 +        if (iff->in(1)->is_Bool()) {
    1.82 +          BoolNode* bol = iff->in(1)->as_Bool();
    1.83 +          if (bol->in(1)->is_Cmp()) {
    1.84 +            // If condition is invariant and not a loop exit,
    1.85 +            // then found reason to unswitch.
    1.86 +            if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) {
    1.87 +              unswitch_iff = iff;
    1.88 +            }
    1.89 +          }
    1.90 +        }
    1.91 +      }
    1.92 +    }
    1.93 +    n = n_dom;
    1.94 +  }
    1.95 +  return unswitch_iff;
    1.96 +}
    1.97 +
    1.98 +//------------------------------do_unswitching-----------------------------
    1.99 +// Clone loop with an invariant test (that does not exit) and
   1.100 +// insert a clone of the test that selects which version to
   1.101 +// execute.
   1.102 +void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) {
   1.103 +
   1.104 +  // Find first invariant test that doesn't exit the loop
   1.105 +  LoopNode *head = loop->_head->as_Loop();
   1.106 +
   1.107 +  IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop);
   1.108 +  assert(unswitch_iff != NULL, "should be at least one");
   1.109 +
   1.110 +  // Need to revert back to normal loop
   1.111 +  if (head->is_CountedLoop() && !head->as_CountedLoop()->is_normal_loop()) {
   1.112 +    head->as_CountedLoop()->set_normal_loop();
   1.113 +  }
   1.114 +
   1.115 +  ProjNode* proj_true = create_slow_version_of_loop(loop, old_new);
   1.116 +
   1.117 +  assert(proj_true->is_IfTrue() && proj_true->unique_ctrl_out() == head, "by construction");
   1.118 +
   1.119 +  // Increment unswitch count
   1.120 +  LoopNode* head_clone = old_new[head->_idx]->as_Loop();
   1.121 +  int nct = head->unswitch_count() + 1;
   1.122 +  head->set_unswitch_count(nct);
   1.123 +  head_clone->set_unswitch_count(nct);
   1.124 +
   1.125 +  // Add test to new "if" outside of loop
   1.126 +  IfNode* invar_iff   = proj_true->in(0)->as_If();
   1.127 +  Node* invar_iff_c   = invar_iff->in(0);
   1.128 +  BoolNode* bol       = unswitch_iff->in(1)->as_Bool();
   1.129 +  invar_iff->set_req(1, bol);
   1.130 +  invar_iff->_prob    = unswitch_iff->_prob;
   1.131 +
   1.132 +  ProjNode* proj_false = invar_iff->proj_out(0)->as_Proj();
   1.133 +
   1.134 +  // Hoist invariant casts out of each loop to the appropiate
   1.135 +  // control projection.
   1.136 +
   1.137 +  Node_List worklist;
   1.138 +
   1.139 +  for (DUIterator_Fast imax, i = unswitch_iff->fast_outs(imax); i < imax; i++) {
   1.140 +    ProjNode* proj= unswitch_iff->fast_out(i)->as_Proj();
   1.141 +    // Copy to a worklist for easier manipulation
   1.142 +    for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) {
   1.143 +      Node* use = proj->fast_out(j);
   1.144 +      if (use->Opcode() == Op_CheckCastPP && loop->is_invariant(use->in(1))) {
   1.145 +        worklist.push(use);
   1.146 +      }
   1.147 +    }
   1.148 +    ProjNode* invar_proj = invar_iff->proj_out(proj->_con)->as_Proj();
   1.149 +    while (worklist.size() > 0) {
   1.150 +      Node* use = worklist.pop();
   1.151 +      Node* nuse = use->clone();
   1.152 +      nuse->set_req(0, invar_proj);
   1.153 +      _igvn.hash_delete(use);
   1.154 +      use->set_req(1, nuse);
   1.155 +      _igvn._worklist.push(use);
   1.156 +      register_new_node(nuse, invar_proj);
   1.157 +      // Same for the clone
   1.158 +      Node* use_clone = old_new[use->_idx];
   1.159 +      _igvn.hash_delete(use_clone);
   1.160 +      use_clone->set_req(1, nuse);
   1.161 +      _igvn._worklist.push(use_clone);
   1.162 +    }
   1.163 +  }
   1.164 +
   1.165 +  // Hardwire the control paths in the loops into if(true) and if(false)
   1.166 +  _igvn.hash_delete(unswitch_iff);
   1.167 +  short_circuit_if(unswitch_iff, proj_true);
   1.168 +  _igvn._worklist.push(unswitch_iff);
   1.169 +
   1.170 +  IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If();
   1.171 +  _igvn.hash_delete(unswitch_iff_clone);
   1.172 +  short_circuit_if(unswitch_iff_clone, proj_false);
   1.173 +  _igvn._worklist.push(unswitch_iff_clone);
   1.174 +
   1.175 +  // Reoptimize loops
   1.176 +  loop->record_for_igvn();
   1.177 +  for(int i = loop->_body.size() - 1; i >= 0 ; i--) {
   1.178 +    Node *n = loop->_body[i];
   1.179 +    Node *n_clone = old_new[n->_idx];
   1.180 +    _igvn._worklist.push(n_clone);
   1.181 +  }
   1.182 +
   1.183 +#ifndef PRODUCT
   1.184 +  if (TraceLoopUnswitching) {
   1.185 +    tty->print_cr("Loop unswitching orig: %d @ %d  new: %d @ %d",
   1.186 +                  head->_idx,                unswitch_iff->_idx,
   1.187 +                  old_new[head->_idx]->_idx, unswitch_iff_clone->_idx);
   1.188 +  }
   1.189 +#endif
   1.190 +
   1.191 +  C->set_major_progress();
   1.192 +}
   1.193 +
   1.194 +//-------------------------create_slow_version_of_loop------------------------
   1.195 +// Create a slow version of the loop by cloning the loop
   1.196 +// and inserting an if to select fast-slow versions.
   1.197 +// Return control projection of the entry to the fast version.
   1.198 +ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop,
   1.199 +                                                      Node_List &old_new) {
   1.200 +  LoopNode* head  = loop->_head->as_Loop();
   1.201 +  Node*     entry = head->in(LoopNode::EntryControl);
   1.202 +  _igvn.hash_delete(entry);
   1.203 +  _igvn._worklist.push(entry);
   1.204 +  IdealLoopTree* outer_loop = loop->_parent;
   1.205 +
   1.206 +  Node *cont      = _igvn.intcon(1);
   1.207 +  set_ctrl(cont, C->root());
   1.208 +  Node* opq       = new (C, 2) Opaque1Node(cont);
   1.209 +  register_node(opq, outer_loop, entry, dom_depth(entry));
   1.210 +  Node *bol       = new (C, 2) Conv2BNode(opq);
   1.211 +  register_node(bol, outer_loop, entry, dom_depth(entry));
   1.212 +  IfNode* iff = new (C, 2) IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN);
   1.213 +  register_node(iff, outer_loop, entry, dom_depth(entry));
   1.214 +  ProjNode* iffast = new (C, 1) IfTrueNode(iff);
   1.215 +  register_node(iffast, outer_loop, iff, dom_depth(iff));
   1.216 +  ProjNode* ifslow = new (C, 1) IfFalseNode(iff);
   1.217 +  register_node(ifslow, outer_loop, iff, dom_depth(iff));
   1.218 +
   1.219 +  // Clone the loop body.  The clone becomes the fast loop.  The
   1.220 +  // original pre-header will (illegally) have 2 control users (old & new loops).
   1.221 +  clone_loop(loop, old_new, dom_depth(head), iff);
   1.222 +  assert(old_new[head->_idx]->is_Loop(), "" );
   1.223 +
   1.224 +  // Fast (true) control
   1.225 +  _igvn.hash_delete(head);
   1.226 +  head->set_req(LoopNode::EntryControl, iffast);
   1.227 +  set_idom(head, iffast, dom_depth(head));
   1.228 +  _igvn._worklist.push(head);
   1.229 +
   1.230 +  // Slow (false) control
   1.231 +  LoopNode* slow_head = old_new[head->_idx]->as_Loop();
   1.232 +  _igvn.hash_delete(slow_head);
   1.233 +  slow_head->set_req(LoopNode::EntryControl, ifslow);
   1.234 +  set_idom(slow_head, ifslow, dom_depth(slow_head));
   1.235 +  _igvn._worklist.push(slow_head);
   1.236 +
   1.237 +  recompute_dom_depth();
   1.238 +
   1.239 +  return iffast;
   1.240 +}

mercurial