jdk-24/test/hotspot/jtreg/compiler/vectorization/TestOptionVectorizeIR.java
Emanuel Peter a02d65efcc 8310308: IR Framework: check for type and size of vector nodes
Reviewed-by: chagedorn, thartmann
2023-08-15 10:08:51 +00:00

804 lines
21 KiB
Java

/*
* Copyright (c) 2023, 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 8298935
* @summary Test forced vectorization, and check IR for vector instructions
* @requires vm.compiler2.enabled
* @library /test/lib /
* @run driver compiler.vectorization.TestOptionVectorizeIR
*/
package compiler.vectorization;
import compiler.lib.ir_framework.*;
public class TestOptionVectorizeIR {
static int RANGE = 1024*2;
static int ITER = 100;
int[] gold1 = new int[RANGE];
int[] gold2 = new int[RANGE];
int[] gold3 = new int[RANGE];
int[] gold4 = new int[RANGE];
int[] gold5 = new int[RANGE];
int[] gold6 = new int[RANGE];
long[] gold10 = new long[RANGE];
long[] gold11 = new long[RANGE];
long[] gold12 = new long[RANGE];
long[] gold13 = new long[RANGE];
short[] gold20 = new short[RANGE];
short[] gold21 = new short[RANGE];
short[] gold22 = new short[RANGE];
short[] gold23 = new short[RANGE];
byte[] gold30 = new byte[RANGE];
byte[] gold31 = new byte[RANGE];
byte[] gold32 = new byte[RANGE];
byte[] gold33 = new byte[RANGE];
char[] gold40 = new char[RANGE];
char[] gold41 = new char[RANGE];
char[] gold42 = new char[RANGE];
char[] gold43 = new char[RANGE];
float[] gold50 = new float[RANGE];
float[] gold51 = new float[RANGE];
float[] gold52 = new float[RANGE];
float[] gold53 = new float[RANGE];
double[] gold60 = new double[RANGE];
double[] gold61 = new double[RANGE];
double[] gold62 = new double[RANGE];
double[] gold63 = new double[RANGE];
public static void main(String args[]) {
TestFramework.runWithFlags("-XX:CompileCommand=option,compiler.vectorization.TestOptionVectorizeIR::test*,Vectorize");
}
TestOptionVectorizeIR() {
// compute the gold standard in interpreter mode
// test1
test1(gold1);
// test2
test1(gold2);
test2(gold2);
// test3
test1(gold3);
test3(gold3, 2, 3);
// test4
test1(gold4);
test4(gold4);
// test5
test1(gold5);
test5(gold5);
// test6
test1(gold6);
test6(gold6);
// long
init(gold10);
test10(gold10);
init(gold11);
test11(gold11);
init(gold12);
test12(gold12);
init(gold13);
test13(gold13);
// short
init(gold20);
test20(gold20);
init(gold21);
test21(gold21);
init(gold22);
test22(gold22);
init(gold23);
test23(gold23);
// byte
init(gold30);
test30(gold30);
init(gold31);
test31(gold31);
init(gold32);
test32(gold32);
init(gold33);
test33(gold33);
// char
init(gold40);
test40(gold40);
init(gold41);
test41(gold41);
init(gold42);
test42(gold42);
init(gold43);
test43(gold43);
// float
init(gold50);
test50(gold50);
init(gold51);
test51(gold51);
init(gold52);
test52(gold52);
init(gold53);
test53(gold53);
// double
init(gold60);
test60(gold60);
init(gold61);
test61(gold61);
init(gold62);
test62(gold62);
init(gold63);
test63(gold63);
}
@Run(test = "test1")
@Warmup(100)
public void runTest1() {
int[] data = new int[RANGE];
test1(data);
verify("test1", data, gold1);
}
@Run(test = "test2")
@Warmup(100)
public void runTest2() {
int[] data = new int[RANGE];
test1(data);
test2(data);
verify("test2", data, gold2);
}
@Run(test = "test3")
@Warmup(100)
public void runTest3() {
int[] data = new int[RANGE];
test1(data);
test3(data, 2, 3);
verify("test3", data, gold3);
}
@Run(test = "test4")
@Warmup(100)
public void runTest4() {
int[] data = new int[RANGE];
test1(data);
test4(data);
verify("test4", data, gold4);
}
@Run(test = "test5")
@Warmup(100)
public void runTest5() {
int[] data = new int[RANGE];
test1(data);
test5(data);
verify("test5", data, gold5);
}
@Run(test = "test6")
@Warmup(100)
public void runTest6() {
int[] data = new int[RANGE];
test1(data);
test6(data);
verify("test6", data, gold6);
}
@Test
static void test1(int[] data) {
for (int j = 0; j < RANGE; j++) {
// Vectorizes even if it is not forced
data[j] = j;
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.ADD_VI, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test2(int[] data) {
for (int j = 0; j < RANGE - 1; j++) {
// Only vectorizes if forced, because of offset by 1
data[j] = data[j] + data[j + 1];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.REPLICATE_I, "> 0", IRNode.ADD_VI, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test3(int[] data, int A, int B) {
for (int j = 0; j < RANGE - 1; j++) {
// Only vectorizes if forced, because of offset by 1
data[j] = A * data[j] + B * data[j + 1];
}
}
@Test
static void test4(int[] data) {
for (int j = 0; j < RANGE - 1; j++) {
// write forward -> cyclic dependency -> cannot vectorize
// independent(s1, s2) for adjacent loads should detect this
data[j + 1] = data[j];
}
}
@Test
static void test5(int[] data) {
for (int j = 0; j < RANGE - 3; j++) {
// write forward -> cyclic dependency -> cannot vectorize
// independent(s1, s2) for adjacent loads cannot detect this
// Checks with memory_alignment are disabled via compile option
data[j + 2] = data[j];
}
}
@Test
static void test6(int[] data) {
for (int j = 0; j < RANGE - 3; j++) {
// write forward -> cyclic dependency -> cannot vectorize
// independent(s1, s2) for adjacent loads cannot detect this
// Checks with memory_alignment are disabled via compile option
data[j + 3] = data[j];
}
}
// ------------------------- Long -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test10(long[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test11(long[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test12(long[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test13(long[] data) {
// 128-bit vectors -> can vectorize because only 2 elements
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test10")
@Warmup(100)
public void runTest10() {
long[] data = new long[RANGE];
init(data);
test10(data);
verify("test10", data, gold10);
}
@Run(test = "test11")
@Warmup(100)
public void runTest11() {
long[] data = new long[RANGE];
init(data);
test11(data);
verify("test11", data, gold11);
}
@Run(test = "test12")
@Warmup(100)
public void runTest12() {
long[] data = new long[RANGE];
init(data);
test12(data);
verify("test12", data, gold12);
}
@Run(test = "test13")
@Warmup(100)
public void runTest13() {
long[] data = new long[RANGE];
init(data);
test13(data);
verify("test13", data, gold13);
}
// ------------------------- Short -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test20(short[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test21(short[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test22(short[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test23(short[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test20")
@Warmup(100)
public void runTest20() {
short[] data = new short[RANGE];
init(data);
test20(data);
verify("test20", data, gold20);
}
@Run(test = "test21")
@Warmup(100)
public void runTest21() {
short[] data = new short[RANGE];
init(data);
test21(data);
verify("test21", data, gold21);
}
@Run(test = "test22")
@Warmup(100)
public void runTest22() {
short[] data = new short[RANGE];
init(data);
test22(data);
verify("test22", data, gold22);
}
@Run(test = "test23")
@Warmup(100)
public void runTest23() {
short[] data = new short[RANGE];
init(data);
test23(data);
verify("test23", data, gold23);
}
// ------------------------- Byte -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.ADD_VB, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test30(byte[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.ADD_VB, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test31(byte[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test32(byte[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test33(byte[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test30")
@Warmup(100)
public void runTest30() {
byte[] data = new byte[RANGE];
init(data);
test30(data);
verify("test30", data, gold30);
}
@Run(test = "test31")
@Warmup(100)
public void runTest31() {
byte[] data = new byte[RANGE];
init(data);
test31(data);
verify("test31", data, gold31);
}
@Run(test = "test32")
@Warmup(100)
public void runTest32() {
byte[] data = new byte[RANGE];
init(data);
test32(data);
verify("test32", data, gold32);
}
@Run(test = "test33")
@Warmup(100)
public void runTest33() {
byte[] data = new byte[RANGE];
init(data);
test33(data);
verify("test33", data, gold33);
}
// ------------------------- Char -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test40(char[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.ADD_VS, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test41(char[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test42(char[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test43(char[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test40")
@Warmup(100)
public void runTest40() {
char[] data = new char[RANGE];
init(data);
test40(data);
verify("test40", data, gold40);
}
@Run(test = "test41")
@Warmup(100)
public void runTest41() {
char[] data = new char[RANGE];
init(data);
test41(data);
verify("test41", data, gold41);
}
@Run(test = "test42")
@Warmup(100)
public void runTest42() {
char[] data = new char[RANGE];
init(data);
test42(data);
verify("test42", data, gold42);
}
@Run(test = "test43")
@Warmup(100)
public void runTest43() {
char[] data = new char[RANGE];
init(data);
test43(data);
verify("test43", data, gold43);
}
// ------------------------- Float -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_VF, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test50(float[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.ADD_VF, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test51(float[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test52(float[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test53(float[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test50")
@Warmup(100)
public void runTest50() {
float[] data = new float[RANGE];
init(data);
test50(data);
verify("test50", data, gold50);
}
@Run(test = "test51")
@Warmup(100)
public void runTest51() {
float[] data = new float[RANGE];
init(data);
test51(data);
verify("test51", data, gold51);
}
@Run(test = "test52")
@Warmup(100)
public void runTest52() {
float[] data = new float[RANGE];
init(data);
test52(data);
verify("test52", data, gold52);
}
@Run(test = "test53")
@Warmup(100)
public void runTest53() {
float[] data = new float[RANGE];
init(data);
test53(data);
verify("test53", data, gold53);
}
// ------------------------- Double -----------------------------
@Test
@IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.ADD_VD, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test60(double[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 2];
}
}
@Test
@IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.ADD_VD, "> 0", IRNode.STORE_VECTOR, "> 0"},
applyIf = {"AlignVector", "false"},
applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"})
static void test61(double[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j + 1];
}
}
@Test
static void test62(double[] data) {
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 1];
}
}
@Test
static void test63(double[] data) {
// 128-bit vectors -> can vectorize because only 2 elements
for (int j = 2; j < RANGE - 2; j++) {
data[j] += data[j - 2];
}
}
@Run(test = "test60")
@Warmup(100)
public void runTest60() {
double[] data = new double[RANGE];
init(data);
test60(data);
verify("test60", data, gold60);
}
@Run(test = "test61")
@Warmup(100)
public void runTest61() {
double[] data = new double[RANGE];
init(data);
test61(data);
verify("test61", data, gold61);
}
@Run(test = "test62")
@Warmup(100)
public void runTest62() {
double[] data = new double[RANGE];
init(data);
test62(data);
verify("test62", data, gold62);
}
@Run(test = "test63")
@Warmup(100)
public void runTest63() {
double[] data = new double[RANGE];
init(data);
test63(data);
verify("test63", data, gold63);
}
static void init(long[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = j;
}
}
static void init(short[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = (short)j;
}
}
static void init(byte[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = (byte)j;
}
}
static void init(char[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = (char)j;
}
}
static void init(float[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = j;
}
}
static void init(double[] data) {
for (int j = 0; j < RANGE; j++) {
data[j] = j;
}
}
static void verify(String name, int[] data, int[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, long[] data, long[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, short[] data, short[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, byte[] data, byte[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, char[] data, char[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, float[] data, float[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
static void verify(String name, double[] data, double[] gold) {
for (int i = 0; i < RANGE; i++) {
if (data[i] != gold[i]) {
throw new RuntimeException(" Invalid " + name + " result: data[" + i + "]: " + data[i] + " != " + gold[i]);
}
}
}
}