hotspot/src/share/vm/opto/loopTransform.cpp
changeset 30211 442fbbb31f75
parent 29344 49ad0989c84f
child 30593 69f942690128
--- a/hotspot/src/share/vm/opto/loopTransform.cpp	Fri Mar 27 13:47:33 2015 +0100
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp	Wed Apr 01 18:07:50 2015 -0700
@@ -38,6 +38,7 @@
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
+#include "opto/vectornode.hpp"
 
 //------------------------------is_loop_exit-----------------------------------
 // Given an IfNode, return the loop-exiting projection or NULL if both
@@ -1524,6 +1525,44 @@
   }
 }
 
+void PhaseIdealLoop::mark_reductions(IdealLoopTree *loop) {
+  if (SuperWordReductions == false) return;
+
+  CountedLoopNode* loop_head = loop->_head->as_CountedLoop();
+  if (loop_head->unrolled_count() > 1) {
+    return;
+  }
+
+  Node* trip_phi = loop_head->phi();
+  for (DUIterator_Fast imax, i = loop_head->fast_outs(imax); i < imax; i++) {
+    Node* phi = loop_head->fast_out(i);
+    if (phi->is_Phi() && phi->outcnt() > 0 && phi != trip_phi) {
+      // For definitions which are loop inclusive and not tripcounts.
+      Node* def_node = phi->in(LoopNode::LoopBackControl);
+
+      if (def_node != NULL) {
+        Node* n_ctrl = get_ctrl(def_node);
+        if (n_ctrl != NULL && loop->is_member(get_loop(n_ctrl))) {
+          // Now test it to see if it fits the standard pattern for a reduction operator.
+          int opc = def_node->Opcode();
+          if (opc != ReductionNode::opcode(opc, def_node->bottom_type()->basic_type())) {
+            if (!def_node->is_reduction()) { // Not marked yet
+              // To be a reduction, the arithmetic node must have the phi as input and provide a def to it
+              for (unsigned j = 1; j < def_node->req(); j++) {
+                Node* in = def_node->in(j);
+                if (in == phi) {
+                  def_node->add_flag(Node::Flag_is_reduction);
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 //------------------------------dominates_backedge---------------------------------
 // Returns true if ctrl is executed on every complete iteration
 bool IdealLoopTree::dominates_backedge(Node* ctrl) {
@@ -2361,8 +2400,10 @@
     // 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.