From 7cd25ed605469e3946a204b7b18d975c9768f2df Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Tue, 13 Feb 2024 13:50:59 +0000 Subject: [PATCH] 8322854: Incorrect rematerialization of scalar replaced objects in C2 Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/macro.cpp | 9 ++- .../c2/TestReduceAllocationAndMemoryLoop.java | 70 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 262fff7f8e9..c2aa017197e 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -167,7 +167,8 @@ void PhaseMacroExpand::eliminate_gc_barrier(Node* p2x) { // Search for a memory operation for the specified memory slice. static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) { Node *orig_mem = mem; - Node *alloc_mem = alloc->in(TypeFunc::Memory); + Node *alloc_mem = alloc->as_Allocate()->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false); + assert(alloc_mem != nullptr, "Allocation without a memory projection."); const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr(); while (true) { if (mem == alloc_mem || mem == start_mem ) { @@ -371,7 +372,8 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type * return nullptr; // Give up: phi tree too deep } Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); - Node *alloc_mem = alloc->in(TypeFunc::Memory); + Node *alloc_mem = alloc->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false); + assert(alloc_mem != nullptr, "Allocation without a memory projection."); uint length = mem->req(); GrowableArray values(length, length, nullptr); @@ -456,7 +458,8 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType int offset = adr_t->offset(); Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); Node *alloc_ctrl = alloc->in(TypeFunc::Control); - Node *alloc_mem = alloc->in(TypeFunc::Memory); + Node *alloc_mem = alloc->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false); + assert(alloc_mem != nullptr, "Allocation without a memory projection."); VectorSet visited; bool done = sfpt_mem == alloc_mem; diff --git a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java new file mode 100644 index 00000000000..765dcee7c5b --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2024, 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 8322854 + * @summary Check that the RAM optimization works when there is a memory loop. + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndMemoryLoop*::test* + * -XX:-TieredCompilation -Xbatch + * compiler.c2.TestReduceAllocationAndMemoryLoop + */ + +package compiler.c2; + +public class TestReduceAllocationAndMemoryLoop { + public static void main(String[] args) throws Exception { + // Warmup + for (int i = 0; i < 50_000; ++i) { + test(false, 10); + } + + // Trigger deoptimization + MyClass obj = test(false, 11); + if (obj.val != 42) { + throw new RuntimeException("Test failed, val = " + obj.val); + } + } + + static class MyClass { + final int val; + + public MyClass(int val) { + this.val = val; + } + } + + public static MyClass test(boolean alwaysFalse, int limit) { + for (int i = 0; ; ++i) { + MyClass obj = new MyClass(42); + if (alwaysFalse || i > 10) { + return obj; + } + if (i == limit) { + return null; + } + } + } +}