package valhalla.vector; import jdk.experimental.value.ValueType; import jdk.internal.org.objectweb.asm.ClassWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import static java.lang.invoke.MethodType.methodType; import static valhalla.vector.Utils.assertEquals; public class VectorTest { static final ValueType VT = ValueType.forClass(Long2.class); static /* QLong2[] */ Object initL2Array(int length) { try { Object arr = MethodHandles.arrayConstructor(VT.arrayValueClass()).invoke(length); for (int i = 0; i < length; i++) { Long2 v = new Long2(2 * i, 2 * i + 1); MethodHandles.arrayElementSetter(VT.arrayValueClass()).invoke(arr, i, v); } return arr; } catch (Throwable e) { throw new Error(e); } } static final MethodHandle SUM_ARRAY_L2 = VectorUtils.reducerLoop(VT, VectorLibrary.L2.ADD_L, VectorLibrary.L2.HADD_L, VT.defaultValueConstant()). asType(methodType(long.class, Object.class)); /** * long sum(QLong2[] a) { * QLong2 v = QLong2.default; // (0,0) * for (int i = 0; i < a.length; i++) { * v = QLong2(v.lo + a[i].lo, v.hi + a[i].hi); * } * return v.lo + v.hi; * } */ // @DontInline static long sumArrayL2(Object arr) { try { return (long) SUM_ARRAY_L2.invokeExact(arr); } catch (Throwable e) { throw new Error(e); } } static void testSumArray(int size) { Object arr = initL2Array(size); // QLong2[size] long expected = size * (2*size - 1); for (int i = 0; i < 20_000; i++) { long sum = sumArrayL2(arr); assertEquals(expected, sum); } } /*========================================================*/ static MethodHandle createConditional() { // T target(A...,B...); // T fallback(A...,B...); // T adapter(A... a,B... b) { // if (test(a...)) // return target(a..., b...); // else // return fallback(a..., b...); // } MethodHandle test = MethodHandles.identity(boolean.class); MethodHandle add = VectorLibrary.L2.ADD_L; MethodHandle addVL = MethodHandles.filterArguments(add, 1, VT.unbox()); MethodHandle inc = MethodHandles.insertArguments(addVL, 1, new Long2(1L, 1L)); MethodHandle incZ = MethodHandles.dropArguments(inc, 0, boolean.class); MethodHandle idZ = MethodHandles.dropArguments(VT.identity(), 0, boolean.class); // (boolean, QLong2)QLong2 MethodHandle gwt = MethodHandles.guardWithTest(test, incZ, idZ); return gwt; } static final MethodHandle conditionalMH = createConditional(). asType(methodType(Long2.class, boolean.class, Long2.class)); // @DontInline static Long2 conditional(boolean b, Long2 v) { try { return (Long2) conditionalMH.invokeExact(b, v); } catch (Throwable e) { throw new Error(e); } } static void testConditional() { Long2 v = new Long2(1L, 2L); for (int i = 0; i < 20_000; i++) { conditional(true, v); conditional(false, v); } } /*========================================================*/ public static void main(String[] args) { if (args.length == 0) { args = new String[] { "1", "5", "10", "0"}; } for (String arg : args) { int size = Integer.parseInt(arg); testSumArray(size); } testConditional(); } }