aot_intrinsic.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. /*
  2. * Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_intrinsic.h"
  6. float32
  7. aot_intrinsic_fadd_f32(float32 a, float32 b)
  8. {
  9. return a + b;
  10. }
  11. float64
  12. aot_intrinsic_fadd_f64(float64 a, float64 b)
  13. {
  14. return a + b;
  15. }
  16. float32
  17. aot_intrinsic_fsub_f32(float32 a, float32 b)
  18. {
  19. return a - b;
  20. }
  21. float64
  22. aot_intrinsic_fsub_f64(float64 a, float64 b)
  23. {
  24. return a - b;
  25. }
  26. float32
  27. aot_intrinsic_fmul_f32(float32 a, float32 b)
  28. {
  29. return a * b;
  30. }
  31. float64
  32. aot_intrinsic_fmul_f64(float64 a, float64 b)
  33. {
  34. return a * b;
  35. }
  36. float32
  37. aot_intrinsic_fdiv_f32(float32 a, float32 b)
  38. {
  39. return a / b;
  40. }
  41. float64
  42. aot_intrinsic_fdiv_f64(float64 a, float64 b)
  43. {
  44. return a / b;
  45. }
  46. float32
  47. aot_intrinsic_fabs_f32(float32 a)
  48. {
  49. return fabsf(a);
  50. }
  51. float64
  52. aot_intrinsic_fabs_f64(float64 a)
  53. {
  54. return fabs(a);
  55. }
  56. float32
  57. aot_intrinsic_ceil_f32(float32 a)
  58. {
  59. return ceilf(a);
  60. }
  61. float64
  62. aot_intrinsic_ceil_f64(float64 a)
  63. {
  64. return ceil(a);
  65. }
  66. float32
  67. aot_intrinsic_floor_f32(float32 a)
  68. {
  69. return floorf(a);
  70. }
  71. float64
  72. aot_intrinsic_floor_f64(float64 a)
  73. {
  74. return floor(a);
  75. }
  76. float32
  77. aot_intrinsic_trunc_f32(float32 a)
  78. {
  79. return truncf(a);
  80. }
  81. float64
  82. aot_intrinsic_trunc_f64(float64 a)
  83. {
  84. return trunc(a);
  85. }
  86. float32
  87. aot_intrinsic_rint_f32(float32 a)
  88. {
  89. return rintf(a);
  90. }
  91. float64
  92. aot_intrinsic_rint_f64(float64 a)
  93. {
  94. return rint(a);
  95. }
  96. float32
  97. aot_intrinsic_sqrt_f32(float32 a)
  98. {
  99. return sqrtf(a);
  100. }
  101. float64
  102. aot_intrinsic_sqrt_f64(float64 a)
  103. {
  104. return sqrt(a);
  105. }
  106. float32
  107. aot_intrinsic_copysign_f32(float32 a, float32 b)
  108. {
  109. return signbit(b) ? -fabsf(a) : fabsf(a);
  110. }
  111. float64
  112. aot_intrinsic_copysign_f64(float64 a, float64 b)
  113. {
  114. return signbit(b) ? -fabs(a) : fabs(a);
  115. }
  116. float32
  117. aot_intrinsic_fmin_f32(float32 a, float32 b)
  118. {
  119. if (isnan(a) || isnan(b))
  120. return NAN;
  121. else if (a == 0 && a == b)
  122. return signbit(a) ? a : b;
  123. else
  124. return a > b ? b : a;
  125. }
  126. float64
  127. aot_intrinsic_fmin_f64(float64 a, float64 b)
  128. {
  129. if (isnan(a) || isnan(b))
  130. return NAN;
  131. else if (a == 0 && a == b)
  132. return signbit(a) ? a : b;
  133. else
  134. return a > b ? b : a;
  135. }
  136. float32
  137. aot_intrinsic_fmax_f32(float32 a, float32 b)
  138. {
  139. if (isnan(a) || isnan(b))
  140. return NAN;
  141. else if (a == 0 && a == b)
  142. return signbit(a) ? b : a;
  143. else
  144. return a > b ? a : b;
  145. }
  146. float64
  147. aot_intrinsic_fmax_f64(float64 a, float64 b)
  148. {
  149. if (isnan(a) || isnan(b))
  150. return NAN;
  151. else if (a == 0 && a == b)
  152. return signbit(a) ? b : a;
  153. else
  154. return a > b ? a : b;
  155. }
  156. uint32
  157. aot_intrinsic_clz_i32(uint32 type)
  158. {
  159. uint32 num = 0;
  160. if (type == 0)
  161. return 32;
  162. while (!(type & 0x80000000)) {
  163. num++;
  164. type <<= 1;
  165. }
  166. return num;
  167. }
  168. uint32
  169. aot_intrinsic_clz_i64(uint64 type)
  170. {
  171. uint32 num = 0;
  172. if (type == 0)
  173. return 64;
  174. while (!(type & 0x8000000000000000LL)) {
  175. num++;
  176. type <<= 1;
  177. }
  178. return num;
  179. }
  180. uint32
  181. aot_intrinsic_ctz_i32(uint32 type)
  182. {
  183. uint32 num = 0;
  184. if (type == 0)
  185. return 32;
  186. while (!(type & 1)) {
  187. num++;
  188. type >>= 1;
  189. }
  190. return num;
  191. }
  192. uint32
  193. aot_intrinsic_ctz_i64(uint64 type)
  194. {
  195. uint32 num = 0;
  196. if (type == 0)
  197. return 64;
  198. while (!(type & 1)) {
  199. num++;
  200. type >>= 1;
  201. }
  202. return num;
  203. }
  204. uint32
  205. aot_intrinsic_popcnt_i32(uint32 u)
  206. {
  207. uint32 ret = 0;
  208. while (u) {
  209. u = (u & (u - 1));
  210. ret++;
  211. }
  212. return ret;
  213. }
  214. uint32
  215. aot_intrinsic_popcnt_i64(uint64 u)
  216. {
  217. uint32 ret = 0;
  218. while (u) {
  219. u = (u & (u - 1));
  220. ret++;
  221. }
  222. return ret;
  223. }
  224. float32
  225. aot_intrinsic_i32_to_f32(int32 i)
  226. {
  227. return (float32)i;
  228. }
  229. float32
  230. aot_intrinsic_u32_to_f32(uint32 u)
  231. {
  232. return (float32)u;
  233. }
  234. float64
  235. aot_intrinsic_i32_to_f64(int32 i)
  236. {
  237. return (float64)i;
  238. }
  239. float64
  240. aot_intrinsic_u32_to_f64(uint32 u)
  241. {
  242. return (float64)u;
  243. }
  244. float32
  245. aot_intrinsic_i64_to_f32(int64 i)
  246. {
  247. return (float32)i;
  248. }
  249. float32
  250. aot_intrinsic_u64_to_f32(uint64 u)
  251. {
  252. return (float32)u;
  253. }
  254. float64
  255. aot_intrinsic_i64_to_f64(int64 i)
  256. {
  257. return (float64)i;
  258. }
  259. float64
  260. aot_intrinsic_u64_to_f64(uint64 u)
  261. {
  262. return (float64)u;
  263. }
  264. int32
  265. aot_intrinsic_f32_to_i32(float32 f)
  266. {
  267. return (int32)f;
  268. }
  269. uint32
  270. aot_intrinsic_f32_to_u32(float32 f)
  271. {
  272. return (uint32)f;
  273. }
  274. int64
  275. aot_intrinsic_f32_to_i64(float32 f)
  276. {
  277. return (int64)f;
  278. }
  279. uint64
  280. aot_intrinsic_f32_to_u64(float32 f)
  281. {
  282. return (uint64)f;
  283. }
  284. int32
  285. aot_intrinsic_f64_to_i32(float64 f)
  286. {
  287. return (int32)f;
  288. }
  289. uint32
  290. aot_intrinsic_f64_to_u32(float64 f)
  291. {
  292. return (uint32)f;
  293. }
  294. int64
  295. aot_intrinsic_f64_to_i64(float64 f)
  296. {
  297. return (int64)f;
  298. }
  299. uint64
  300. aot_intrinsic_f64_to_u64(float64 f)
  301. {
  302. return (uint64)f;
  303. }
  304. float64
  305. aot_intrinsic_f32_to_f64(float32 f)
  306. {
  307. return (float64)f;
  308. }
  309. float32
  310. aot_intrinsic_f64_to_f32(float64 f)
  311. {
  312. return (float32)f;
  313. }
  314. int32
  315. aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs)
  316. {
  317. switch (cond) {
  318. case FLOAT_EQ:
  319. return lhs == rhs ? 1 : 0;
  320. case FLOAT_LT:
  321. return lhs < rhs ? 1 : 0;
  322. case FLOAT_GT:
  323. return lhs > rhs ? 1 : 0;
  324. case FLOAT_LE:
  325. return lhs <= rhs ? 1 : 0;
  326. case FLOAT_GE:
  327. return lhs >= rhs ? 1 : 0;
  328. case FLOAT_NE:
  329. return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
  330. case FLOAT_UNO:
  331. return (isnan(lhs) || isnan(rhs)) ? 1 : 0;
  332. default:
  333. break;
  334. }
  335. return 0;
  336. }
  337. int32
  338. aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs)
  339. {
  340. switch (cond) {
  341. case FLOAT_EQ:
  342. return lhs == rhs ? 1 : 0;
  343. case FLOAT_LT:
  344. return lhs < rhs ? 1 : 0;
  345. case FLOAT_GT:
  346. return lhs > rhs ? 1 : 0;
  347. case FLOAT_LE:
  348. return lhs <= rhs ? 1 : 0;
  349. case FLOAT_GE:
  350. return lhs >= rhs ? 1 : 0;
  351. case FLOAT_NE:
  352. return (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
  353. case FLOAT_UNO:
  354. return (isnan(lhs) || isnan(rhs)) ? 1 : 0;
  355. default:
  356. break;
  357. }
  358. return 0;
  359. }
  360. int64
  361. aot_intrinsic_i64_div_s(int64 l, int64 r)
  362. {
  363. return l / r;
  364. }
  365. int32
  366. aot_intrinsic_i32_div_s(int32 l, int32 r)
  367. {
  368. return l / r;
  369. }
  370. uint32
  371. aot_intrinsic_i32_div_u(uint32 l, uint32 r)
  372. {
  373. return l / r;
  374. }
  375. int32
  376. aot_intrinsic_i32_rem_s(int32 l, int32 r)
  377. {
  378. return l % r;
  379. }
  380. uint32
  381. aot_intrinsic_i32_rem_u(uint32 l, uint32 r)
  382. {
  383. return l % r;
  384. }
  385. uint64
  386. aot_intrinsic_i64_div_u(uint64 l, uint64 r)
  387. {
  388. return l / r;
  389. }
  390. int64
  391. aot_intrinsic_i64_rem_s(int64 l, int64 r)
  392. {
  393. return l % r;
  394. }
  395. uint64
  396. aot_intrinsic_i64_rem_u(uint64 l, uint64 r)
  397. {
  398. return l % r;
  399. }
  400. uint64
  401. aot_intrinsic_i64_bit_or(uint64 l, uint64 r)
  402. {
  403. return l | r;
  404. }
  405. uint64
  406. aot_intrinsic_i64_bit_and(uint64 l, uint64 r)
  407. {
  408. return l & r;
  409. }
  410. #if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
  411. typedef struct {
  412. const char *llvm_intrinsic;
  413. const char *native_intrinsic;
  414. uint64 flag;
  415. } aot_intrinsic;
  416. /* clang-format off */
  417. static const aot_intrinsic g_intrinsic_mapping[] = {
  418. { "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD },
  419. { "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD },
  420. { "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB },
  421. { "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB },
  422. { "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL },
  423. { "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL },
  424. { "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV },
  425. { "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV },
  426. { "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS },
  427. { "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS },
  428. { "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL },
  429. { "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL },
  430. { "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR },
  431. { "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR },
  432. { "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC },
  433. { "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC },
  434. { "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT },
  435. { "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT },
  436. { "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT },
  437. { "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT },
  438. { "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN },
  439. { "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN },
  440. { "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN },
  441. { "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN },
  442. { "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX },
  443. { "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX },
  444. { "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ },
  445. { "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ },
  446. { "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ },
  447. { "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ },
  448. { "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT },
  449. { "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT },
  450. { "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
  451. { "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 },
  452. { "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 },
  453. { "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 },
  454. { "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
  455. { "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 },
  456. { "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 },
  457. { "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 },
  458. { "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 },
  459. { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 },
  460. { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 },
  461. { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 },
  462. { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 },
  463. { "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 },
  464. { "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 },
  465. { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 },
  466. { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 },
  467. { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 },
  468. { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP },
  469. { "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP },
  470. { "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST },
  471. { "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST },
  472. { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST },
  473. { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST },
  474. { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S},
  475. { "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S},
  476. { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U},
  477. { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S},
  478. { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U},
  479. { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U},
  480. { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S},
  481. { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U},
  482. { "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR},
  483. { "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND},
  484. };
  485. /* clang-format on */
  486. static const uint32 g_intrinsic_count =
  487. sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic);
  488. const char *
  489. aot_intrinsic_get_symbol(const char *llvm_intrinsic)
  490. {
  491. uint32 cnt;
  492. for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
  493. if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
  494. return g_intrinsic_mapping[cnt].native_intrinsic;
  495. }
  496. }
  497. return NULL;
  498. }
  499. static void
  500. add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag)
  501. {
  502. uint64 group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
  503. if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
  504. comp_ctx->flags[group] |= flag;
  505. }
  506. else {
  507. bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
  508. "intrinsic exceeds max limit.");
  509. }
  510. }
  511. static void
  512. add_i64_common_intrinsics(AOTCompContext *comp_ctx)
  513. {
  514. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_S);
  515. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_U);
  516. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_S);
  517. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_U);
  518. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_OR);
  519. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_AND);
  520. }
  521. static void
  522. add_i32_common_intrinsics(AOTCompContext *comp_ctx)
  523. {
  524. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_S);
  525. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U);
  526. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S);
  527. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U);
  528. }
  529. static void
  530. add_f32_common_intrinsics(AOTCompContext *comp_ctx)
  531. {
  532. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FABS);
  533. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FADD);
  534. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FSUB);
  535. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FMUL);
  536. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FDIV);
  537. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_SQRT);
  538. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CMP);
  539. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_MIN);
  540. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_MAX);
  541. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CEIL);
  542. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FLOOR);
  543. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TRUNC);
  544. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_RINT);
  545. }
  546. static void
  547. add_f64_common_intrinsics(AOTCompContext *comp_ctx)
  548. {
  549. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FABS);
  550. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FADD);
  551. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FSUB);
  552. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FMUL);
  553. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MIN);
  554. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_MAX);
  555. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CEIL);
  556. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FLOOR);
  557. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TRUNC);
  558. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_RINT);
  559. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FDIV);
  560. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_SQRT);
  561. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CMP);
  562. }
  563. static void
  564. add_f32xi32_intrinsics(AOTCompContext *comp_ctx)
  565. {
  566. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32);
  567. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32);
  568. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32);
  569. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32);
  570. }
  571. static void
  572. add_f64xi32_intrinsics(AOTCompContext *comp_ctx)
  573. {
  574. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32);
  575. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32);
  576. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64);
  577. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64);
  578. }
  579. static void
  580. add_f32xi64_intrinsics(AOTCompContext *comp_ctx)
  581. {
  582. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64);
  583. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64);
  584. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32);
  585. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32);
  586. }
  587. static void
  588. add_f64xi64_intrinsics(AOTCompContext *comp_ctx)
  589. {
  590. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64);
  591. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64);
  592. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64);
  593. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64);
  594. }
  595. static void
  596. add_common_float_integer_conversion(AOTCompContext *comp_ctx)
  597. {
  598. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F32);
  599. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F32);
  600. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_TO_F64);
  601. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U32_TO_F64);
  602. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F32);
  603. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F32);
  604. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_TO_F64);
  605. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_U64_TO_F64);
  606. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I32);
  607. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U32);
  608. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_I64);
  609. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_U64);
  610. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I32);
  611. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U32);
  612. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_I64);
  613. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_U64);
  614. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_TO_F32);
  615. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_TO_F64);
  616. }
  617. bool
  618. aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
  619. const char *llvm_intrinsic)
  620. {
  621. uint32 cnt;
  622. uint64 flag;
  623. uint64 group;
  624. for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
  625. if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
  626. flag = g_intrinsic_mapping[cnt].flag;
  627. group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
  628. flag &= AOT_INTRINSIC_FLAG_MASK;
  629. if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
  630. if (comp_ctx->flags[group] & flag) {
  631. return true;
  632. }
  633. }
  634. else {
  635. bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
  636. "intrinsic exceeds max limit.");
  637. }
  638. }
  639. }
  640. return false;
  641. }
  642. void
  643. aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
  644. {
  645. uint32 i;
  646. memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
  647. /* Intrinsics from command line have highest priority */
  648. if (comp_ctx->builtin_intrinsics) {
  649. /* Handle 'all' group */
  650. if (strstr(comp_ctx->builtin_intrinsics, "all")) {
  651. for (i = 0; i < g_intrinsic_count; i++) {
  652. add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag);
  653. }
  654. return;
  655. }
  656. /* Handle 'i32.common' group */
  657. if (strstr(comp_ctx->builtin_intrinsics, "i32.common")) {
  658. add_i32_common_intrinsics(comp_ctx);
  659. }
  660. /* Handle 'i64.common' group */
  661. if (strstr(comp_ctx->builtin_intrinsics, "i64.common")) {
  662. add_i64_common_intrinsics(comp_ctx);
  663. }
  664. /* Handle 'fp.common' group */
  665. if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) {
  666. add_f32_common_intrinsics(comp_ctx);
  667. add_f64_common_intrinsics(comp_ctx);
  668. }
  669. /* Handle 'f32.common' group */
  670. if (strstr(comp_ctx->builtin_intrinsics, "f32.common")) {
  671. add_f32_common_intrinsics(comp_ctx);
  672. }
  673. /* Handle 'f64.common' group */
  674. if (strstr(comp_ctx->builtin_intrinsics, "f64.common")) {
  675. add_f64_common_intrinsics(comp_ctx);
  676. }
  677. /* Handle 'f32xi32' group */
  678. if (strstr(comp_ctx->builtin_intrinsics, "f32xi32")) {
  679. add_f32xi32_intrinsics(comp_ctx);
  680. }
  681. /* Handle 'f64xi32' group */
  682. if (strstr(comp_ctx->builtin_intrinsics, "f64xi32")) {
  683. add_f64xi32_intrinsics(comp_ctx);
  684. }
  685. /* Handle 'f32xi64' group */
  686. if (strstr(comp_ctx->builtin_intrinsics, "f32xi64")) {
  687. add_f32xi64_intrinsics(comp_ctx);
  688. }
  689. /* Handle 'f64xi64' group */
  690. if (strstr(comp_ctx->builtin_intrinsics, "f64xi64")) {
  691. add_f64xi64_intrinsics(comp_ctx);
  692. }
  693. /* Handle 'fpxint' group */
  694. if (strstr(comp_ctx->builtin_intrinsics, "fpxint")) {
  695. add_f32xi32_intrinsics(comp_ctx);
  696. add_f64xi32_intrinsics(comp_ctx);
  697. add_f32xi64_intrinsics(comp_ctx);
  698. add_f64xi64_intrinsics(comp_ctx);
  699. }
  700. /* Handle 'constop' group */
  701. if (strstr(comp_ctx->builtin_intrinsics, "constop")) {
  702. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
  703. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST);
  704. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
  705. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
  706. }
  707. /* Handle 'fp.common' group */
  708. if (strstr(comp_ctx->builtin_intrinsics, "fp.common")) {
  709. add_f32_common_intrinsics(comp_ctx);
  710. add_f64_common_intrinsics(comp_ctx);
  711. }
  712. /* Handle other single items */
  713. for (i = 0; i < g_intrinsic_count; i++) {
  714. if (strstr(comp_ctx->builtin_intrinsics,
  715. g_intrinsic_mapping[i].llvm_intrinsic)) {
  716. add_intrinsic_capability(comp_ctx, g_intrinsic_mapping[i].flag);
  717. }
  718. }
  719. return;
  720. }
  721. if (!comp_ctx->target_cpu)
  722. return;
  723. if (!strncmp(comp_ctx->target_arch, "thumb", 5)) {
  724. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
  725. add_i32_common_intrinsics(comp_ctx);
  726. if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) {
  727. }
  728. else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) {
  729. add_f64_common_intrinsics(comp_ctx);
  730. }
  731. else {
  732. add_f32_common_intrinsics(comp_ctx);
  733. add_f64_common_intrinsics(comp_ctx);
  734. add_i64_common_intrinsics(comp_ctx);
  735. add_common_float_integer_conversion(comp_ctx);
  736. }
  737. }
  738. else if (!strncmp(comp_ctx->target_arch, "riscv", 5)) {
  739. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
  740. /*
  741. * Note: Use builtin intrinsics since hardware float operation
  742. * will cause rodata relocation
  743. */
  744. add_f32_common_intrinsics(comp_ctx);
  745. add_f64_common_intrinsics(comp_ctx);
  746. add_common_float_integer_conversion(comp_ctx);
  747. if (!strncmp(comp_ctx->target_arch, "riscv32", 7)) {
  748. add_i64_common_intrinsics(comp_ctx);
  749. }
  750. }
  751. else if (!strncmp(comp_ctx->target_arch, "xtensa", 6)) {
  752. /*
  753. * Note: Use builtin intrinsics since hardware float operation
  754. * will cause rodata relocation
  755. */
  756. add_f32_common_intrinsics(comp_ctx);
  757. add_i32_common_intrinsics(comp_ctx);
  758. add_f64_common_intrinsics(comp_ctx);
  759. add_i64_common_intrinsics(comp_ctx);
  760. add_common_float_integer_conversion(comp_ctx);
  761. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
  762. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
  763. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_CONST);
  764. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_CONST);
  765. }
  766. else {
  767. /*
  768. * Use constant value table by default
  769. */
  770. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_CONST);
  771. add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_CONST);
  772. }
  773. }
  774. #endif /* WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */