jit_emit_compare.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "jit_emit_compare.h"
  6. #include "jit_emit_function.h"
  7. #include "../jit_frontend.h"
  8. #include "../jit_codegen.h"
  9. static bool
  10. jit_compile_op_compare_integer(JitCompContext *cc, IntCond cond, bool is64Bit)
  11. {
  12. JitReg lhs, rhs, res, const_zero, const_one;
  13. if (cond < INT_EQZ || cond > INT_GE_U) {
  14. jit_set_last_error(cc, "unsupported comparation operation");
  15. goto fail;
  16. }
  17. res = jit_cc_new_reg_I32(cc);
  18. const_zero = NEW_CONST(I32, 0);
  19. const_one = NEW_CONST(I32, 1);
  20. if (is64Bit) {
  21. if (INT_EQZ == cond) {
  22. rhs = NEW_CONST(I64, 0);
  23. }
  24. else {
  25. POP_I64(rhs);
  26. }
  27. POP_I64(lhs);
  28. }
  29. else {
  30. if (INT_EQZ == cond) {
  31. rhs = NEW_CONST(I32, 0);
  32. }
  33. else {
  34. POP_I32(rhs);
  35. }
  36. POP_I32(lhs);
  37. }
  38. GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
  39. switch (cond) {
  40. case INT_EQ:
  41. case INT_EQZ:
  42. {
  43. GEN_INSN(SELECTEQ, res, cc->cmp_reg, const_one, const_zero);
  44. break;
  45. }
  46. case INT_NE:
  47. {
  48. GEN_INSN(SELECTNE, res, cc->cmp_reg, const_one, const_zero);
  49. break;
  50. }
  51. case INT_LT_S:
  52. {
  53. GEN_INSN(SELECTLTS, res, cc->cmp_reg, const_one, const_zero);
  54. break;
  55. }
  56. case INT_LT_U:
  57. {
  58. GEN_INSN(SELECTLTU, res, cc->cmp_reg, const_one, const_zero);
  59. break;
  60. }
  61. case INT_GT_S:
  62. {
  63. GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
  64. break;
  65. }
  66. case INT_GT_U:
  67. {
  68. GEN_INSN(SELECTGTU, res, cc->cmp_reg, const_one, const_zero);
  69. break;
  70. }
  71. case INT_LE_S:
  72. {
  73. GEN_INSN(SELECTLES, res, cc->cmp_reg, const_one, const_zero);
  74. break;
  75. }
  76. case INT_LE_U:
  77. {
  78. GEN_INSN(SELECTLEU, res, cc->cmp_reg, const_one, const_zero);
  79. break;
  80. }
  81. case INT_GE_S:
  82. {
  83. GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
  84. break;
  85. }
  86. default: /* INT_GE_U */
  87. {
  88. GEN_INSN(SELECTGEU, res, cc->cmp_reg, const_one, const_zero);
  89. break;
  90. }
  91. }
  92. PUSH_I32(res);
  93. return true;
  94. fail:
  95. return false;
  96. }
  97. bool
  98. jit_compile_op_i32_compare(JitCompContext *cc, IntCond cond)
  99. {
  100. return jit_compile_op_compare_integer(cc, cond, false);
  101. }
  102. bool
  103. jit_compile_op_i64_compare(JitCompContext *cc, IntCond cond)
  104. {
  105. return jit_compile_op_compare_integer(cc, cond, true);
  106. }
  107. static int32
  108. float_cmp_eq(float f1, float f2)
  109. {
  110. if (isnan(f1) || isnan(f2))
  111. return 0;
  112. return f1 == f2;
  113. }
  114. static int32
  115. float_cmp_ne(float f1, float f2)
  116. {
  117. if (isnan(f1) || isnan(f2))
  118. return 1;
  119. return f1 != f2;
  120. }
  121. static int32
  122. double_cmp_eq(double d1, double d2)
  123. {
  124. if (isnan(d1) || isnan(d2))
  125. return 0;
  126. return d1 == d2;
  127. }
  128. static int32
  129. double_cmp_ne(double d1, double d2)
  130. {
  131. if (isnan(d1) || isnan(d2))
  132. return 1;
  133. return d1 != d2;
  134. }
  135. static bool
  136. jit_compile_op_compare_float_point(JitCompContext *cc, FloatCond cond,
  137. JitReg lhs, JitReg rhs)
  138. {
  139. JitReg res, args[2], const_zero, const_one;
  140. JitRegKind kind;
  141. void *func;
  142. if (cond == FLOAT_EQ || cond == FLOAT_NE) {
  143. kind = jit_reg_kind(lhs);
  144. if (cond == FLOAT_EQ)
  145. func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_eq
  146. : (void *)double_cmp_eq;
  147. else
  148. func = (kind == JIT_REG_KIND_F32) ? (void *)float_cmp_ne
  149. : (void *)double_cmp_ne;
  150. res = jit_cc_new_reg_I32(cc);
  151. args[0] = lhs;
  152. args[1] = rhs;
  153. if (!jit_emit_callnative(cc, func, res, args, 2)) {
  154. goto fail;
  155. }
  156. }
  157. else {
  158. res = jit_cc_new_reg_I32(cc);
  159. const_zero = NEW_CONST(I32, 0);
  160. const_one = NEW_CONST(I32, 1);
  161. switch (cond) {
  162. case FLOAT_LT:
  163. {
  164. GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
  165. GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
  166. break;
  167. }
  168. case FLOAT_GT:
  169. {
  170. GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
  171. GEN_INSN(SELECTGTS, res, cc->cmp_reg, const_one, const_zero);
  172. break;
  173. }
  174. case FLOAT_LE:
  175. {
  176. GEN_INSN(CMP, cc->cmp_reg, rhs, lhs);
  177. GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
  178. break;
  179. }
  180. case FLOAT_GE:
  181. {
  182. GEN_INSN(CMP, cc->cmp_reg, lhs, rhs);
  183. GEN_INSN(SELECTGES, res, cc->cmp_reg, const_one, const_zero);
  184. break;
  185. }
  186. default:
  187. {
  188. bh_assert(!"unknown FloatCond");
  189. goto fail;
  190. }
  191. }
  192. }
  193. PUSH_I32(res);
  194. return true;
  195. fail:
  196. return false;
  197. }
  198. bool
  199. jit_compile_op_f32_compare(JitCompContext *cc, FloatCond cond)
  200. {
  201. JitReg res, const_zero, const_one;
  202. JitReg lhs, rhs;
  203. POP_F32(rhs);
  204. POP_F32(lhs);
  205. if (jit_reg_is_const(lhs) && jit_reg_is_const(rhs)) {
  206. float32 lvalue = jit_cc_get_const_F32(cc, lhs);
  207. float32 rvalue = jit_cc_get_const_F32(cc, rhs);
  208. const_zero = NEW_CONST(I32, 0);
  209. const_one = NEW_CONST(I32, 1);
  210. switch (cond) {
  211. case FLOAT_EQ:
  212. {
  213. res = (lvalue == rvalue) ? const_one : const_zero;
  214. break;
  215. }
  216. case FLOAT_NE:
  217. {
  218. res = (lvalue != rvalue) ? const_one : const_zero;
  219. break;
  220. }
  221. case FLOAT_LT:
  222. {
  223. res = (lvalue < rvalue) ? const_one : const_zero;
  224. break;
  225. }
  226. case FLOAT_GT:
  227. {
  228. res = (lvalue > rvalue) ? const_one : const_zero;
  229. break;
  230. }
  231. case FLOAT_LE:
  232. {
  233. res = (lvalue <= rvalue) ? const_one : const_zero;
  234. break;
  235. }
  236. case FLOAT_GE:
  237. {
  238. res = (lvalue >= rvalue) ? const_one : const_zero;
  239. break;
  240. }
  241. default:
  242. {
  243. bh_assert(!"unknown FloatCond");
  244. goto fail;
  245. }
  246. }
  247. PUSH_I32(res);
  248. return true;
  249. }
  250. return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
  251. fail:
  252. return false;
  253. }
  254. bool
  255. jit_compile_op_f64_compare(JitCompContext *cc, FloatCond cond)
  256. {
  257. JitReg res, const_zero, const_one;
  258. JitReg lhs, rhs;
  259. POP_F64(rhs);
  260. POP_F64(lhs);
  261. if (jit_reg_is_const(lhs) && jit_reg_is_const(rhs)) {
  262. float64 lvalue = jit_cc_get_const_F64(cc, lhs);
  263. float64 rvalue = jit_cc_get_const_F64(cc, rhs);
  264. const_zero = NEW_CONST(I32, 0);
  265. const_one = NEW_CONST(I32, 1);
  266. switch (cond) {
  267. case FLOAT_EQ:
  268. {
  269. res = (lvalue == rvalue) ? const_one : const_zero;
  270. break;
  271. }
  272. case FLOAT_NE:
  273. {
  274. res = (lvalue != rvalue) ? const_one : const_zero;
  275. break;
  276. }
  277. case FLOAT_LT:
  278. {
  279. res = (lvalue < rvalue) ? const_one : const_zero;
  280. break;
  281. }
  282. case FLOAT_GT:
  283. {
  284. res = (lvalue > rvalue) ? const_one : const_zero;
  285. break;
  286. }
  287. case FLOAT_LE:
  288. {
  289. res = (lvalue <= rvalue) ? const_one : const_zero;
  290. break;
  291. }
  292. case FLOAT_GE:
  293. {
  294. res = (lvalue >= rvalue) ? const_one : const_zero;
  295. break;
  296. }
  297. default:
  298. {
  299. bh_assert(!"unknown FloatCond");
  300. goto fail;
  301. }
  302. }
  303. PUSH_I32(res);
  304. return true;
  305. }
  306. return jit_compile_op_compare_float_point(cc, cond, lhs, rhs);
  307. fail:
  308. return false;
  309. }