1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.internal.vm.vector; 25 26 import jdk.internal.HotSpotIntrinsicCandidate; 27 import jdk.internal.misc.Unsafe; 28 import jdk.internal.vm.annotation.ForceInline; 29 30 import java.nio.Buffer; 31 import java.nio.ByteBuffer; 32 import java.util.Objects; 33 import java.util.function.*; 34 35 public class VectorSupport { 36 static { 37 registerNatives(); 38 } 39 40 private static final Unsafe U = Unsafe.getUnsafe(); 41 42 // Unary 43 public static final int VECTOR_OP_ABS = 0; 44 public static final int VECTOR_OP_NEG = 1; 45 public static final int VECTOR_OP_SQRT = 2; 46 47 // Binary 48 public static final int VECTOR_OP_ADD = 4; 49 public static final int VECTOR_OP_SUB = 5; 50 public static final int VECTOR_OP_MUL = 6; 51 public static final int VECTOR_OP_DIV = 7; 52 public static final int VECTOR_OP_MIN = 8; 53 public static final int VECTOR_OP_MAX = 9; 54 55 public static final int VECTOR_OP_AND = 10; 56 public static final int VECTOR_OP_OR = 11; 57 public static final int VECTOR_OP_XOR = 12; 58 59 // Ternary 60 public static final int VECTOR_OP_FMA = 13; 61 62 // Broadcast int 63 public static final int VECTOR_OP_LSHIFT = 14; 64 public static final int VECTOR_OP_RSHIFT = 15; 65 public static final int VECTOR_OP_URSHIFT = 16; 66 67 public static final int VECTOR_OP_CAST = 17; 68 public static final int VECTOR_OP_REINTERPRET = 18; 69 70 // enum BoolTest 71 public static final int BT_eq = 0; 72 public static final int BT_ne = 4; 73 public static final int BT_le = 5; 74 public static final int BT_ge = 7; 75 public static final int BT_lt = 3; 76 public static final int BT_gt = 1; 77 public static final int BT_overflow = 2; 78 public static final int BT_no_overflow = 6; 79 80 // BasicType codes, for primitives only: 81 public static final int 82 T_FLOAT = 6, 83 T_DOUBLE = 7, 84 T_BYTE = 8, 85 T_SHORT = 9, 86 T_INT = 10, 87 T_LONG = 11; 88 89 /* ============================================================================ */ 90 91 public static class VectorSpecies<E> {} 92 93 public static class VectorPayload { 94 private final Object payload; // array of primitives 95 96 public VectorPayload(Object payload) { 97 this.payload = payload; 98 } 99 100 protected final Object getPayload() { 101 return VectorSupport.maybeRebox(this).payload; 102 } 103 } 104 105 public static class Vector<E> extends VectorPayload { 106 public Vector(Object payload) { 107 super(payload); 108 } 109 } 110 111 public static class VectorShuffle<E> extends VectorPayload { 112 public VectorShuffle(Object payload) { 113 super(payload); 114 } 115 } 116 public static class VectorMask<E> extends VectorPayload { 117 public VectorMask(Object payload) { 118 super(payload); 119 } 120 } 121 122 /* ============================================================================ */ 123 public interface BroadcastOperation<VM, E, S extends VectorSpecies<E>> { 124 VM broadcast(long l, S s); 125 } 126 127 @HotSpotIntrinsicCandidate 128 public static 129 <VM, E, S extends VectorSpecies<E>> 130 VM broadcastCoerced(Class<? extends VM> vmClass, Class<E> E, int length, 131 long bits, S s, 132 BroadcastOperation<VM, E, S> defaultImpl) { 133 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 134 return defaultImpl.broadcast(bits, s); 135 } 136 137 /* ============================================================================ */ 138 public interface ShuffleIotaOperation<E, S extends VectorSpecies<E>> { 139 VectorShuffle<E> apply(int length, int start, int step, S s); 140 } 141 142 @HotSpotIntrinsicCandidate 143 public static 144 <E, S extends VectorSpecies<E>> 145 VectorShuffle<E> shuffleIota(Class<?> E, Class<?> ShuffleClass, S s, int length, 146 int start, int step, int wrap, ShuffleIotaOperation<E, S> defaultImpl) { 147 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 148 return defaultImpl.apply(length, start, step, s); 149 } 150 151 public interface ShuffleToVectorOperation<VM, Sh, E> { 152 VM apply(Sh s); 153 } 154 155 @HotSpotIntrinsicCandidate 156 public static 157 <VM ,Sh extends VectorShuffle<E>, E> 158 VM shuffleToVector(Class<?> VM, Class<?>E , Class<?> ShuffleClass, Sh s, int length, 159 ShuffleToVectorOperation<VM,Sh,E> defaultImpl) { 160 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 161 return defaultImpl.apply(s); 162 } 163 164 /* ============================================================================ */ 165 public interface IndexOperation<V extends Vector<E>, E, S extends VectorSpecies<E>> { 166 V index(V v, int step, S s); 167 } 168 169 //FIXME @HotSpotIntrinsicCandidate 170 public static 171 <V extends Vector<E>, E, S extends VectorSpecies<E>> 172 V indexVector(Class<? extends V> vClass, Class<E> E, int length, 173 V v, int step, S s, 174 IndexOperation<V, E, S> defaultImpl) { 175 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 176 return defaultImpl.index(v, step, s); 177 } 178 179 /* ============================================================================ */ 180 181 @HotSpotIntrinsicCandidate 182 public static 183 <V extends Vector<?>> 184 long reductionCoerced(int oprId, Class<?> vectorClass, Class<?> elementType, int length, 185 V v, 186 Function<V,Long> defaultImpl) { 187 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 188 return defaultImpl.apply(v); 189 } 190 191 /* ============================================================================ */ 192 193 public interface VecExtractOp<V> { 194 long apply(V v1, int idx); 195 } 196 197 @HotSpotIntrinsicCandidate 198 public static 199 <V extends Vector<?>> 200 long extract(Class<?> vectorClass, Class<?> elementType, int vlen, 201 V vec, int ix, 202 VecExtractOp<V> defaultImpl) { 203 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 204 return defaultImpl.apply(vec, ix); 205 } 206 207 /* ============================================================================ */ 208 209 public interface VecInsertOp<V> { 210 V apply(V v1, int idx, long val); 211 } 212 213 @HotSpotIntrinsicCandidate 214 public static 215 <V extends Vector<?>> 216 V insert(Class<? extends V> vectorClass, Class<?> elementType, int vlen, 217 V vec, int ix, long val, 218 VecInsertOp<V> defaultImpl) { 219 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 220 return defaultImpl.apply(vec, ix, val); 221 } 222 223 /* ============================================================================ */ 224 225 @HotSpotIntrinsicCandidate 226 public static 227 <VM> 228 VM unaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 229 VM vm, 230 Function<VM, VM> defaultImpl) { 231 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 232 return defaultImpl.apply(vm); 233 } 234 235 /* ============================================================================ */ 236 237 @HotSpotIntrinsicCandidate 238 public static 239 <VM> 240 VM binaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 241 VM vm1, VM vm2, 242 BiFunction<VM, VM, VM> defaultImpl) { 243 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 244 return defaultImpl.apply(vm1, vm2); 245 } 246 247 /* ============================================================================ */ 248 249 public interface TernaryOperation<V> { 250 V apply(V v1, V v2, V v3); 251 } 252 253 @HotSpotIntrinsicCandidate 254 public static 255 <VM> 256 VM ternaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 257 VM vm1, VM vm2, VM vm3, 258 TernaryOperation<VM> defaultImpl) { 259 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 260 return defaultImpl.apply(vm1, vm2, vm3); 261 } 262 263 /* ============================================================================ */ 264 265 // Memory operations 266 267 public interface LoadOperation<C, V, E, S extends VectorSpecies<E>> { 268 V load(C container, int index, S s); 269 } 270 271 @HotSpotIntrinsicCandidate 272 public static 273 <C, VM, E, S extends VectorSpecies<E>> 274 VM load(Class<? extends VM> vmClass, Class<E> E, int length, 275 Object base, long offset, // Unsafe addressing 276 C container, int index, S s, // Arguments for default implementation 277 LoadOperation<C, VM, E, S> defaultImpl) { 278 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 279 return defaultImpl.load(container, index, s); 280 } 281 282 /* ============================================================================ */ 283 284 public interface LoadVectorOperationWithMap<C, V extends Vector<?>, E, S extends VectorSpecies<E>> { 285 V loadWithMap(C container, int index, int[] indexMap, int indexM, S s); 286 } 287 288 @HotSpotIntrinsicCandidate 289 public static 290 <C, V extends Vector<?>, W extends Vector<Integer>, E, S extends VectorSpecies<E>> 291 V loadWithMap(Class<?> vectorClass, Class<E> E, int length, Class<?> vectorIndexClass, 292 Object base, long offset, // Unsafe addressing 293 W index_vector, 294 C container, int index, int[] indexMap, int indexM, S s, // Arguments for default implementation 295 LoadVectorOperationWithMap<C, V, E, S> defaultImpl) { 296 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 297 return defaultImpl.loadWithMap(container, index, indexMap, indexM, s); 298 } 299 300 /* ============================================================================ */ 301 302 public interface StoreVectorOperation<C, V extends Vector<?>> { 303 void store(C container, int index, V v); 304 } 305 306 @HotSpotIntrinsicCandidate 307 public static 308 <C, V extends Vector<?>> 309 void store(Class<?> vectorClass, Class<?> elementType, int length, 310 Object base, long offset, // Unsafe addressing 311 V v, 312 C container, int index, // Arguments for default implementation 313 StoreVectorOperation<C, V> defaultImpl) { 314 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 315 defaultImpl.store(container, index, v); 316 } 317 318 /* ============================================================================ */ 319 320 public interface StoreVectorOperationWithMap<C, V extends Vector<?>> { 321 void storeWithMap(C container, int index, V v, int[] indexMap, int indexM); 322 } 323 324 @HotSpotIntrinsicCandidate 325 public static 326 <C, V extends Vector<?>, W extends Vector<Integer>> 327 void storeWithMap(Class<?> vectorClass, Class<?> elementType, int length, Class<?> vectorIndexClass, 328 Object base, long offset, // Unsafe addressing 329 W index_vector, V v, 330 C container, int index, int[] indexMap, int indexM, // Arguments for default implementation 331 StoreVectorOperationWithMap<C, V> defaultImpl) { 332 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 333 defaultImpl.storeWithMap(container, index, v, indexMap, indexM); 334 } 335 336 /* ============================================================================ */ 337 338 @HotSpotIntrinsicCandidate 339 public static 340 <VM> 341 boolean test(int cond, Class<?> vmClass, Class<?> elementType, int length, 342 VM vm1, VM vm2, 343 BiFunction<VM, VM, Boolean> defaultImpl) { 344 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 345 return defaultImpl.apply(vm1, vm2); 346 } 347 348 /* ============================================================================ */ 349 350 public interface VectorCompareOp<V,M> { 351 M apply(int cond, V v1, V v2); 352 } 353 354 @HotSpotIntrinsicCandidate 355 public static <V extends Vector<E>, 356 M extends VectorMask<E>, 357 E> 358 M compare(int cond, Class<? extends V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 359 V v1, V v2, 360 VectorCompareOp<V,M> defaultImpl) { 361 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 362 return defaultImpl.apply(cond, v1, v2); 363 } 364 365 /* ============================================================================ */ 366 367 public interface VectorRearrangeOp<V extends Vector<E>, 368 Sh extends VectorShuffle<E>, 369 E> { 370 V apply(V v1, Sh shuffle); 371 } 372 373 @HotSpotIntrinsicCandidate 374 public static 375 <V extends Vector<E>, 376 Sh extends VectorShuffle<E>, 377 E> 378 V rearrangeOp(Class<? extends V> vectorClass, Class<Sh> shuffleClass, Class<?> elementType, int vlen, 379 V v1, Sh sh, 380 VectorRearrangeOp<V,Sh, E> defaultImpl) { 381 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 382 return defaultImpl.apply(v1, sh); 383 } 384 385 /* ============================================================================ */ 386 387 public interface VectorBlendOp<V extends Vector<E>, 388 M extends VectorMask<E>, 389 E> { 390 V apply(V v1, V v2, M mask); 391 } 392 393 @HotSpotIntrinsicCandidate 394 public static 395 <V extends Vector<E>, 396 M extends VectorMask<E>, 397 E> 398 V blend(Class<? extends V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 399 V v1, V v2, M m, 400 VectorBlendOp<V,M, E> defaultImpl) { 401 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 402 return defaultImpl.apply(v1, v2, m); 403 } 404 405 /* ============================================================================ */ 406 407 public interface VectorBroadcastIntOp<V extends Vector<?>> { 408 V apply(V v, int n); 409 } 410 411 @HotSpotIntrinsicCandidate 412 public static 413 <V extends Vector<?>> 414 V broadcastInt(int opr, Class<? extends V> vectorClass, Class<?> elementType, int length, 415 V v, int n, 416 VectorBroadcastIntOp<V> defaultImpl) { 417 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 418 return defaultImpl.apply(v, n); 419 } 420 421 /* ============================================================================ */ 422 423 public interface VectorConvertOp<VOUT, VIN, S> { 424 VOUT apply(VIN v, S species); 425 } 426 427 // Users of this intrinsic assume that it respects 428 // REGISTER_ENDIAN, which is currently ByteOrder.LITTLE_ENDIAN. 429 // See javadoc for REGISTER_ENDIAN. 430 431 @HotSpotIntrinsicCandidate 432 public static <VOUT extends VectorPayload, 433 VIN extends VectorPayload, 434 S extends VectorSpecies<?>> 435 VOUT convert(int oprId, 436 Class<?> fromVectorClass, Class<?> fromElementType, int fromVLen, 437 Class<?> toVectorClass, Class<?> toElementType, int toVLen, 438 VIN v, S s, 439 VectorConvertOp<VOUT, VIN, S> defaultImpl) { 440 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 441 return defaultImpl.apply(v, s); 442 } 443 444 /* ============================================================================ */ 445 446 @HotSpotIntrinsicCandidate 447 public static <V> V maybeRebox(V v) { 448 // The fence is added here to avoid memory aliasing problems in C2 between scalar & vector accesses. 449 // TODO: move the fence generation into C2. Generate only when reboxing is taking place. 450 U.loadFence(); 451 return v; 452 } 453 454 /* ============================================================================ */ 455 456 // query the JVM's supported vector sizes and types 457 public static native int getMaxLaneCount(Class<?> etype); 458 459 /* ============================================================================ */ 460 461 public static boolean isNonCapturingLambda(Object o) { 462 return o.getClass().getDeclaredFields().length == 0; 463 } 464 465 /* ============================================================================ */ 466 467 private static native int registerNatives(); 468 }