simd_conversions.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "simd_conversions.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 bool
  11. is_target_x86(AOTCompContext *comp_ctx)
  12. {
  13. return !strncmp(comp_ctx->target_arch, "x86_64", 6) ||
  14. !strncmp(comp_ctx->target_arch, "i386", 4);
  15. }
  16. static bool
  17. simd_integer_narrow(AOTCompContext *comp_ctx,
  18. AOTFuncContext *func_ctx,
  19. bool is_signed,
  20. LLVMTypeRef in_vector_type,
  21. LLVMTypeRef out_vector_type,
  22. const char *instrinsic)
  23. {
  24. LLVMValueRef vector1, vector2, result;
  25. LLVMTypeRef param_types[2] = { in_vector_type, in_vector_type };
  26. if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  27. in_vector_type, "vec2"))) {
  28. goto fail;
  29. }
  30. if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  31. in_vector_type, "vec1"))) {
  32. goto fail;
  33. }
  34. if (!(result =
  35. aot_call_llvm_intrinsic(comp_ctx, instrinsic, out_vector_type,
  36. param_types, 2, vector1, vector2))) {
  37. HANDLE_FAILURE("LLVMBuildCall");
  38. goto fail;
  39. }
  40. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  41. "ret"))) {
  42. HANDLE_FAILURE("LLVMBuildBitCast");
  43. goto fail;
  44. }
  45. PUSH_V128(result);
  46. return true;
  47. fail:
  48. return false;
  49. }
  50. static LLVMValueRef
  51. build_intx4_vector(const AOTCompContext *comp_ctx,
  52. const LLVMTypeRef element_type,
  53. const int *element_value)
  54. {
  55. LLVMValueRef vector, elements[4];
  56. unsigned i;
  57. for (i = 0; i < 4; i++) {
  58. if (!(elements[i] =
  59. LLVMConstInt(element_type, element_value[i], true))) {
  60. HANDLE_FAILURE("LLVMConstInst");
  61. goto fail;
  62. }
  63. }
  64. if (!(vector = LLVMConstVector(elements, 4))) {
  65. HANDLE_FAILURE("LLVMConstVector");
  66. goto fail;
  67. }
  68. return vector;
  69. fail:
  70. return NULL;
  71. }
  72. static LLVMValueRef
  73. build_intx8_vector(const AOTCompContext *comp_ctx,
  74. const LLVMTypeRef element_type,
  75. const int *element_value)
  76. {
  77. LLVMValueRef vector, elements[8];
  78. unsigned i;
  79. for (i = 0; i < 8; i++) {
  80. if (!(elements[i] =
  81. LLVMConstInt(element_type, element_value[i], true))) {
  82. HANDLE_FAILURE("LLVMConstInst");
  83. goto fail;
  84. }
  85. }
  86. if (!(vector = LLVMConstVector(elements, 8))) {
  87. HANDLE_FAILURE("LLVMConstVector");
  88. goto fail;
  89. }
  90. return vector;
  91. fail:
  92. return NULL;
  93. }
  94. static LLVMValueRef
  95. build_intx16_vector(const AOTCompContext *comp_ctx,
  96. const LLVMTypeRef element_type,
  97. const int *element_value)
  98. {
  99. LLVMValueRef vector, elements[16];
  100. unsigned i;
  101. for (i = 0; i < 16; i++) {
  102. if (!(elements[i] =
  103. LLVMConstInt(element_type, element_value[i], true))) {
  104. HANDLE_FAILURE("LLVMConstInst");
  105. goto fail;
  106. }
  107. }
  108. if (!(vector = LLVMConstVector(elements, 16))) {
  109. HANDLE_FAILURE("LLVMConstVector");
  110. goto fail;
  111. }
  112. return vector;
  113. fail:
  114. return NULL;
  115. }
  116. bool
  117. aot_compile_simd_i8x16_narrow_i16x8_x86(AOTCompContext *comp_ctx,
  118. AOTFuncContext *func_ctx,
  119. bool is_signed)
  120. {
  121. return simd_integer_narrow(
  122. comp_ctx, func_ctx, is_signed, V128_i16x8_TYPE, V128_i8x16_TYPE,
  123. is_signed ? "llvm.x86.sse2.packsswb.128" : "llvm.x86.sse2.packuswb.128");
  124. }
  125. bool
  126. aot_compile_simd_i16x8_narrow_i32x4_x86(AOTCompContext *comp_ctx,
  127. AOTFuncContext *func_ctx,
  128. bool is_signed)
  129. {
  130. return simd_integer_narrow(
  131. comp_ctx, func_ctx, is_signed, V128_i32x4_TYPE, V128_i16x8_TYPE,
  132. is_signed ? "llvm.x86.sse2.packssdw.128" : "llvm.x86.sse41.packusdw");
  133. }
  134. static bool
  135. aot_compile_simd_i8x16_narrow_i16x8_common(AOTCompContext *comp_ctx,
  136. AOTFuncContext *func_ctx,
  137. bool is_signed)
  138. {
  139. LLVMValueRef vector1, vector2, result, vector_min, vector_max, shuffle,
  140. vector1_clamped, vector2_clamped, vector1_trunced, vector2_trunced,
  141. shuffle_vector;
  142. LLVMValueRef v1_gt_max, v1_lt_min, v2_gt_max, v2_lt_min;
  143. int min_s_array[8] = { 0xff80, 0xff80, 0xff80, 0xff80,
  144. 0xff80, 0xff80, 0xff80, 0xff80 };
  145. int max_s_array[8] = { 0x007f, 0x007f, 0x007f, 0x007f,
  146. 0x007f, 0x007f, 0x007f, 0x007f };
  147. int min_u_array[8] = { 0x0000, 0x0000, 0x0000, 0x0000,
  148. 0x0000, 0x0000, 0x0000, 0x0000 };
  149. int max_u_array[8] = { 0x00ff, 0x00ff, 0x00ff, 0x00ff,
  150. 0x00ff, 0x00ff, 0x00ff, 0x00ff };
  151. int shuffle_array[16] = { 0, 1, 2, 3, 4, 5, 6, 7,
  152. 8, 9, 10, 11, 12, 13, 14, 15 };
  153. if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  154. V128_i16x8_TYPE, "vec2"))) {
  155. goto fail;
  156. }
  157. if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  158. V128_i16x8_TYPE, "vec1"))) {
  159. goto fail;
  160. }
  161. if (!(vector_min = build_intx8_vector(
  162. comp_ctx, INT16_TYPE, is_signed ? min_s_array : min_u_array))) {
  163. goto fail;
  164. }
  165. if (!(vector_max = build_intx8_vector(
  166. comp_ctx, INT16_TYPE, is_signed ? max_s_array : max_u_array))) {
  167. goto fail;
  168. }
  169. if (!(shuffle = build_intx16_vector(comp_ctx, I32_TYPE, shuffle_array))) {
  170. goto fail;
  171. }
  172. if (!(v1_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector1,
  173. vector_max, "v1_great_than_max"))) {
  174. HANDLE_FAILURE("LLVMBuldICmp");
  175. goto fail;
  176. }
  177. if (!(v2_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector2,
  178. vector_max, "v2_great_than_max"))) {
  179. HANDLE_FAILURE("LLVMBuldICmp");
  180. goto fail;
  181. }
  182. if (!(v1_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector1,
  183. vector_min, "v1_less_than_min"))) {
  184. HANDLE_FAILURE("LLVMBuldICmp");
  185. goto fail;
  186. }
  187. if (!(v2_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector2,
  188. vector_min, "v2_less_than_min"))) {
  189. HANDLE_FAILURE("LLVMBuldICmp");
  190. goto fail;
  191. }
  192. if (!(vector1_clamped =
  193. LLVMBuildSelect(comp_ctx->builder, v1_gt_max, vector_max, vector1,
  194. "vector1_clamped_max"))) {
  195. HANDLE_FAILURE("LLVMBuildSelect");
  196. goto fail;
  197. }
  198. if (!(vector1_clamped =
  199. LLVMBuildSelect(comp_ctx->builder, v1_lt_min, vector_min,
  200. vector1_clamped, "vector1_clamped_min"))) {
  201. HANDLE_FAILURE("LLVMBuildSelect");
  202. goto fail;
  203. }
  204. if (!(vector2_clamped =
  205. LLVMBuildSelect(comp_ctx->builder, v2_gt_max, vector_max, vector2,
  206. "vector2_clamped_max"))) {
  207. HANDLE_FAILURE("LLVMBuildSelect");
  208. goto fail;
  209. }
  210. if (!(vector2_clamped =
  211. LLVMBuildSelect(comp_ctx->builder, v2_lt_min, vector_min,
  212. vector2_clamped, "vector2_clamped_min"))) {
  213. HANDLE_FAILURE("LLVMBuildSelect");
  214. goto fail;
  215. }
  216. if (!(vector1_trunced =
  217. LLVMBuildTrunc(comp_ctx->builder, vector1_clamped,
  218. LLVMVectorType(INT8_TYPE, 8), "vector1_trunced"))) {
  219. HANDLE_FAILURE("LLVMBuildTrunc");
  220. goto fail;
  221. }
  222. if (!(vector2_trunced =
  223. LLVMBuildTrunc(comp_ctx->builder, vector2_clamped,
  224. LLVMVectorType(INT8_TYPE, 8), "vector2_trunced"))) {
  225. HANDLE_FAILURE("LLVMBuildTrunc");
  226. goto fail;
  227. }
  228. if (!(shuffle_vector = LLVMBuildShuffleVector(
  229. comp_ctx->builder, vector1_trunced, vector2_trunced, shuffle,
  230. "shuffle_vector"))) {
  231. HANDLE_FAILURE("LLVMBuildShuffleVector");
  232. goto fail;
  233. }
  234. if (!(result = LLVMBuildBitCast(comp_ctx->builder, shuffle_vector,
  235. V128_i64x2_TYPE, "ret"))) {
  236. HANDLE_FAILURE("LLVMBuildBitCast");
  237. goto fail;
  238. }
  239. PUSH_V128(result);
  240. return true;
  241. fail:
  242. return false;
  243. }
  244. bool
  245. aot_compile_simd_i8x16_narrow_i16x8(AOTCompContext *comp_ctx,
  246. AOTFuncContext *func_ctx,
  247. bool is_signed)
  248. {
  249. if (is_target_x86(comp_ctx)) {
  250. return aot_compile_simd_i8x16_narrow_i16x8_x86(comp_ctx, func_ctx,
  251. is_signed);
  252. }
  253. else {
  254. return aot_compile_simd_i8x16_narrow_i16x8_common(comp_ctx, func_ctx,
  255. is_signed);
  256. }
  257. }
  258. static bool
  259. aot_compile_simd_i16x8_narrow_i32x4_common(AOTCompContext *comp_ctx,
  260. AOTFuncContext *func_ctx,
  261. bool is_signed)
  262. {
  263. LLVMValueRef vector1, vector2, result, vector_min, vector_max, shuffle,
  264. vector1_clamped, vector2_clamped, vector1_trunced, vector2_trunced,
  265. shuffle_vector;
  266. LLVMValueRef v1_gt_max, v1_lt_min, v2_gt_max, v2_lt_min;
  267. int min_s_array[4] = { 0xffff8000, 0xffff8000, 0xffff8000, 0xffff8000 };
  268. int32 max_s_array[4] = { 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff };
  269. int min_u_array[4] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
  270. int max_u_array[4] = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff };
  271. int shuffle_array[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
  272. if (!(vector2 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  273. V128_i32x4_TYPE, "vec2"))) {
  274. goto fail;
  275. }
  276. if (!(vector1 = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  277. V128_i32x4_TYPE, "vec1"))) {
  278. goto fail;
  279. }
  280. if (!(vector_min = build_intx4_vector(
  281. comp_ctx, I32_TYPE, is_signed ? min_s_array : min_u_array))) {
  282. goto fail;
  283. }
  284. if (!(vector_max = build_intx4_vector(
  285. comp_ctx, I32_TYPE, is_signed ? max_s_array : max_u_array))) {
  286. goto fail;
  287. }
  288. if (!(shuffle = build_intx8_vector(comp_ctx, I32_TYPE, shuffle_array))) {
  289. goto fail;
  290. }
  291. if (!(v1_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector1,
  292. vector_max, "v1_great_than_max"))) {
  293. HANDLE_FAILURE("LLVMBuldICmp");
  294. goto fail;
  295. }
  296. if (!(v2_gt_max = LLVMBuildICmp(comp_ctx->builder, LLVMIntSGT, vector2,
  297. vector_max, "v2_great_than_max"))) {
  298. HANDLE_FAILURE("LLVMBuldICmp");
  299. goto fail;
  300. }
  301. if (!(v1_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector1,
  302. vector_min, "v1_less_than_min"))) {
  303. HANDLE_FAILURE("LLVMBuldICmp");
  304. goto fail;
  305. }
  306. if (!(v2_lt_min = LLVMBuildICmp(comp_ctx->builder, LLVMIntSLT, vector2,
  307. vector_min, "v2_less_than_min"))) {
  308. HANDLE_FAILURE("LLVMBuldICmp");
  309. goto fail;
  310. }
  311. if (!(vector1_clamped =
  312. LLVMBuildSelect(comp_ctx->builder, v1_gt_max, vector_max, vector1,
  313. "vector1_clamped_max"))) {
  314. HANDLE_FAILURE("LLVMBuildSelect");
  315. goto fail;
  316. }
  317. if (!(vector1_clamped =
  318. LLVMBuildSelect(comp_ctx->builder, v1_lt_min, vector_min,
  319. vector1_clamped, "vector1_clamped_min"))) {
  320. HANDLE_FAILURE("LLVMBuildSelect");
  321. goto fail;
  322. }
  323. if (!(vector2_clamped =
  324. LLVMBuildSelect(comp_ctx->builder, v2_gt_max, vector_max, vector2,
  325. "vector2_clamped_max"))) {
  326. HANDLE_FAILURE("LLVMBuildSelect");
  327. goto fail;
  328. }
  329. if (!(vector2_clamped =
  330. LLVMBuildSelect(comp_ctx->builder, v2_lt_min, vector_min,
  331. vector2_clamped, "vector2_clamped_min"))) {
  332. HANDLE_FAILURE("LLVMBuildSelect");
  333. goto fail;
  334. }
  335. if (!(vector1_trunced = LLVMBuildTrunc(comp_ctx->builder, vector1_clamped,
  336. LLVMVectorType(INT16_TYPE, 4),
  337. "vector1_trunced"))) {
  338. HANDLE_FAILURE("LLVMBuildTrunc");
  339. goto fail;
  340. }
  341. if (!(vector2_trunced = LLVMBuildTrunc(comp_ctx->builder, vector2_clamped,
  342. LLVMVectorType(INT16_TYPE, 4),
  343. "vector2_trunced"))) {
  344. HANDLE_FAILURE("LLVMBuildTrunc");
  345. goto fail;
  346. }
  347. if (!(shuffle_vector = LLVMBuildShuffleVector(
  348. comp_ctx->builder, vector1_trunced, vector2_trunced, shuffle,
  349. "shuffle_vector"))) {
  350. HANDLE_FAILURE("LLVMBuildShuffleVector");
  351. goto fail;
  352. }
  353. if (!(result = LLVMBuildBitCast(comp_ctx->builder, shuffle_vector,
  354. V128_i64x2_TYPE, "ret"))) {
  355. HANDLE_FAILURE("LLVMBuildBitCast");
  356. goto fail;
  357. }
  358. PUSH_V128(result);
  359. return true;
  360. fail:
  361. return false;
  362. }
  363. bool
  364. aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
  365. AOTFuncContext *func_ctx,
  366. bool is_signed)
  367. {
  368. if (is_target_x86(comp_ctx)) {
  369. return aot_compile_simd_i16x8_narrow_i32x4_x86(comp_ctx, func_ctx,
  370. is_signed);
  371. }
  372. else {
  373. return aot_compile_simd_i16x8_narrow_i32x4_common(comp_ctx, func_ctx,
  374. is_signed);
  375. }
  376. }
  377. bool
  378. aot_compile_simd_i16x8_widen_i8x16(AOTCompContext *comp_ctx,
  379. AOTFuncContext *func_ctx,
  380. bool is_low_half,
  381. bool is_signed)
  382. {
  383. LLVMValueRef vector, undef, mask_high[8], mask_low[8], mask, shuffled,
  384. result;
  385. uint8 mask_high_value[8] = { 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf },
  386. mask_low_value[8] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 }, i;
  387. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  388. V128_i8x16_TYPE, "vec"))) {
  389. goto fail;
  390. }
  391. if (!(undef = LLVMGetUndef(V128_i8x16_TYPE))) {
  392. HANDLE_FAILURE("LLVMGetUndef");
  393. goto fail;
  394. }
  395. /* create a mask */
  396. for (i = 0; i < 8; i++) {
  397. mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true);
  398. mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true);
  399. }
  400. mask = is_low_half ? LLVMConstVector(mask_low, 8)
  401. : LLVMConstVector(mask_high, 8);
  402. if (!mask) {
  403. HANDLE_FAILURE("LLVMConstVector");
  404. goto fail;
  405. }
  406. /* retrive the low or high half */
  407. if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef,
  408. mask, "shuffled"))) {
  409. HANDLE_FAILURE("LLVMBuildShuffleVector");
  410. goto fail;
  411. }
  412. if (is_signed) {
  413. if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled,
  414. V128_i16x8_TYPE, "ext"))) {
  415. HANDLE_FAILURE("LLVMBuildSExt");
  416. goto fail;
  417. }
  418. }
  419. else {
  420. if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled,
  421. V128_i16x8_TYPE, "ext"))) {
  422. HANDLE_FAILURE("LLVMBuildZExt");
  423. goto fail;
  424. }
  425. }
  426. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  427. "ret"))) {
  428. HANDLE_FAILURE("LLVMBuildBitCast");
  429. goto fail;
  430. }
  431. PUSH_V128(result);
  432. return true;
  433. fail:
  434. return false;
  435. }
  436. bool
  437. aot_compile_simd_i32x4_widen_i16x8(AOTCompContext *comp_ctx,
  438. AOTFuncContext *func_ctx,
  439. bool is_low_half,
  440. bool is_signed)
  441. {
  442. LLVMValueRef vector, undef, mask_high[4], mask_low[4], mask, shuffled,
  443. result;
  444. uint8 mask_high_value[4] = { 0x4, 0x5, 0x6, 0x7 },
  445. mask_low_value[4] = { 0x0, 0x1, 0x2, 0x3 }, i;
  446. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  447. V128_i16x8_TYPE, "vec"))) {
  448. goto fail;
  449. }
  450. if (!(undef = LLVMGetUndef(V128_i16x8_TYPE))) {
  451. HANDLE_FAILURE("LLVMGetUndef");
  452. goto fail;
  453. }
  454. /* create a mask */
  455. for (i = 0; i < 4; i++) {
  456. mask_high[i] = LLVMConstInt(I32_TYPE, mask_high_value[i], true);
  457. mask_low[i] = LLVMConstInt(I32_TYPE, mask_low_value[i], true);
  458. }
  459. mask = is_low_half ? LLVMConstVector(mask_low, 4)
  460. : LLVMConstVector(mask_high, 4);
  461. if (!mask) {
  462. HANDLE_FAILURE("LLVMConstVector");
  463. goto fail;
  464. }
  465. /* retrive the low or high half */
  466. if (!(shuffled = LLVMBuildShuffleVector(comp_ctx->builder, vector, undef,
  467. mask, "shuffled"))) {
  468. HANDLE_FAILURE("LLVMBuildShuffleVector");
  469. goto fail;
  470. }
  471. if (is_signed) {
  472. if (!(result = LLVMBuildSExt(comp_ctx->builder, shuffled,
  473. V128_i32x4_TYPE, "ext"))) {
  474. HANDLE_FAILURE("LLVMBuildSExt");
  475. goto fail;
  476. }
  477. }
  478. else {
  479. if (!(result = LLVMBuildZExt(comp_ctx->builder, shuffled,
  480. V128_i32x4_TYPE, "ext"))) {
  481. HANDLE_FAILURE("LLVMBuildZExt");
  482. goto fail;
  483. }
  484. }
  485. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  486. "ret"))) {
  487. HANDLE_FAILURE("LLVMBuildBitCast");
  488. goto fail;
  489. }
  490. PUSH_V128(result);
  491. return true;
  492. fail:
  493. return false;
  494. }
  495. static LLVMValueRef
  496. simd_build_const_f32x4(AOTCompContext *comp_ctx,
  497. AOTFuncContext *func_ctx,
  498. float f)
  499. {
  500. LLVMValueRef elements[4], vector;
  501. if (!(elements[0] = LLVMConstReal(F32_TYPE, f))) {
  502. HANDLE_FAILURE("LLVMConstInt");
  503. goto fail;
  504. }
  505. elements[1] = elements[2] = elements[3] = elements[0];
  506. if (!(vector = LLVMConstVector(elements, 4))) {
  507. HANDLE_FAILURE("LLVMConstVector");
  508. goto fail;
  509. }
  510. return vector;
  511. fail:
  512. return NULL;
  513. }
  514. static LLVMValueRef
  515. simd_build_const_i32x4(AOTCompContext *comp_ctx,
  516. AOTFuncContext *func_ctx,
  517. uint64 integer,
  518. bool is_signed)
  519. {
  520. LLVMValueRef elements[4], vector;
  521. if (!(elements[0] = LLVMConstInt(I32_TYPE, integer, is_signed))) {
  522. HANDLE_FAILURE("LLVMConstInt");
  523. goto fail;
  524. }
  525. elements[1] = elements[2] = elements[3] = elements[0];
  526. if (!(vector = LLVMConstVector(elements, 4))) {
  527. HANDLE_FAILURE("LLVMConstVector");
  528. goto fail;
  529. }
  530. return vector;
  531. fail:
  532. return NULL;
  533. }
  534. bool
  535. aot_compile_simd_i32x4_trunc_sat_f32x4(AOTCompContext *comp_ctx,
  536. AOTFuncContext *func_ctx,
  537. bool is_signed)
  538. {
  539. LLVMValueRef vector, zeros, is_nan, max_float_v, min_float_v, is_ge_max,
  540. is_le_min, result, max_int_v, min_int_v;
  541. uint32 max_ui = 0xFFffFFff, min_ui = 0x0;
  542. int32 max_si = 0x7FFFffff, min_si = 0x80000000;
  543. float max_f_ui = 4294967296.0f, min_f_ui = 0.0f, max_f_si = 2147483647.0f,
  544. min_f_si = -2147483648.0f;
  545. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  546. V128_f32x4_TYPE, "vec"))) {
  547. goto fail;
  548. }
  549. if (!(zeros = LLVMConstNull(V128_f32x4_TYPE))) {
  550. HANDLE_FAILURE("LLVMConstNull");
  551. goto fail;
  552. }
  553. if (is_signed) {
  554. if (!(max_float_v =
  555. simd_build_const_f32x4(comp_ctx, func_ctx, max_f_si))) {
  556. goto fail;
  557. }
  558. if (!(min_float_v =
  559. simd_build_const_f32x4(comp_ctx, func_ctx, min_f_si))) {
  560. goto fail;
  561. }
  562. if (!(max_int_v =
  563. simd_build_const_i32x4(comp_ctx, func_ctx, max_si, true))) {
  564. goto fail;
  565. }
  566. if (!(min_int_v =
  567. simd_build_const_i32x4(comp_ctx, func_ctx, min_si, true))) {
  568. goto fail;
  569. }
  570. }
  571. else {
  572. if (!(max_float_v =
  573. simd_build_const_f32x4(comp_ctx, func_ctx, max_f_ui))) {
  574. goto fail;
  575. }
  576. if (!(min_float_v =
  577. simd_build_const_f32x4(comp_ctx, func_ctx, min_f_ui))) {
  578. goto fail;
  579. }
  580. if (!(max_int_v =
  581. simd_build_const_i32x4(comp_ctx, func_ctx, max_ui, false))) {
  582. goto fail;
  583. }
  584. if (!(min_int_v =
  585. simd_build_const_i32x4(comp_ctx, func_ctx, min_ui, false))) {
  586. goto fail;
  587. }
  588. }
  589. if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealORD, vector, zeros,
  590. "is_nan"))) {
  591. HANDLE_FAILURE("LLVMBuildFCmp");
  592. goto fail;
  593. }
  594. if (!(is_le_min = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, vector,
  595. min_float_v, "le_min"))) {
  596. HANDLE_FAILURE("LLVMBuildFCmp");
  597. goto fail;
  598. }
  599. if (!(is_ge_max = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, vector,
  600. max_float_v, "ge_max"))) {
  601. HANDLE_FAILURE("LLVMBuildFCmp");
  602. goto fail;
  603. }
  604. if (is_signed) {
  605. if (!(result = LLVMBuildFPToSI(comp_ctx->builder, vector,
  606. V128_i32x4_TYPE, "truncated"))) {
  607. HANDLE_FAILURE("LLVMBuildSIToFP");
  608. goto fail;
  609. }
  610. }
  611. else {
  612. if (!(result = LLVMBuildFPToUI(comp_ctx->builder, vector,
  613. V128_i32x4_TYPE, "truncated"))) {
  614. HANDLE_FAILURE("LLVMBuildUIToFP");
  615. goto fail;
  616. }
  617. }
  618. if (!(result = LLVMBuildSelect(comp_ctx->builder, is_ge_max, max_int_v,
  619. result, "sat_w_max"))) {
  620. HANDLE_FAILURE("LLVMBuildSelect");
  621. goto fail;
  622. }
  623. if (!(result = LLVMBuildSelect(comp_ctx->builder, is_le_min, min_int_v,
  624. result, "sat_w_min"))) {
  625. HANDLE_FAILURE("LLVMBuildSelect");
  626. goto fail;
  627. }
  628. if (!(result = LLVMBuildSelect(comp_ctx->builder, is_nan, result,
  629. V128_i32x4_ZERO, "sat_w_nan"))) {
  630. HANDLE_FAILURE("LLVMBuildSelect");
  631. goto fail;
  632. }
  633. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  634. "ret"))) {
  635. HANDLE_FAILURE("LLVMBuildBitCast");
  636. goto fail;
  637. }
  638. PUSH_V128(result);
  639. return true;
  640. fail:
  641. return false;
  642. }
  643. bool
  644. aot_compile_simd_f32x4_convert_i32x4(AOTCompContext *comp_ctx,
  645. AOTFuncContext *func_ctx,
  646. bool is_signed)
  647. {
  648. LLVMValueRef vector, result;
  649. if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
  650. V128_i32x4_TYPE, "vec"))) {
  651. goto fail;
  652. }
  653. if (is_signed) {
  654. if (!(result = LLVMBuildSIToFP(comp_ctx->builder, vector,
  655. V128_f32x4_TYPE, "converted"))) {
  656. HANDLE_FAILURE("LLVMBuildSIToFP");
  657. goto fail;
  658. }
  659. }
  660. else {
  661. if (!(result = LLVMBuildUIToFP(comp_ctx->builder, vector,
  662. V128_f32x4_TYPE, "converted"))) {
  663. HANDLE_FAILURE("LLVMBuildSIToFP");
  664. goto fail;
  665. }
  666. }
  667. if (!(result = LLVMBuildBitCast(comp_ctx->builder, result, V128_i64x2_TYPE,
  668. "ret"))) {
  669. HANDLE_FAILURE("LLVMBuildBitCast");
  670. goto fail;
  671. }
  672. PUSH_V128(result);
  673. return true;
  674. fail:
  675. return false;
  676. }