changeset 2055:57090cdd4e01

7017746: Regression : C2 compiler crash due to SIGSEGV in PhaseCFG::schedule_early() Summary: Add TEMP edges (and KILL projections) before duplicated operands are removed in Expand() methods. Reviewed-by: never
author kvn
date Thu, 10 Feb 2011 14:25:59 -0800
parents befa5106b5e9
children c6491db25cb2
files src/cpu/sparc/vm/sparc.ad src/share/vm/adlc/output_c.cpp src/share/vm/opto/node.cpp test/compiler/7017746/Test.java
diffstat 4 files changed, 135 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/sparc.ad	Fri Feb 11 09:16:18 2011 -0800
+++ b/src/cpu/sparc/vm/sparc.ad	Thu Feb 10 14:25:59 2011 -0800
@@ -8125,6 +8125,17 @@
 %}
 #endif
 
+instruct cmpLTMask0( iRegI dst, iRegI src, immI0 zero, flagsReg ccr ) %{
+  match(Set dst (CmpLTMask src zero));
+  effect(KILL ccr);
+  size(4);
+  format %{ "SRA    $src,#31,$dst\t# cmpLTMask0" %}
+  ins_encode %{
+    __ sra($src$$Register, 31, $dst$$Register);
+  %}
+  ins_pipe(ialu_reg_imm);
+%}
+
 instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
   match(Set dst (CmpLTMask p q));
   effect( KILL ccr );
@@ -8144,19 +8155,7 @@
 
   format %{ "SUBcc  $p,$q,$p\t! p' = p-q\n\t"
             "ADD    $p,$y,$tmp\t! g3=p-q+y\n\t"
-            "MOVl   $tmp,$p\t! p' < 0 ? p'+y : p'" %}
-  ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) );
-  ins_pipe( cadd_cmpltmask );
-%}
-
-instruct cadd_cmpLTMask2( iRegI p, iRegI q, iRegI y, iRegI tmp, flagsReg ccr ) %{
-  match(Set p (AddI (SubI p q) (AndI (CmpLTMask p q) y)));
-  effect( KILL ccr, TEMP tmp);
-  ins_cost(DEFAULT_COST*3);
-
-  format %{ "SUBcc  $p,$q,$p\t! p' = p-q\n\t"
-            "ADD    $p,$y,$tmp\t! g3=p-q+y\n\t"
-            "MOVl   $tmp,$p\t! p' < 0 ? p'+y : p'" %}
+            "MOVlt  $tmp,$p\t! p' < 0 ? p'+y : p'" %}
   ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) );
   ins_pipe( cadd_cmpltmask );
 %}
--- a/src/share/vm/adlc/output_c.cpp	Fri Feb 11 09:16:18 2011 -0800
+++ b/src/share/vm/adlc/output_c.cpp	Thu Feb 10 14:25:59 2011 -0800
@@ -1698,7 +1698,75 @@
     fprintf(fp,"\n");
   } // done generating expand rule
 
-  else if( node->_matrule != NULL ) {
+  // Generate projections for instruction's additional DEFs and KILLs
+  if( ! node->expands() && (node->needs_projections() || node->has_temps())) {
+    // Get string representing the MachNode that projections point at
+    const char *machNode = "this";
+    // Generate the projections
+    fprintf(fp,"  // Add projection edges for additional defs or kills\n");
+
+    // Examine each component to see if it is a DEF or KILL
+    node->_components.reset();
+    // Skip the first component, if already handled as (SET dst (...))
+    Component *comp = NULL;
+    // For kills, the choice of projection numbers is arbitrary
+    int proj_no = 1;
+    bool declared_def  = false;
+    bool declared_kill = false;
+
+    while( (comp = node->_components.iter()) != NULL ) {
+      // Lookup register class associated with operand type
+      Form        *form = (Form*)_globalNames[comp->_type];
+      assert( form, "component type must be a defined form");
+      OperandForm *op   = form->is_operand();
+
+      if (comp->is(Component::TEMP)) {
+        fprintf(fp, "  // TEMP %s\n", comp->_name);
+        if (!declared_def) {
+          // Define the variable "def" to hold new MachProjNodes
+          fprintf(fp, "  MachTempNode *def;\n");
+          declared_def = true;
+        }
+        if (op && op->_interface && op->_interface->is_RegInterface()) {
+          fprintf(fp,"  def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n",
+                  machOperEnum(op->_ident));
+          fprintf(fp,"  add_req(def);\n");
+          // The operand for TEMP is already constructed during
+          // this mach node construction, see buildMachNode().
+          //
+          // int idx  = node->operand_position_format(comp->_name);
+          // fprintf(fp,"  set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n",
+          //         idx, machOperEnum(op->_ident));
+        } else {
+          assert(false, "can't have temps which aren't registers");
+        }
+      } else if (comp->isa(Component::KILL)) {
+        fprintf(fp, "  // DEF/KILL %s\n", comp->_name);
+
+        if (!declared_kill) {
+          // Define the variable "kill" to hold new MachProjNodes
+          fprintf(fp, "  MachProjNode *kill;\n");
+          declared_kill = true;
+        }
+
+        assert( op, "Support additional KILLS for base operands");
+        const char *regmask    = reg_mask(*op);
+        const char *ideal_type = op->ideal_type(_globalNames, _register);
+
+        if (!op->is_bound_register()) {
+          syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n",
+                     node->_ident, comp->_type, comp->_name);
+        }
+
+        fprintf(fp,"  kill = ");
+        fprintf(fp,"new (C, 1) MachProjNode( %s, %d, (%s), Op_%s );\n",
+                machNode, proj_no++, regmask, ideal_type);
+        fprintf(fp,"  proj_list.push(kill);\n");
+      }
+    }
+  }
+
+  if( !node->expands() && node->_matrule != NULL ) {
     // Remove duplicated operands and inputs which use the same name.
     // Seach through match operands for the same name usage.
     uint cur_num_opnds = node->num_opnds();
@@ -1752,72 +1820,6 @@
     }
   }
 
