simd_comparisons.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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,
  84. AOTFuncContext *func_ctx,
  85. IntCond cond,
  86. LLVMTypeRef vector_type)
  87. {
  88. LLVMValueRef vec1, vec2, result;
  89. LLVMIntPredicate int_pred;
  90. if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  91. "vec2"))) {
  92. goto fail;
  93. }
  94. if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  95. "vec1"))) {
  96. goto fail;
  97. }
  98. if (!int_cond_2_predicate(cond, &int_pred)) {
  99. HANDLE_FAILURE("int_cond_2_predicate");
  100. goto fail;
  101. }
  102. /* icmp <N x iX> %vec1, %vec2 */
  103. if (!(result =
  104. LLVMBuildICmp(comp_ctx->builder, int_pred, vec1, vec2, "cmp"))) {
  105. HANDLE_FAILURE("LLVMBuildICmp");
  106. goto fail;
  107. }
  108. /* sext <N x i1> %result to <N x iX> */
  109. if (!(result =
  110. LLVMBuildSExt(comp_ctx->builder, result, vector_type, "ext"))) {
  111. HANDLE_FAILURE("LLVMBuildSExt");
  112. goto fail;
  113. }
  114. /* bitcast <N x iX> %result to <2 x i64> */
  115. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  116. "result"))) {
  117. HANDLE_FAILURE("LLVMBuildBitCast");
  118. goto fail;
  119. }
  120. PUSH_V128(result);
  121. return true;
  122. fail:
  123. return false;
  124. }
  125. bool
  126. aot_compile_simd_i8x16_compare(AOTCompContext *comp_ctx,
  127. AOTFuncContext *func_ctx,
  128. IntCond cond)
  129. {
  130. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i8x16_TYPE);
  131. }
  132. bool
  133. aot_compile_simd_i16x8_compare(AOTCompContext *comp_ctx,
  134. AOTFuncContext *func_ctx,
  135. IntCond cond)
  136. {
  137. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i16x8_TYPE);
  138. }
  139. bool
  140. aot_compile_simd_i32x4_compare(AOTCompContext *comp_ctx,
  141. AOTFuncContext *func_ctx,
  142. IntCond cond)
  143. {
  144. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i32x4_TYPE);
  145. }
  146. bool
  147. aot_compile_simd_i64x2_compare(AOTCompContext *comp_ctx,
  148. AOTFuncContext *func_ctx,
  149. IntCond cond)
  150. {
  151. return interger_vector_compare(comp_ctx, func_ctx, cond, V128_i64x2_TYPE);
  152. }
  153. static bool
  154. float_vector_compare(AOTCompContext *comp_ctx,
  155. AOTFuncContext *func_ctx,
  156. FloatCond cond,
  157. LLVMTypeRef vector_type,
  158. LLVMTypeRef result_type)
  159. {
  160. LLVMValueRef vec1, vec2, result;
  161. LLVMRealPredicate real_pred;
  162. if (!(vec2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  163. "vec2"))) {
  164. goto fail;
  165. }
  166. if (!(vec1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
  167. "vec1"))) {
  168. goto fail;
  169. }
  170. if (!float_cond_2_predicate(cond, &real_pred)) {
  171. HANDLE_FAILURE("float_cond_2_predicate");
  172. goto fail;
  173. }
  174. /* fcmp <N x iX> %vec1, %vec2 */
  175. if (!(result =
  176. LLVMBuildFCmp(comp_ctx->builder, real_pred, vec1, vec2, "cmp"))) {
  177. HANDLE_FAILURE("LLVMBuildFCmp");
  178. goto fail;
  179. }
  180. /* sext <N x i1> %result to <N x iX> */
  181. if (!(result =
  182. LLVMBuildSExt(comp_ctx->builder, result, result_type, "ext"))) {
  183. HANDLE_FAILURE("LLVMBuildSExt");
  184. goto fail;
  185. }
  186. /* bitcast <N x iX> %result to <2 x i64> */
  187. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  188. "result"))) {
  189. HANDLE_FAILURE("LLVMBuildBitCast");
  190. goto fail;
  191. }
  192. PUSH_V128(result);
  193. return true;
  194. fail:
  195. return false;
  196. }
  197. bool
  198. aot_compile_simd_f32x4_compare(AOTCompContext *comp_ctx,
  199. AOTFuncContext *func_ctx,
  200. FloatCond cond)
  201. {
  202. return float_vector_compare(comp_ctx, func_ctx, cond, V128_f32x4_TYPE,
  203. V128_i32x4_TYPE);
  204. }
  205. bool
  206. aot_compile_simd_f64x2_compare(AOTCompContext *comp_ctx,
  207. AOTFuncContext *func_ctx,
  208. FloatCond cond)
  209. {
  210. return float_vector_compare(comp_ctx, func_ctx, cond, V128_f64x2_TYPE,
  211. V128_i64x2_TYPE);
  212. }