simd_floating_point.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_floating_point.h"
  6. #include "simd_common.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../aot_emit_numberic.h"
  9. #include "../../aot/aot_runtime.h"
  10. static LLVMValueRef
  11. simd_v128_float_cmp(AOTCompContext *comp_ctx,
  12. AOTFuncContext *func_ctx,
  13. FloatArithmetic arith_op,
  14. LLVMValueRef lhs,
  15. LLVMValueRef rhs)
  16. {
  17. LLVMValueRef result;
  18. LLVMRealPredicate op;
  19. op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT;
  20. if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
  21. HANDLE_FAILURE("LLVMBuildFCmp");
  22. goto fail;
  23. }
  24. if (!(result =
  25. LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
  26. HANDLE_FAILURE("LLVMBuildSelect");
  27. goto fail;
  28. }
  29. return result;
  30. fail:
  31. return NULL;
  32. }
  33. static bool
  34. simd_v128_float_arith(AOTCompContext *comp_ctx,
  35. AOTFuncContext *func_ctx,
  36. FloatArithmetic arith_op,
  37. LLVMTypeRef vector_type)
  38. {
  39. LLVMValueRef lhs, rhs, result;
  40. if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  41. "rhs"))) {
  42. goto fail;
  43. }
  44. if (!(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  45. "lhs"))) {
  46. goto fail;
  47. }
  48. switch (arith_op) {
  49. case FLOAT_ADD:
  50. if (!(result =
  51. LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum"))) {
  52. HANDLE_FAILURE("LLVMBuildFAdd");
  53. goto fail;
  54. }
  55. break;
  56. case FLOAT_SUB:
  57. if (!(result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs,
  58. "difference"))) {
  59. HANDLE_FAILURE("LLVMBuildFSub");
  60. goto fail;
  61. }
  62. break;
  63. case FLOAT_MUL:
  64. if (!(result =
  65. LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product"))) {
  66. HANDLE_FAILURE("LLVMBuildFMul");
  67. goto fail;
  68. }
  69. break;
  70. case FLOAT_DIV:
  71. if (!(result =
  72. LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient"))) {
  73. HANDLE_FAILURE("LLVMBuildFDiv");
  74. goto fail;
  75. }
  76. break;
  77. case FLOAT_MIN:
  78. if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MIN,
  79. lhs, rhs))) {
  80. goto fail;
  81. }
  82. break;
  83. case FLOAT_MAX:
  84. if (!(result = simd_v128_float_cmp(comp_ctx, func_ctx, FLOAT_MAX,
  85. lhs, rhs))) {
  86. goto fail;
  87. }
  88. break;
  89. default:
  90. result = NULL;
  91. bh_assert(0);
  92. break;
  93. }
  94. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  95. "ret"))) {
  96. HANDLE_FAILURE("LLVMBuildBitCast");
  97. goto fail;
  98. }
  99. /* push result into the stack */
  100. PUSH_V128(result);
  101. return true;
  102. fail:
  103. return false;
  104. }
  105. bool
  106. aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx,
  107. AOTFuncContext *func_ctx,
  108. FloatArithmetic arith_op)
  109. {
  110. return simd_v128_float_arith(comp_ctx, func_ctx, arith_op,
  111. V128_f32x4_TYPE);
  112. }
  113. bool
  114. aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx,
  115. AOTFuncContext *func_ctx,
  116. FloatArithmetic arith_op)
  117. {
  118. return simd_v128_float_arith(comp_ctx, func_ctx, arith_op,
  119. V128_f64x2_TYPE);
  120. }
  121. static bool
  122. simd_v128_float_neg(AOTCompContext *comp_ctx,
  123. AOTFuncContext *func_ctx,
  124. LLVMTypeRef vector_type)
  125. {
  126. LLVMValueRef number, result;
  127. if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  128. "number"))) {
  129. goto fail;
  130. }
  131. if (!(result = LLVMBuildFNeg(comp_ctx->builder, number, "neg"))) {
  132. HANDLE_FAILURE("LLVMBuildFNeg");
  133. goto fail;
  134. }
  135. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  136. "ret"))) {
  137. HANDLE_FAILURE("LLVMBuildBitCast");
  138. goto fail;
  139. }
  140. /* push result into the stack */
  141. PUSH_V128(result);
  142. return true;
  143. fail:
  144. return false;
  145. }
  146. bool
  147. aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  148. {
  149. return simd_v128_float_neg(comp_ctx, func_ctx, V128_f32x4_TYPE);
  150. }
  151. bool
  152. aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  153. {
  154. return simd_v128_float_neg(comp_ctx, func_ctx, V128_f64x2_TYPE);
  155. }
  156. static bool
  157. simd_v128_float_abs(AOTCompContext *comp_ctx,
  158. AOTFuncContext *func_ctx,
  159. LLVMTypeRef vector_type,
  160. const char *intrinsic)
  161. {
  162. LLVMValueRef vector, result;
  163. LLVMTypeRef param_types[1] = { vector_type };
  164. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  165. "vec"))) {
  166. goto fail;
  167. }
  168. if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
  169. param_types, 1, vector))) {
  170. HANDLE_FAILURE("LLVMBuildCall");
  171. goto fail;
  172. }
  173. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  174. "ret"))) {
  175. HANDLE_FAILURE("LLVMBuildBitCast");
  176. goto fail;
  177. }
  178. /* push result into the stack */
  179. PUSH_V128(result);
  180. return true;
  181. fail:
  182. return false;
  183. }
  184. bool
  185. aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  186. {
  187. return simd_v128_float_abs(comp_ctx, func_ctx, V128_f32x4_TYPE,
  188. "llvm.fabs.v4f32");
  189. }
  190. bool
  191. aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  192. {
  193. return simd_v128_float_abs(comp_ctx, func_ctx, V128_f64x2_TYPE,
  194. "llvm.fabs.v2f64");
  195. }
  196. static bool
  197. simd_v128_float_sqrt(AOTCompContext *comp_ctx,
  198. AOTFuncContext *func_ctx,
  199. LLVMTypeRef vector_type,
  200. const char *intrinsic)
  201. {
  202. LLVMValueRef number, result;
  203. LLVMTypeRef param_types[1] = { vector_type };
  204. if (!(number = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  205. "number"))) {
  206. goto fail;
  207. }
  208. if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
  209. param_types, 1, number))) {
  210. HANDLE_FAILURE("LLVMBuildCall");
  211. goto fail;
  212. }
  213. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  214. "ret"))) {
  215. HANDLE_FAILURE("LLVMBuildBitCast");
  216. goto fail;
  217. }
  218. /* push result into the stack */
  219. PUSH_V128(result);
  220. return true;
  221. fail:
  222. return false;
  223. }
  224. bool
  225. aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  226. {
  227. return simd_v128_float_sqrt(comp_ctx, func_ctx, V128_f32x4_TYPE,
  228. "llvm.sqrt.v4f32");
  229. }
  230. bool
  231. aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
  232. {
  233. return simd_v128_float_sqrt(comp_ctx, func_ctx, V128_f64x2_TYPE,
  234. "llvm.sqrt.v2f64");
  235. }