Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: third_party/zlib/neon_adler32.c

Issue 2676493007: NEON implementation for Adler32
Patch Set: Coding style. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/zlib/neon_adler32.h ('k') | third_party/zlib/neon_adler32.patch » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright 2017 The Chromium Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 */
5
6 #include "neon_adler32.h"
7 #ifdef __ARM_NEON__
8 #include <arm_neon.h>
9
10 static void NEON_accum32(uint32_t *s, const unsigned char *buf,
11 unsigned int len)
12 {
13 static const uint8_t taps[32] = {
14 32, 31, 30, 29, 28, 27, 26, 25,
15 24, 23, 22, 21, 20, 19, 18, 17,
16 16, 15, 14, 13, 12, 11, 10, 9,
17 8, 7, 6, 5, 4, 3, 2, 1 };
18
19 uint32x2_t adacc2, s2acc2, as;
20 uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
21
22 uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
23 adacc = vsetq_lane_u32(s[0], adacc, 0);
24 s2acc = vsetq_lane_u32(s[1], s2acc, 0);
25
26 while (len >= 2) {
27 uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16);
28 uint16x8_t adler, sum2;
29 s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
30 adler = vpaddlq_u8( d0);
31 adler = vpadalq_u8(adler, d1);
32 sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0));
33 sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
34 sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1));
35 sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1));
36 adacc = vpadalq_u16(adacc, adler);
37 s2acc = vpadalq_u16(s2acc, sum2);
38 len -= 2;
39 buf += 32;
40 }
41
42 while (len > 0) {
43 uint8x16_t d0 = vld1q_u8(buf);
44 uint16x8_t adler, sum2;
45 s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
46 adler = vpaddlq_u8(d0);
47 sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0));
48 sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
49 adacc = vpadalq_u16(adacc, adler);
50 s2acc = vpadalq_u16(s2acc, sum2);
51 buf += 16;
52 len--;
53 }
54
55 adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
56 s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc));
57 as = vpadd_u32(adacc2, s2acc2);
58 s[0] = vget_lane_u32(as, 0);
59 s[1] = vget_lane_u32(as, 1);
60 }
61
62 static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf,
63 unsigned int len)
64 {
65 /* Oldie K&R code integration. */
66 unsigned int i;
67 for (i = 0; i < len; ++i) {
68 pair[0] += buf[i];
69 pair[1] += pair[0];
70 }
71 }
72
73 unsigned long NEON_adler32(unsigned long adler, const unsigned char *buf,
74 const unsigned int len)
75 {
76 /* The largest prime smaller than 65536. */
77 const uint32_t M_BASE = 65521;
78 /* This is the threshold where doing accumulation may overflow. */
79 const int M_NMAX = 5552;
80
81 unsigned long sum2;
82 uint32_t pair[2];
83 int n = M_NMAX;
84 unsigned int done = 0;
85 /* Oldie K&R code integration. */
86 unsigned int i;
87
88 /* Split Adler-32 into component sums, it can be supplied by
89 * the caller sites (e.g. in a PNG file).
90 */
91 sum2 = (adler >> 16) & 0xffff;
92 adler &= 0xffff;
93 pair[0] = adler;
94 pair[1] = sum2;
95
96 for (i = 0; i < len; i += n) {
97 if ((i + n) > len)
98 n = len - i;
99
100 if (n < 16)
101 break;
102
103 NEON_accum32(pair, buf + i, n / 16);
104 pair[0] %= M_BASE;
105 pair[1] %= M_BASE;
106
107 done += (n / 16) * 16;
108 }
109
110 /* Handle the tail elements. */
111 if (done < len) {
112 NEON_handle_tail(pair, (buf + done), len - done);
113 pair[0] %= M_BASE;
114 pair[1] %= M_BASE;
115 }
116
117 /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */
118 return (pair[1] << 16) | pair[0];
119 }
120 #endif
OLDNEW
« no previous file with comments | « third_party/zlib/neon_adler32.h ('k') | third_party/zlib/neon_adler32.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698