Skip to content

Commit 8f91731

Browse files
Automatic merge of master into galahad
2 parents eacb6fb + 9ad216f commit 8f91731

File tree

15 files changed

+1116
-4
lines changed

15 files changed

+1116
-4
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.replacements.test;
26+
27+
import java.util.Arrays;
28+
29+
import org.junit.Assume;
30+
import org.junit.Test;
31+
32+
import jdk.graal.compiler.nodes.Invoke;
33+
import jdk.graal.compiler.nodes.StructuredGraph;
34+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
35+
import jdk.graal.compiler.replacements.ConstantBindingParameterPlugin;
36+
import jdk.graal.compiler.replacements.nodes.ArrayFillNode;
37+
import jdk.vm.ci.aarch64.AArch64;
38+
import jdk.vm.ci.code.InstalledCode;
39+
import jdk.vm.ci.meta.ResolvedJavaMethod;
40+
41+
public class ArraysFillTest extends ArraysSubstitutionsTestBase {
42+
private static final int[] LENGTHS = {0, 1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 31, 65, 127, 255, 1023, 1024, 1025};
43+
44+
private void testFills(Class<?> type, Object constant) {
45+
Assume.assumeTrue((getTarget().arch instanceof AArch64));
46+
for (int length : LENGTHS) {
47+
testFillsSubstitution(new ArraysFillTestConfig(type, length, constant));
48+
}
49+
}
50+
51+
@Test
52+
public void testFillBooleanFalse() {
53+
testFills(boolean.class, false);
54+
}
55+
56+
@Test
57+
public void testFillBooleanTrue() {
58+
testFills(boolean.class, true);
59+
}
60+
61+
@Test
62+
public void testFillCharA() {
63+
testFills(char.class, 'A');
64+
}
65+
66+
@Test
67+
public void testFillChar0() {
68+
testFills(char.class, '0');
69+
}
70+
71+
@Test
72+
public void testFillByteMin() {
73+
testFills(byte.class, Byte.MIN_VALUE);
74+
}
75+
76+
@Test
77+
public void testFillByteMax() {
78+
testFills(byte.class, Byte.MAX_VALUE);
79+
}
80+
81+
@Test
82+
public void testFillShortMin() {
83+
testFills(short.class, Short.MIN_VALUE);
84+
}
85+
86+
@Test
87+
public void testFillShortMax() {
88+
testFills(short.class, Short.MAX_VALUE);
89+
}
90+
91+
@Test
92+
public void testFillIntMin() {
93+
testFills(int.class, Integer.MIN_VALUE);
94+
}
95+
96+
@Test
97+
public void testFillIntMax() {
98+
testFills(int.class, Integer.MAX_VALUE);
99+
}
100+
101+
@Test
102+
public void testFillLongMin() {
103+
testFills(long.class, Long.MIN_VALUE);
104+
}
105+
106+
@Test
107+
public void testFillLongMax() {
108+
testFills(long.class, Long.MAX_VALUE);
109+
}
110+
111+
@Test
112+
public void testFillFloatMin() {
113+
testFills(float.class, Float.MIN_VALUE);
114+
}
115+
116+
@Test
117+
public void testFillFloatMax() {
118+
testFills(float.class, Float.MAX_VALUE);
119+
}
120+
121+
@Test
122+
public void testFillDoubleMin() {
123+
testFills(double.class, Double.MIN_VALUE);
124+
}
125+
126+
@Test
127+
public void testFillDoubleMax() {
128+
testFills(double.class, Double.MAX_VALUE);
129+
}
130+
131+
private Object[] constantArgs;
132+
133+
@Override
134+
protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
135+
if (constantArgs != null) {
136+
ConstantBindingParameterPlugin constantBinding = new ConstantBindingParameterPlugin(constantArgs, this.getMetaAccess(), this.getSnippetReflection());
137+
conf.getPlugins().appendParameterPlugin(constantBinding);
138+
}
139+
return super.editGraphBuilderConfiguration(conf);
140+
}
141+
142+
protected void testFillsSubstitution(ArraysFillTestConfig config) {
143+
ResolvedJavaMethod realMethod = getResolvedJavaMethod(Arrays.class, "fill", config.parameterType());
144+
ResolvedJavaMethod testMethod = getResolvedJavaMethod(config.testMethodName());
145+
StructuredGraph graph = testGraph(config.testMethodName());
146+
147+
// Check to see if the resulting graph contains the expected node
148+
StructuredGraph replacement = getReplacements().getInlineSubstitution(realMethod, 0, false, Invoke.InlineControl.Normal, false, null, graph.allowAssumptions(), graph.getOptions());
149+
if (replacement == null) {
150+
assertInGraph(graph, ArrayFillNode.class);
151+
}
152+
153+
// Force compilation
154+
InstalledCode code = getCode(testMethod, null, true);
155+
assert code != null;
156+
157+
Object array1 = config.newArray();
158+
Object array2 = config.newArray();
159+
Object array3 = config.newArray();
160+
161+
invokeSafe(realMethod, null, array1, config.getConstant());
162+
invokeSafe(testMethod, null, array2, config.getConstant());
163+
executeVarargsSafe(code, array3, config.getConstant());
164+
165+
// Verify that the original method and the substitution produce the same value
166+
assertDeepEquals(array1, array2);
167+
168+
// Verify that the generated code and the original produce the same value
169+
assertDeepEquals(array2, array3);
170+
}
171+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.replacements.test;
26+
27+
import jdk.graal.compiler.replacements.test.ArraysSubstitutionsTestBase.ArrayBuilder;
28+
29+
class ArraysFillTestConfig {
30+
private Class<?> type = null;
31+
private Object constant = null;
32+
private int length = 0;
33+
34+
private Object[] parameterTypes = new Object[]{
35+
new Class<?>[]{boolean[].class, boolean.class},
36+
new Class<?>[]{byte[].class, byte.class},
37+
new Class<?>[]{char[].class, char.class},
38+
new Class<?>[]{short[].class, short.class},
39+
new Class<?>[]{int[].class, int.class},
40+
new Class<?>[]{long[].class, long.class},
41+
new Class<?>[]{float[].class, float.class},
42+
new Class<?>[]{double[].class, double.class}
43+
};
44+
45+
private ArrayBuilder[] builders = new ArrayBuilder[]{
46+
ArraysSubstitutionsTestBase::booleanArray,
47+
ArraysSubstitutionsTestBase::byteArray,
48+
ArraysSubstitutionsTestBase::charArray,
49+
ArraysSubstitutionsTestBase::shortArray,
50+
ArraysSubstitutionsTestBase::intArray,
51+
ArraysSubstitutionsTestBase::longArray,
52+
ArraysSubstitutionsTestBase::floatArray,
53+
ArraysSubstitutionsTestBase::doubleArray,
54+
};
55+
56+
private String[] testMethodNames = new String[]{
57+
"arraysFillBoolean",
58+
"arraysFillByte",
59+
"arraysFillChar",
60+
"arraysFillShort",
61+
"arraysFillInt",
62+
"arraysFillLong",
63+
"arraysFillFloat",
64+
"arraysFillDouble",
65+
};
66+
67+
ArraysFillTestConfig(Class<?> type, int length, Object constant) {
68+
this.type = type;
69+
this.length = length;
70+
this.constant = constant;
71+
}
72+
73+
public String testMethodName() throws IllegalArgumentException {
74+
return testMethodNames[index()];
75+
}
76+
77+
public Object newArray() throws IllegalArgumentException {
78+
ArrayBuilder builder = builders[index()];
79+
return builder.newArray(this.length, 0, 0);
80+
}
81+
82+
public Class<?>[] parameterType() throws IllegalArgumentException {
83+
return (Class<?>[]) parameterTypes[index()];
84+
}
85+
86+
public Object getConstant() {
87+
return this.constant;
88+
}
89+
90+
private int index() {
91+
if (type == boolean.class) {
92+
return 0;
93+
} else if (type == byte.class) {
94+
return 1;
95+
} else if (type == char.class) {
96+
return 2;
97+
} else if (type == short.class) {
98+
return 3;
99+
} else if (type == int.class) {
100+
return 4;
101+
} else if (type == long.class) {
102+
return 5;
103+
} else if (type == float.class) {
104+
return 6;
105+
} else if (type == double.class) {
106+
return 7;
107+
} else {
108+
throw new IllegalArgumentException("Unexpected type for 'type' field: " + type);
109+
}
110+
}
111+
}

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArraysSubstitutionsTestBase.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,38 @@ public static boolean arraysEqualsLong(long[] a, long[] b) {
6363
return Arrays.equals(a, b);
6464
}
6565

