Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6591322

During the Split-If optimization, handle all invariant data uses before all the invariant control uses

XMLWordPrintable

    • generic
    • generic

      During the Split-If optimization, C2 should handle all invariant data uses before all the invariant control uses.

      Here is a suggested fix to this problem.

      ==== //java/main-dev/java/hotspot5/src/share/vm/opto/loopnode.hpp#15 - /home/cliffc/HotSpot/cliffc-bugs/hotspot5/src/share/vm/opto/loopnode.hpp ====
      @@ -600,6 +600,7 @@
         // normal "loop-exit" condition. All uses of loop-invariant old-loop values
         // now come from (one or more) Phis that merge their new-loop equivalents.
         void clone_loop( IdealLoopTree *loop, Node_List &old_new, int dom_depth, bool clone_after );
      + void handle_invariant_uses( Node *old, IdealLoopTree *loop, Node_List &old_new, Node_List *worklist, Node **old_idoms, int old_idom_size, int new_counter, int loopbodysize, Node_List **split_if_set, Node_List **split_bool_set);
       
         // If we got the effect of peeling, either by actually peeling or by
         // making a pre-loop which must execute at least once, we can remove
      ==== //java/main-dev/java/hotspot5/src/share/vm/opto/loopopts.cpp#17 - /home/cliffc/HotSpot/cliffc-bugs/hotspot5/src/share/vm/opto/loopopts.cpp ====
      @@ -1504,15 +1504,57 @@
         Node_List *split_bool_set = NULL;
         for( i = 0; i < loopbodysize; i++ ) {
           Node* old = loop->_body.at(i);
      - Node* nnn = old_new[old->_idx];
      - // Copy uses to a worklist, so I can munge the def-use info
      - // with impunity.
      - for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++)
      - worklist.push(old->fast_out(j));
      + if( !old->is_CFG() )
      + handle_invariant_uses(old,loop,old_new,&worklist,old_idoms,old_idom_size,new_counter,loopbodysize,&split_if_set,&split_bool_set);
      + }
      + for( i = 0; i < loopbodysize; i++ ) {
      + Node* old = loop->_body.at(i);
      + if( old->is_CFG() )
      + handle_invariant_uses(old,loop,old_new,&worklist,old_idoms,old_idom_size,new_counter,loopbodysize,&split_if_set,&split_bool_set);
      + }
      +
      + // Check for IFs that need splitting/cloning. Happens if an IF outside of
      + // the loop uses a condition set in the loop. The original IF probably
      + // takes control from one or more OLD Regions (which in turn get from NEW
      + // Regions). In any case, there will be a set of Phis for each merge point
      + // from the IF up to where the original BOOL def exists the loop.
      + if( split_if_set ) {
      + while( split_if_set->size() ) {
      + Node *iff = split_if_set->pop();
      + PhiNode *phi = iff->in(1)->is_Phi();
      + if( phi ) {
      + BoolNode *b = clone_iff( phi, loop );
      + _igvn.hash_delete(iff);
      + _igvn._worklist.push(iff);
      + iff->set_req(1, b);
      + }
      + }
      + }
      + if( split_bool_set ) {
      + while( split_bool_set->size() ) {
      + Node *b = split_bool_set->pop();
      + Node *phi = b->in(1);
      + assert( phi->is_Phi(), "" );
      + CmpNode *cmp = clone_bool( (PhiNode*)phi, loop );
      + _igvn.hash_delete(b);
      + _igvn._worklist.push(b);
      + b->set_req(1, cmp);
      + }
      + }
      +
      +}
      +
      +//------------------------------handle_invariant_uses--------------------------
      +void PhaseIdealLoop::handle_invariant_uses( Node *old, IdealLoopTree *loop, Node_List &old_new, Node_List *worklist, Node **old_idoms, int old_idom_size, int new_counter, int loopbodysize, Node_List **split_if_set, Node_List **split_bool_set ) {
      + Node* nnn = old_new[old->_idx];
      + // Copy uses to a worklist, so I can munge the def-use info
      + // with impunity.
      + for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++)
      + worklist->push(old->fast_out(j));
       
      - while( worklist.size() ) {
      + while( worklist->size() ) {
             assert0( loopbodysize == loop->_body.size() );
      - Node *use = worklist.pop();
      + Node *use = worklist->pop();
             if (!has_node(use)) continue; // Ignore dead nodes
             if (use->in(0) == C->top()) continue;
             IdealLoopTree *use_loop = get_loop( has_ctrl(use) ? get_ctrl_no_assert(use) : use );
      @@ -1528,14 +1570,14 @@
               if( use->is_If() || use->is_CMove() ) {
                 // Since this code is highly unlikely, we lazily build the worklist
                 // of such Nodes to go split.
      - if( !split_if_set )
      - split_if_set = new Node_List(area);
      - split_if_set->push(use);
      + if( !*split_if_set )
      + *split_if_set = new Node_List(Thread::current()->resource_area());
      + (*split_if_set)->push(use);
               }
               if( use->is_Bool() ) {
      - if( !split_bool_set )
      - split_bool_set = new Node_List(area);
      - split_bool_set->push(use);
      + if( !*split_bool_set )
      + *split_bool_set = new Node_List(Thread::current()->resource_area());
      + (*split_bool_set)->push(use);
               }
       
               // Get "block" use is in
      @@ -1569,7 +1611,7 @@
                   phi = PhiNode::make( prev, old );
                   // Now recursively fix up the new uses of old!
                   for( uint i = 1; i < prev->req(); i++ ) {
      - worklist.push(phi); // Onto worklist once for each 'old' input
      + worklist->push(phi); // Onto worklist once for each 'old' input
                   }
                 }
               } else {
      @@ -1626,38 +1668,8 @@
             }
             assert0( loopbodysize == loop->_body.size() );
           }
      - }
      +}
       
      - // Check for IFs that need splitting/cloning. Happens if an IF outside of
      - // the loop uses a condition set in the loop. The original IF probably
      - // takes control from one or more OLD Regions (which in turn get from NEW
      - // Regions). In any case, there will be a set of Phis for each merge point
      - // from the IF up to where the original BOOL def exists the loop.
      - if( split_if_set ) {
      - while( split_if_set->size() ) {
      - Node *iff = split_if_set->pop();
      - PhiNode *phi = iff->in(1)->is_Phi();
      - if( phi ) {
      - BoolNode *b = clone_iff( phi, loop );
      - _igvn.hash_delete(iff);
      - _igvn._worklist.push(iff);
      - iff->set_req(1, b);
      - }
      - }
      - }
      - if( split_bool_set ) {
      - while( split_bool_set->size() ) {
      - Node *b = split_bool_set->pop();
      - Node *phi = b->in(1);
      - assert( phi->is_Phi(), "" );
      - CmpNode *cmp = clone_bool( (PhiNode*)phi, loop );
      - _igvn.hash_delete(b);
      - _igvn._worklist.push(b);
      - b->set_req(1, cmp);
      - }
      - }
      -
      -}
       
       //------------------------------reorg_offsets----------------------------------
       // Reorganize offset computations to lower register pressure. Mostly

            Unassigned Unassigned
            mmma Marvin Ma (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: