1 package jdk.incubator.vector;
   2 
   3 import jdk.internal.HotSpotIntrinsicCandidate;
   4 import jdk.internal.misc.Unsafe;
   5 import jdk.internal.vm.annotation.ForceInline;
   6 
   7 import java.util.Objects;
   8 import java.util.function.*;
   9 
  10 /*non-public*/ class VectorIntrinsics {
  11     private static final Unsafe U = Unsafe.getUnsafe();
  12 
  13     // Unary
  14     static final int VECTOR_OP_ABS  = 0;
  15     static final int VECTOR_OP_NEG  = 1;
  16     static final int VECTOR_OP_SQRT = 2;
  17     static final int VECTOR_OP_NOT  = 3;
  18 
  19     // Binary
  20     static final int VECTOR_OP_ADD  = 4;
  21     static final int VECTOR_OP_SUB  = 5;
  22     static final int VECTOR_OP_MUL  = 6;
  23     static final int VECTOR_OP_DIV  = 7;
  24     static final int VECTOR_OP_MIN  = 8;
  25     static final int VECTOR_OP_MAX  = 9;
  26 
  27     static final int VECTOR_OP_AND  = 10;
  28     static final int VECTOR_OP_OR   = 11;
  29     static final int VECTOR_OP_XOR  = 12;
  30 
  31     // Ternary
  32     static final int VECTOR_OP_FMA  = 13;
  33 
  34     // Broadcast int
  35     static final int VECTOR_OP_LSHIFT  = 14;
  36     static final int VECTOR_OP_RSHIFT  = 15;
  37     static final int VECTOR_OP_URSHIFT = 16;
  38 
  39     // Copied from open/src/hotspot/cpu/x86/assembler_x86.hpp
  40     // enum Condition { // The x86 condition codes used for conditional jumps/moves.
  41     static final int COND_zero          = 0x4;
  42     static final int COND_notZero       = 0x5;
  43     static final int COND_equal         = 0x4;
  44     static final int COND_notEqual      = 0x5;
  45     static final int COND_less          = 0xc;
  46     static final int COND_lessEqual     = 0xe;
  47     static final int COND_greater       = 0xf;
  48     static final int COND_greaterEqual  = 0xd;
  49     static final int COND_below         = 0x2;
  50     static final int COND_belowEqual    = 0x6;
  51     static final int COND_above         = 0x7;
  52     static final int COND_aboveEqual    = 0x3;
  53     static final int COND_overflow      = 0x0;
  54     static final int COND_noOverflow    = 0x1;
  55     static final int COND_carrySet      = 0x2;
  56     static final int COND_carryClear    = 0x3;
  57     static final int COND_negative      = 0x8;
  58     static final int COND_positive      = 0x9;
  59     static final int COND_parity        = 0xa;
  60     static final int COND_noParity      = 0xb;
  61 
  62 
  63     // enum BoolTest
  64     static final int BT_eq = 0;
  65     static final int BT_ne = 4;
  66     static final int BT_le = 5;
  67     static final int BT_ge = 7;
  68     static final int BT_lt = 3;
  69     static final int BT_gt = 1;
  70     static final int BT_overflow = 2;
  71     static final int BT_no_overflow = 6;
  72 
  73     /* ============================================================================ */
  74 
  75     @HotSpotIntrinsicCandidate
  76     static <V> V broadcastCoerced(Class<V> vectorClass, Class<?> elementType, int vlen,
  77                                   long bits,
  78                                   LongFunction<V> defaultImpl) {
  79         return defaultImpl.apply(bits);
  80     }
  81 
  82     @HotSpotIntrinsicCandidate
  83     static
  84     <V extends Vector<?,?>>
  85     long reductionCoerced(int oprId, Class<?> vectorClass, Class<?> elementType, int vlen,
  86                           V v,
  87                           Function<V,Long> defaultImpl) {
  88         return defaultImpl.apply(v);
  89     }
  90 
  91     /* ============================================================================ */
  92 
  93     @HotSpotIntrinsicCandidate
  94     static <V> V unaryOp(int oprId, Class<V> vectorClass, Class<?> elementType, int vlen,
  95                          V v1, /*Vector.Mask<E,S> m,*/
  96                          Function<V,V> defaultImpl) {
  97         return defaultImpl.apply(v1);
  98     }
  99 
 100     /* ============================================================================ */
 101 
 102     @HotSpotIntrinsicCandidate
 103     static <V> V binaryOp(int oprId, Class<? extends V> vectorClass, Class<?> elementType, int vlen,
 104                           V v1, V v2, /*Vector.Mask<E,S> m,*/
 105                           BiFunction<V,V,V> defaultImpl) {
 106         return defaultImpl.apply(v1, v2);
 107     }
 108 
 109     /* ============================================================================ */
 110 
 111     interface TernaryOperation<V> {
 112         V apply(V v1, V v2, V v3);
 113     }
 114 
 115     @SuppressWarnings("unchecked")
 116     @HotSpotIntrinsicCandidate
 117     static <V> V ternaryOp(int oprId, Class<V> vectorClass, Class<?> elementType, int vlen,
 118                            V v1, V v2, V v3, /*Vector.Mask<E,S> m,*/
 119                            TernaryOperation<V> defaultImpl) {
 120         return defaultImpl.apply(v1, v2, v3);
 121     }
 122 
 123     /* ============================================================================ */
 124 
 125     // Memory operations
 126 
 127     // FIXME: arrays are erased to Object
 128 
 129     @HotSpotIntrinsicCandidate
 130     static
 131     <V extends Vector<?,?>>
 132     V load(Class<?> vectorClass, Class<?> elementType, int vlen,
 133            Object array, int index, /* Vector.Mask<E,S> m*/
 134            BiFunction<Object, Integer, V> defaultImpl) {
 135         return defaultImpl.apply(array, index);
 136     }
 137 
 138     interface StoreVectorOperation<V extends Vector<?,?>> {
 139         void store(Object array, int index, V v);
 140     }
 141 
 142     @HotSpotIntrinsicCandidate
 143     static
 144     <V extends Vector<?,?>>
 145     void store(Class<?> vectorClass, Class<?> elementType, int vlen,
 146                Object array, int index, V v, /*Vector.Mask<E,S> m*/
 147                StoreVectorOperation<V> defaultImpl) {
 148         defaultImpl.store(array, index, v);
 149     }
 150 
 151     /* ============================================================================ */
 152 
 153     @HotSpotIntrinsicCandidate
 154     static <V> boolean test(int cond, Class<?> vectorClass, Class<?> elementType, int vlen,
 155                             V v1, V v2,
 156                             BiFunction<V, V, Boolean> defaultImpl) {
 157         return defaultImpl.apply(v1, v2);
 158     }
 159 
 160     /* ============================================================================ */
 161 
 162     interface VectorCompareOp<V,M> {
 163         M apply(V v1, V v2);
 164     }
 165 
 166     @HotSpotIntrinsicCandidate
 167     static <V extends Vector<E,S>,
 168             M extends Vector.Mask<E,S>,
 169             S extends Vector.Shape, E>
 170     M compare(int cond, Class<V> vectorClass, Class<M> maskClass, Class<?> elementType, int vlen,
 171               V v1, V v2,
 172               VectorCompareOp<V,M> defaultImpl) {
 173         return defaultImpl.apply(v1, v2);
 174     }
 175 
 176     /* ============================================================================ */
 177 
 178     interface VectorBlendOp<V extends Vector<E,S>,
 179                             M extends Vector.Mask<E,S>,
 180                             S extends Vector.Shape, E> {
 181         V apply(V v1, V v2, M mask);
 182     }
 183 
 184     @HotSpotIntrinsicCandidate
 185     static
 186     <V extends Vector<E,S>,
 187      M extends Vector.Mask<E,S>,
 188      S extends Vector.Shape, E>
 189     V blend(Class<V> vectorClass, Class<M> maskClass, Class<?> elementType, int vlen,
 190             V v1, V v2, M m,
 191             VectorBlendOp<V,M,S,E> defaultImpl) {
 192         return defaultImpl.apply(v1, v2, m);
 193     }
 194 
 195     /* ============================================================================ */
 196 
 197     interface VectorBroadcastIntOp<V extends Vector<?,?>> {
 198         V apply(V v, int i);
 199     }
 200 
 201     @HotSpotIntrinsicCandidate
 202     static
 203     <V extends Vector<?,?>>
 204     V broadcastInt(int opr, Class<V> vectorClass, Class<?> elementType, int vlen,
 205                    V v, int i,
 206                    VectorBroadcastIntOp<V> defaultImpl) {
 207         return defaultImpl.apply(v, i);
 208     }
 209 
 210     /* ============================================================================ */
 211 
 212     interface VectorReinterpretOp<VT, VF> {
 213         VT apply(VF v, Class<?> elementType);
 214     }
 215 
 216     @HotSpotIntrinsicCandidate
 217     static
 218     <VT, VF>
 219     VT reinterpret(Class<VF> fromVectorClass, Class<?> fromElementType, int fromVLen,
 220                    Class<?> toElementType, int toVLen, VF v,
 221                    VectorReinterpretOp<VT,VF> defaultImpl) {
 222         return defaultImpl.apply(v, toElementType);
 223     }
 224 
 225     /* ============================================================================ */
 226 
 227     interface VectorCastOp<VT, VF> {
 228         VT apply(VF v, Class<?> elementType);
 229     }
 230 
 231     @HotSpotIntrinsicCandidate
 232     static
 233     <VT, VF>
 234     VT cast(Class<VF> fromVectorClass, Class<?> fromElementType, int fromVLen,
 235             Class<?> toElementType, int toVLen, VF v,
 236             VectorCastOp<VT,VF> defaultImpl) {
 237         return defaultImpl.apply(v, toElementType);
 238     }
 239 
 240     /* ============================================================================ */
 241 
 242     @HotSpotIntrinsicCandidate
 243     static <V> V maybeRebox(V v) {
 244         // The fence is added here to avoid memory aliasing problems in C2 between scalar & vector accesses.
 245         // TODO: move the fence generation into C2. Generate only when reboxing is taking place.
 246         U.loadFence();
 247         return v;
 248     }
 249 
 250     /* ============================================================================ */
 251 
 252     static final int VECTOR_ACCESS_OOB_CHECK = Integer.getInteger("jdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK", 2);
 253 
 254     @ForceInline
 255     static int checkIndex(int ix, int length, int vlen) {
 256         switch (VectorIntrinsics.VECTOR_ACCESS_OOB_CHECK) {
 257             case 0: return ix; // no range check
 258             case 1: return Objects.checkFromIndexSize(ix, vlen, length);
 259             case 2: return Objects.checkIndex(ix, length - (vlen - 1));
 260             default: throw new InternalError();
 261         }
 262     }
 263 }