blob: 671befa550a90411de9a6f289fcb68a69d34a7c7 [file] [log] [blame]
/*
* Copyright (c) 2011 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This test ensures that the backends can deal with bit manipulation
* intrinsics.
*/
#include <stdio.h>
#include <stdint.h>
#include "native_client/tests/toolchain/utils.h"
/* __builtin_popcount[ll](x) */
uint32_t llvm_intrinsic_ctpop(uint32_t) __asm__("llvm.ctpop.i32");
uint64_t llvm_intrinsic_ctpopll(uint64_t) __asm__("llvm.ctpop.i64");
/* __builtin_clz[ll](x) */
uint32_t llvm_intrinsic_ctlz(uint32_t, _Bool) __asm__("llvm.ctlz.i32");
uint64_t llvm_intrinsic_ctlzll(uint64_t, _Bool) __asm__("llvm.ctlz.i64");
/* __builtin_ctz[ll](x) */
uint32_t llvm_intrinsic_cttz(uint32_t, _Bool) __asm__("llvm.cttz.i32");
uint64_t llvm_intrinsic_cttzll(uint64_t, _Bool) __asm__("llvm.cttz.i64");
/* __builtin_bswap{16,32,64}(x) */
uint16_t llvm_intrinsic_bswap16(uint16_t) __asm__("llvm.bswap.i16");
uint32_t llvm_intrinsic_bswap32(uint32_t) __asm__("llvm.bswap.i32");
uint64_t llvm_intrinsic_bswap64(uint64_t) __asm__("llvm.bswap.i64");
/* volatile prevents partial evaluation by llvm */
volatile uint16_t i16[] = {0, 0xabcd, 0xdcba, 0xffff};
volatile uint32_t i32[] = {0, 0x01234567, 0x12345670, 0xffffffff};
volatile uint64_t i64[] = {0, 0x0123456789abcdefll,
0x0123456789abcdef0ll, 0xffffffffffffffffll};
/*
* LLVM had a bug generating ARM code with large array offsets. The function
* needs a constant offset > 255 to trigger the bug.
*/
volatile uint16_t i16l[257] = {[256] = 0xabcd};
volatile uint32_t i32l[257] = {[256] = 0x01234567};
volatile uint64_t i64l[257] = {[256] = 0x0123456789abcdefll};
#define print_op(op, x) \
printf("%30s: %u\n", #op " (llvm)", (unsigned) llvm_intrinsic_ ## op(x))
#define print_op2(op, x, y) \
printf("%30s: %u\n", #op " (llvm)", (unsigned) llvm_intrinsic_ ## op(x, y))
#define print_op_builtin(op, x) \
printf("%30s: %u\n", #op " (builtin)", (unsigned) __builtin_ ## op(x))
int main(int argc, char* argv[]) {
int i;
for (i = 0; i < ARRAY_SIZE_UNSAFE(i16); ++i) {
printf("\n%30s: 0x%04hx\n", "i16 value is", i16[i]);
printf("%30s: 0x%04hx\n", "bswap (llvm)", llvm_intrinsic_bswap16(i16[i]));
printf("%30s: 0x%04hx\n", "bswap (builtin)", __builtin_bswap16(i16[i]));
}
for (i = 0; i < ARRAY_SIZE_UNSAFE(i32); ++i) {
printf("\n%30s: 0x%08x\n", "i32 value is", i32[i]);
print_op(ctpop, i32[i]);
print_op_builtin(popcount, i32[i]);
print_op2(ctlz, i32[i], 0 /* Don't return undef for 0 input! */);
/* 0 gives undefined results for the builtin on x86 */
if (i32[i] == 0)
printf("%30s: %u\n", "clz (builtin-manual-check)", 32);
else
print_op_builtin(clz, i32[i]);
print_op2(cttz, i32[i], 0 /* Don't return undef for 0 input! */);
/* 0 gives undefined results for the builtin on x86 */
if (i32[i] == 0)
printf("%30s: %u\n", "ctz (builtin-manual-check)", 32);
else
print_op_builtin(ctz, i32[i]);
printf("%30s: 0x%08x\n", "bswap (llvm)", llvm_intrinsic_bswap32(i32[i]));
printf("%30s: 0x%08x\n", "bswap (builtin)", __builtin_bswap32(i32[i]));
}
for (i = 0; i < ARRAY_SIZE_UNSAFE(i64); ++i) {
printf("\n%30s: 0x%016llx\n", "i64 value is", i64[i]);
print_op(ctpopll, i64[i]);
print_op_builtin(popcountll, i64[i]);
print_op2(ctlzll, i64[i], 0 /* Don't return undef for 0 input! */);
/* 0 gives undefined results for the builtin on x86 */
if (i64[i] == 0)
printf("%30s: %u\n", "clzll (builtin-manual-check)", 64);
else
print_op_builtin(clzll, i64[i]);
print_op2(cttzll, i64[i], 0 /* Don't return undef for 0 input! */);
/* 0 gives undefined results for the builtin on x86 */
if (i64[i] == 0)
printf("%30s: %u\n", "ctzll (builtin-manual-check)", 64);
else
print_op_builtin(ctzll, i64[i]);
printf("%30s: 0x%016llx\n", "bswapll (llvm)",
llvm_intrinsic_bswap64(i64[i]));
printf("%30s: 0x%016llx\n", "bswapll (builtin)",
__builtin_bswap64(i64[i]));
}
printf("\nLarge offset tests:\n");
printf("%30s: 0x%04hx\n", "bswap (llvm)", llvm_intrinsic_bswap16(i16l[256]));
printf("%30s: 0x%04hx\n", "bswap (builtin)", __builtin_bswap16(i16l[256]));
printf("%30s: 0x%08x\n", "bswap (llvm)", llvm_intrinsic_bswap32(i32l[256]));
printf("%30s: 0x%08x\n", "bswap (builtin)", __builtin_bswap32(i32l[256]));
printf("%30s: 0x%016llx\n", "bswapll (llvm)",
llvm_intrinsic_bswap64(i64l[256]));
printf("%30s: 0x%016llx\n", "bswapll (builtin)",
__builtin_bswap64(i64l[256]));
return 0;
}