simd_comparisons.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_comparisons.h"
  6. #include "simd_common.h"
  7. #include "../aot_emit_exception.h"
  8. #include "../../aot/aot_runtime.h"
  9. static bool
  10. float_cond_2_predicate(FloatCond cond, LLVMRealPredicate *out)
  11. {
  12. switch (cond) {
  13. case FLOAT_EQ:
  14. *out = LLVMRealOEQ;
  15. break;
  16. case FLOAT_NE:
  17. *out = LLVMRealUNE;
  18. break;
  19. case FLOAT_LT:
  20. *out = LLVMRealOLT;
  21. break;
  22. case FLOAT_GT:
  23. *out = LLVMRealOGT;
  24. break;
  25. case FLOAT_LE:
  26. *out = LLVMRealOLE;
  27. break;
  28. case FLOAT_GE:
  29. *out = LLVMRealOGE;
  30. break;
  31. default:
  32. bh_assert(0);
  33. goto fail;
  34. }
  35. return true;
  36. fail:
  37. return false;
  38. }
  39. static bool
  40. int_cond_2_predicate(IntCond cond, LLVMIntPredicate *out)
  41. {
  42. switch (cond) {
  43. case INT_EQZ:
  44. case INT_EQ:
  45. *out = LLVMIntEQ;
  46. break;
  47. case INT_NE:
  48. *out = LLVMIntNE;
  49. break;
  50. case INT_LT_S:
  51. *out = LLVMIntSLT;
  52. break;
  53. case INT_LT_U:
  54. *out = LLVMIntULT;
  55. break;
  56. case INT_GT_S:
  57. *out = LLVMIntSGT;
  58. break;
  59. case INT_GT_U:
  60. *out = LLVMIntUGT;
  61. break;
  62. case INT_LE_S:
  63. *out = LLVMIntSLE;
  64. break;
  65. case INT_LE_U:
  66. *out = LLVMIntULE;
  67. break;
  68. case INT_GE_S:
  69. *out = LLVMIntSGE;
  70. break;
  71. case INT_GE_U:
  72. *out = LLVMIntUGE;
  73. break;
  74. default:
  75. bh_assert(0);
  76. goto fail;
  77. }
  78. return true;
  79. fail:
  80. return false;
  81. }
  82. static bool
  83. interger_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  84. IntCond cond, LLVMTypeRef vector_type)
  85. {
  86. LLVMValueRef vec1, vec2, result;
  87. LLVMIntPredicate int_pred;
  88. if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  89. "vec2"))) {
  90. goto fail;
  91. }
  92. if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  93. "vec1"))) {
  94. goto fail;
  95. }
  96. if (!int_cond_2_predicate(cond, &int_pred)) {
  97. HANDLE_FAILURE("int_cond_2_predicate");
  98. goto fail;
  99. }
  100. /* icmp <N x iX> %vec1, %vec2 */
  101. if (!(result =
  102. LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) {
  103. HANDLE_FAILURE("LLVMBuildICmp");
  104. goto fail;
  105. }
  106. /* sext <N x i1> %result to <N x iX> */
  107. if (!(result =
  108. LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) {
  109. HANDLE_FAILURE("LLVMBuildSExt");
  110. goto fail;
  111. }
  112. /* bitcast <N x iX> %result to <2 x i64> */
  113. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  114. "result"))) {
  115. HANDLE_FAILURE("LLVMBuildBitCast");
  116. goto fail;
  117. }
  118. PUSH_V128(result);
  119. return true;
  120. fail:
  121. return false;
  122. }
  123. bool
  124. aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
  125. AOTFuncContext *func_ctx, IntCond cond)
  126. {
  127. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i8x16_TYPE);
  128. }
  129. bool
  130. aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
  131. AOTFuncContext *func_ctx, IntCond cond)
  132. {
  133. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i16x8_TYPE);
  134. }
  135. bool
  136. aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
  137. AOTFuncContext *func_ctx, IntCond cond)
  138. {
  139. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i32x4_TYPE);
  140. }
  141. bool
  142. aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx,
  143. AOTFuncContext *func_ctx, IntCond cond)
  144. {
  145. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i64x2_TYPE);
  146. }
  147. static bool
  148. float_vector_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
  149. FloatCond cond, LLVMTypeRef vector_type,
  150. LLVMTypeRef result_type)
  151. {
  152. LLVMValueRef vec1, vec2, result;
  153. LLVMRealPredicate real_pred;
  154. if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  155. "vec2"))) {
  156. goto fail;
  157. }
  158. if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  159. "vec1"))) {
  160. goto fail;
  161. }
  162. if (!float_cond_2_predicate(cond, &real_pred)) {
  163. HANDLE_FAILURE("float_cond_2_predicate");
  164. goto fail;
  165. }
  166. /* fcmp <N x iX> %vec1, %vec2 */
  167. if (!(result =
  168. LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) {
  169. HANDLE_FAILURE("LLVMBuildFCmp");
  170. goto fail;
  171. }
  172. /* sext <N x i1> %result to <N x iX> */
  173. if (!(result =
  174. LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) {
  175. HANDLE_FAILURE("LLVMBuildSExt");
  176. goto fail;
  177. }
  178. /* bitcast <N x iX> %result to <2 x i64> */
  179. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  180. "result"))) {
  181. HANDLE_FAILURE("LLVMBuildBitCast");
  182. goto fail;
  183. }
  184. PUSH_V128(result);
  185. return true;
  186. fail:
  187. return false;
  188. }
  189. bool
  190. aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
  191. AOTFuncContext *func_ctx, FloatCond cond)
  192. {
  193. return float_vector_compare(comp_ctx, func_ctx, cond, V128_f32x4_TYPE,
  194. V128_i32x4_TYPE);
  195. }
  196. bool
  197. aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
  198. AOTFuncContext *func_ctx, FloatCond cond)
  199. {
  200. return float_vector_compare(comp_ctx, func_ctx, cond, V128_f64x2_TYPE,
  201. V128_i64x2_TYPE);
  202. }