mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-22 12:04:39 +02:00
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
Recompile without subsuming loads if RA try to clone a node with anti_dependence. Reviewed-by: never
This commit is contained in:
parent
d7310fb0f7
commit
b092cb33e6
4 changed files with 106 additions and 7 deletions
|
@ -911,6 +911,7 @@ postaloc.cpp machnode.hpp
|
||||||
reg_split.cpp addnode.hpp
|
reg_split.cpp addnode.hpp
|
||||||
reg_split.cpp allocation.inline.hpp
|
reg_split.cpp allocation.inline.hpp
|
||||||
reg_split.cpp callnode.hpp
|
reg_split.cpp callnode.hpp
|
||||||
|
reg_split.cpp c2compiler.hpp
|
||||||
reg_split.cpp cfgnode.hpp
|
reg_split.cpp cfgnode.hpp
|
||||||
reg_split.cpp chaitin.hpp
|
reg_split.cpp chaitin.hpp
|
||||||
reg_split.cpp loopnode.hpp
|
reg_split.cpp loopnode.hpp
|
||||||
|
|
|
@ -113,7 +113,8 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
|
||||||
if( !m->is_Mach() ) continue;
|
if( !m->is_Mach() ) continue;
|
||||||
MachNode *mach = m->as_Mach();
|
MachNode *mach = m->as_Mach();
|
||||||
was_store = false;
|
was_store = false;
|
||||||
switch( mach->ideal_Opcode() ) {
|
int iop = mach->ideal_Opcode();
|
||||||
|
switch( iop ) {
|
||||||
case Op_LoadB:
|
case Op_LoadB:
|
||||||
case Op_LoadUS:
|
case Op_LoadUS:
|
||||||
case Op_LoadD:
|
case Op_LoadD:
|
||||||
|
@ -155,6 +156,12 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
|
||||||
default: // Also check for embedded loads
|
default: // Also check for embedded loads
|
||||||
if( !mach->needs_anti_dependence_check() )
|
if( !mach->needs_anti_dependence_check() )
|
||||||
continue; // Not an memory op; skip it
|
continue; // Not an memory op; skip it
|
||||||
|
if( must_clone[iop] ) {
|
||||||
|
// Do not move nodes which produce flags because
|
||||||
|
// RA will try to clone it to place near branch and
|
||||||
|
// it will cause recompilation, see clone_node().
|
||||||
|
continue;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
// Check that value is used in memory address in
|
// Check that value is used in memory address in
|
||||||
// instructions with embedded load (CmpP val1,(val2+off)).
|
// instructions with embedded load (CmpP val1,(val2+off)).
|
||||||
|
@ -957,6 +964,8 @@ void Block::call_catch_cleanup(Block_Array &bbs) {
|
||||||
Block *sb = _succs[i];
|
Block *sb = _succs[i];
|
||||||
// Clone the entire area; ignoring the edge fixup for now.
|
// Clone the entire area; ignoring the edge fixup for now.
|
||||||
for( uint j = end; j > beg; j-- ) {
|
for( uint j = end; j > beg; j-- ) {
|
||||||
|
// It is safe here to clone a node with anti_dependence
|
||||||
|
// since clones dominate on each path.
|
||||||
Node *clone = _nodes[j-1]->clone();
|
Node *clone = _nodes[j-1]->clone();
|
||||||
sb->_nodes.insert( 1, clone );
|
sb->_nodes.insert( 1, clone );
|
||||||
bbs.map(clone->_idx,sb);
|
bbs.map(clone->_idx,sb);
|
||||||
|
|
|
@ -271,6 +271,32 @@ uint PhaseChaitin::split_USE( Node *def, Block *b, Node *use, uint useidx, uint
|
||||||
return maxlrg;
|
return maxlrg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------clone_node----------------------------
|
||||||
|
// Clone node with anti dependence check.
|
||||||
|
Node* clone_node(Node* def, Block *b, Compile* C) {
|
||||||
|
if (def->needs_anti_dependence_check()) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
if (Verbose) {
|
||||||
|
tty->print_cr("RA attempts to clone node with anti_dependence:");
|
||||||
|
def->dump(-1); tty->cr();
|
||||||
|
tty->print_cr("into block:");
|
||||||
|
b->dump();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (C->subsume_loads() == true && !C->failing()) {
|
||||||
|
// Retry with subsume_loads == false
|
||||||
|
// If this is the first failure, the sentinel string will "stick"
|
||||||
|
// to the Compile object, and the C2Compiler will see it and retry.
|
||||||
|
C->record_failure(C2Compiler::retry_no_subsuming_loads());
|
||||||
|
} else {
|
||||||
|
// Bailout without retry
|
||||||
|
C->record_method_not_compilable("RA Split failed: attempt to clone node with anti_dependence");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return def->clone();
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------split_Rematerialize----------------------------
|
//------------------------------split_Rematerialize----------------------------
|
||||||
// Clone a local copy of the def.
|
// Clone a local copy of the def.
|
||||||
Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits, int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru ) {
|
Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits, int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru ) {
|
||||||
|
@ -298,8 +324,8 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *spill = def->clone();
|
Node *spill = clone_node(def, b, C);
|
||||||
if (C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
|
if (spill == NULL || C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
|
||||||
// Check when generating nodes
|
// Check when generating nodes
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -834,13 +860,13 @@ uint PhaseChaitin::Split( uint maxlrg ) {
|
||||||
// The effect of this clone is to drop the node out of the block,
|
// The effect of this clone is to drop the node out of the block,
|
||||||
// so that the allocator does not see it anymore, and therefore
|
// so that the allocator does not see it anymore, and therefore
|
||||||
// does not attempt to assign it a register.
|
// does not attempt to assign it a register.
|
||||||
def = def->clone();
|
def = clone_node(def, b, C);
|
||||||
|
if (def == NULL || C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
_names.extend(def->_idx,0);
|
_names.extend(def->_idx,0);
|
||||||
_cfg._bbs.map(def->_idx,b);
|
_cfg._bbs.map(def->_idx,b);
|
||||||
n->set_req(inpidx, def);
|
n->set_req(inpidx, def);
|
||||||
if (C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
63
hotspot/test/compiler/6973329/Test.java
Normal file
63
hotspot/test/compiler/6973329/Test.java
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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 6973329
|
||||||
|
* @summary C2 with Zero based COOP produces code with broken anti-dependency on x86
|
||||||
|
*
|
||||||
|
* @run main/othervm -Xbatch -Xcomp -XX:CompileOnly=Test Test
|
||||||
|
*/
|
||||||
|
|
||||||
|
class A {
|
||||||
|
A next;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
public int get_n() {
|
||||||
|
return n+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
A a;
|
||||||
|
|
||||||
|
void test (A new_next) {
|
||||||
|
A prev_next = a.next;
|
||||||
|
a.next = new_next;
|
||||||
|
if (prev_next == null) {
|
||||||
|
a.n = a.get_n();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String args[]) {
|
||||||
|
Test t = new Test();
|
||||||
|
t.a = new A();
|
||||||
|
t.a.n = 1;
|
||||||
|
t.test(new A());
|
||||||
|
if (t.a.n != 2) {
|
||||||
|
System.out.println("Wrong value: " + t.a.n + " expected: 2");
|
||||||
|
System.exit(97);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue