blob: b56d775ce75a6bc9a684485157ea1db902197688 [file] [log] [blame]
/*
* A performance regression test for bit reverse. The bit reverse algorithm on
* PPC was O(N) and had lots of dependency between contiguous instructions. We
* replace it with a faster O(lgN) algorithm in the following two patches:
* https://reviews.llvm.org/D33572
* https://reviews.llvm.org/D34908
* This test case tests both the 32-bit and 64-bit bit reverse to ensure the
* new implementation is functionally correct and has a better performance.
*/
#include <stdio.h>
#include <stdlib.h>
#define NUM 0x1000000
unsigned __attribute__((noinline)) ReverseBits32(unsigned n) {
n = ((n >> 1) & 0x55555555u) | ((n & 0x55555555u) << 1);
n = ((n >> 2) & 0x33333333u) | ((n & 0x33333333u) << 2);
n = ((n >> 4) & 0x0F0F0F0Fu) | ((n & 0x0F0F0F0Fu) << 4);
return ((n & 0xff000000u) >> 24) | ((n & 0x00ff0000u) >> 8) |
((n & 0x0000ff00u) << 8) | ((n & 0x000000ffu) << 24);
}
unsigned long long __attribute__((noinline)) ReverseBits64(unsigned long long n) {
n = ((n >> 1) & 0x5555555555555555ull) | ((n & 0x5555555555555555ull) << 1);
n = ((n >> 2) & 0x3333333333333333ull) | ((n & 0x3333333333333333ull) << 2);
n = ((n >> 4) & 0x0F0F0F0F0F0F0F0Full) | ((n & 0x0F0F0F0F0F0F0F0Full) << 4);
return ((n & 0xFF00000000000000ull) >> 56) |
((n & 0x00FF000000000000ull) >> 40) |
((n & 0x0000FF0000000000ull) >> 24) |
((n & 0x000000FF00000000ull) >> 8) |
((n & 0x00000000000000FFull) << 56) |
((n & 0x000000000000FF00ull) << 40) |
((n & 0x0000000000FF0000ull) << 24) |
((n & 0x00000000FF000000ull) << 8);
}
int main (void) {
unsigned long long sum32 = 0, sum64 = 0;
unsigned int rev32 = strtoll("0x12345678", NULL, 16);
unsigned long long rev64 = strtoll("0x0123456789012345", NULL, 16);
// Check for compilers that don't support __has_builtin
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
// Check for compilers that support __has_builtin but not __builtin_bitreverse*
#if (!__has_builtin(__builtin_bitreverse32) ||\
!__has_builtin(__builtin_bitreverse64))
printf("0x%x -> 0x%x\n", rev32, ReverseBits32(rev32));
printf("0x%llx -> 0x%llx\n", rev64, ReverseBits64(rev64));
return 0;
#else
for (int i = 0; i < NUM; ++i) {
sum32 += ReverseBits32(i);
sum64 += ReverseBits64(i);
}
for (int i = 0; i < NUM; ++i) {
sum32 -= __builtin_bitreverse32(i);
sum64 -= __builtin_bitreverse64(i);
}
printf("0x%x -> 0x%x\n", rev32, __builtin_bitreverse32(rev32));
printf("0x%llx -> 0x%llx\n", rev64, __builtin_bitreverse64(rev64));
return sum32 == 0 && sum64 == 0 ? 0 : 1;
#endif
}