simd_bitmask_extracts.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_bitmask_extracts.h"
  6. #include "simd_common.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../../aot/aot_runtime.h"
  9. enum integer_bitmask_type {
  10. e_bitmask_i8x16,
  11. e_bitmask_i16x8,
  12. e_bitmask_i32x4,
  13. e_bitmask_i64x2,
  14. };
  15. /* TODO: should use a much clever intrinsic */
  16. static bool
  17. simd_build_bitmask(const AOTCompContext *comp_ctx,
  18. const AOTFuncContext *func_ctx,
  19. enum integer_bitmask_type itype)
  20. {
  21. LLVMValueRef vector, mask, result;
  22. uint8 i;
  23. LLVMTypeRef vector_ext_type;
  24. uint32 lanes[] = { 16, 8, 4, 2 };
  25. uint32 lane_bits[] = { 8, 16, 32, 64 };
  26. LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };
  27. LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
  28. V128_i32x4_TYPE, V128_i64x2_TYPE };
  29. int32 mask_element[16] = { 0 };
  30. const char *intrinsic[] = {
  31. "llvm.vector.reduce.or.v16i64",
  32. "llvm.vector.reduce.or.v8i64",
  33. "llvm.vector.reduce.or.v4i64",
  34. "llvm.vector.reduce.or.v2i64",
  35. };
  36. LLVMValueRef ashr_distance;
  37. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  38. vector_type[itype], "vec"))) {
  39. goto fail;
  40. }
  41. /* fill every bit in a lange with its sign bit */
  42. if (!(ashr_distance = simd_build_splat_const_integer_vector(
  43. comp_ctx, element_type[itype], lane_bits[itype] - 1,
  44. lanes[itype]))) {
  45. goto fail;
  46. }
  47. if (!(vector = LLVMBuildAShr(comp_ctx->builder, vector, ashr_distance,
  48. "vec_ashr"))) {
  49. HANDLE_FAILURE("LLVMBuildAShr");
  50. goto fail;
  51. }
  52. if (!(vector_ext_type = LLVMVectorType(I64_TYPE, lanes[itype]))) {
  53. HANDLE_FAILURE("LLVMVectorType");
  54. goto fail;
  55. }
  56. if (e_bitmask_i64x2 != itype) {
  57. if (!(vector = LLVMBuildSExt(comp_ctx->builder, vector, vector_ext_type,
  58. "zext_to_i64"))) {
  59. goto fail;
  60. }
  61. }
  62. for (i = 0; i < 16; i++) {
  63. mask_element[i] = 0x1 << i;
  64. }
  65. if (!(mask = simd_build_const_integer_vector(comp_ctx, I64_TYPE,
  66. mask_element, lanes[itype]))) {
  67. goto fail;
  68. }
  69. if (!(vector =
  70. LLVMBuildAnd(comp_ctx->builder, vector, mask, "mask_bits"))) {
  71. HANDLE_FAILURE("LLVMBuildAnd");
  72. goto fail;
  73. }
  74. if (!(result =
  75. aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype],
  76. I64_TYPE, &vector_ext_type, 1, vector))) {
  77. goto fail;
  78. }
  79. if (!(result =
  80. LLVMBuildTrunc(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
  81. HANDLE_FAILURE("LLVMBuildTrunc");
  82. goto fail;
  83. }
  84. PUSH_I32(result);
  85. return true;
  86. fail:
  87. return false;
  88. }
  89. bool
  90. aot_compile_simd_i8x16_bitmask(AOTCompContext *comp_ctx,
  91. AOTFuncContext *func_ctx)
  92. {
  93. return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i8x16);
  94. }
  95. bool
  96. aot_compile_simd_i16x8_bitmask(AOTCompContext *comp_ctx,
  97. AOTFuncContext *func_ctx)
  98. {
  99. return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i16x8);
  100. }
  101. bool
  102. aot_compile_simd_i32x4_bitmask(AOTCompContext *comp_ctx,
  103. AOTFuncContext *func_ctx)
  104. {
  105. return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i32x4);
  106. }
  107. bool
  108. aot_compile_simd_i64x2_bitmask(AOTCompContext *comp_ctx,
  109. AOTFuncContext *func_ctx)
  110. {
  111. return simd_build_bitmask(comp_ctx, func_ctx, e_bitmask_i64x2);
  112. }