u8.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. if (bytes >= 512) {
  2. __m256i y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12, y13, y14,
  3. y15;
  4. /* the naive way seems as fast (if not a bit faster) than the vector way */
  5. __m256i z0 = _mm256_set1_epi32(x[0]);
  6. __m256i z5 = _mm256_set1_epi32(x[1]);
  7. __m256i z10 = _mm256_set1_epi32(x[2]);
  8. __m256i z15 = _mm256_set1_epi32(x[3]);
  9. __m256i z12 = _mm256_set1_epi32(x[4]);
  10. __m256i z1 = _mm256_set1_epi32(x[5]);
  11. __m256i z6 = _mm256_set1_epi32(x[6]);
  12. __m256i z11 = _mm256_set1_epi32(x[7]);
  13. __m256i z8; /* useless */
  14. __m256i z13 = _mm256_set1_epi32(x[9]);
  15. __m256i z2 = _mm256_set1_epi32(x[10]);
  16. __m256i z7 = _mm256_set1_epi32(x[11]);
  17. __m256i z4 = _mm256_set1_epi32(x[12]);
  18. __m256i z9; /* useless */
  19. __m256i z14 = _mm256_set1_epi32(x[14]);
  20. __m256i z3 = _mm256_set1_epi32(x[15]);
  21. __m256i orig0 = z0;
  22. __m256i orig1 = z1;
  23. __m256i orig2 = z2;
  24. __m256i orig3 = z3;
  25. __m256i orig4 = z4;
  26. __m256i orig5 = z5;
  27. __m256i orig6 = z6;
  28. __m256i orig7 = z7;
  29. __m256i orig8;
  30. __m256i orig9;
  31. __m256i orig10 = z10;
  32. __m256i orig11 = z11;
  33. __m256i orig12 = z12;
  34. __m256i orig13 = z13;
  35. __m256i orig14 = z14;
  36. __m256i orig15 = z15;
  37. uint32_t in8;
  38. uint32_t in9;
  39. int i;
  40. while (bytes >= 512) {
  41. /* vector implementation for z8 and z9 */
  42. /* faster than the naive version for 8 blocks */
  43. const __m256i addv8 = _mm256_set_epi64x(3, 2, 1, 0);
  44. const __m256i addv9 = _mm256_set_epi64x(7, 6, 5, 4);
  45. const __m256i permute = _mm256_set_epi32(7, 6, 3, 2, 5, 4, 1, 0);
  46. __m256i t8, t9;
  47. uint64_t in89;
  48. in8 = x[8];
  49. in9 = x[13]; /* see arrays above for the address translation */
  50. in89 = ((uint64_t) in8) | (((uint64_t) in9) << 32);
  51. z8 = z9 = _mm256_broadcastq_epi64(_mm_cvtsi64_si128(in89));
  52. t8 = _mm256_add_epi64(addv8, z8);
  53. t9 = _mm256_add_epi64(addv9, z9);
  54. z8 = _mm256_unpacklo_epi32(t8, t9);
  55. z9 = _mm256_unpackhi_epi32(t8, t9);
  56. t8 = _mm256_unpacklo_epi32(z8, z9);
  57. t9 = _mm256_unpackhi_epi32(z8, z9);
  58. /* required because unpack* are intra-lane */
  59. z8 = _mm256_permutevar8x32_epi32(t8, permute);
  60. z9 = _mm256_permutevar8x32_epi32(t9, permute);
  61. orig8 = z8;
  62. orig9 = z9;
  63. in89 += 8;
  64. x[8] = in89 & 0xFFFFFFFF;
  65. x[13] = (in89 >> 32) & 0xFFFFFFFF;
  66. z5 = orig5;
  67. z10 = orig10;
  68. z15 = orig15;
  69. z14 = orig14;
  70. z3 = orig3;
  71. z6 = orig6;
  72. z11 = orig11;
  73. z1 = orig1;
  74. z7 = orig7;
  75. z13 = orig13;
  76. z2 = orig2;
  77. z9 = orig9;
  78. z0 = orig0;
  79. z12 = orig12;
  80. z4 = orig4;
  81. z8 = orig8;
  82. for (i = 0; i < ROUNDS; i += 2) {
  83. /* the inner loop is a direct translation (regexp search/replace)
  84. * from the amd64-xmm6 ASM */
  85. __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13,
  86. r14, r15;
  87. y4 = z12;
  88. y4 = _mm256_add_epi32(y4, z0);
  89. r4 = y4;
  90. y4 = _mm256_slli_epi32(y4, 7);
  91. z4 = _mm256_xor_si256(z4, y4);
  92. r4 = _mm256_srli_epi32(r4, 25);
  93. z4 = _mm256_xor_si256(z4, r4);
  94. y9 = z1;
  95. y9 = _mm256_add_epi32(y9, z5);
  96. r9 = y9;
  97. y9 = _mm256_slli_epi32(y9, 7);
  98. z9 = _mm256_xor_si256(z9, y9);
  99. r9 = _mm256_srli_epi32(r9, 25);
  100. z9 = _mm256_xor_si256(z9, r9);
  101. y8 = z0;
  102. y8 = _mm256_add_epi32(y8, z4);
  103. r8 = y8;
  104. y8 = _mm256_slli_epi32(y8, 9);
  105. z8 = _mm256_xor_si256(z8, y8);
  106. r8 = _mm256_srli_epi32(r8, 23);
  107. z8 = _mm256_xor_si256(z8, r8);
  108. y13 = z5;
  109. y13 = _mm256_add_epi32(y13, z9);
  110. r13 = y13;
  111. y13 = _mm256_slli_epi32(y13, 9);
  112. z13 = _mm256_xor_si256(z13, y13);
  113. r13 = _mm256_srli_epi32(r13, 23);
  114. z13 = _mm256_xor_si256(z13, r13);
  115. y12 = z4;
  116. y12 = _mm256_add_epi32(y12, z8);
  117. r12 = y12;
  118. y12 = _mm256_slli_epi32(y12, 13);
  119. z12 = _mm256_xor_si256(z12, y12);
  120. r12 = _mm256_srli_epi32(r12, 19);
  121. z12 = _mm256_xor_si256(z12, r12);
  122. y1 = z9;
  123. y1 = _mm256_add_epi32(y1, z13);
  124. r1 = y1;
  125. y1 = _mm256_slli_epi32(y1, 13);
  126. z1 = _mm256_xor_si256(z1, y1);
  127. r1 = _mm256_srli_epi32(r1, 19);
  128. z1 = _mm256_xor_si256(z1, r1);
  129. y0 = z8;
  130. y0 = _mm256_add_epi32(y0, z12);
  131. r0 = y0;
  132. y0 = _mm256_slli_epi32(y0, 18);
  133. z0 = _mm256_xor_si256(z0, y0);
  134. r0 = _mm256_srli_epi32(r0, 14);
  135. z0 = _mm256_xor_si256(z0, r0);
  136. y5 = z13;
  137. y5 = _mm256_add_epi32(y5, z1);
  138. r5 = y5;
  139. y5 = _mm256_slli_epi32(y5, 18);
  140. z5 = _mm256_xor_si256(z5, y5);
  141. r5 = _mm256_srli_epi32(r5, 14);
  142. z5 = _mm256_xor_si256(z5, r5);
  143. y14 = z6;
  144. y14 = _mm256_add_epi32(y14, z10);
  145. r14 = y14;
  146. y14 = _mm256_slli_epi32(y14, 7);
  147. z14 = _mm256_xor_si256(z14, y14);
  148. r14 = _mm256_srli_epi32(r14, 25);
  149. z14 = _mm256_xor_si256(z14, r14);
  150. y3 = z11;
  151. y3 = _mm256_add_epi32(y3, z15);
  152. r3 = y3;
  153. y3 = _mm256_slli_epi32(y3, 7);
  154. z3 = _mm256_xor_si256(z3, y3);
  155. r3 = _mm256_srli_epi32(r3, 25);
  156. z3 = _mm256_xor_si256(z3, r3);
  157. y2 = z10;
  158. y2 = _mm256_add_epi32(y2, z14);
  159. r2 = y2;
  160. y2 = _mm256_slli_epi32(y2, 9);
  161. z2 = _mm256_xor_si256(z2, y2);
  162. r2 = _mm256_srli_epi32(r2, 23);
  163. z2 = _mm256_xor_si256(z2, r2);
  164. y7 = z15;
  165. y7 = _mm256_add_epi32(y7, z3);
  166. r7 = y7;
  167. y7 = _mm256_slli_epi32(y7, 9);
  168. z7 = _mm256_xor_si256(z7, y7);
  169. r7 = _mm256_srli_epi32(r7, 23);
  170. z7 = _mm256_xor_si256(z7, r7);
  171. y6 = z14;
  172. y6 = _mm256_add_epi32(y6, z2);
  173. r6 = y6;
  174. y6 = _mm256_slli_epi32(y6, 13);
  175. z6 = _mm256_xor_si256(z6, y6);
  176. r6 = _mm256_srli_epi32(r6, 19);
  177. z6 = _mm256_xor_si256(z6, r6);
  178. y11 = z3;
  179. y11 = _mm256_add_epi32(y11, z7);
  180. r11 = y11;
  181. y11 = _mm256_slli_epi32(y11, 13);
  182. z11 = _mm256_xor_si256(z11, y11);
  183. r11 = _mm256_srli_epi32(r11, 19);
  184. z11 = _mm256_xor_si256(z11, r11);
  185. y10 = z2;
  186. y10 = _mm256_add_epi32(y10, z6);
  187. r10 = y10;
  188. y10 = _mm256_slli_epi32(y10, 18);
  189. z10 = _mm256_xor_si256(z10, y10);
  190. r10 = _mm256_srli_epi32(r10, 14);
  191. z10 = _mm256_xor_si256(z10, r10);
  192. y1 = z3;
  193. y1 = _mm256_add_epi32(y1, z0);
  194. r1 = y1;
  195. y1 = _mm256_slli_epi32(y1, 7);
  196. z1 = _mm256_xor_si256(z1, y1);
  197. r1 = _mm256_srli_epi32(r1, 25);
  198. z1 = _mm256_xor_si256(z1, r1);
  199. y15 = z7;
  200. y15 = _mm256_add_epi32(y15, z11);
  201. r15 = y15;
  202. y15 = _mm256_slli_epi32(y15, 18);
  203. z15 = _mm256_xor_si256(z15, y15);
  204. r15 = _mm256_srli_epi32(r15, 14);
  205. z15 = _mm256_xor_si256(z15, r15);
  206. y6 = z4;
  207. y6 = _mm256_add_epi32(y6, z5);
  208. r6 = y6;
  209. y6 = _mm256_slli_epi32(y6, 7);
  210. z6 = _mm256_xor_si256(z6, y6);
  211. r6 = _mm256_srli_epi32(r6, 25);
  212. z6 = _mm256_xor_si256(z6, r6);
  213. y2 = z0;
  214. y2 = _mm256_add_epi32(y2, z1);
  215. r2 = y2;
  216. y2 = _mm256_slli_epi32(y2, 9);
  217. z2 = _mm256_xor_si256(z2, y2);
  218. r2 = _mm256_srli_epi32(r2, 23);
  219. z2 = _mm256_xor_si256(z2, r2);
  220. y7 = z5;
  221. y7 = _mm256_add_epi32(y7, z6);
  222. r7 = y7;
  223. y7 = _mm256_slli_epi32(y7, 9);
  224. z7 = _mm256_xor_si256(z7, y7);
  225. r7 = _mm256_srli_epi32(r7, 23);
  226. z7 = _mm256_xor_si256(z7, r7);
  227. y3 = z1;
  228. y3 = _mm256_add_epi32(y3, z2);
  229. r3 = y3;
  230. y3 = _mm256_slli_epi32(y3, 13);
  231. z3 = _mm256_xor_si256(z3, y3);
  232. r3 = _mm256_srli_epi32(r3, 19);
  233. z3 = _mm256_xor_si256(z3, r3);
  234. y4 = z6;
  235. y4 = _mm256_add_epi32(y4, z7);
  236. r4 = y4;
  237. y4 = _mm256_slli_epi32(y4, 13);
  238. z4 = _mm256_xor_si256(z4, y4);
  239. r4 = _mm256_srli_epi32(r4, 19);
  240. z4 = _mm256_xor_si256(z4, r4);
  241. y0 = z2;
  242. y0 = _mm256_add_epi32(y0, z3);
  243. r0 = y0;
  244. y0 = _mm256_slli_epi32(y0, 18);
  245. z0 = _mm256_xor_si256(z0, y0);
  246. r0 = _mm256_srli_epi32(r0, 14);
  247. z0 = _mm256_xor_si256(z0, r0);
  248. y5 = z7;
  249. y5 = _mm256_add_epi32(y5, z4);
  250. r5 = y5;
  251. y5 = _mm256_slli_epi32(y5, 18);
  252. z5 = _mm256_xor_si256(z5, y5);
  253. r5 = _mm256_srli_epi32(r5, 14);
  254. z5 = _mm256_xor_si256(z5, r5);
  255. y11 = z9;
  256. y11 = _mm256_add_epi32(y11, z10);
  257. r11 = y11;
  258. y11 = _mm256_slli_epi32(y11, 7);
  259. z11 = _mm256_xor_si256(z11, y11);
  260. r11 = _mm256_srli_epi32(r11, 25);
  261. z11 = _mm256_xor_si256(z11, r11);
  262. y12 = z14;
  263. y12 = _mm256_add_epi32(y12, z15);
  264. r12 = y12;
  265. y12 = _mm256_slli_epi32(y12, 7);
  266. z12 = _mm256_xor_si256(z12, y12);
  267. r12 = _mm256_srli_epi32(r12, 25);
  268. z12 = _mm256_xor_si256(z12, r12);
  269. y8 = z10;
  270. y8 = _mm256_add_epi32(y8, z11);
  271. r8 = y8;
  272. y8 = _mm256_slli_epi32(y8, 9);
  273. z8 = _mm256_xor_si256(z8, y8);
  274. r8 = _mm256_srli_epi32(r8, 23);
  275. z8 = _mm256_xor_si256(z8, r8);
  276. y13 = z15;
  277. y13 = _mm256_add_epi32(y13, z12);
  278. r13 = y13;
  279. y13 = _mm256_slli_epi32(y13, 9);
  280. z13 = _mm256_xor_si256(z13, y13);
  281. r13 = _mm256_srli_epi32(r13, 23);
  282. z13 = _mm256_xor_si256(z13, r13);
  283. y9 = z11;
  284. y9 = _mm256_add_epi32(y9, z8);
  285. r9 = y9;
  286. y9 = _mm256_slli_epi32(y9, 13);
  287. z9 = _mm256_xor_si256(z9, y9);
  288. r9 = _mm256_srli_epi32(r9, 19);
  289. z9 = _mm256_xor_si256(z9, r9);
  290. y14 = z12;
  291. y14 = _mm256_add_epi32(y14, z13);
  292. r14 = y14;
  293. y14 = _mm256_slli_epi32(y14, 13);
  294. z14 = _mm256_xor_si256(z14, y14);
  295. r14 = _mm256_srli_epi32(r14, 19);
  296. z14 = _mm256_xor_si256(z14, r14);
  297. y10 = z8;
  298. y10 = _mm256_add_epi32(y10, z9);
  299. r10 = y10;
  300. y10 = _mm256_slli_epi32(y10, 18);
  301. z10 = _mm256_xor_si256(z10, y10);
  302. r10 = _mm256_srli_epi32(r10, 14);
  303. z10 = _mm256_xor_si256(z10, r10);
  304. y15 = z13;
  305. y15 = _mm256_add_epi32(y15, z14);
  306. r15 = y15;
  307. y15 = _mm256_slli_epi32(y15, 18);
  308. z15 = _mm256_xor_si256(z15, y15);
  309. r15 = _mm256_srli_epi32(r15, 14);
  310. z15 = _mm256_xor_si256(z15, r15);
  311. }
  312. /* store data ; this macro first transpose data in-registers, and then store
  313. * them in memory. much faster with icc. */
  314. #define ONEQUAD_TRANSPOSE(A, B, C, D) \
  315. { \
  316. __m128i t0, t1, t2, t3; \
  317. z##A = _mm256_add_epi32(z##A, orig##A); \
  318. z##B = _mm256_add_epi32(z##B, orig##B); \
  319. z##C = _mm256_add_epi32(z##C, orig##C); \
  320. z##D = _mm256_add_epi32(z##D, orig##D); \
  321. y##A = _mm256_unpacklo_epi32(z##A, z##B); \
  322. y##B = _mm256_unpacklo_epi32(z##C, z##D); \
  323. y##C = _mm256_unpackhi_epi32(z##A, z##B); \
  324. y##D = _mm256_unpackhi_epi32(z##C, z##D); \
  325. z##A = _mm256_unpacklo_epi64(y##A, y##B); \
  326. z##B = _mm256_unpackhi_epi64(y##A, y##B); \
  327. z##C = _mm256_unpacklo_epi64(y##C, y##D); \
  328. z##D = _mm256_unpackhi_epi64(y##C, y##D); \
  329. t0 = _mm_xor_si128(_mm256_extracti128_si256(z##A, 0), \
  330. _mm_loadu_si128((const __m128i*) (m + 0))); \
  331. _mm_storeu_si128((__m128i*) (c + 0), t0); \
  332. t1 = _mm_xor_si128(_mm256_extracti128_si256(z##B, 0), \
  333. _mm_loadu_si128((const __m128i*) (m + 64))); \
  334. _mm_storeu_si128((__m128i*) (c + 64), t1); \
  335. t2 = _mm_xor_si128(_mm256_extracti128_si256(z##C, 0), \
  336. _mm_loadu_si128((const __m128i*) (m + 128))); \
  337. _mm_storeu_si128((__m128i*) (c + 128), t2); \
  338. t3 = _mm_xor_si128(_mm256_extracti128_si256(z##D, 0), \
  339. _mm_loadu_si128((const __m128i*) (m + 192))); \
  340. _mm_storeu_si128((__m128i*) (c + 192), t3); \
  341. t0 = _mm_xor_si128(_mm256_extracti128_si256(z##A, 1), \
  342. _mm_loadu_si128((const __m128i*) (m + 256))); \
  343. _mm_storeu_si128((__m128i*) (c + 256), t0); \
  344. t1 = _mm_xor_si128(_mm256_extracti128_si256(z##B, 1), \
  345. _mm_loadu_si128((const __m128i*) (m + 320))); \
  346. _mm_storeu_si128((__m128i*) (c + 320), t1); \
  347. t2 = _mm_xor_si128(_mm256_extracti128_si256(z##C, 1), \
  348. _mm_loadu_si128((const __m128i*) (m + 384))); \
  349. _mm_storeu_si128((__m128i*) (c + 384), t2); \
  350. t3 = _mm_xor_si128(_mm256_extracti128_si256(z##D, 1), \
  351. _mm_loadu_si128((const __m128i*) (m + 448))); \
  352. _mm_storeu_si128((__m128i*) (c + 448), t3); \
  353. }
  354. #define ONEQUAD(A, B, C, D) ONEQUAD_TRANSPOSE(A, B, C, D)
  355. #define ONEQUAD_UNPCK(A, B, C, D) \
  356. { \
  357. z##A = _mm256_add_epi32(z##A, orig##A); \
  358. z##B = _mm256_add_epi32(z##B, orig##B); \
  359. z##C = _mm256_add_epi32(z##C, orig##C); \
  360. z##D = _mm256_add_epi32(z##D, orig##D); \
  361. y##A = _mm256_unpacklo_epi32(z##A, z##B); \
  362. y##B = _mm256_unpacklo_epi32(z##C, z##D); \
  363. y##C = _mm256_unpackhi_epi32(z##A, z##B); \
  364. y##D = _mm256_unpackhi_epi32(z##C, z##D); \
  365. z##A = _mm256_unpacklo_epi64(y##A, y##B); \
  366. z##B = _mm256_unpackhi_epi64(y##A, y##B); \
  367. z##C = _mm256_unpacklo_epi64(y##C, y##D); \
  368. z##D = _mm256_unpackhi_epi64(y##C, y##D); \
  369. }
  370. #define ONEOCTO(A, B, C, D, A2, B2, C2, D2) \
  371. { \
  372. ONEQUAD_UNPCK(A, B, C, D); \
  373. ONEQUAD_UNPCK(A2, B2, C2, D2); \
  374. y##A = _mm256_permute2x128_si256(z##A, z##A2, 0x20); \
  375. y##A2 = _mm256_permute2x128_si256(z##A, z##A2, 0x31); \
  376. y##B = _mm256_permute2x128_si256(z##B, z##B2, 0x20); \
  377. y##B2 = _mm256_permute2x128_si256(z##B, z##B2, 0x31); \
  378. y##C = _mm256_permute2x128_si256(z##C, z##C2, 0x20); \
  379. y##C2 = _mm256_permute2x128_si256(z##C, z##C2, 0x31); \
  380. y##D = _mm256_permute2x128_si256(z##D, z##D2, 0x20); \
  381. y##D2 = _mm256_permute2x128_si256(z##D, z##D2, 0x31); \
  382. y##A = _mm256_xor_si256(y##A, \
  383. _mm256_loadu_si256((const __m256i*) (m + 0))); \
  384. y##B = _mm256_xor_si256( \
  385. y##B, _mm256_loadu_si256((const __m256i*) (m + 64))); \
  386. y##C = _mm256_xor_si256( \
  387. y##C, _mm256_loadu_si256((const __m256i*) (m + 128))); \
  388. y##D = _mm256_xor_si256( \
  389. y##D, _mm256_loadu_si256((const __m256i*) (m + 192))); \
  390. y##A2 = _mm256_xor_si256( \
  391. y##A2, _mm256_loadu_si256((const __m256i*) (m + 256))); \
  392. y##B2 = _mm256_xor_si256( \
  393. y##B2, _mm256_loadu_si256((const __m256i*) (m + 320))); \
  394. y##C2 = _mm256_xor_si256( \
  395. y##C2, _mm256_loadu_si256((const __m256i*) (m + 384))); \
  396. y##D2 = _mm256_xor_si256( \
  397. y##D2, _mm256_loadu_si256((const __m256i*) (m + 448))); \
  398. _mm256_storeu_si256((__m256i*) (c + 0), y##A); \
  399. _mm256_storeu_si256((__m256i*) (c + 64), y##B); \
  400. _mm256_storeu_si256((__m256i*) (c + 128), y##C); \
  401. _mm256_storeu_si256((__m256i*) (c + 192), y##D); \
  402. _mm256_storeu_si256((__m256i*) (c + 256), y##A2); \
  403. _mm256_storeu_si256((__m256i*) (c + 320), y##B2); \
  404. _mm256_storeu_si256((__m256i*) (c + 384), y##C2); \
  405. _mm256_storeu_si256((__m256i*) (c + 448), y##D2); \
  406. }
  407. ONEOCTO(0, 1, 2, 3, 4, 5, 6, 7);
  408. m += 32;
  409. c += 32;
  410. ONEOCTO(8, 9, 10, 11, 12, 13, 14, 15);
  411. m -= 32;
  412. c -= 32;
  413. #undef ONEQUAD
  414. #undef ONEQUAD_TRANSPOSE
  415. #undef ONEQUAD_UNPCK
  416. #undef ONEOCTO
  417. bytes -= 512;
  418. c += 512;
  419. m += 512;
  420. }
  421. }