simd_bit_shifts.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_bit_shifts.h"
  6. #include "simd_common.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../../aot/aot_runtime.h"
  9. enum integer_shift {
  10. e_shift_i8x16,
  11. e_shift_i16x8,
  12. e_shift_i32x4,
  13. e_shift_i64x2,
  14. };
  15. static bool
  16. simd_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  17. IntShift shift_op, enum integer_shift itype)
  18. {
  19. LLVMValueRef vector, offset, result = NULL;
  20. LLVMTypeRef vector_type[] = { V128_i8x16_TYPE, V128_i16x8_TYPE,
  21. V128_i32x4_TYPE, V128_i64x2_TYPE };
  22. LLVMTypeRef element_type[] = { INT8_TYPE, INT16_TYPE, I32_TYPE, I64_TYPE };
  23. LLVMValueRef undef[] = { LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
  24. LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef) };
  25. LLVMValueRef mask[] = { LLVM_CONST(i8x16_vec_zero),
  26. LLVM_CONST(i16x8_vec_zero),
  27. LLVM_CONST(i32x4_vec_zero),
  28. LLVM_CONST(i64x2_vec_zero) };
  29. LLVMValueRef lane_shift_masks[] = {
  30. LLVMConstInt(I32_TYPE, 7, true),
  31. LLVMConstInt(I32_TYPE, 15, true),
  32. LLVMConstInt(I32_TYPE, 31, true),
  33. LLVMConstInt(I32_TYPE, 63, true),
  34. };
  35. POP_I32(offset);
  36. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  37. vector_type[itype], "vec"))) {
  38. return false;
  39. }
  40. /* offset = offset & shift_mask */
  41. if (!lane_shift_masks[itype]
  42. || !(offset = LLVMBuildAnd(comp_ctx->builder, offset,
  43. lane_shift_masks[itype], "offset_fix"))) {
  44. HANDLE_FAILURE("LLVMBuildAnd");
  45. return false;
  46. }
  47. /* change type */
  48. if (itype < e_shift_i32x4) {
  49. offset = LLVMBuildTrunc(comp_ctx->builder, offset, element_type[itype],
  50. "offset_trunc");
  51. }
  52. else if (itype == e_shift_i64x2) {
  53. offset = LLVMBuildZExt(comp_ctx->builder, offset, element_type[itype],
  54. "offset_ext");
  55. }
  56. if (!offset) {
  57. HANDLE_FAILURE("LLVMBuildZext/LLVMBuildTrunc");
  58. return false;
  59. }
  60. /* splat to a vector */
  61. if (!(offset =
  62. LLVMBuildInsertElement(comp_ctx->builder, undef[itype], offset,
  63. I32_ZERO, "offset_vector_base"))) {
  64. HANDLE_FAILURE("LLVMBuildInsertElement");
  65. return false;
  66. }
  67. if (!(offset =
  68. LLVMBuildShuffleVector(comp_ctx->builder, offset, undef[itype],
  69. mask[itype], "offset_vector"))) {
  70. HANDLE_FAILURE("LLVMBuildShuffleVector");
  71. return false;
  72. }
  73. switch (shift_op) {
  74. case INT_SHL:
  75. {
  76. result = LLVMBuildShl(comp_ctx->builder, vector, offset, "shl");
  77. break;
  78. }
  79. case INT_SHR_S:
  80. {
  81. result = LLVMBuildAShr(comp_ctx->builder, vector, offset, "ashr");
  82. break;
  83. }
  84. case INT_SHR_U:
  85. {
  86. result = LLVMBuildLShr(comp_ctx->builder, vector, offset, "lshr");
  87. break;
  88. }
  89. default:
  90. {
  91. break;
  92. }
  93. }
  94. if (!result) {
  95. HANDLE_FAILURE("LLVMBuildShl/LLVMBuildLShr/LLVMBuildAShr");
  96. goto fail;
  97. }
  98. return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
  99. fail:
  100. return false;
  101. }
  102. bool
  103. aot_compile_simd_i8x16_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  104. IntShift shift_op)
  105. {
  106. return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i8x16);
  107. }
  108. bool
  109. aot_compile_simd_i16x8_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  110. IntShift shift_op)
  111. {
  112. return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i16x8);
  113. }
  114. bool
  115. aot_compile_simd_i32x4_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  116. IntShift shift_op)
  117. {
  118. return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i32x4);
  119. }
  120. bool
  121. aot_compile_simd_i64x2_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  122. IntShift shift_op)
  123. {
  124. return simd_shift(comp_ctx, func_ctx, shift_op, e_shift_i64x2);
  125. }