-
-  // Generate projections for instruction's additional DEFs and KILLs
-  if( ! node->expands() && (node->needs_projections() || node->has_temps())) {
-    // Get string representing the MachNode that projections point at
-    const char *machNode = "this";
-    // Generate the projections
-    fprintf(fp,"  // Add projection edges for additional defs or kills\n");
-
-    // Examine each component to see if it is a DEF or KILL
-    node->_components.reset();
-    // Skip the first component, if already handled as (SET dst (...))
-    Component *comp = NULL;
-    // For kills, the choice of projection numbers is arbitrary
-    int proj_no = 1;
-    bool declared_def  = false;
-    bool declared_kill = false;
-
-    while( (comp = node->_components.iter()) != NULL ) {
-      // Lookup register class associated with operand type
-      Form        *form = (Form*)_globalNames[comp->_type];
-      assert( form, "component type must be a defined form");
-      OperandForm *op   = form->is_operand();
-
-      if (comp->is(Component::TEMP)) {
-        fprintf(fp, "  // TEMP %s\n", comp->_name);
-        if (!declared_def) {
-          // Define the variable "def" to hold new MachProjNodes
-          fprintf(fp, "  MachTempNode *def;\n");
-          declared_def = true;
-        }
-        if (op && op->_interface && op->_interface->is_RegInterface()) {
-          fprintf(fp,"  def = new (C) MachTempNode(state->MachOperGenerator( %s, C ));\n",
-                  machOperEnum(op->_ident));
-          fprintf(fp,"  add_req(def);\n");
-          int idx  = node->operand_position_format(comp->_name);
-          fprintf(fp,"  set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n",
-                  idx, machOperEnum(op->_ident));
-        } else {
-          assert(false, "can't have temps which aren't registers");
-        }
-      } else if (comp->isa(Component::KILL)) {
-        fprintf(fp, "  // DEF/KILL %s\n", comp->_name);
-
-        if (!declared_kill) {
-          // Define the variable "kill" to hold new MachProjNodes
-          fprintf(fp, "  MachProjNode *kill;\n");
-          declared_kill = true;
-        }
-
-        assert( op, "Support additional KILLS for base operands");
-        const char *regmask    = reg_mask(*op);
-        const char *ideal_type = op->ideal_type(_globalNames, _register);
-
-        if (!op->is_bound_register()) {
-          syntax_err(node->_linenum, "In %s only bound registers can be killed: %s %s\n",
-                     node->_ident, comp->_type, comp->_name);
-        }
-
-        fprintf(fp,"  kill = ");
-        fprintf(fp,"new (C, 1) MachProjNode( %s, %d, (%s), Op_%s );\n",
-                machNode, proj_no++, regmask, ideal_type);
-        fprintf(fp,"  proj_list.push(kill);\n");
-      }
-    }
-  }
-
   // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
   // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
   if (node->is_mach_constant()) {
@@ -3776,12 +3778,10 @@
       }
       dont_care = true;
       // For each operand not in the match rule, call MachOperGenerator
-      // with the enum for the opcode that needs to be built
-      // and the node just built, the parent of the operand.
+      // with the enum for the opcode that needs to be built.
       ComponentList clist = inst->_components;
       int         index  = clist.operand_position(comp->_name, comp->_usedef);
       const char *opcode = machOperEnum(comp->_type);
-      const char *parent = "node";
       fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
       fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
       }
--- a/src/share/vm/opto/node.cpp	Fri Feb 11 09:16:18 2011 -0800
+++ b/src/share/vm/opto/node.cpp	Thu Feb 10 14:25:59 2011 -0800
@@ -743,6 +743,9 @@
 //------------------------------del_req----------------------------------------
 // Delete the required edge and compact the edge array
 void Node::del_req( uint idx ) {
+  assert( idx < _cnt, "oob");
+  assert( !VerifyHashTableKeys || _hash_lock == 0,
+          "remove node from hash table before modifying it");
   // First remove corresponding def-use edge
   Node *n = in(idx);
   if (n != NULL) n->del_out((Node *)this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/7017746/Test.java	Thu Feb 10 14:25:59 2011 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7017746
+ * @summary Regression : C2 compiler crash due to SIGSEGV in PhaseCFG::schedule_early()
+ *
+ * @run main/othervm -Xbatch Test
+ */
+
+public class Test {
+
+  int i;
+
+  static int test(Test t, int a, int b) {
+    int j = t.i;
+    int x = a - b;
+    if (a < b) x = x + j;
+    return x - j;
+  }
+
+  public static void main(String args[]) {
+    Test t = new Test();
+    for (int n = 0; n < 1000000; n++) {
+      int i = test(t, 1, 2);
+    }
+  }
+}
+