66+
public static void arraysFillBoolean(boolean[] a, boolean b) {
67+
Arrays.fill(a, b);
68+
}
69+
70+
public static void arraysFillByte(byte[] a, byte b) {
71+
Arrays.fill(a, b);
72+
}
73+
74+
public static void arraysFillChar(char[] a, char b) {
75+
Arrays.fill(a, b);
76+
}
77+
78+
public static void arraysFillShort(short[] a, short b) {
79+
Arrays.fill(a, b);
80+
}
81+
82+
public static void arraysFillInt(int[] a, int b) {
83+
Arrays.fill(a, b);
84+
}
85+
86+
public static void arraysFillLong(long[] a, long b) {
87+
Arrays.fill(a, b);
88+
}
89+
90+
public static void arraysFillFloat(float[] a, float b) {
91+
Arrays.fill(a, b);
92+
}
93+
94+
public static void arraysFillDouble(double[] a, double b) {
95+
Arrays.fill(a, b);
96+
}
97+
6698
interface ArrayBuilder {
6799
Object newArray(int length, int firstValue, int lastValue);
68100
}
@@ -150,4 +182,32 @@ static long[] longArray(int length, int firstValue, int lastValue) {
150182
}
151183
return arr;
152184
}
185+
186+
static float[] floatArray(int length, float firstValue, float lastValue) {
187+
float[] arr = new float[length];
188+
for (int i = 0; i < length; i++) {
189+
arr[i] = i;
190+
}
191+
if (length > 0) {
192+
arr[0] = firstValue;
193+
}
194+
if (length > 1) {
195+
arr[length - 1] = lastValue;
196+
}
197+
return arr;
198+
}
199+
200+
static double[] doubleArray(int length, double firstValue, double lastValue) {
201+
double[] arr = new double[length];
202+
for (int i = 0; i < length; i++) {
203+
arr[i] = i;
204+
}
205+
if (length > 0) {
206+
arr[0] = firstValue;
207+
}
208+
if (length > 1) {
209+
arr[length - 1] = lastValue;
210+
}
211+
return arr;
212+
}
153213
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,21 @@ public void bfm(int size, Register dst, Register src, int r, int s) {
24492449
bitfieldInstruction(BFM, dst, src, r, s, generalFromSize(size));
24502450
}
24512451

2452+
/**
2453+
* C6.2.30 Bitfield insert.
2454+
*
2455+
* @param size register size. Has to be 32 or 64.
2456+
* @param dst general purpose register. May not be null, stackpointer or zero-register.
2457+
* @param src general purpose register. May not be null, stackpointer or zero-register.
2458+
* @param lsb start index of target register to override with bits from src register.
2459+
* @param width number of bits to copy from src register.
2460+
*/
2461+
public void bfi(int size, Register dst, Register src, int lsb, int width) {
2462+
assert verifySizeAndRegistersRR(size, dst, src);
2463+
2464+
bfm(size, dst, src, ((size - lsb) & (size - 1)), (width - 1));
2465+
}
2466+
24522467
/**
24532468
* C6.2.337 Unsigned bitfield move.
24542469
*

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import jdk.graal.compiler.lir.aarch64.AArch64ArithmeticOp;
5656
import jdk.graal.compiler.lir.aarch64.AArch64ArrayCompareToOp;
5757
import jdk.graal.compiler.lir.aarch64.AArch64ArrayCopyWithConversionsOp;
58+
import jdk.graal.compiler.lir.aarch64.AArch64ArrayFillOp;
5859
import jdk.graal.compiler.lir.aarch64.AArch64ArrayEqualsOp;
5960
import jdk.graal.compiler.lir.aarch64.AArch64ArrayIndexOfOp;
6061
import jdk.graal.compiler.lir.aarch64.AArch64ArrayRegionCompareToOp;
@@ -623,6 +624,11 @@ public void emitArrayCopyWithConversion(EnumSet<?> runtimeCheckedCPUFeatures, Va
623624
emitConvertNullToZero(arrayDst), asAllocatable(offsetDst), emitConvertNullToZero(arraySrc), asAllocatable(offsetSrc), asAllocatable(length), asAllocatable(dynamicStrides)));
624625
}
625626

627+
@Override
628+
public void emitArrayFill(JavaKind kind, EnumSet<?> runtimeCheckedCPUFeatures, Value array, Value arrayBaseOffset, Value length, Value value) {
629+
append(new AArch64ArrayFillOp(kind, emitConvertNullToZero(array), asAllocatable(arrayBaseOffset), asAllocatable(length), asAllocatable(value)));
630+
}
631+
626632
@Override
627633
public Variable emitArrayEquals(JavaKind kind, EnumSet<?> runtimeCheckedCPUFeatures,
628634
Value arrayA, Value offsetA, Value arrayB, Value offsetB, Value length) {

0 commit comments

Comments
 (0)