diff src/share/vm/opto/divnode.cpp @ 6142:121e5708ae96

7169782: C2: SIGSEGV in LShiftLNode::Ideal(PhaseGVN*, bool) Summary: keep intermediate node alive till the end of the graph construction using dummy hook node trick Reviewed-by: kvn, twisti Contributed-by: vladimir.x.ivanov@oracle.com
author kvn
date Tue, 12 Jun 2012 09:47:23 -0700
parents f95d63e2154a
children e626685e9f6c
line wrap: on
line diff
--- a/src/share/vm/opto/divnode.cpp	Tue Jun 12 10:02:36 2012 +0200
+++ b/src/share/vm/opto/divnode.cpp	Tue Jun 12 09:47:23 2012 -0700
@@ -284,9 +284,14 @@
 
   const int N = 64;
 
+  // Dummy node to keep intermediate nodes alive during construction
+  Node* hook = new (phase->C, 4) Node(4);
+
   // u0 = u & 0xFFFFFFFF;  u1 = u >> 32;
   Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
   Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
+  hook->init_req(0, u0);
+  hook->init_req(1, u1);
 
   // v0 = v & 0xFFFFFFFF;  v1 = v >> 32;
   Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF);
@@ -299,19 +304,14 @@
   Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0));
   Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2)));
   Node* t    = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp));
+  hook->init_req(2, t);
 
   // w1 = t & 0xFFFFFFFF;
-  Node* w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF));
+  Node* w1 = phase->transform(new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF)));
+  hook->init_req(3, w1);
 
   // w2 = t >> 32;
-  Node* w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2));
-
-  // 6732154: Construct both w1 and w2 before transforming, so t
-  // doesn't go dead prematurely.
-  // 6837011: We need to transform w2 before w1 because the
-  // transformation of w1 could return t.
-  w2 = phase->transform(w2);
-  w1 = phase->transform(w1);
+  Node* w2 = phase->transform(new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2)));
 
   // w1 = u0*v1 + w1;
   Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1));
@@ -322,6 +322,16 @@
   Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2));
   Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2)));
 
+  // Remove the bogus extra edges used to keep things alive
+  PhaseIterGVN* igvn = phase->is_IterGVN();
+  if (igvn != NULL) {
+    igvn->remove_dead_node(hook);
+  } else {
+    for (int i = 0; i < 4; i++) {
+      hook->set_req(i, NULL);
+    }
+  }
+
   return new (phase->C, 3) AddLNode(temp1, temp2);
 }