Skip to content

Instantly share code, notes, and snippets.

@stryku
Created April 2, 2020 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stryku/b8177a66f79540f912ca8b7909ffccda to your computer and use it in GitHub Desktop.
Save stryku/b8177a66f79540f912ca8b7909ffccda to your computer and use it in GitHub Desktop.
Branchless conversion of a hex character to its value
// Requires google's benchmark library: https://github.com/google/benchmark
#include <benchmark/benchmark.h>
#include <cstdint>
constexpr auto k_samples_count = 1000000u;
uint8_t random_char()
{
constexpr char chars[] = "0123456789abcdefABCDEF";
return chars[rand() % 22u];
}
char to_value_with_branches(uint8_t c)
{
if (c >= 'a') {
c -= 'a' - ':';
} else if (c >= 'A') {
c -= 'A' - ':';
}
return c - '0';
}
static void OldRustyCalculations(benchmark::State& state)
{
srand(0);
while (state.KeepRunning()) {
for (auto i = 0u; i < k_samples_count; ++i) {
const auto c = to_value_with_branches(random_char());
benchmark::DoNotOptimize(c);
}
}
}
BENCHMARK(OldRustyCalculations);
char to_value_branchless(uint8_t c)
{
constexpr uint8_t to_add[] = { 0, 9 };
const bool is_alpha_char = (c & 0b01000000u);
return (c & 0x0fu) + to_add[is_alpha_char];
}
static void ShinyBranchless(benchmark::State& state)
{
srand(0);
while (state.KeepRunning()) {
for (auto i = 0u; i < k_samples_count; ++i) {
const auto c = to_value_branchless(random_char());
benchmark::DoNotOptimize(c);
}
}
}
BENCHMARK(ShinyBranchless);
BENCHMARK_MAIN();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment