# HG changeset patch # User pli # Date 1596072489 0 # Thu Jul 30 01:28:09 2020 +0000 # Node ID a20c11405387e61bd0dc3f27c76d66c39ed428f2 # Parent 5c94296da4a63f3c1de465b600843dbf189c5dd8 Jtreg tests for "8231441: AArch64: Initial SVE backend support" diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/CodegenTestRunner.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/CodegenTestRunner.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/CodegenTestRunner.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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.vectorization.aarch64; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import sun.hotspot.WhiteBox; +import sun.hotspot.cpuinfo.CPUInfo; + +import compiler.whitebox.CompilerWhiteBoxTest; + +public class CodegenTestRunner { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + protected @interface CallMath {} + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + protected @interface CheckOpto { + String neon() default ""; + String sve() default ""; + String sve2() default ""; + } + + private void checkMethod(Method method, int sveLevel) throws Exception { + String className = getClass().getName(); + String methodName = method.getName(); + + // Check if test method is valid + if (method.getParameterCount() > 0) { + throw new RuntimeException("Test method should have zero parameter"); + } + + // Find expected NEON/SVE instructions from the annotation + CheckOpto optos = method.getAnnotation(CheckOpto.class); + String opcodes, suffix; + switch (sveLevel) { + case 0: + opcodes = optos.neon(); + suffix = "# vector \\([0-9]+[A-Z]+\\)"; // 16B, 8H, 4S, 2D, ... + break; + case 1: + opcodes = optos.sve(); + suffix = "\\(sve\\)"; + break; + case 2: + opcodes = optos.sve2(); + suffix = "\\(sve2\\)"; + break; + default: + throw new RuntimeException("Unexpected SVE level"); + } + + // Skip this check if the expected instruction is not defined + if (opcodes.equals("")) { + return; + } + + // Create a process to compile specified method + String[] procArgs = { + "-Xbootclasspath/a:.", + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:-BackgroundCompilation", + "-XX:+PrintOptoAssembly", + "-XX:UseSVE=" + sveLevel, + "-XX:CompileOnly=" + className + "::" + methodName, + className, + methodName + }; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // The sub-process should exit with no error + output.shouldHaveExitValue(0); + output.stderrShouldBeEmptyIgnoreVMWarnings(); + + // Pattern match of the printed OptoAssembly to check the existence of + // expected SIMD instructions + // E.g. + // 27c sve_add V16, V17, V16 # vector (sve) + // matches + // "{SPACES}{opc}{SPACES}{ANYTHING}{suffix}" + for (String opc : opcodes.split("\\|")) { + // Check comma-separated opto instructions + String regex = "\\s+" + opc + "\\s+.+" + suffix; + output.stdoutShouldMatch(regex); + } + } + + private void testMethodsWithSVELevel(int sveLevel) { + Class testClass = getClass(); + for (Method testMethod : testClass.getDeclaredMethods()) { + // Check all methods with CheckOpto annotation + if (testMethod.isAnnotationPresent(CheckOpto.class)) { + try { + checkMethod(testMethod, sveLevel); + } catch (Exception e) { + // Report failed case and exit + System.err.println("Test failed in " + testClass.getName() + + "." + testMethod.getName() + ": " + e.getMessage()); + System.exit(1); + } + } + } + } + + private void checkCPUFeatureAndRun() { + if (CPUInfo.hasFeature("sve2")) { + testMethodsWithSVELevel(2); + } + if (CPUInfo.hasFeature("sve")) { + testMethodsWithSVELevel(1); + } + // always check NEON + testMethodsWithSVELevel(0); + } + + private void compileMethodByName(String methodName) { + try { + Method method = getClass().getDeclaredMethod(methodName); + if (method.isAnnotationPresent(CallMath.class)) { + // For method that calls intrinsified math methods, the class + // java.lang.Math should be loaded before the compilation to + // avoid C2 generating unexpected uncommon traps + try { + Class.forName("java.lang.Math"); + } catch (ClassNotFoundException e) { + System.err.println("Failed to load class java.lang.Math"); + } + } + WHITE_BOX.enqueueMethodForCompilation( + method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); + } catch (NoSuchMethodException e) { + System.err.println("Method " + methodName + " not found"); + } + } + + protected void run(String[] args) { + if (args.length == 0) { + // We are in the main java process running the test runner + // Create sub-processes to run the case with all supported SVE level + checkCPUFeatureAndRun(); + } else if (args.length == 1) { + // We are in the forked java process running the case + // Compile the method specified by args[0] for SIMD instruction check + compileMethodByName(args[0]); + } else { + System.err.println("Unexpected args[] length"); + System.exit(1); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorByteTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorByteTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorByteTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector byte + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorByteTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorByteTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private byte[] a = new byte[SIZE]; + private byte[] b = new byte[SIZE]; + private byte[] c = new byte[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "abs", sve = "sve_abs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) Math.abs(a[i]); + } + } + + @CheckOpto(neon = "addv", sve = "sve_add") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] + b[i]); + } + } + + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] - b[i]); + } + } + + @CheckOpto(neon = "mulv", sve = "sve_mul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] * b[i]); + } + } + +/* + // TODO: We need to check why vector multiply-add and multiply-sub are not + // generated for the byte type. + @CheckOpto(neon = "mlav", sve = "sve_mla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (c[i] + a[i] * b[i]); + } + } + + @CheckOpto(neon = "mlsv", sve = "sve_mls") + public void vectorMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (c[i] - a[i] * b[i]); + } + } +*/ + + // ---------------- Logic ---------------- + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorNot() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) ~a[i]; + } + } + + @CheckOpto(neon = "and", sve = "sve_and") + public void vectorAnd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] & b[i]); + } + } + + @CheckOpto(neon = "orr", sve = "sve_orr") + public void vectorOr() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] | b[i]); + } + } + + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorXor() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] ^ b[i]); + } + } + + // ---------------- Shift ---------------- + @CheckOpto(neon = "shl", sve = "sve_dup|sve_lsl") + public void vectorShiftLeft() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] << 3); + } + } + + @CheckOpto(neon = "sshr", sve = "sve_dup|sve_asr") + public void vectorSignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = (byte) (a[i] >> 2); + } + } + + // Unsigned shift right for signed narrow types (byte and short) should not + // be vectorized since the instruction behavior is different from JLS. + + // ---------------- Reduction ---------------- + // There's no reduction for narrowed integer types. + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorByteTest().run(args); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorDoubleTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorDoubleTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorDoubleTest.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector double + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorDoubleTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorDoubleTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private double[] a = new double[SIZE]; + private double[] b = new double[SIZE]; + private double[] c = new double[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "fneg", sve = "sve_fneg") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "fabs", sve = "sve_fabs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.abs(a[i]); + } + } + + @CallMath + @CheckOpto(sve = "sve_frint") + public void vectorCeil() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.ceil(a[i]); + } + } + + @CallMath + @CheckOpto(sve = "sve_frint") + public void vectorFloor() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.floor(a[i]); + } + } + + @CallMath + @CheckOpto(sve = "sve_frint") + public void vectorRint() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.rint(a[i]); + } + } + + @CallMath + @CheckOpto(neon = "fsqrt", sve = "sve_fsqrt") + public void vectorSqrt() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.sqrt(a[i]); + } + } + + @CheckOpto(neon = "fadd", sve = "sve_fadd") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] + b[i]; + } + } + + @CheckOpto(neon = "fsub", sve = "sve_fsub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] - b[i]; + } + } + + @CheckOpto(neon = "fmul", sve = "sve_fmul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] * b[i]; + } + } + + @CheckOpto(neon = "fdiv", sve = "sve_fdiv") + public void vectorDiv() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] / b[i]; + } + } + + @CallMath + @CheckOpto(neon = "fmax", sve = "sve_fmax") + public void vectorMax() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.max(a[i], b[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmin", sve = "sve_fmin") + public void vectorMin() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.min(a[i], b[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmla", sve = "sve_fmla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], b[i], c[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmls", sve = "sve_fmls") + public void vectorMulSub1() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(-a[i], b[i], c[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmls", sve = "sve_fmls") + public void vectorMulSub2() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], -b[i], c[i]); + } + } + + // Vector fnmla isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmla") + public void vectorNegateMulAdd1() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(-a[i], b[i], -c[i]); + } + } + + // Vector fnmla isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmla") + public void vectorNegateMulAdd2() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], -b[i], -c[i]); + } + } + + // Vector fnmls isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmls") + public void vectorNegateMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], b[i], -c[i]); + } + } + + // ---------------- Reduction ---------------- + @CheckOpto(sve = "sve_fsub|sve_fadda") + public double reductionAdd() { + double sum = 0.0; + for (int i = 0; i < SIZE; i++) { + sum += (a[i] - b[i]); + } + return sum; + } + + @CallMath + @CheckOpto(sve = "sve_fsub|sve_fminv") + public double reductionMin() { + double min = Double.POSITIVE_INFINITY; + for (int i = 0; i < SIZE; i++) { + min = Math.min(min, a[i] - b[i]); + } + return min; + } + + @CallMath + @CheckOpto(sve = "sve_fsub|sve_fmaxv") + public double reductionMax() { + double max = Double.NEGATIVE_INFINITY; + for (int i = 0; i < SIZE; i++) { + max = Math.max(max, a[i] - b[i]); + } + return max; + } + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorDoubleTest().run(args); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorFloatTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorFloatTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorFloatTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector float + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorFloatTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorFloatTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private float[] a = new float[SIZE]; + private float[] b = new float[SIZE]; + private float[] c = new float[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "fneg", sve = "sve_fneg") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "fabs", sve = "sve_fabs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.abs(a[i]); + } + } + + @CallMath + @CheckOpto(neon = "fsqrt", sve = "sve_fsqrt") + public void vectorSqrt() { + for (int i = 0; i < SIZE; i++) { + c[i] = (float) Math.sqrt(a[i]); + } + } + + @CheckOpto(neon = "fadd", sve = "sve_fadd") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] + b[i]; + } + } + + @CheckOpto(neon = "fsub", sve = "sve_fsub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] - b[i]; + } + } + + @CheckOpto(neon = "fmul", sve = "sve_fmul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] * b[i]; + } + } + + @CheckOpto(neon = "fdiv", sve = "sve_fdiv") + public void vectorDiv() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] / b[i]; + } + } + + @CallMath + @CheckOpto(neon = "fmax", sve = "sve_fmax") + public void vectorMax() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.max(a[i], b[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmin", sve = "sve_fmin") + public void vectorMin() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.min(a[i], b[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmla", sve = "sve_fmla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], b[i], c[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmls", sve = "sve_fmls") + public void vectorMulSub1() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(-a[i], b[i], c[i]); + } + } + + @CallMath + @CheckOpto(neon = "fmls", sve = "sve_fmls") + public void vectorMulSub2() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], -b[i], c[i]); + } + } + + // Vector fnmla isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmla") + public void vectorNegateMulAdd1() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(-a[i], b[i], -c[i]); + } + } + + // Vector fnmla isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmla") + public void vectorNegateMulAdd2() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], -b[i], -c[i]); + } + } + + // Vector fnmls isn't implemented in NEON backend. + @CallMath + @CheckOpto(sve = "sve_fnmls") + public void vectorNegateMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.fma(a[i], b[i], -c[i]); + } + } + + // ---------------- Reduction ---------------- + @CheckOpto(sve = "sve_fsub|sve_fadda") + public float reductionAdd() { + float sum = 0.0f; + for (int i = 0; i < SIZE; i++) { + sum += (a[i] - b[i]); + } + return sum; + } + + @CallMath + @CheckOpto(sve = "sve_fsub|sve_fminv") + public float reductionMin() { + float min = Float.POSITIVE_INFINITY; + for (int i = 0; i < SIZE; i++) { + min = Math.min(min, a[i] - b[i]); + } + return min; + } + + @CallMath + @CheckOpto(sve = "sve_fsub|sve_fmaxv") + public float reductionMax() { + float max = Float.NEGATIVE_INFINITY; + for (int i = 0; i < SIZE; i++) { + max = Math.max(max, a[i] - b[i]); + } + return max; + } + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorFloatTest().run(args); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorIntTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorIntTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorIntTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector int + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorIntTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorIntTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private int[] a = new int[SIZE]; + private int[] b = new int[SIZE]; + private int[] c = new int[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "abs", sve = "sve_abs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.abs(a[i]); + } + } + + @CheckOpto(neon = "addv", sve = "sve_add") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] + b[i]; + } + } + + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] - b[i]; + } + } + + @CheckOpto(neon = "mulv", sve = "sve_mul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] * b[i]; + } + } + + @CheckOpto(neon = "mlav", sve = "sve_mla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = c[i] + a[i] * b[i]; + } + } + + @CheckOpto(neon = "mlsv", sve = "sve_mls") + public void vectorMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = c[i] - a[i] * b[i]; + } + } + + // ---------------- Logic ---------------- + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorNot() { + for (int i = 0; i < SIZE; i++) { + c[i] = ~a[i]; + } + } + + @CheckOpto(neon = "and", sve = "sve_and") + public void vectorAnd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] & b[i]; + } + } + + @CheckOpto(neon = "orr", sve = "sve_orr") + public void vectorOr() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] | b[i]; + } + } + + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorXor() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] ^ b[i]; + } + } + + // ---------------- Shift ---------------- + @CheckOpto(neon = "shl", sve = "sve_dup|sve_lsl") + public void vectorShiftLeft() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] << 3; + } + } + + @CheckOpto(neon = "sshr", sve = "sve_dup|sve_asr") + public void vectorSignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] >> 2; + } + } + + @CheckOpto(neon = "ushr", sve = "sve_dup|sve_lsr") + public void vectorUnsignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] >>> 5; + } + } + + // ---------------- Reduction ---------------- + // Temporarily skip NEON reduction checks since the opto assembly of NEON + // reduction instructions doesn't have the "# vector (T)" suffix. + @CheckOpto(sve = "sve_sub|sve_uaddv") + public int reductionAdd() { + int sum = 0; + for (int i = 0; i < SIZE; i++) { + sum += (a[i] - b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_andv") + public int reductionAnd() { + int sum = -1; + for (int i = 0; i < SIZE; i++) { + sum &= (a[i] + b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_orv") + public int reductionOr() { + int sum = 0; + for (int i = 0; i < SIZE; i++) { + sum |= (a[i] + b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_xorv") + public int reductionXor() { + int sum = 0; + for (int i = 0; i < SIZE; i++) { + sum ^= (a[i] + b[i]); + } + return sum; + } + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorIntTest().run(args); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorLongTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorLongTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorLongTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector long + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorLongTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorLongTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private long[] a = new long[SIZE]; + private long[] b = new long[SIZE]; + private long[] c = new long[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "abs", sve = "sve_abs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = Math.abs(a[i]); + } + } + + @CheckOpto(neon = "addv", sve = "sve_add") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] + b[i]; + } + } + + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] - b[i]; + } + } + + // NEON doesn't have vector multiply for long type. + @CheckOpto(sve = "sve_mul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] * b[i]; + } + } + + // NEON doesn't have vector multiply-add for long type. + @CheckOpto(sve = "sve_mla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = c[i] + a[i] * b[i]; + } + } + + // NEON doesn't have vector multiply-sub for long type. + @CheckOpto(sve = "sve_mls") + public void vectorMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = c[i] - a[i] * b[i]; + } + } + + // ---------------- Logic ---------------- + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorNot() { + for (int i = 0; i < SIZE; i++) { + c[i] = ~a[i]; + } + } + + @CheckOpto(neon = "and", sve = "sve_and") + public void vectorAnd() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] & b[i]; + } + } + + @CheckOpto(neon = "orr", sve = "sve_orr") + public void vectorOr() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] | b[i]; + } + } + + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorXor() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] ^ b[i]; + } + } + + // ---------------- Shift ---------------- + @CheckOpto(neon = "shl", sve = "sve_dup|sve_lsl") + public void vectorShiftLeft() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] << 3; + } + } + + @CheckOpto(neon = "sshr", sve = "sve_dup|sve_asr") + public void vectorSignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] >> 2; + } + } + + @CheckOpto(neon = "ushr", sve = "sve_dup|sve_lsr") + public void vectorUnsignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = a[i] >>> 5; + } + } + + // ---------------- Reduction ---------------- + // Temporarily skip NEON reduction checks since the opto assembly of NEON + // reduction instructions doesn't have the "# vector (T)" suffix. + @CheckOpto(sve = "sve_sub|sve_uaddv") + public long reductionAdd() { + long sum = 0L; + for (int i = 0; i < SIZE; i++) { + sum += (a[i] - b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_andv") + public long reductionAnd() { + long sum = -1L; + for (int i = 0; i < SIZE; i++) { + sum &= (a[i] + b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_orv") + public long reductionOr() { + long sum = 0L; + for (int i = 0; i < SIZE; i++) { + sum |= (a[i] + b[i]); + } + return sum; + } + + @CheckOpto(sve = "sve_add|sve_xorv") + public long reductionXor() { + long sum = 0L; + for (int i = 0; i < SIZE; i++) { + sum ^= (a[i] + b[i]); + } + return sum; + } + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorLongTest().run(args); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorShortTest.java b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorShortTest.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/aarch64/VectorShortTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. 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 + * @summary AArch64 SIMD codegen test for vector short + * @library /test/lib / + * + * @build sun.hotspot.WhiteBox + * compiler.vectorization.aarch64.CodegenTestRunner + * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. + * -XX:+WhiteBoxAPI + * compiler.vectorization.aarch64.VectorShortTest + * + * @requires os.arch == "aarch64" & vm.debug == true & + * vm.compiler2.enabled & !vm.graal.enabled + */ + +package compiler.vectorization.aarch64; + +public class VectorShortTest extends CodegenTestRunner { + + private static final int SIZE = 5432; + + private short[] a = new short[SIZE]; + private short[] b = new short[SIZE]; + private short[] c = new short[SIZE]; + + // ---------------- Arithmetic ---------------- + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorNeg() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) -a[i]; + } + } + + @CallMath + @CheckOpto(neon = "abs", sve = "sve_abs") + public void vectorAbs() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) Math.abs(a[i]); + } + } + + @CheckOpto(neon = "addv", sve = "sve_add") + public void vectorAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] + b[i]); + } + } + + @CheckOpto(neon = "subv", sve = "sve_sub") + public void vectorSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] - b[i]); + } + } + + @CheckOpto(neon = "mulv", sve = "sve_mul") + public void vectorMul() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] * b[i]); + } + } + + @CheckOpto(neon = "mlav", sve = "sve_mla") + public void vectorMulAdd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (c[i] + a[i] * b[i]); + } + } + + @CheckOpto(neon = "mlsv", sve = "sve_mls") + public void vectorMulSub() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (c[i] - a[i] * b[i]); + } + } + + // ---------------- Logic ---------------- + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorNot() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) ~a[i]; + } + } + + @CheckOpto(neon = "and", sve = "sve_and") + public void vectorAnd() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] & b[i]); + } + } + + @CheckOpto(neon = "orr", sve = "sve_orr") + public void vectorOr() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] | b[i]); + } + } + + @CheckOpto(neon = "xor", sve = "sve_eor") + public void vectorXor() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] ^ b[i]); + } + } + + // ---------------- Shift ---------------- + @CheckOpto(neon = "shl", sve = "sve_dup|sve_lsl") + public void vectorShiftLeft() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] << 3); + } + } + + @CheckOpto(neon = "sshr", sve = "sve_dup|sve_asr") + public void vectorSignedShiftRight() { + for (int i = 0; i < SIZE; i++) { + c[i] = (short) (a[i] >> 2); + } + } + + // Unsigned shift right for signed narrow types (byte and short) should not + // be vectorized since the instruction behavior is different from JLS. + + // ---------------- Reduction ---------------- + // There's no reduction for narrow integer types. + + public static void main(String[] args) { + // Delegate work to the test runner + new VectorShortTest().run(args); + } +} +