mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
7017746: Regression : C2 compiler crash due to SIGSEGV in PhaseCFG::schedule_early()
Add TEMP edges (and KILL projections) before duplicated operands are removed in Expand() methods. Reviewed-by: never
This commit is contained in:
parent
4c567f5969
commit
5d3ab72d1d
4 changed files with 135 additions and 83 deletions
|
@ -8125,6 +8125,17 @@ instruct convP2B( iRegI dst, iRegP src ) %{
|
||||||
%}
|
%}
|
||||||
#endif
|
#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 ) %{
|
instruct cmpLTMask_reg_reg( iRegI dst, iRegI p, iRegI q, flagsReg ccr ) %{
|
||||||
match(Set dst (CmpLTMask p q));
|
match(Set dst (CmpLTMask p q));
|
||||||
effect( KILL ccr );
|
effect( KILL ccr );
|
||||||
|
@ -8144,19 +8155,7 @@ instruct cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, iRegI tmp, flagsReg ccr ) %{
|
||||||
|
|
||||||
format %{ "SUBcc $p,$q,$p\t! p' = p-q\n\t"
|
format %{ "SUBcc $p,$q,$p\t! p' = p-q\n\t"
|
||||||
"ADD $p,$y,$tmp\t! g3=p-q+y\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 );
|
|
||||||
%}
|
|
||||||
|
|
||||||
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'" %}
|
|
||||||
ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) );
|
ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) );
|
||||||
ins_pipe( cadd_cmpltmask );
|
ins_pipe( cadd_cmpltmask );
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -1698,7 +1698,75 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
|
||||||
fprintf(fp,"\n");
|
fprintf(fp,"\n");
|
||||||
} // done generating expand rule
|
} // 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.
|
// Remove duplicated operands and inputs which use the same name.
|
||||||
// Seach through match operands for the same name usage.
|
// Seach through match operands for the same name usage.
|
||||||
uint cur_num_opnds = node->num_opnds();
|
uint cur_num_opnds = node->num_opnds();
|
||||||
|
@ -1752,72 +1820,6 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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.
|
// 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).
|
// NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
|
||||||
if (node->is_mach_constant()) {
|
if (node->is_mach_constant()) {
|
||||||
|
@ -3776,12 +3778,10 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
|
||||||
}
|
}
|
||||||
dont_care = true;
|
dont_care = true;
|
||||||
// For each operand not in the match rule, call MachOperGenerator
|
// For each operand not in the match rule, call MachOperGenerator
|
||||||
// with the enum for the opcode that needs to be built
|
// with the enum for the opcode that needs to be built.
|
||||||
// and the node just built, the parent of the operand.
|
|
||||||
ComponentList clist = inst->_components;
|
ComponentList clist = inst->_components;
|
||||||
int index = clist.operand_position(comp->_name, comp->_usedef);
|
int index = clist.operand_position(comp->_name, comp->_usedef);
|
||||||
const char *opcode = machOperEnum(comp->_type);
|
const char *opcode = machOperEnum(comp->_type);
|
||||||
const char *parent = "node";
|
|
||||||
fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
|
fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
|
||||||
fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
|
fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -743,6 +743,9 @@ void Node::add_req_batch( Node *n, uint m ) {
|
||||||
//------------------------------del_req----------------------------------------
|
//------------------------------del_req----------------------------------------
|
||||||
// Delete the required edge and compact the edge array
|
// Delete the required edge and compact the edge array
|
||||||
void Node::del_req( uint idx ) {
|
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
|
// First remove corresponding def-use edge
|
||||||
Node *n = in(idx);
|
Node *n = in(idx);
|
||||||
if (n != NULL) n->del_out((Node *)this);
|
if (n != NULL) n->del_out((Node *)this);
|
||||||
|
|
50
hotspot/test/compiler/7017746/Test.java
Normal file
50
hotspot/test/compiler/7017746/Test.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue