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

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

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.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 From d62eac3b93d61dc07c7b4c0d1738db14415b6309 Mon Sep 17 00:00:00 2001
2 From: Adenilson Cavalcanti <adenilson.cavalcanti@arm.com>
3 Date: Mon, 30 Jan 2017 15:30:38 -0800
4 Subject: [PATCH] NEON implementation for Adler32
5
6 The checksum is calculated in the uncompressed PNG data
7 and can be made much faster by using SIMD.
8
9 Tests in ARMv8 yielded an improvement of about 3x
10 (e.g. walltime was 350ms x 125ms for a 4096x4096 bytes
11 executed 30 times).
12 ---
13 third_party/zlib/BUILD.gn | 5 ++
14 third_party/zlib/README.chromium | 4 +-
15 third_party/zlib/adler32.c | 8 +++
16 third_party/zlib/neon_adler32.c | 120 +++++++++++++++++++++++++++++++++++++++
17 third_party/zlib/neon_adler32.h | 13 +++++
18 5 files changed, 149 insertions(+), 1 deletion(-)
19 create mode 100644 third_party/zlib/neon_adler32.c
20 create mode 100644 third_party/zlib/neon_adler32.h
21
22 diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn
23 index 5086563..09dfa5f 100644
24 --- a/third_party/zlib/BUILD.gn
25 +++ b/third_party/zlib/BUILD.gn
26 @@ -73,6 +73,11 @@ static_library("zlib") {
27
28 if (!is_ios && (current_cpu == "x86" || current_cpu == "x64")) {
29 sources += [ "x86.c" ]
30 + } else if (current_cpu == "arm" || current_cpu == "arm64") {
31 + sources += [
32 + "neon_adler32.c",
33 + "neon_adler32.h",
34 + ]
35 }
36
37 configs -= [ "//build/config/compiler:chromium_code" ]
38 diff --git a/third_party/zlib/README.chromium b/third_party/zlib/README.chromium
39 index fe6bc10..166eb33 100644
40 --- a/third_party/zlib/README.chromium
41 +++ b/third_party/zlib/README.chromium
42 @@ -24,5 +24,7 @@ Local Modifications:
43 additions.
44 - google.patch contains changes from the upstream version, mostly related to
45 the build.
46 - - Intel SIMD optimisations from https://github.com/jtkukunas/zlib/ have been
47 + - Intel SIMD optimizations from https://github.com/jtkukunas/zlib/ have been
48 integrated. These changes are reflected in simd.patch.
49 + - NEON SIMD optimizations for Adler32 checksum were integrated. Changes
50 + are reflected in neon_adler32.patch.
51 \ No newline at end of file
52 diff --git a/third_party/zlib/adler32.c b/third_party/zlib/adler32.c
53 index d0be438..0b74c72 100644
54 --- a/third_party/zlib/adler32.c
55 +++ b/third_party/zlib/adler32.c
56 @@ -6,6 +6,9 @@
57 /* @(#) $Id$ */
58
59 #include "zutil.h"
60 +#ifdef __ARM_NEON__
61 +#include "neon_adler32.h"
62 +#endif
63
64 local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
65
66 @@ -65,6 +68,11 @@ uLong ZEXPORT adler32_z(adler, buf, len)
67 const Bytef *buf;
68 z_size_t len;
69 {
70 +#ifdef __ARM_NEON__
71 + if (len > 31)
72 + return NEON_adler32(adler, buf, len);
73 +#endif
74 +
75 unsigned long sum2;
76 unsigned n;
77
78 diff --git a/third_party/zlib/neon_adler32.c b/third_party/zlib/neon_adler32.c
79 new file mode 100644
80 index 0000000..a0f95fb
81 --- /dev/null
82 +++ b/third_party/zlib/neon_adler32.c
83 @@ -0,0 +1,120 @@
84 +/* Copyright 2017 The Chromium Authors. All rights reserved.
85 + * Use of this source code is governed by a BSD-style license that can be
86 + * found in the LICENSE file.
87 +*/
88 +
89 +#include "neon_adler32.h"
90 +#ifdef __ARM_NEON__
91 +#include <arm_neon.h>
92 +
93 +static void NEON_accum32(uint32_t *s, const unsigned char *buf,
94 + unsigned int len)
95 +{
96 + static const uint8_t taps[32] = {
97 + 32, 31, 30, 29, 28, 27, 26, 25,
98 + 24, 23, 22, 21, 20, 19, 18, 17,
99 + 16, 15, 14, 13, 12, 11, 10, 9,
100 + 8, 7, 6, 5, 4, 3, 2, 1 };
101 +
102 + uint32x2_t adacc2, s2acc2, as;
103 + uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16);
104 +
105 + uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0);
106 + adacc = vsetq_lane_u32(s[0], adacc, 0);
107 + s2acc = vsetq_lane_u32(s[1], s2acc, 0);
108 +
109 + while (len >= 2) {
110 + uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16);
111 + uint16x8_t adler, sum2;
112 + s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5));
113 + adler = vpaddlq_u8( d0);
114 + adler = vpadalq_u8(adler, d1);
115 + sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0));
116 + sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0));
117 + sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1));
118 + sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1));
119 + adacc = vpadalq_u16(adacc, adler);
120 + s2acc = vpadalq_u16(s2acc, sum2);
121 + len -= 2;
122 + buf += 32;
123 + }
124 +
125 + while (len > 0) {
126 + uint8x16_t d0 = vld1q_u8(buf);
127 + uint16x8_t adler, sum2;
128 + s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4));
129 + adler = vpaddlq_u8(d0);
130 + sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0));
131 + sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0));
132 + adacc = vpadalq_u16(adacc, adler);
133 + s2acc = vpadalq_u16(s2acc, sum2);
134 + buf += 16;
135 + len--;
136 + }
137 +
138 + adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc));
139 + s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc));
140 + as = vpadd_u32(adacc2, s2acc2);
141 + s[0] = vget_lane_u32(as, 0);
142 + s[1] = vget_lane_u32(as, 1);
143 +}
144 +
145 +static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf,
146 + unsigned int len)
147 +{
148 + /* Oldie K&R code integration. */
149 + unsigned int i;
150 + for (i = 0; i < len; ++i) {
151 + pair[0] += buf[i];
152 + pair[1] += pair[0];
153 + }
154 +}
155 +
156 +unsigned long NEON_adler32(unsigned long adler, const unsigned char *buf,
157 + const unsigned int len)
158 +{
159 + /* The largest prime smaller than 65536. */
160 + const uint32_t M_BASE = 65521;
161 + /* This is the threshold where doing accumulation may overflow. */
162 + const int M_NMAX = 5552;
163 +
164 + unsigned long sum2;
165 + uint32_t pair[2];
166 + int n = M_NMAX;
167 + unsigned int done = 0;
168 + /* Oldie K&R code integration. */
169 + unsigned int i;
170 +
171 + /* Split Adler-32 into component sums, it can be supplied by
172 + * the caller sites (e.g. in a PNG file).
173 + */
174 + sum2 = (adler >> 16) & 0xffff;
175 + adler &= 0xffff;
176 + pair[0] = adler;
177 + pair[1] = sum2;
178 +
179 + for (i = 0; i < len; i += n) {
180 + if ((i + n) > len)
181 + n = len - i;
182 +
183 + if (n < 16)
184 + break;
185 +
186 + NEON_accum32(pair, buf + i, n / 16);
187 + pair[0] %= M_BASE;
188 + pair[1] %= M_BASE;
189 +
190 + done += (n / 16) * 16;
191 + }
192 +
193 + /* Handle the tail elements. */
194 + if (done < len) {
195 + NEON_handle_tail(pair, (buf + done), len - done);
196 + pair[0] %= M_BASE;
197 + pair[1] %= M_BASE;
198 + }
199 +
200 + /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */
201 + return (pair[1] << 16) | pair[0];
202 +}
203 +#endif
204 diff --git a/third_party/zlib/neon_adler32.h b/third_party/zlib/neon_adler32.h
205 new file mode 100644
206 index 0000000..febe9a1
207 --- /dev/null
208 +++ b/third_party/zlib/neon_adler32.h
209 @@ -0,0 +1,13 @@
210 +/* Copyright 2017 The Chromium Authors. All rights reserved.
211 + * Use of this source code is governed by a BSD-style license that can be
212 + * found in the LICENSE file.
213 +*/
214 +#ifndef __NEON_ADLER32__
215 +#define __NEON_ADLER32__
216 +
217 +#ifdef __ARM_NEON__
218 +unsigned long NEON_adler32(unsigned long adler,
219 + const unsigned char* buf,
220 + const unsigned int len);
221 +#endif
222 +#endif
223 --
224 2.7.4
225
OLDNEW
« no previous file with comments | « third_party/zlib/neon_adler32.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698