< prev index next >

src/hotspot/share/opto/superword.cpp

Print this page

        

@@ -2137,21 +2137,45 @@
   } else if (pk->at(0)->is_Load()) { //load
     // all loads in the pack should have the same memory state. By default,
     // we use the memory state of the last load. However, if any load could
     // not be moved down due to the dependence constraint, we use the memory
     // state of the first load.
-    Node* last_mem  = executed_last(pk)->in(MemNode::Memory);
-    Node* first_mem = executed_first(pk)->in(MemNode::Memory);
+
+    // We first need to find the "first" and "last" loads. Start with
+    // arbitrary values:
+    Node* last_mem  = pk->at(0)->in(MemNode::Memory);
+    Node* first_mem = last_mem;
+    // Walk the memory graph from the current first load until the
+    // start of the loop and check if nodes on the way are memory
+    // edges of loads in the pack. The last one we encounter is the
+    // first load.
+    for (Node* current = first_mem; in_bb(current); current = current->is_Phi() ? current->in(LoopNode::EntryControl) : current->in(MemNode::Memory)) {
+      assert(current->is_Mem() || (current->is_Phi() && current->in(0) == bb()), "unexpected memory");
+      for (uint i = 1; i < pk->size(); i++) {
+        Node* ld = pk->at(i);
+        if (ld->in(MemNode::Memory) == current) {
+          first_mem = current;
+          break;
+        }
+      }
+    }
+    // Find the last load by going over the pack again, and walking
+    // the memory graph from the loads of the pack to the memory of
+    // the first load. If we encounter the memory of the current last
+    // load, then we started from further down in the memory graph and
+    // the load we started from is the last load. Check for dependence
+    // constraints in that loop as well.
     bool schedule_last = true;
     for (uint i = 0; i < pk->size(); i++) {
       Node* ld = pk->at(i);
-      for (Node* current = last_mem; current != ld->in(MemNode::Memory);
-           current=current->in(MemNode::Memory)) {
-        assert(current != first_mem, "corrupted memory graph");
-        if(current->is_Mem() && !independent(current, ld)){
+      for (Node* current = ld->in(MemNode::Memory); current != first_mem; current = current->in(MemNode::Memory)) {
+        assert(current->is_Mem() && in_bb(current), "unexpected memory");
+        if (current->in(MemNode::Memory) == last_mem) {
+          last_mem = ld->in(MemNode::Memory);
+        }
+        if (!independent(current, ld)) {
           schedule_last = false; // a later store depends on this load
-          break;
         }
       }
     }
 
     Node* mem_input = schedule_last ? last_mem : first_mem;
< prev index next >