authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-03-10 10:00:07+13:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-03-10 10:00:07+13:00
log7a893691c0aedf4d7ae68a9eb06800e4094381cc
treea1f4315923fb78ff938edeb6d5bd124b47a1bb5d
parent5a7a0e8518bcb9e63c06dba21d9c9e2bb0827330

Unroll Sha3 inner loop

Issue #699 since fixed. Nearly a x3 perf improvement. Using --release-fast. Sha3_256 (before): 96 Mb/s Sha3_256 (after): 267 Mb/s Sha3_512 (before): 53 Mb/s Sha3_512 (after): 142 Mb/s No real gains from unrolling other initialization loops in crypto functions so have been left as is.

3 files changed, 10 insertions(+), 14 deletions(-)

std/crypto/md5.zig-1
...@@ -108,7 +108,6 @@ pub const Md5 = struct {...@@ -108,7 +108,6 @@ pub const Md5 = struct {
108108
109 var s: [16]u32 = undefined;109 var s: [16]u32 = undefined;
110110
111 // ERROR: cannot unroll this at comptime
112 var i: usize = 0;111 var i: usize = 0;
113 while (i < 16) : (i += 1) {112 while (i < 16) : (i += 1) {
114 // NOTE: Performing or's separately improves perf by ~10%113 // NOTE: Performing or's separately improves perf by ~10%
std/crypto/sha2.zig-2
...@@ -156,7 +156,6 @@ fn Sha2_32(comptime params: Sha2Params32) type { return struct {...@@ -156,7 +156,6 @@ fn Sha2_32(comptime params: Sha2Params32) type { return struct {
156156
157 var s: [64]u32 = undefined;157 var s: [64]u32 = undefined;
158158
159 // ERROR: Cannot unroll at compile-time.
160 var i: usize = 0;159 var i: usize = 0;
161 while (i < 16) : (i += 1) {160 while (i < 16) : (i += 1) {
162 s[i] = 0;161 s[i] = 0;
...@@ -472,7 +471,6 @@ fn Sha2_64(comptime params: Sha2Params64) type { return struct {...@@ -472,7 +471,6 @@ fn Sha2_64(comptime params: Sha2Params64) type { return struct {
472471
473 var s: [80]u64 = undefined;472 var s: [80]u64 = undefined;
474473
475 // ERROR: Cannot unroll at compile-time.
476 var i: usize = 0;474 var i: usize = 0;
477 while (i < 16) : (i += 1) {475 while (i < 16) : (i += 1) {
478 s[i] = 0;476 s[i] = 0;
std/crypto/sha3.zig+10-11
...@@ -123,35 +123,34 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -123,35 +123,34 @@ fn keccak_f(comptime F: usize, d: []u8) void {
123 *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]);123 *r = mem.readIntLE(u64, d[8*i .. 8*i + 8]);
124 }124 }
125125
126 var x: usize = 0;126 comptime var x: usize = 0;
127 var y: usize = 0;127 comptime var y: usize = 0;
128 // TODO: Cannot unroll all loops here due to comptime differences.128 for (RC[0..no_rounds]) |round| {
129 inline for (RC[0..no_rounds]) |round| {
130 // theta129 // theta
131 x = 0; while (x < 5) : (x += 1) {130 x = 0; inline while (x < 5) : (x += 1) {
132 c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20];131 c[x] = s[x] ^ s[x+5] ^ s[x+10] ^ s[x+15] ^ s[x+20];
133 }132 }
134 x = 0; while (x < 5) : (x += 1) {133 x = 0; inline while (x < 5) : (x += 1) {
135 t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1));134 t[0] = c[M5[x+4]] ^ math.rotl(u64, c[M5[x+1]], usize(1));
136 y = 0; while (y < 5) : (y += 1) {135 y = 0; inline while (y < 5) : (y += 1) {
137 s[x + y*5] ^= t[0];136 s[x + y*5] ^= t[0];
138 }137 }
139 }138 }
140139
141 // rho+pi140 // rho+pi
142 t[0] = s[1];141 t[0] = s[1];
143 x = 0; while (x < 24) : (x += 1) {142 x = 0; inline while (x < 24) : (x += 1) {
144 c[0] = s[PIL[x]];143 c[0] = s[PIL[x]];
145 s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]);144 s[PIL[x]] = math.rotl(u64, t[0], ROTC[x]);
146 t[0] = c[0];145 t[0] = c[0];
147 }146 }
148147
149 // chi148 // chi
150 y = 0; while (y < 5) : (y += 1) {149 y = 0; inline while (y < 5) : (y += 1) {
151 x = 0; while (x < 5) : (x += 1) {150 x = 0; inline while (x < 5) : (x += 1) {
152 c[x] = s[x + y*5];151 c[x] = s[x + y*5];
153 }152 }
154 x = 0; while (x < 5) : (x += 1) {153 x = 0; inline while (x < 5) : (x += 1) {
155 s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]);154 s[x + y*5] = c[x] ^ (~c[M5[x+1]] & c[M5[x+2]]);
156 }155 }
157 }156 }