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.nio.Buffer; 8 import java.nio.ByteBuffer; 9 import java.util.Objects; 10 import java.util.function.*; 11 12 import jdk.incubator.vector.Vector; 13 14 /*non-public*/ class VectorIntrinsics { 15 static final Unsafe U = Unsafe.getUnsafe(); 16 17 static final long BUFFER_ADDRESS 18 = U.objectFieldOffset(Buffer.class, "address"); 19 20 // Buffer.limit 21 static final long BUFFER_LIMIT 22 = U.objectFieldOffset(Buffer.class, "limit"); 23 24 // ByteBuffer.hb 25 static final long BYTE_BUFFER_HB 26 = U.objectFieldOffset(ByteBuffer.class, "hb"); 27 28 // ByteBuffer.isReadOnly 29 static final long BYTE_BUFFER_IS_READ_ONLY 30 = U.objectFieldOffset(ByteBuffer.class, "isReadOnly"); 31 32 // Unary 33 static final int VECTOR_OP_ABS = 0; 34 static final int VECTOR_OP_NEG = 1; 35 static final int VECTOR_OP_SQRT = 2; 36 static final int VECTOR_OP_NOT = 3; 37 38 // Binary 39 static final int VECTOR_OP_ADD = 4; 40 static final int VECTOR_OP_SUB = 5; 41 static final int VECTOR_OP_MUL = 6; 42 static final int VECTOR_OP_DIV = 7; 43 static final int VECTOR_OP_MIN = 8; 44 static final int VECTOR_OP_MAX = 9; 45 46 static final int VECTOR_OP_AND = 10; 47 static final int VECTOR_OP_OR = 11; 48 static final int VECTOR_OP_XOR = 12; 49 50 // Ternary 51 static final int VECTOR_OP_FMA = 13; 52 53 // Broadcast int 54 static final int VECTOR_OP_LSHIFT = 14; 55 static final int VECTOR_OP_RSHIFT = 15; 56 static final int VECTOR_OP_URSHIFT = 16; 57 58 // Math routines 59 static final int VECTOR_OP_TAN = 101; 60 static final int VECTOR_OP_TANH = 102; 61 static final int VECTOR_OP_SIN = 103; 62 static final int VECTOR_OP_SINH = 104; 63 static final int VECTOR_OP_COS = 105; 64 static final int VECTOR_OP_COSH = 106; 65 static final int VECTOR_OP_ASIN = 107; 66 static final int VECTOR_OP_ACOS = 108; 67 static final int VECTOR_OP_ATAN = 109; 68 static final int VECTOR_OP_ATAN2 = 110; 69 static final int VECTOR_OP_CBRT = 111; 70 static final int VECTOR_OP_LOG = 112; 71 static final int VECTOR_OP_LOG10 = 113; 72 static final int VECTOR_OP_LOG1P = 114; 73 static final int VECTOR_OP_POW = 115; 74 static final int VECTOR_OP_EXP = 116; 75 static final int VECTOR_OP_EXPM1 = 117; 76 static final int VECTOR_OP_HYPOT = 118; 77 78 // enum BoolTest 79 static final int BT_eq = 0; 80 static final int BT_ne = 4; 81 static final int BT_le = 5; 82 static final int BT_ge = 7; 83 static final int BT_lt = 3; 84 static final int BT_gt = 1; 85 static final int BT_overflow = 2; 86 static final int BT_no_overflow = 6; 87 88 /* ============================================================================ */ 89 interface BroadcastOperation<V, E> { 90 V broadcast(long l, Vector.Species<E> s); 91 } 92 93 @HotSpotIntrinsicCandidate 94 static 95 <VM, E> 96 VM broadcastCoerced(Class<VM> vmClass, Class<?> E, int length, 97 long bits, Vector.Species<E> s, 98 BroadcastOperation<VM, E> defaultImpl) { 99 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 100 return defaultImpl.broadcast(bits, s); 101 } 102 103 /* ============================================================================ */ 104 105 @HotSpotIntrinsicCandidate 106 static 107 <V extends Vector<?>> 108 long reductionCoerced(int oprId, Class<?> vectorClass, Class<?> elementType, int length, 109 V v, 110 Function<V,Long> defaultImpl) { 111 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 112 return defaultImpl.apply(v); 113 } 114 115 /* ============================================================================ */ 116 117 interface VecExtractOp<V> { 118 long apply(V v1, int idx); 119 } 120 121 @HotSpotIntrinsicCandidate 122 static 123 <V extends Vector<?>> 124 long extract(Class<?> vectorClass, Class<?> elementType, int vlen, 125 V vec, int ix, 126 VecExtractOp<V> defaultImpl) { 127 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 128 return defaultImpl.apply(vec, ix); 129 } 130 131 /* ============================================================================ */ 132 133 interface VecInsertOp<V> { 134 V apply(V v1, int idx, long val); 135 } 136 137 @HotSpotIntrinsicCandidate 138 static <V extends Vector<?>> 139 V insert(Class<V> vectorClass, Class<?> elementType, int vlen, 140 V vec, int ix, long val, 141 VecInsertOp<V> defaultImpl) { 142 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 143 return defaultImpl.apply(vec, ix, val); 144 } 145 146 /* ============================================================================ */ 147 148 @HotSpotIntrinsicCandidate 149 static 150 <VM> 151 VM unaryOp(int oprId, Class<VM> vmClass, Class<?> elementType, int length, 152 VM vm, /*Vector.Mask<E,S> m,*/ 153 Function<VM, VM> defaultImpl) { 154 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 155 return defaultImpl.apply(vm); 156 } 157 158 /* ============================================================================ */ 159 160 @HotSpotIntrinsicCandidate 161 static 162 <VM> 163 VM binaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 164 VM vm1, VM vm2, /*Vector.Mask<E,S> m,*/ 165 BiFunction<VM, VM, VM> defaultImpl) { 166 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 167 return defaultImpl.apply(vm1, vm2); 168 } 169 170 /* ============================================================================ */ 171 172 interface TernaryOperation<V> { 173 V apply(V v1, V v2, V v3); 174 } 175 176 @HotSpotIntrinsicCandidate 177 static 178 <VM> 179 VM ternaryOp(int oprId, Class<VM> vmClass, Class<?> elementType, int length, 180 VM vm1, VM vm2, VM vm3, /*Vector.Mask<E,S> m,*/ 181 TernaryOperation<VM> defaultImpl) { 182 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 183 return defaultImpl.apply(vm1, vm2, vm3); 184 } 185 186 /* ============================================================================ */ 187 188 // Memory operations 189 190 interface LoadOperation<C, V, E> { 191 V load(C container, int index, Vector.Species<E> s); 192 } 193 194 @HotSpotIntrinsicCandidate 195 static 196 <C, VM, E> 197 VM load(Class<VM> vmClass, Class<?> E, int length, 198 Object base, long offset, // Unsafe addressing 199 // Vector.Mask<E,S> m, 200 C container, int index, Vector.Species<E> s, // Arguments for default implementation 201 LoadOperation<C, VM, E> defaultImpl) { 202 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 203 return defaultImpl.load(container, index, s); 204 } 205 206 /* ============================================================================ */ 207 208 interface LoadVectorOperationWithMap<C, V extends Vector<?>, E> { 209 V loadWithMap(C container, int index, int[] indexMap, int indexM, Vector.Species<E> s); 210 } 211 212 @HotSpotIntrinsicCandidate 213 static 214 <C, V extends Vector<?>, W extends IntVector, E> 215 V loadWithMap(Class<?> vectorClass, Class<?> E, int length, Class<?> vectorIndexClass, 216 Object base, long offset, // Unsafe addressing 217 W index_vector, 218 C container, int index, int[] indexMap, int indexM, Vector.Species<E> s, // Arguments for default implementation 219 LoadVectorOperationWithMap<C, V, E> defaultImpl) { 220 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 221 return defaultImpl.loadWithMap(container, index, indexMap, indexM, s); 222 } 223 224 /* ============================================================================ */ 225 226 interface StoreVectorOperation<C, V extends Vector<?>> { 227 void store(C container, int index, V v); 228 } 229 230 @HotSpotIntrinsicCandidate 231 static 232 <C, V extends Vector<?>> 233 void store(Class<?> vectorClass, Class<?> elementType, int length, 234 Object base, long offset, // Unsafe addressing 235 V v, 236 // Vector.Mask<E,S> m, 237 C container, int index, // Arguments for default implementation 238 StoreVectorOperation<C, V> defaultImpl) { 239 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 240 defaultImpl.store(container, index, v); 241 } 242 243 /* ============================================================================ */ 244 245 interface StoreVectorOperationWithMap<C, V extends Vector<?>> { 246 void storeWithMap(C container, int index, V v, int[] indexMap, int indexM); 247 } 248 249 @HotSpotIntrinsicCandidate 250 static 251 <C, V extends Vector<?>, W extends IntVector> 252 void storeWithMap(Class<?> vectorClass, Class<?> elementType, int length, Class<?> vectorIndexClass, 253 Object base, long offset, // Unsafe addressing 254 W index_vector, V v, 255 C container, int index, int[] indexMap, int indexM, // Arguments for default implementation 256 StoreVectorOperationWithMap<C, V> defaultImpl) { 257 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 258 defaultImpl.storeWithMap(container, index, v, indexMap, indexM); 259 } 260 261 /* ============================================================================ */ 262 263 @HotSpotIntrinsicCandidate 264 static 265 <VM> 266 boolean test(int cond, Class<?> vmClass, Class<?> elementType, int length, 267 VM vm1, VM vm2, 268 BiFunction<VM, VM, Boolean> defaultImpl) { 269 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 270 return defaultImpl.apply(vm1, vm2); 271 } 272 273 /* ============================================================================ */ 274 275 interface VectorCompareOp<V,M> { 276 M apply(V v1, V v2); 277 } 278 279 @HotSpotIntrinsicCandidate 280 static <V extends Vector<E>, 281 M extends Vector.Mask<E>, 282 E> 283 M compare(int cond, Class<V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 284 V v1, V v2, 285 VectorCompareOp<V,M> defaultImpl) { 286 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 287 return defaultImpl.apply(v1, v2); 288 } 289 290 /* ============================================================================ */ 291 292 interface VectorRearrangeOp<V extends Vector<E>, 293 Sh extends Vector.Shuffle<E>, 294 E> { 295 V apply(V v1, Sh shuffle); 296 } 297 298 @HotSpotIntrinsicCandidate 299 static 300 <V extends Vector<E>, 301 Sh extends Vector.Shuffle<E>, 302 E> 303 V rearrangeOp(Class<V> vectorClass, Class<Sh> shuffleClass, Class<?> elementType, int vlen, 304 V v1, Sh sh, 305 VectorRearrangeOp<V,Sh, E> defaultImpl) { 306 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 307 return defaultImpl.apply(v1, sh); 308 } 309 310 /* ============================================================================ */ 311 312 interface VectorBlendOp<V extends Vector<E>, 313 M extends Vector.Mask<E>, 314 E> { 315 V apply(V v1, V v2, M mask); 316 } 317 318 @HotSpotIntrinsicCandidate 319 static 320 <V extends Vector<E>, 321 M extends Vector.Mask<E>, 322 E> 323 V blend(Class<V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 324 V v1, V v2, M m, 325 VectorBlendOp<V,M, E> defaultImpl) { 326 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 327 return defaultImpl.apply(v1, v2, m); 328 } 329 330 /* ============================================================================ */ 331 332 interface VectorBroadcastIntOp<V extends Vector<?>> { 333 V apply(V v, int i); 334 } 335 336 @HotSpotIntrinsicCandidate 337 static 338 <V extends Vector<?>> 339 V broadcastInt(int opr, Class<V> vectorClass, Class<?> elementType, int length, 340 V v, int i, 341 VectorBroadcastIntOp<V> defaultImpl) { 342 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 343 return defaultImpl.apply(v, i); 344 } 345 346 /* ============================================================================ */ 347 348 interface VectorReinterpretOp<S, VIN, V> { 349 V apply(S species, VIN v); 350 } 351 352 @HotSpotIntrinsicCandidate 353 static 354 <S, VIN, V> 355 V reinterpret(Class<?> fromVectorClass, 356 Class<?> fromElementType, int fromVLen, 357 Class<?> toVectorClass, 358 Class<?> toElementType, int toVLen, 359 VIN v, S s, 360 VectorReinterpretOp<S, VIN, V> defaultImpl) { 361 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 362 return defaultImpl.apply(s, v); 363 } 364 365 /* ============================================================================ */ 366 367 interface VectorCastOp<S, VIN, V> { 368 V apply(S species, VIN v); 369 } 370 371 @HotSpotIntrinsicCandidate 372 static 373 <S, VIN, V> 374 V cast(Class<?> fromVectorClass, 375 Class<?> fromElementType, int fromVLen, 376 Class<?> toVectorClass, 377 Class<?> toElementType, int toVLen, 378 VIN v, S s, 379 VectorCastOp<S, VIN, V> defaultImpl) { 380 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 381 return defaultImpl.apply(s, v); 382 } 383 384 /* ============================================================================ */ 385 386 @HotSpotIntrinsicCandidate 387 static <V> V maybeRebox(V v) { 388 // The fence is added here to avoid memory aliasing problems in C2 between scalar & vector accesses. 389 // TODO: move the fence generation into C2. Generate only when reboxing is taking place. 390 U.loadFence(); 391 return v; 392 } 393 394 /* ============================================================================ */ 395 396 static final int VECTOR_ACCESS_OOB_CHECK = Integer.getInteger("jdk.incubator.vector.VECTOR_ACCESS_OOB_CHECK", 2); 397 398 @ForceInline 399 static int checkIndex(int ix, int length, int vlen) { 400 switch (VectorIntrinsics.VECTOR_ACCESS_OOB_CHECK) { 401 case 0: return ix; // no range check 402 case 1: return Objects.checkFromIndexSize(ix, vlen, length); 403 case 2: return Objects.checkIndex(ix, length - (vlen - 1)); 404 default: throw new InternalError(); 405 } 406 } 407 408 @ForceInline 409 static IntVector checkIndex(IntVector vix, int length) { 410 switch (VectorIntrinsics.VECTOR_ACCESS_OOB_CHECK) { 411 case 0: return vix; // no range check 412 case 1: // fall-through 413 case 2: 414 if(vix.lessThan(0).anyTrue() || vix.greaterThanEq(length).anyTrue()) { 415 String msg = String.format("Range check failed: vector %s out of bounds for length %d", vix, length); 416 throw new ArrayIndexOutOfBoundsException(msg); 417 } 418 return vix; 419 default: throw new InternalError(); 420 } 421 } 422 423 static boolean isNonCapturingLambda(Object o) { 424 return o.getClass().getDeclaredFields().length == 0; 425 } 426 }