--- old/src/hotspot/share/opto/macro.cpp 2019-08-05 14:26:37.828438644 +0200 +++ new/src/hotspot/share/opto/macro.cpp 2019-08-05 14:26:37.696433898 +0200 @@ -348,6 +348,7 @@ } 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 @@ } 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* 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 @@ Arena *a = Thread::current()->resource_area(); VectorSet visited(a); - bool done = sfpt_mem == alloc_mem; Node *mem = sfpt_mem; while (!done) { --- /dev/null 2019-08-05 06:51:02.003999979 +0200 +++ new/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java 2019-08-05 14:26:38.068447273 +0200 @@ -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); + } + } + } +}