package jdk.incubator.vector; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.misc.Unsafe; import jdk.internal.vm.annotation.ForceInline; import java.util.Objects; import java.util.function.*; /*non-public*/ class VectorIntrinsics { private static final Unsafe U = Unsafe.getUnsafe(); // Unary static final int VECTOR_OP_ABS = 0; static final int VECTOR_OP_NEG = 1; static final int VECTOR_OP_SQRT = 2; static final int VECTOR_OP_NOT = 3; // Binary static final int VECTOR_OP_ADD = 4; static final int VECTOR_OP_SUB = 5; static final int VECTOR_OP_MUL = 6; static final int VECTOR_OP_DIV = 7; static final int VECTOR_OP_MIN = 8; static final int VECTOR_OP_MAX = 9; static final int VECTOR_OP_AND = 10; static final int VECTOR_OP_OR = 11; static final int VECTOR_OP_XOR = 12; // Ternary static final int VECTOR_OP_FMA = 13; // Broadcast int static final int VECTOR_OP_LSHIFT = 14; static final int VECTOR_OP_RSHIFT = 15; static final int VECTOR_OP_URSHIFT = 16; // Copied from open/src/hotspot/cpu/x86/assembler_x86.hpp // enum Condition { // The x86 condition codes used for conditional jumps/moves. static final int COND_zero = 0x4; static final int COND_notZero = 0x5; static final int COND_equal = 0x4; static final int COND_notEqual = 0x5; static final int COND_less = 0xc; static final int COND_lessEqual = 0xe; static final int COND_greater = 0xf; static final int COND_greaterEqual = 0xd; static final int COND_below = 0x2; static final int COND_belowEqual = 0x6; static final int COND_above = 0x7; static final int COND_aboveEqual = 0x3; static final int COND_overflow = 0x0; static final int COND_noOverflow = 0x1; static final int COND_carrySet = 0x2; static final int COND_carryClear = 0x3; static final int COND_negative = 0x8; static final int COND_positive = 0x9; static final int COND_parity = 0xa; static final int COND_noParity = 0xb; // enum BoolTest static final int BT_eq = 0; static final int BT_ne = 4; static final int BT_le = 5; static final int BT_ge = 7; static final int BT_lt = 3; static final int BT_gt = 1; static final int BT_overflow = 2; static final int BT_no_overflow = 6; /* ============================================================================ */ @HotSpotIntrinsicCandidate static V broadcastCoerced(Class vectorClass, Class elementType, int vlen, long bits, LongFunction defaultImpl) { return defaultImpl.apply(bits); } @HotSpotIntrinsicCandidate static > long reductionCoerced(int oprId, Class vectorClass, Class elementType, int vlen, V v, Function defaultImpl) { return defaultImpl.apply(v); } /* ============================================================================ */ @HotSpotIntrinsicCandidate static V unaryOp(int oprId, Class vectorClass, Class elementType, int vlen, V v1, /*Vector.Mask m,*/ Function defaultImpl) { return defaultImpl.apply(v1); } /* ============================================================================ */ @HotSpotIntrinsicCandidate static V binaryOp(int oprId, Class vectorClass, Class elementType, int vlen, V v1, V v2, /*Vector.Mask m,*/ BiFunction defaultImpl) { return defaultImpl.apply(v1, v2); } /* ============================================================================ */ interface TernaryOperation { V apply(V v1, V v2, V v3); } @SuppressWarnings("unchecked") @HotSpotIntrinsicCandidate static V ternaryOp(int oprId, Class vectorClass, Class elementType, int vlen, V v1, V v2, V v3, /*Vector.Mask m,*/ TernaryOperation defaultImpl) { return defaultImpl.apply(v1, v2, v3); } /* ============================================================================ */ // Memory operations // FIXME: arrays are erased to Object @HotSpotIntrinsicCandidate static > V load(Class vectorClass, Class elementType, int vlen, Object array, int index, /* Vector.Mask m*/ BiFunction defaultImpl) { return defaultImpl.apply(array, index); } interface StoreVectorOperation> { void store(Object array, int index, V v); } @HotSpotIntrinsicCandidate static > void store(Class vectorClass, Class elementType, int vlen, Object array, int index, V v, /*Vector.Mask m*/ StoreVectorOperation defaultImpl) { defaultImpl.store(array, index, v); } /* ============================================================================ */ @HotSpotIntrinsicCandidate static boolean test(int cond, Class vectorClass, Class elementType, int vlen, V v1, V v2, BiFunction defaultImpl) { return defaultImpl.apply(v1, v2); } /* ============================================================================ */ interface VectorCompareOp { M apply(V v1, V v2); } @HotSpotIntrinsicCandidate static , M extends Vector.Mask, S extends Vector.Shape, E> M compare(int cond, Class vectorClass, Class maskClass, Class elementType, int vlen, V v1, V v2, VectorCompareOp defaultImpl) { return defaultImpl.apply(v1, v2); } /* ============================================================================ */ interface VectorBlendOp, M extends Vector.Mask, S extends Vector.Shape, E> { V apply(V v1, V v2, M mask); } @HotSpotIntrinsicCandidate static , M extends Vector.Mask, S extends Vector.Shape, E> V blend(Class vectorClass, Class maskClass, Class elementType, int vlen, V v1, V v2, M m, VectorBlendOp defaultImpl) { return defaultImpl.apply(v1, v2, m); } /* ============================================================================ */ interface VectorBroadcastIntOp> { V apply(V v, int i); } @HotSpotIntrinsicCandidate static > V broadcastInt(int opr, Class vectorClass, Class elementType, int vlen, V v, int i, VectorBroadcastIntOp defaultImpl) { return defaultImpl.apply(v, i); } /* ============================================================================ */ interface VectorReinterpretOp { VT apply(VF v, Class elementType); } @HotSpotIntrinsicCandidate static VT reinterpret(Class fromVectorClass, Class fromElementType, int fromVLen, Class toElementType, int toVLen, VF v, VectorReinterpretOp defaultImpl) { return defaultImpl.apply(v, toElementType); } /* ============================================================================ */ interface VectorCastOp { VT apply(VF v, Class elementType); } @HotSpotIntrinsicCandidate static VT cast(Class fromVectorClass, Class fromElementType, int fromVLen, Class toElementType, int toVLen, VF v, VectorCastOp defaultImpl) { return defaultImpl.apply(v, toElementType); } /* ============================================================================ */ @HotSpotIntrinsicCandidate static V maybeRebox(V v) { // The fence is added here to avoid memory aliasing problems in C2 between scalar & vector accesses. // TODO: move the fence generation into C2. Generate only when reboxing is taking place. U.loadFence(); return v; } /* ============================================================================ */ static final int VECTOR_ACCESS_OOB_CHECK = Integer.getInteger("jdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK", 2); @ForceInline static int checkIndex(int ix, int length, int vlen) { switch (VectorIntrinsics.VECTOR_ACCESS_OOB_CHECK) { case 0: return ix; // no range check case 1: return Objects.checkFromIndexSize(ix, vlen, length); case 2: return Objects.checkIndex(ix, length - (vlen - 1)); default: throw new InternalError(); } } }