8275317: AArch64: Support some type conversion vectorization in SLP

Reviewed-by: thartmann, ngasson
This commit is contained in:
Faye Gao 2021-11-17 08:19:46 +00:00 committed by Tobias Hartmann
parent 08f65a59a7
commit 9aa30de4bb
5 changed files with 229 additions and 5 deletions

View File

@ -2558,6 +2558,14 @@ void SuperWord::output() {
Node* in = vector_opd(p, 1); Node* in = vector_opd(p, 1);
vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n)); vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
vlen_in_bytes = vn->as_Vector()->length_in_bytes(); vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else if (opc == Op_ConvI2F || opc == Op_ConvL2D ||
opc == Op_ConvF2I || opc == Op_ConvD2L) {
assert(n->req() == 2, "only one input expected");
BasicType bt = velt_basic_type(n);
int vopc = VectorNode::opcode(opc, bt);
Node* in = vector_opd(p, 1);
vn = VectorCastNode::make(vopc, in, bt, vlen);
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
} else if (is_cmov_pack(p)) { } else if (is_cmov_pack(p)) {
if (can_process_post_loop) { if (can_process_post_loop) {
// do not refactor of flow in post loop context // do not refactor of flow in post loop context

View File

@ -224,6 +224,14 @@ int VectorNode::opcode(int sopc, BasicType bt) {
return Op_StoreVector; return Op_StoreVector;
case Op_MulAddS2I: case Op_MulAddS2I:
return Op_MulAddVS2VI; return Op_MulAddVS2VI;
case Op_ConvI2F:
return Op_VectorCastI2X;
case Op_ConvL2D:
return Op_VectorCastL2X;
case Op_ConvF2I:
return Op_VectorCastF2X;
case Op_ConvD2L:
return Op_VectorCastD2X;
default: default:
return 0; // Unimplemented return 0; // Unimplemented

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -75,6 +75,8 @@ public class TestIntFloatVect {
test_vi_unaln(a1, b1, (int)123, 103.f); test_vi_unaln(a1, b1, (int)123, 103.f);
test_cp_unalndst(a1, a2, b1, b2); test_cp_unalndst(a1, a2, b1, b2);
test_cp_unalnsrc(a1, a2, b1, b2); test_cp_unalnsrc(a1, a2, b1, b2);
test_conv_i2f(a1, b1);
test_conv_f2i(a1, b1);
} }
// Initialize // Initialize
for (int i=0; i<ARRLEN; i++) { for (int i=0; i<ARRLEN; i++) {
@ -338,6 +340,72 @@ public class TestIntFloatVect {
errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], (int)v); errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], (int)v);
errn += verify("test_cp_unalnsrc_overlap: b1", i, b1[i], (float)v); errn += verify("test_cp_unalnsrc_overlap: b1", i, b1[i], (float)v);
} }
// Reset to test conversion from int to float.
for (int i=0; i<ARRLEN; i++) {
a1[i] = (int)i;
}
test_conv_i2f(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_i2f: a1", i, b1[i], (float)i);
}
// Reset to test conversion from float to int.
for (int i=0; i<ARRLEN; i++) {
b1[i] = (float)(i+1);
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (i+1));
}
// Reset to test NAN conversion from int to float.
for (int i=0; i<ARRLEN; i++) {
a1[i] = Integer.MIN_VALUE;
}
test_conv_i2f(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_i2f: a1", i, b1[i], (float)Integer.MIN_VALUE);
}
for (int i=0; i<ARRLEN; i++) {
a1[i] = Integer.MAX_VALUE;
}
test_conv_i2f(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_i2f: a1", i, b1[i], (float)Integer.MAX_VALUE);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = Float.NaN;
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (int)Float.NaN);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = Float.POSITIVE_INFINITY;
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (int)Float.POSITIVE_INFINITY);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = Float.NEGATIVE_INFINITY;
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (int)Float.NEGATIVE_INFINITY);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = 0.0f;
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (int)0.0);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = -0.0f;
}
test_conv_f2i(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_f2i: a1", i, a1[i], (int)(-0.0));
}
} }
@ -448,6 +516,18 @@ public class TestIntFloatVect {
} }
end = System.currentTimeMillis(); end = System.currentTimeMillis();
System.out.println("test_cp_unalnsrc: " + (end - start)); System.out.println("test_cp_unalnsrc: " + (end - start));
start = System.currentTimeMillis();
for (int i=0; i<ITERS; i++) {
test_conv_i2f(a1, b1);
}
end = System.currentTimeMillis();
System.out.println("test_conv_i2f: " + (end - start));
start = System.currentTimeMillis();
for (int i=0; i<ITERS; i++) {
test_conv_f2i(a1, b1);
}
end = System.currentTimeMillis();
System.out.println("test_conv_f2i: " + (end - start));
return errn; return errn;
} }
@ -556,6 +636,16 @@ public class TestIntFloatVect {
c[i] = d[i+UNALIGN_OFF]; c[i] = d[i+UNALIGN_OFF];
} }
} }
static void test_conv_i2f(int[] a, float[] b){
for (int i = 0; i < a.length; i+=1) {
b[i] = (float)a[i];
}
}
static void test_conv_f2i(int[] a, float[] b){
for (int i = 0; i < a.length; i+=1) {
a[i] = (int)b[i];
}
}
static int verify(String text, int i, int elem, int val) { static int verify(String text, int i, int elem, int val) {
if (elem != val) { if (elem != val) {
@ -565,7 +655,7 @@ public class TestIntFloatVect {
return 0; return 0;
} }
static int verify(String text, int i, float elem, float val) { static int verify(String text, int i, float elem, float val) {
if (elem != val) { if (elem != val && !(Float.isNaN(elem) && Float.isNaN(val))) {
System.err.println(text + "[" + i + "] = " + elem + " != " + val); System.err.println(text + "[" + i + "] = " + elem + " != " + val);
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -75,6 +75,8 @@ public class TestLongDoubleVect {
test_vi_unaln(a1, b1, (long)123, 103.); test_vi_unaln(a1, b1, (long)123, 103.);
test_cp_unalndst(a1, a2, b1, b2); test_cp_unalndst(a1, a2, b1, b2);
test_cp_unalnsrc(a1, a2, b1, b2); test_cp_unalnsrc(a1, a2, b1, b2);
test_conv_l2d(a1, b1);
test_conv_d2l(a1, b1);
} }
// Initialize // Initialize
for (int i=0; i<ARRLEN; i++) { for (int i=0; i<ARRLEN; i++) {
@ -338,6 +340,72 @@ public class TestLongDoubleVect {
errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], (long)v); errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], (long)v);
errn += verify("test_cp_unalnsrc_overlap: b1", i, b1[i], (double)v); errn += verify("test_cp_unalnsrc_overlap: b1", i, b1[i], (double)v);
} }
// Reset to test conversion from int to float.
for (int i=0; i<ARRLEN; i++) {
a1[i] = (long)i;
}
test_conv_l2d(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_l2d: a1", i, b1[i], (double)i);
}
// Reset to test conversion from float to int.
for (int i=0; i<ARRLEN; i++) {
b1[i] = (double)(i+1);
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)(i+1));
}
// Reset to test special conversion from int to float.
for (int i=0; i<ARRLEN; i++) {
b1[i] = Double.NaN;
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)Double.NaN);
}
for (int i=0; i<ARRLEN; i++) {
a1[i] = Long.MIN_VALUE;
}
test_conv_l2d(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_l2d: a1", i, b1[i], (double)Long.MIN_VALUE);
}
for (int i=0; i<ARRLEN; i++) {
a1[i] = Long.MAX_VALUE;
}
test_conv_l2d(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_l2d: a1", i, b1[i], (double)Long.MAX_VALUE);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = Double.POSITIVE_INFINITY;
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)Double.POSITIVE_INFINITY);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = Double.NEGATIVE_INFINITY;
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)Double.NEGATIVE_INFINITY);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = 0.0;
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)0.0);
}
for (int i=0; i<ARRLEN; i++) {
b1[i] = -0.0;
}
test_conv_d2l(a1, b1);
for (int i=0; i<ARRLEN; i++) {
errn += verify("test_conv_d2l: a1", i, a1[i], (long)(-0.0));
}
} }
@ -448,6 +516,18 @@ public class TestLongDoubleVect {
} }
end = System.currentTimeMillis(); end = System.currentTimeMillis();
System.out.println("test_cp_unalnsrc: " + (end - start)); System.out.println("test_cp_unalnsrc: " + (end - start));
start = System.currentTimeMillis();
for (int i=0; i<ITERS; i++) {
test_conv_l2d(a1, b1);
}
end = System.currentTimeMillis();
System.out.println("test_conv_l2d: " + (end - start));
start = System.currentTimeMillis();
for (int i=0; i<ITERS; i++) {
test_conv_d2l(a1, b1);
}
end = System.currentTimeMillis();
System.out.println("test_conv_d2l: " + (end - start));
return errn; return errn;
} }
@ -556,6 +636,16 @@ public class TestLongDoubleVect {
c[i] = d[i+UNALIGN_OFF]; c[i] = d[i+UNALIGN_OFF];
} }
} }
static void test_conv_l2d(long[] a, double[] b){
for (int i = 0; i < a.length; i+=1) {
b[i] = (double)a[i];
}
}
static void test_conv_d2l(long[] a, double[] b){
for (int i = 0; i < a.length; i+=1) {
a[i] = (long)b[i];
}
}
static int verify(String text, int i, long elem, long val) { static int verify(String text, int i, long elem, long val) {
if (elem != val) { if (elem != val) {
@ -565,7 +655,7 @@ public class TestLongDoubleVect {
return 0; return 0;
} }
static int verify(String text, int i, double elem, double val) { static int verify(String text, int i, double elem, double val) {
if (elem != val) { if (elem != val && !(Double.isNaN(elem) && Double.isNaN(val))) {
System.err.println(text + "[" + i + "] = " + elem + " != " + val); System.err.println(text + "[" + i + "] = " + elem + " != " + val);
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -195,6 +195,34 @@ public abstract class TypeVectorOperations {
} }
} }
@Benchmark
public void convert_i2f() {
for (int i = 0; i < COUNT; i++) {
resF[i] = (float) ints[i];
}
}
@Benchmark
public void convert_f2i() {
for (int i = 0; i < COUNT; i++) {
resI[i] = (int) floats[i];
}
}
@Benchmark
public void convert_l2d() {
for (int i = 0; i < COUNT; i++) {
resD[i] = (double) longs[i];
}
}
@Benchmark
public void convert_d2l() {
for (int i = 0; i < COUNT; i++) {
resL[i] = (long) doubles[i];
}
}
@Fork(value = 1, jvmArgsPrepend = { @Fork(value = 1, jvmArgsPrepend = {
"-XX:+UseSuperWord" "-XX:+UseSuperWord"
}) })