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