< prev index next >

src/share/vm/opto/loopTransform.cpp

Print this page

        

@@ -1522,10 +1522,78 @@
     assert((cl->trip_count() & 1) == 0, "missed peeling");
     do_unroll(loop, old_new, false);
   }
 }
 
+void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) {
+  if (SuperWordReductions == false) return;
+
+  for (uint i = 0; i < loop->_body.size(); i++) {
+    Node *n = loop->_body[i];
+    if (n != NULL && n->is_Phi()) {
+      PhiNode *phi = n->as_Phi();
+      // for definitions which are loop inclusive and not tripcounts
+      if (phi != NULL && phi->is_tripcount() == false) {
+        uint len = n->len();
+        Node *defNode = n->in(len - 1);
+
+        if (defNode != NULL) {
+          Node *n_ctrl = get_ctrl(defNode);
+          if (n_ctrl != NULL && loop->is_member(get_loop(n_ctrl))) {
+            uint flags = defNode->flags();
+
+            // This is a loop carried depedence, set if needed
+            if ((flags & Node::Flag_is_loop_carried_dep) != Node::Flag_is_loop_carried_dep)
+              defNode->add_flag(Node::Flag_is_loop_carried_dep);
+
+            // now test it to see if it fits the standard pattern for a reduction operator
+            switch (defNode->Opcode()) {
+              // the communitative operators
+            case Op_AddI:
+            case Op_AddL:
+            case Op_AddF:
+            case Op_AddD:
+            case Op_MulI:
+            case Op_MulL:
+            case Op_MulF:
+            case Op_MulD:
+              if ((flags & Node::Flag_has_reduction) != Node::Flag_has_reduction)
+              {
+                // To be a reduction, the arithmetic node must source the phi and provide a def to it
+                int end = defNode->req();
+                for (int j = 1; j < end; j++) {
+                  Node* in = defNode->in(j);
+                  if (in == n){
+                    defNode->add_flag(Node::Flag_has_reduction);
+                    break;
+                  }
+                }
+              }
+              break;
+
+              // the non communitative operators
+            case Op_DivI:
+            case Op_DivL:
+            case Op_DivF:
+            case Op_DivD:
+            case Op_SubI:
+            case Op_SubL:
+            case Op_SubF:
+            case Op_SubD:
+              // TODO: these need ordering constraints
+              break;
+
+            default:
+              break;
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 //------------------------------dominates_backedge---------------------------------
 // Returns true if ctrl is executed on every complete iteration
 bool IdealLoopTree::dominates_backedge(Node* ctrl) {
   assert(ctrl->is_CFG(), "must be control");
   Node* backedge = _head->as_Loop()->in(LoopNode::LoopBackControl);

@@ -2359,12 +2427,14 @@
     // Double loop body for unrolling.  Adjust the minimum-trip test (will do
     // twice as many iterations as before) and the main body limit (only do
     // an even number of trips).  If we are peeling, we might enable some RCE
     // and we'd rather unroll the post-RCE'd loop SO... do not unroll if
     // peeling.
-    if (should_unroll && !should_peel)
-      phase->do_unroll(this,old_new, true);
+    if (should_unroll && !should_peel) {
+      phase->mark_reductions(this);
+      phase->do_unroll(this, old_new, true);
+    }
 
     // Adjust the pre-loop limits to align the main body
     // iterations.
     if (should_align)
       Unimplemented();
< prev index next >