simd_construct_values.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_common.h"
  6. #include "simd_construct_values.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../interpreter/wasm_opcode.h"
  9. #include "../../aot/aot_runtime.h"
  10. bool
  11. aot_compile_simd_v128_const(AOTCompContext *comp_ctx,
  12. AOTFuncContext *func_ctx,
  13. const uint8 *imm_bytes)
  14. {
  15. uint64 imm1, imm2;
  16. LLVMValueRef first_long, agg1, second_long, agg2;
  17. wasm_runtime_read_v128(imm_bytes, &imm1, &imm2);
  18. /* %agg1 = insertelement <2 x i64> undef, i16 0, i64 ${*imm} */
  19. if (!(first_long = I64_CONST(imm1))) {
  20. HANDLE_FAILURE("LLVMConstInt");
  21. goto fail;
  22. }
  23. if (!(agg1 =
  24. LLVMBuildInsertElement(comp_ctx->builder, LLVM_CONST(i64x2_undef),
  25. first_long, I32_ZERO, "agg1"))) {
  26. HANDLE_FAILURE("LLVMBuildInsertElement");
  27. goto fail;
  28. }
  29. /* %agg2 = insertelement <2 x i64> %agg1, i16 1, i64 ${*(imm + 1)} */
  30. if (!(second_long = I64_CONST(imm2))) {
  31. HANDLE_FAILURE("LLVMGetUndef");
  32. goto fail;
  33. }
  34. if (!(agg2 = LLVMBuildInsertElement(comp_ctx->builder, agg1, second_long,
  35. I32_ONE, "agg2"))) {
  36. HANDLE_FAILURE("LLVMBuildInsertElement");
  37. goto fail;
  38. }
  39. PUSH_V128(agg2);
  40. return true;
  41. fail:
  42. return false;
  43. }
  44. bool
  45. aot_compile_simd_splat(AOTCompContext *comp_ctx,
  46. AOTFuncContext *func_ctx,
  47. uint8 opcode)
  48. {
  49. uint32 opcode_index = opcode - SIMD_i8x16_splat;
  50. LLVMValueRef value = NULL, base, new_vector;
  51. LLVMValueRef undefs[] = {
  52. LLVM_CONST(i8x16_undef), LLVM_CONST(i16x8_undef),
  53. LLVM_CONST(i32x4_undef), LLVM_CONST(i64x2_undef),
  54. LLVM_CONST(f32x4_undef), LLVM_CONST(f64x2_undef),
  55. };
  56. LLVMValueRef masks[] = {
  57. LLVM_CONST(i32x16_zero), LLVM_CONST(i32x8_zero),
  58. LLVM_CONST(i32x4_zero), LLVM_CONST(i32x2_zero),
  59. LLVM_CONST(i32x4_zero), LLVM_CONST(i32x2_zero),
  60. };
  61. switch (opcode) {
  62. case SIMD_i8x16_splat:
  63. {
  64. LLVMValueRef input;
  65. POP_I32(input);
  66. /* trunc i32 %input to i8 */
  67. value =
  68. LLVMBuildTrunc(comp_ctx->builder, input, INT8_TYPE, "trunc");
  69. break;
  70. }
  71. case SIMD_i16x8_splat:
  72. {
  73. LLVMValueRef input;
  74. POP_I32(input);
  75. /* trunc i32 %input to i16 */
  76. value =
  77. LLVMBuildTrunc(comp_ctx->builder, input, INT16_TYPE, "trunc");
  78. break;
  79. }
  80. case SIMD_i32x4_splat:
  81. {
  82. POP_I32(value);
  83. break;
  84. }
  85. case SIMD_i64x2_splat:
  86. {
  87. POP(value, VALUE_TYPE_I64);
  88. break;
  89. }
  90. case SIMD_f32x4_splat:
  91. {
  92. POP(value, VALUE_TYPE_F32);
  93. break;
  94. }
  95. case SIMD_f64x2_splat:
  96. {
  97. POP(value, VALUE_TYPE_F64);
  98. break;
  99. }
  100. default:
  101. {
  102. break;
  103. }
  104. }
  105. if (!value) {
  106. goto fail;
  107. }
  108. /* insertelement <n x ty> undef, ty %value, i32 0 */
  109. if (!(base =
  110. LLVMBuildInsertElement(comp_ctx->builder, undefs[opcode_index],
  111. value, I32_ZERO, "base"))) {
  112. HANDLE_FAILURE("LLVMBuildInsertElement");
  113. goto fail;
  114. }
  115. /* shufflevector <ty1> %base, <ty2> undef, <n x i32> zeroinitializer */
  116. if (!(new_vector = LLVMBuildShuffleVector(
  117. comp_ctx->builder, base, undefs[opcode_index], masks[opcode_index],
  118. "new_vector"))) {
  119. HANDLE_FAILURE("LLVMBuildShuffleVector");
  120. goto fail;
  121. }
  122. return simd_bitcast_and_push_v128(comp_ctx, func_ctx, new_vector,
  123. "result");
  124. fail:
  125. return false;
  126. }