Skip to content

Commit 6ebf3b5

Browse files
authored
Merge pull request #1566 from evoskuil/master
Native hash style, comments, optimization.
2 parents af5a0dc + f565476 commit 6ebf3b5

9 files changed

Lines changed: 59 additions & 54 deletions

File tree

include/bitcoin/system/hash/sha/algorithm.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ class algorithm
234234
INLINE static constexpr void input(buffer_t& buffer, const block_t& block) NOEXCEPT;
235235
INLINE static constexpr void input_left(auto& buffer, const half_t& half) NOEXCEPT;
236236
INLINE static constexpr void input_right(auto& buffer, const half_t& half) NOEXCEPT;
237-
INLINE static constexpr void reinput_left(auto& buffer, const auto& left) NOEXCEPT;
238-
INLINE static constexpr void reinput_right(auto& buffer, const auto& right) NOEXCEPT;
237+
INLINE static constexpr void inject_left(auto& buffer, const auto& left) NOEXCEPT;
238+
INLINE static constexpr void inject_right(auto& buffer, const auto& right) NOEXCEPT;
239239
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
240240

241241
/// Padding.

include/bitcoin/system/impl/hash/sha/algorithm_double.ipp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ double_hash(const block_t& block) NOEXCEPT
8484
{
8585
static_assert(is_same_type<state_t, chunk_t>);
8686

87-
const auto hash2 = [](const block_t& block) NOEXCEPT
87+
const auto hasher = [](const block_t& block) NOEXCEPT
8888
{
8989
auto state = H::get;
9090
buffer_t buffer{};
@@ -95,7 +95,7 @@ double_hash(const block_t& block) NOEXCEPT
9595
compress(state, buffer);
9696

9797
// Second hash
98-
reinput_left(buffer, state);
98+
inject_left(buffer, state);
9999
pad_half(buffer);
100100
schedule(buffer);
101101
state = H::get;
@@ -106,15 +106,15 @@ double_hash(const block_t& block) NOEXCEPT
106106

107107
if (std::is_constant_evaluated())
108108
{
109-
return hash2(block);
109+
return hasher(block);
110110
}
111111
else if constexpr (native && SHA::strength == 256)
112112
{
113113
return native_double_hash(block);
114114
}
115115
else
116116
{
117-
return hash2(block);
117+
return hasher(block);
118118
}
119119
}
120120

@@ -124,7 +124,7 @@ double_hash(const half_t& half) NOEXCEPT
124124
{
125125
static_assert(is_same_type<state_t, chunk_t>);
126126

127-
const auto hash2 = [](const half_t& half) NOEXCEPT
127+
const auto hasher = [](const half_t& half) NOEXCEPT
128128
{
129129
auto state = H::get;
130130
buffer_t buffer{};
@@ -134,7 +134,7 @@ double_hash(const half_t& half) NOEXCEPT
134134
compress(state, buffer);
135135

136136
// Second hash
137-
reinput_left(buffer, state);
137+
inject_left(buffer, state);
138138
pad_half(buffer);
139139
schedule(buffer);
140140
state = H::get;
@@ -145,15 +145,15 @@ double_hash(const half_t& half) NOEXCEPT
145145

146146
if (std::is_constant_evaluated())
147147
{
148-
return hash2(half);
148+
return hasher(half);
149149
}
150150
else if constexpr (native && SHA::strength == 256)
151151
{
152152
return native_double_hash(half);
153153
}
154154
else
155155
{
156-
return hash2(half);
156+
return hasher(half);
157157
}
158158
}
159159

@@ -163,7 +163,7 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
163163
{
164164
static_assert(is_same_type<state_t, chunk_t>);
165165

166-
const auto hash2 = [](const half_t& left, const half_t& right) NOEXCEPT
166+
const auto hasher = [](const half_t& left, const half_t& right) NOEXCEPT
167167
{
168168
auto state = H::get;
169169
buffer_t buffer{};
@@ -175,7 +175,7 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
175175
compress(state, buffer);
176176

177177
// Second hash
178-
reinput_left(buffer, state);
178+
inject_left(buffer, state);
179179
pad_half(buffer);
180180
schedule(buffer);
181181
state = H::get;
@@ -186,15 +186,15 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
186186

187187
if (std::is_constant_evaluated())
188188
{
189-
return hash2(left, right);
189+
return hasher(left, right);
190190
}
191191
else if constexpr (native && SHA::strength == 256)
192192
{
193193
return native_double_hash(left, right);
194194
}
195195
else
196196
{
197-
return hash2(left, right);
197+
return hasher(left, right);
198198
}
199199
}
200200

include/bitcoin/system/impl/hash/sha/algorithm_functions.ipp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
* You should have received a copy of the GNU Affero General Public License
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
19-
#ifndef LIBBITCOIN_SYSTEM_HASH_SHA_ALGORITHM_FUCNTIONS_IPP
20-
#define LIBBITCOIN_SYSTEM_HASH_SHA_ALGORITHM_FUCNTIONS_IPP
19+
#ifndef LIBBITCOIN_SYSTEM_HASH_SHA_ALGORITHM_FUNCTIONS_IPP
20+
#define LIBBITCOIN_SYSTEM_HASH_SHA_ALGORITHM_FUNCTIONS_IPP
2121

2222
// 4.1 Functions
2323
// ============================================================================

include/bitcoin/system/impl/hash/sha/algorithm_konstant.ipp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,16 @@ TEMPLATE
252252
INLINE constexpr void CLASS::
253253
konstant(buffer_t& buffer) NOEXCEPT
254254
{
255-
if (std::is_constant_evaluated())
256-
{
257-
konstant_(buffer);
258-
}
259-
else if constexpr (vector && !with_clang)
260-
{
261-
vector_konstant(buffer);
262-
}
263-
else
255+
// This optimization is neutral in 4/8/16 lane sha256 perf.
256+
////if (std::is_constant_evaluated())
257+
////{
258+
//// konstant_(buffer);
259+
////}
260+
////else if constexpr (vector && !with_clang)
261+
////{
262+
//// vector_konstant(buffer);
263+
////}
264+
////else
264265
{
265266
konstant_(buffer);
266267
}

include/bitcoin/system/impl/hash/sha/algorithm_merkle.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ merkle_hash_vector(idigests_t& digests, iblocks_t& blocks) NOEXCEPT
372372
compress_(xstate, xbuffer);
373373

374374
// Second hash
375-
reinput_left(xbuffer, xstate);
375+
inject_left(xbuffer, xstate);
376376
pad_half(xbuffer);
377377
schedule_(xbuffer);
378378
xstate = initial;

include/bitcoin/system/impl/hash/sha/algorithm_native.ipp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121

2222
// Native (SHA-NI or NEON)
2323
// ============================================================================
24-
// The iterative method is used for sha native as it is an order of magnitude
25-
// more efficient and cannot benefit from vectorization.
24+
// The rotating variables method is used for sha native. Tha native
25+
// instructions rely on register locality to achieve performance benefits.
26+
// Implementation of native sha using buffer expansion is horribly slow.
27+
// This split creates bifurcations (additional complexities) in this template.
2628

2729
namespace libbitcoin {
2830
namespace system {
@@ -98,9 +100,6 @@ round_4(xint128_t& state0, xint128_t& state1, xint128_t message) NOEXCEPT
98100

99101
// Platform agnostic.
100102
// ----------------------------------------------------------------------------
101-
// Individual state vars are used vs. array to ensure register persistence.
102-
// This creates bifurcations in this template because of the lack of a buffer
103-
// and the differing optimal locations for applying endianness conversions.
104103

105104
TEMPLATE
106105
template <bool Swap>
@@ -223,6 +222,9 @@ native_transform(state_t& state, const auto& block) NOEXCEPT
223222
// accumulation and performs big-endian conversion from state_t to digest_t.
224223
// As padding blocks are generated and therefore do not require endianness
225224
// conversion, those calls are not applied when transforming the pad block.
225+
// This lack of conversion also applies to double hashing. In both cases
226+
// the "inject" functions are using in place of the "input" functions.
227+
// There is no benefit to caching pading because it is not prescheduled.
226228
// ----------------------------------------------------------------------------
227229

228230
TEMPLATE
@@ -251,8 +253,6 @@ template <size_t Blocks>
251253
typename CLASS::digest_t CLASS::
252254
native_finalize(state_t& state) NOEXCEPT
253255
{
254-
// We could use Blocks to cache padding but given the padding blocks are
255-
// unscheduled when performing native transformations there's no benefit.
256256
return native_finalize(state, Blocks);
257257
}
258258

@@ -273,7 +273,7 @@ native_finalize_second(const state_t& state) NOEXCEPT
273273
// Hash a state value and finalize it.
274274
auto state2 = H::get;
275275
words_t block{};
276-
reinput_left(block, state); // swapped
276+
inject_left(block, state); // swapped
277277
pad_half(block); // swapped
278278
return native_finalize(state2, block); // no block swap (swaps state)
279279
}
@@ -288,7 +288,7 @@ native_finalize_double(state_t& state, size_t blocks) NOEXCEPT
288288

289289
// This is native_finalize_second() but reuses the initial block.
290290
auto state2 = H::get;
291-
reinput_left(block, state); // swapped
291+
inject_left(block, state); // swapped
292292
pad_half(block); // swapped
293293
return native_finalize(state2, block); // no block swap (swaps state)
294294
}
@@ -316,8 +316,8 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
316316
{
317317
auto state = H::get;
318318
words_t block{};
319-
reinput_left(block, array_cast<word_t>(left)); // unswapped
320-
reinput_right(block, array_cast<word_t>(right)); // unswapped
319+
inject_left(block, array_cast<word_t>(left)); // unswapped
320+
inject_right(block, array_cast<word_t>(right)); // unswapped
321321
native_transform<true>(state, block); // swap
322322
return native_finalize<one>(state); // no block swap (swaps state)
323323
}
@@ -335,7 +335,7 @@ native_double_hash(const block_t& block) NOEXCEPT
335335

336336
// Second hash
337337
words_t block2{};
338-
reinput_left(block2, state); // swapped
338+
inject_left(block2, state); // swapped
339339
pad_half(block2); // swapped
340340
state = H::get; // [reuse state var]
341341
return native_finalize(state, block2); // no block swap (swaps state)
@@ -352,7 +352,7 @@ native_double_hash(const half_t& half) NOEXCEPT
352352
native_transform<false>(state, block); // no block swap
353353

354354
// Second hash
355-
reinput_left(block, state); // swapped
355+
inject_left(block, state); // swapped
356356
pad_half(block); // swapped
357357
state = H::get; // [reuse state var]
358358
return native_finalize(state, block); // no block swap (swaps state)
@@ -364,13 +364,13 @@ native_double_hash(const half_t& left, const half_t& right) NOEXCEPT
364364
{
365365
auto state = H::get;
366366
words_t block{};
367-
reinput_left(block, array_cast<word_t>(left)); // unswapped
368-
reinput_right(block, array_cast<word_t>(right)); // unswapped
369-
native_transform<true>(state, block); // swap
370-
native_transform<false>(state, pad_block()); // swapped
367+
inject_left(block, array_cast<word_t>(left)); // unswapped
368+
inject_right(block, array_cast<word_t>(right)); // unswapped
369+
native_transform<true>(state, block); // swap
370+
native_transform<false>(state, pad_block()); // swapped
371371

372372
// Second hash
373-
reinput_left(block, state); // swapped
373+
inject_left(block, state); // swapped
374374
pad_half(block); // swapped
375375
state = H::get; // [reuse state var]
376376
return native_finalize(state, block); // no block swap (swaps state)

include/bitcoin/system/impl/hash/sha/algorithm_parsing.ipp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ input(buffer_t& buffer, const block_t& block) NOEXCEPT
5858
}
5959
else if constexpr (bc::is_little_endian)
6060
{
61+
// This optimization is neutral in 4/8/16 lane sha256 perf.
6162
////if constexpr (have_lanes<word_t, 16> && !with_clang)
6263
////{
6364
//// using xword_t = to_extended<word_t, 16>;
@@ -131,6 +132,7 @@ input_left(auto& buffer, const half_t& half) NOEXCEPT
131132
}
132133
else if constexpr (bc::is_little_endian)
133134
{
135+
// This optimization is neutral in 4/8 lane sha256 perf.
134136
////if constexpr (have_lanes<word_t, 8> && !with_clang)
135137
////{
136138
//// using xword_t = to_extended<word_t, 8>;
@@ -185,6 +187,7 @@ input_right(auto& buffer, const half_t& half) NOEXCEPT
185187
}
186188
else if constexpr (bc::is_little_endian)
187189
{
190+
// This optimization is neutral in 4/8 lane sha256 perf.
188191
////if constexpr (have_lanes<word_t, 8> && !with_clang)
189192
////{
190193
//// using xword_t = to_extended<word_t, 8>;
@@ -248,6 +251,7 @@ output(const state_t& state) NOEXCEPT
248251
{
249252
if constexpr (SHA::strength != 160)
250253
{
254+
// This optimization is neutral in 4/8 lane sha256 perf.
251255
////if constexpr (have_lanes<word_t, 8> && !with_clang)
252256
////{
253257
//// using xword_t = to_extended<word_t, 8>;
@@ -306,7 +310,7 @@ output(const state_t& state) NOEXCEPT
306310

307311
TEMPLATE
308312
INLINE constexpr void CLASS::
309-
reinput_left(auto& buffer, const auto& left) NOEXCEPT
313+
inject_left(auto& buffer, const auto& left) NOEXCEPT
310314
{
311315
using words = decltype(buffer);
312316
static_assert(array_count<words> >= SHA::state_words);
@@ -331,7 +335,7 @@ reinput_left(auto& buffer, const auto& left) NOEXCEPT
331335

332336
TEMPLATE
333337
INLINE constexpr void CLASS::
334-
reinput_right(auto& buffer, const auto& right) NOEXCEPT
338+
inject_right(auto& buffer, const auto& right) NOEXCEPT
335339
{
336340
using words = decltype(buffer);
337341
static_assert(array_count<words> >= SHA::state_words);

include/bitcoin/system/impl/hash/sha/algorithm_single.ipp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ TEMPLATE
6262
constexpr typename CLASS::digest_t CLASS::
6363
hash(const half_t& half) NOEXCEPT
6464
{
65-
const auto hash1 = [](const half_t& half) NOEXCEPT
65+
const auto hasher = [](const half_t& half) NOEXCEPT
6666
{
6767
auto state = H::get;
6868
buffer_t buffer{};
@@ -75,23 +75,23 @@ hash(const half_t& half) NOEXCEPT
7575

7676
if (std::is_constant_evaluated())
7777
{
78-
return hash1(half);
78+
return hasher(half);
7979
}
8080
else if constexpr (native && SHA::strength == 256)
8181
{
8282
return native_hash(half);
8383
}
8484
else
8585
{
86-
return hash1(half);
86+
return hasher(half);
8787
}
8888
}
8989

9090
TEMPLATE
9191
constexpr typename CLASS::digest_t CLASS::
9292
hash(const half_t& left, const half_t& right) NOEXCEPT
9393
{
94-
const auto hash1 = [](const half_t& left, const half_t& right) NOEXCEPT
94+
const auto hasher = [](const half_t& left, const half_t& right) NOEXCEPT
9595
{
9696
auto state = H::get;
9797
buffer_t buffer{};
@@ -106,15 +106,15 @@ hash(const half_t& left, const half_t& right) NOEXCEPT
106106

107107
if (std::is_constant_evaluated())
108108
{
109-
return hash1(left, right);
109+
return hasher(left, right);
110110
}
111111
else if constexpr (native && SHA::strength == 256)
112112
{
113113
return native_hash(left, right);
114114
}
115115
else
116116
{
117-
return hash1(left, right);
117+
return hasher(left, right);
118118
}
119119
}
120120

include/bitcoin/system/impl/hash/sha/algorithm_stream.ipp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ finalize_second(const state_t& state) NOEXCEPT
116116
{
117117
auto state2 = H::get;
118118
buffer_t buffer{};
119-
reinput_left(buffer, state);
119+
inject_left(buffer, state);
120120
pad_half(buffer);
121121
schedule(buffer);
122122
compress(state2, buffer);
@@ -150,7 +150,7 @@ finalize_double(state_t& state, size_t blocks) NOEXCEPT
150150

151151
// This is finalize_second() but reuses the initial buffer.
152152
auto state2 = H::get;
153-
reinput_left(buffer, state);
153+
inject_left(buffer, state);
154154
pad_half(buffer);
155155
schedule(buffer);
156156
compress(state2, buffer);

0 commit comments

Comments
 (0)