simd_construct_values.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_construct_values.h"
  6. #include "../aot_emit_exception.h"
  7. #include "../interpreter/wasm_opcode.h"
  8. #include "../../aot/aot_runtime.h"
  9. bool
  10. aot_compile_simd_v128_const(AOTCompContext *comp_ctx,
  11. AOTFuncContext *func_ctx,
  12. const uint8 *imm_bytes)
  13. {
  14. uint64 imm1, imm2;
  15. LLVMValueRef undef, first_long, agg1, second_long, agg2;
  16. wasm_runtime_read_v128(imm_bytes, &imm1, &imm2);
  17. if (!(undef = LLVMGetUndef(V128_i64x2_TYPE))) {
  18. HANDLE_FAILURE("LLVMGetUndef");
  19. goto fail;
  20. }
  21. /* %agg1 = insertelement <2 x i64> undef, i16 0, i64 ${*imm} */
  22. if (!(first_long = I64_CONST(imm1))) {
  23. HANDLE_FAILURE("LLVMConstInt");
  24. goto fail;
  25. }
  26. if (!(agg1 = LLVMBuildInsertElement(comp_ctx->builder, undef, first_long,
  27. I32_ZERO, "agg1"))) {
  28. HANDLE_FAILURE("LLVMBuildInsertElement");
  29. goto fail;
  30. }
  31. /* %agg2 = insertelement <2 x i64> %agg1, i16 1, i64 ${*(imm + 1)} */
  32. if (!(second_long = I64_CONST(imm2))) {
  33. HANDLE_FAILURE("LLVMGetUndef");
  34. goto fail;
  35. }
  36. if (!(agg2 = LLVMBuildInsertElement(comp_ctx->builder, agg1, second_long,
  37. I32_ONE, "agg2"))) {
  38. HANDLE_FAILURE("LLVMBuildInsertElement");
  39. goto fail;
  40. }
  41. PUSH_V128(agg2);
  42. return true;
  43. fail:
  44. return false;
  45. }
  46. bool
  47. aot_compile_simd_splat(AOTCompContext *comp_ctx,
  48. AOTFuncContext *func_ctx,
  49. uint8 splat_opcode)
  50. {
  51. LLVMValueRef value, undef, base, mask, new_vector, result;
  52. LLVMTypeRef all_zero_ty;
  53. switch (splat_opcode) {
  54. case SIMD_i8x16_splat:
  55. {
  56. LLVMValueRef input;
  57. POP_I32(input);
  58. /* trunc i32 %input to i8 */
  59. if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE,
  60. "trunc"))) {
  61. HANDLE_FAILURE("LLVMBuildTrunc");
  62. goto fail;
  63. }
  64. undef = LLVMGetUndef(V128_i8x16_TYPE);
  65. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 16))) {
  66. HANDLE_FAILURE("LLVMVectorType");
  67. goto fail;
  68. }
  69. break;
  70. }
  71. case SIMD_i16x8_splat:
  72. {
  73. LLVMValueRef input;
  74. POP_I32(input);
  75. /* trunc i32 %input to i16 */
  76. if (!(value = LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE,
  77. "trunc"))) {
  78. HANDLE_FAILURE("LLVMBuildTrunc");
  79. goto fail;
  80. }
  81. undef = LLVMGetUndef(V128_i16x8_TYPE);
  82. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 8))) {
  83. HANDLE_FAILURE("LLVMVectorType");
  84. goto fail;
  85. }
  86. break;
  87. }
  88. case SIMD_i32x4_splat:
  89. {
  90. POP_I32(value);
  91. undef = LLVMGetUndef(V128_i32x4_TYPE);
  92. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) {
  93. HANDLE_FAILURE("LLVMVectorType");
  94. goto fail;
  95. }
  96. break;
  97. }
  98. case SIMD_i64x2_splat:
  99. {
  100. POP(value, VALUE_TYPE_I64);
  101. undef = LLVMGetUndef(V128_i64x2_TYPE);
  102. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) {
  103. HANDLE_FAILURE("LLVMVectorType");
  104. goto fail;
  105. }
  106. break;
  107. }
  108. case SIMD_f32x4_splat:
  109. {
  110. POP(value, VALUE_TYPE_F32);
  111. undef = LLVMGetUndef(V128_f32x4_TYPE);
  112. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 4))) {
  113. HANDLE_FAILURE("LLVMVectorType");
  114. goto fail;
  115. }
  116. break;
  117. }
  118. case SIMD_f64x2_splat:
  119. {
  120. POP(value, VALUE_TYPE_F64);
  121. undef = LLVMGetUndef(V128_f64x2_TYPE);
  122. if (!(all_zero_ty = LLVMVectorType(I32_TYPE, 2))) {
  123. HANDLE_FAILURE("LLVMVectorType");
  124. goto fail;
  125. }
  126. break;
  127. }
  128. default:
  129. {
  130. bh_assert(0);
  131. goto fail;
  132. }
  133. }
  134. if (!undef) {
  135. HANDLE_FAILURE("LVMGetUndef");
  136. goto fail;
  137. }
  138. /* insertelement <n x ty> undef, ty %value, i32 0 */
  139. if (!(base = LLVMBuildInsertElement(comp_ctx->builder, undef, value,
  140. I32_ZERO, "base"))) {
  141. HANDLE_FAILURE("LLVMBuildInsertElement");
  142. goto fail;
  143. }
  144. /* <n x i32> zeroinitializer */
  145. if (!(mask = LLVMConstNull(all_zero_ty))) {
  146. HANDLE_FAILURE("LLVMConstNull");
  147. goto fail;
  148. }
  149. /* shufflevector <ty1> %base, <ty2> undef, <n x i32> zeroinitializer */
  150. if (!(new_vector = LLVMBuildShuffleVector(comp_ctx->builder, base, undef,
  151. mask, "new_vector"))) {
  152. HANDLE_FAILURE("LLVMBuildShuffleVector");
  153. goto fail;
  154. }
  155. /* bitcast <ty> <value> to <2 x i64> */
  156. if (!(result = LLVMBuildBitCast(comp_ctx->builder, new_vector,
  157. V128_i64x2_TYPE, "ret"))) {
  158. HANDLE_FAILURE("LLVMBuidlCast");
  159. goto fail;
  160. }
  161. /* push result into the stack */
  162. PUSH_V128(result);
  163. return true;
  164. fail:
  165. return false;
  166. }