jdk/test/hotspot/jtreg/compiler/loopopts/TestArrayFillIntrinsic.java
Roberto Castañeda Lozano de580090cd 8351468: C2: array fill optimization assigns wrong type to intrinsic call
Reviewed-by: epeter, thartmann, qamai
2025-03-24 11:05:46 +00:00

264 lines
9.7 KiB
Java

/*
* Copyright (c) 2025, 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.
*/
package compiler.loopopts;
import java.lang.foreign.*;
import java.util.*;
import jdk.test.lib.Asserts;
import compiler.lib.ir_framework.*;
/**
* @test
* @bug 8351468
* @summary Test replacement of array-filling loops with intrinsic calls in the
* face of matching and mismatching stores.
* @library /test/lib /
* @run driver compiler.loopopts.TestArrayFillIntrinsic
*/
public class TestArrayFillIntrinsic {
public static void main(String[] args) {
// Disabling unrolling is necessary for test robustness, otherwise the
// compiler might decide to unroll the array-filling loop instead of
// replacing it with an intrinsic call even if OptimizeFill is enabled.
TestFramework framework = new TestFramework();
framework.addScenarios(new Scenario(0),
new Scenario(1, "-XX:LoopUnrollLimit=0", "-XX:+OptimizeFill"));
framework.start();
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jbyte_fill", "1"})
static void testFillBooleanArray(boolean[] array, boolean val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jbyte_fill", "1"})
static void testFillByteArray(byte[] array, byte val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jshort_fill", "1"})
static void testFillCharArray(char[] array, char val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jshort_fill", "1"})
static void testFillShortArray(short[] array, short val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jint_fill", "1"})
static void testFillIntArray(int[] array, int val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Test
@IR(applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
applyIfAnd = {"LoopUnrollLimit", "0", "OptimizeFill", "true"},
counts = {IRNode.CALL_OF, "(arrayof_)?jint_fill", "1"})
static void testFillFloatArray(float[] array, float val) {
for (int i = 0; i < array.length; i++) {
array[i] = val;
}
}
@Run(test = {"testFillByteArray",
"testFillBooleanArray",
"testFillCharArray",
"testFillShortArray",
"testFillIntArray",
"testFillFloatArray"})
public void runPositiveTests() {
Random r = RunInfo.getRandom();
int N = r.ints(1, 1024).findFirst().getAsInt();
{
boolean[] array = new boolean[N];
boolean val = r.nextBoolean();
testFillBooleanArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
{
byte[] array = new byte[N];
byte val = (byte)r.nextInt();
testFillByteArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
{
char[] array = new char[N];
char val = (char)r.nextInt();
testFillCharArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
{
short[] array = new short[N];
short val = (short)r.nextInt();
testFillShortArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
{
int[] array = new int[N];
int val = r.nextInt();
testFillIntArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
{
float[] array = new float[N];
float val = r.nextFloat();
testFillFloatArray(array, val);
for (int i = 0; i < array.length; i++) {
Asserts.assertEquals(val, array[i]);
}
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillShortArrayWithByte(MemorySegment array, int n, byte val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_BYTE, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillIntArrayWithByte(MemorySegment array, int n, byte val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_BYTE, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillIntArrayWithShort(MemorySegment array, int n, short val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_SHORT, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillByteArrayWithBoolean(MemorySegment array, int n, boolean val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_BOOLEAN, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillShortArrayWithChar(MemorySegment array, int n, char val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_CHAR, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillCharArrayWithShort(MemorySegment array, int n, short val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_SHORT, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillIntArrayWithFloat(MemorySegment array, int n, float val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_FLOAT, i, val);
}
}
@Test
@IR(failOn = {IRNode.CALL_OF, "(arrayof_)?.*_fill"})
static void testFillFloatArrayWithInt(MemorySegment array, int n, int val) {
for (int i = 0; i < n; i++) {
array.setAtIndex(ValueLayout.JAVA_INT, i, val);
}
}
@Run(test = {"testFillShortArrayWithByte",
"testFillIntArrayWithByte",
"testFillIntArrayWithShort",
"testFillByteArrayWithBoolean",
"testFillShortArrayWithChar",
"testFillCharArrayWithShort",
"testFillIntArrayWithFloat",
"testFillFloatArrayWithInt"})
public void runTypeMismatchTests() {
Random r = RunInfo.getRandom();
int N = r.ints(1, 1024).findFirst().getAsInt();
testFillShortArrayWithByte(MemorySegment.ofArray(new short[N]), N,
(byte)r.nextInt());
testFillIntArrayWithByte(MemorySegment.ofArray(new int[N]), N,
(byte)r.nextInt());
testFillIntArrayWithShort(MemorySegment.ofArray(new int[N]), N,
(short)r.nextInt());
testFillByteArrayWithBoolean(MemorySegment.ofArray(new byte[N]), N,
r.nextBoolean());
testFillShortArrayWithChar(MemorySegment.ofArray(new short[N]), N,
(char)r.nextInt());
testFillCharArrayWithShort(MemorySegment.ofArray(new char[N]), N,
(short)r.nextInt());
testFillIntArrayWithFloat(MemorySegment.ofArray(new int[N]), N,
r.nextFloat());
testFillFloatArrayWithInt(MemorySegment.ofArray(new float[N]), N,
r.nextInt());
}
}