6937111: Restore optimization for Phi of AddP (6552204)
authorkvn
Mon, 05 Apr 2010 10:17:15 -0700
changeset 5537 c075180330cf
parent 5235 9261638fa59c
child 5538 535ef83faf5d
6937111: Restore optimization for Phi of AddP (6552204) Summary: Restored the original code which was removed by the fix for 6614100. Reviewed-by: never
hotspot/src/share/vm/opto/cfgnode.cpp
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Apr 02 15:55:04 2010 -0700
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Mon Apr 05 10:17:15 2010 -0700
@@ -1653,6 +1653,64 @@
     if (opt != NULL)  return opt;
   }
 
+  if (in(1) != NULL && in(1)->Opcode() == Op_AddP && can_reshape) {
+    // Try to undo Phi of AddP:
+    // (Phi (AddP base base y) (AddP base2 base2 y))
+    // becomes:
+    // newbase := (Phi base base2)
+    // (AddP newbase newbase y)
+    //
+    // This occurs as a result of unsuccessful split_thru_phi and
+    // interferes with taking advantage of addressing modes. See the
+    // clone_shift_expressions code in matcher.cpp
+    Node* addp = in(1);
+    const Type* type = addp->in(AddPNode::Base)->bottom_type();
+    Node* y = addp->in(AddPNode::Offset);
+    if (y != NULL && addp->in(AddPNode::Base) == addp->in(AddPNode::Address)) {
+      // make sure that all the inputs are similar to the first one,
+      // i.e. AddP with base == address and same offset as first AddP
+      bool doit = true;
+      for (uint i = 2; i < req(); i++) {
+        if (in(i) == NULL ||
+            in(i)->Opcode() != Op_AddP ||
+            in(i)->in(AddPNode::Base) != in(i)->in(AddPNode::Address) ||
+            in(i)->in(AddPNode::Offset) != y) {
+          doit = false;
+          break;
+        }
+        // Accumulate type for resulting Phi
+        type = type->meet(in(i)->in(AddPNode::Base)->bottom_type());
+      }
+      Node* base = NULL;
+      if (doit) {
+        // Check for neighboring AddP nodes in a tree.
+        // If they have a base, use that it.
+        for (DUIterator_Fast kmax, k = this->fast_outs(kmax); k < kmax; k++) {
+          Node* u = this->fast_out(k);
+          if (u->is_AddP()) {
+            Node* base2 = u->in(AddPNode::Base);
+            if (base2 != NULL && !base2->is_top()) {
+              if (base == NULL)
+                base = base2;
+              else if (base != base2)
+                { doit = false; break; }
+            }
+          }
+        }
+      }
+      if (doit) {
+        if (base == NULL) {
+          base = new (phase->C, in(0)->req()) PhiNode(in(0), type, NULL);
+          for (uint i = 1; i < req(); i++) {
+            base->init_req(i, in(i)->in(AddPNode::Base));
+          }
+          phase->is_IterGVN()->register_new_node_with_optimizer(base);
+        }
+        return new (phase->C, 4) AddPNode(base, base, y);
+      }
+    }
+  }
+
   // Split phis through memory merges, so that the memory merges will go away.
   // Piggy-back this transformation on the search for a unique input....
   // It will be as if the merged memory is the unique value of the phi.