simd_bool_reductions.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_bool_reductions.h"
  6. #include "simd_common.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../../aot/aot_runtime.h"
  9. enum integer_all_true {
  10. e_int_all_true_v16i8,
  11. e_int_all_true_v8i16,
  12. e_int_all_true_v4i32,
  13. e_int_all_true_v2i64,
  14. };
  15. static bool
  16. simd_all_true(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  17. enum integer_all_true itype)
  18. {
  19. LLVMValueRef vector, result;
  20. LLVMTypeRef vector_i1_type;
  21. LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
  22. V128_i32x4_TYPE, V128_i64x2_TYPE };
  23. uint32 lanes[] = { 16, 8, 4, 2 };
  24. const char *intrinsic[] = {
  25. "llvm.vector.reduce.and.v16i1",
  26. "llvm.vector.reduce.and.v8i1",
  27. "llvm.vector.reduce.and.v4i1",
  28. "llvm.vector.reduce.and.v2i1",
  29. };
  30. LLVMValueRef zero[] = {
  31. LLVM_CONST(i8x16_vec_zero),
  32. LLVM_CONST(i16x8_vec_zero),
  33. LLVM_CONST(i32x4_vec_zero),
  34. LLVM_CONST(i64x2_vec_zero),
  35. };
  36. if (!(vector_i1_type = LLVMVectorType(INT1_TYPE, lanes[itype]))) {
  37. HANDLE_FAILURE("LLVMVectorType");
  38. goto fail;
  39. }
  40. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  41. vector_type[itype], "vector"))) {
  42. goto fail;
  43. }
  44. /* compare with zero */
  45. if (!(result = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, vector,
  46. zero[itype], "ne_zero"))) {
  47. HANDLE_FAILURE("LLVMBuildICmp");
  48. goto fail;
  49. }
  50. /* check zero */
  51. if (!(result =
  52. aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic[itype],
  53. INT1_TYPE, &vector_i1_type, 1, result))) {
  54. goto fail;
  55. }
  56. if (!(result =
  57. LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
  58. HANDLE_FAILURE("LLVMBuildZExt");
  59. goto fail;
  60. }
  61. PUSH_I32(result);
  62. return true;
  63. fail:
  64. return false;
  65. }
  66. bool
  67. aot_compile_simd_i8x16_all_true(AOTCompContext *comp_ctx,
  68. AOTFuncContext *func_ctx)
  69. {
  70. return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v16i8);
  71. }
  72. bool
  73. aot_compile_simd_i16x8_all_true(AOTCompContext *comp_ctx,
  74. AOTFuncContext *func_ctx)
  75. {
  76. return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v8i16);
  77. }
  78. bool
  79. aot_compile_simd_i32x4_all_true(AOTCompContext *comp_ctx,
  80. AOTFuncContext *func_ctx)
  81. {
  82. return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v4i32);
  83. }
  84. bool
  85. aot_compile_simd_i64x2_all_true(AOTCompContext *comp_ctx,
  86. AOTFuncContext *func_ctx)
  87. {
  88. return simd_all_true(comp_ctx, func_ctx, e_int_all_true_v2i64);
  89. }
  90. bool
  91. aot_compile_simd_v128_any_true(AOTCompContext *comp_ctx,
  92. AOTFuncContext *func_ctx)
  93. {
  94. LLVMTypeRef vector_type;
  95. LLVMValueRef vector, result;
  96. if (!(vector_type = LLVMVectorType(INT1_TYPE, 128))) {
  97. return false;
  98. }
  99. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  100. "vector"))) {
  101. goto fail;
  102. }
  103. if (!(result = aot_call_llvm_intrinsic(
  104. comp_ctx, func_ctx, "llvm.vector.reduce.or.v128i1", INT1_TYPE,
  105. &vector_type, 1, vector))) {
  106. goto fail;
  107. }
  108. if (!(result =
  109. LLVMBuildZExt(comp_ctx->builder, result, I32_TYPE, "to_i32"))) {
  110. HANDLE_FAILURE("LLVMBuildZExt");
  111. goto fail;
  112. }
  113. PUSH_I32(result);
  114. return true;
  115. fail:
  116. return false;
  117. }