8229016: C2 scalarization crashes with assert(node->Opcode() == Op_CastP2X) failed: ConvP2XNode required

Detect array copy to self to avoid emitting another load to the to-be-removed allocation.

Reviewed-by: kvn
This commit is contained in:
Tobias Hartmann 2019-08-07 12:09:55 +02:00
parent c64f70be82
commit ac2ea95788
2 changed files with 70 additions and 2 deletions

View File

@ -348,6 +348,7 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
}
Node* res = NULL;
if (ac->is_clonebasic()) {
assert(ac->in(ArrayCopyNode::Src) != ac->in(ArrayCopyNode::Dest), "clone source equals destination");
Node* base = ac->in(ArrayCopyNode::Src)->in(AddPNode::Base);
Node* adr = _igvn.transform(new AddPNode(base, base, MakeConX(offset)));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
@ -355,7 +356,7 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
} else {
if (ac->modifies(offset, offset, &_igvn, true)) {
assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result");
uint shift = exact_log2(type2aelembytes(bt));
uint shift = exact_log2(type2aelembytes(bt));
Node* diff = _igvn.transform(new SubINode(ac->in(ArrayCopyNode::SrcPos), ac->in(ArrayCopyNode::DestPos)));
#ifdef _LP64
diff = _igvn.transform(new ConvI2LNode(diff));
@ -366,6 +367,10 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
Node* base = ac->in(ArrayCopyNode::Src);
Node* adr = _igvn.transform(new AddPNode(base, base, off));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
if (ac->in(ArrayCopyNode::Src) == ac->in(ArrayCopyNode::Dest)) {
// Don't emit a new load from src if src == dst but try to get the value from memory instead
return value_from_mem(ac->in(TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr(), alloc);
}
res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl);
}
}
@ -497,7 +502,6 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType
Arena *a = Thread::current()->resource_area();
VectorSet visited(a);
bool done = sfpt_mem == alloc_mem;
Node *mem = sfpt_mem;
while (!done) {

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2019, 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 8229016
* @summary Test correct elimination of array allocation with arraycopy to itself.
* @library /test/lib
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test
* compiler.escapeAnalysis.TestSelfArrayCopy
*/
package compiler.escapeAnalysis;
import jdk.test.lib.Utils;
public class TestSelfArrayCopy {
private static boolean b = false;
private static final int rI1 = Utils.getRandomInstance().nextInt();
private static final int rI2 = Utils.getRandomInstance().nextInt();
private static int test() {
// Non-escaping allocation
Integer[] array = {rI1, rI2};
// Arraycopy with src == dst
System.arraycopy(array, 0, array, 0, array.length - 1);
if (b) {
// Uncommon trap
System.out.println(array[0]);
}
return array[0] + array[1];
}
public static void main(String[] args) {
int expected = rI1 + rI2;
// Trigger compilation
for (int i = 0; i < 20_000; ++i) {
int result = test();
if (result != expected) {
throw new RuntimeException("Incorrect result: " + result + " != " + expected);
}
}
}
}