diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index a37edab8578..9b8ca8283af 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -40,6 +40,7 @@ #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "jvm.h" +#include "logging/logTag.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "nativeInst_aarch64.hpp" @@ -3764,6 +3765,9 @@ Address MacroAssembler::spill_address(int size, int offset, Register tmp) // Aligned - 12 bits unsigned offset shifted Register base = sp; if ((offset & (size-1)) && offset >= (1<<8)) { + if ((size == StackAlignmentInBytes) && !is_aligned(offset, StackAlignmentInBytes)) { + log_develop_trace(newcode)("spill_address: unaligned vector spill (size:%d sp offset:%d)", size, offset); + } add(tmp, base, offset & ((1<<12)-1)); base = tmp; offset &= -1u<<12; @@ -3789,6 +3793,10 @@ Address MacroAssembler::sve_spill_address(int sve_reg_size_in_bytes, int offset, return Address(base, offset / sve_reg_size_in_bytes); } + if ((sve_reg_size_in_bytes != StackAlignmentInBytes) || is_aligned(offset, StackAlignmentInBytes)) { + log_develop_trace(newcode)("sve_spill_address: unaligned vector spill (size:%d sp offset:%d)", sve_reg_size_in_bytes, offset); + } + add(tmp, base, offset); return Address(tmp); } diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 2c83b2d5765..69b26c498bd 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -1821,6 +1821,7 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r // Other alignment can be used by Vector API (VectorPayload in rearrangeOp, // observed with VectorRearrangeTest.java on Power9). if (masm) { + log_develop_trace(newcode)("unaligned vector spill (sp offset:%d)", dst_offset); __ addi(R0, R1_SP, dst_offset); __ stxvx(Rsrc, R0); // matches storeV16_Power9 (regarding element ordering) } @@ -1846,6 +1847,7 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r size += 4; } else { if (masm) { + log_develop_trace(newcode)("unaligned vector spill (sp offset:%d)", src_offset); __ addi(R0, R1_SP, src_offset); __ lxvx(Rdst, R0); } diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 6d0bd117ad9..e1430ec4393 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -136,6 +136,7 @@ class outputStream; LOG_TAG(monitortable) \ LOG_TAG(native) \ LOG_TAG(nestmates) \ + LOG_TAG(newcode) \ LOG_TAG(nmethod) \ LOG_TAG(nmt) \ LOG_TAG(normalize) \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 99a289476ec..3a76362bb65 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1257,6 +1257,12 @@ public class IRNode { machOnly(MEM_TO_REG_SPILL_COPY, "MemToRegSpillCopy"); } + public static final String MEM_TO_REG_SPILL_COPY_TYPE = COMPOSITE_PREFIX + "MEM_TO_REG_SPILL_COPY_TYPE" + POSTFIX; + static { + String regex = START + "MemToRegSpillCopy" + MID + IS_REPLACED + ".*" + END; + machOnly(MEM_TO_REG_SPILL_COPY_TYPE, regex); + } + public static final String MIN = PREFIX + "MIN" + POSTFIX; static { beforeMatchingNameRegex(MIN, "Min(I|L)"); diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorSpilling.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorSpilling.java new file mode 100644 index 00000000000..5e8b9341d8e --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorSpilling.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025 SAP SE. 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. + * + */ + +package compiler.vectorapi; + +import compiler.lib.ir_framework.*; + +import jdk.incubator.vector.IntVector; +import jdk.incubator.vector.VectorSpecies; + +import jdk.test.lib.Asserts; + +/** + * @test + * @bug 8370473 + * @library /test/lib / + * @summary Test alignment of vector spill slots. It should match the vector size. + * @modules jdk.incubator.vector + * @requires vm.opt.final.MaxVectorSize == null | vm.opt.final.MaxVectorSize >= 16 + * + * @run driver compiler.vectorapi.TestVectorSpilling + */ + +public class TestVectorSpilling { + + private static final VectorSpecies I_SPECIES = IntVector.SPECIES_128; + private static int LENGTH = 1024; + + private static int[] ia1; + private static int[] ia2; + private static int[] ir ; + + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } + + static class LData { + // Rading from a volatile field prevents cse optimization + static volatile long vF = 1042; + + long l1, l2, l3, l4, l5, l6, l7, l8; + public LData() { + l1 = vF; l2 = vF; l3 = vF; l4 = vF; l5 = vF; l6 = vF; l7 = vF; l8 = vF; + } + public long sum() { + return l1 + l2 + l3 + l4 + l5 + l6 + l7 + l8; + } + } + + + @Run(test = "test16ByteSpilling") + static void test16ByteSpilling_runner() { + test16ByteSpilling(1, 2, 3, 4, 5, 6, 7, 8, 9); + } + + @Test + @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY_TYPE, "vectorx", "> 0"}, + phase = {CompilePhase.FINAL_CODE}) + static long test16ByteSpilling(long l1, long l2, long l3, long l4, long l5, long l6, long l7, long l8, + long l9 /* odd stack arg */) { + // To be scalar replaced and spilled to stack + LData d1 = new LData(); + LData d2 = new LData(); + LData d3 = new LData(); + + for (int i = 0; i < LENGTH; i += I_SPECIES.length()) { + IntVector a1v = IntVector.fromArray(I_SPECIES, ia1, i); + IntVector a2v = IntVector.fromArray(I_SPECIES, ia2, i); + int scalar = spillPoint(); + a1v.add(a2v) + .add(scalar).intoArray(ir, i); + } + + return l1 + l2 + l3 + l4 + l5 + l6 + l7 + l8 + l9 + d1.sum() + d2.sum() + d3.sum(); + } + + @DontInline + static int spillPoint() { + return 42; + } + + static { + ia1 = new int[LENGTH]; + ia2 = new int[LENGTH]; + ir = new int[LENGTH]; + } + +}