1 /*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 /*
8 * This test ensures that the backends can deal with bit manipulation
9 * intrinsics.
10 */
11
12 #include <stdio.h>
13 #include <stdint.h>
14 #include "native_client/tests/toolchain/utils.h"
15
16 /* __builtin_popcount[ll](x) */
17 uint32_t llvm_intrinsic_ctpop(uint32_t) __asm__("llvm.ctpop.i32");
18 uint64_t llvm_intrinsic_ctpopll(uint64_t) __asm__("llvm.ctpop.i64");
19
20 /* __builtin_clz[ll](x) */
21 uint32_t llvm_intrinsic_ctlz(uint32_t, _Bool) __asm__("llvm.ctlz.i32");
22 uint64_t llvm_intrinsic_ctlzll(uint64_t, _Bool) __asm__("llvm.ctlz.i64");
23
24 /* __builtin_ctz[ll](x) */
25 uint32_t llvm_intrinsic_cttz(uint32_t, _Bool) __asm__("llvm.cttz.i32");
26 uint64_t llvm_intrinsic_cttzll(uint64_t, _Bool) __asm__("llvm.cttz.i64");
27
28 /* __builtin_bswap{16,32,64}(x) */
29 uint16_t llvm_intrinsic_bswap16(uint16_t) __asm__("llvm.bswap.i16");
30 uint32_t llvm_intrinsic_bswap32(uint32_t) __asm__("llvm.bswap.i32");
31 uint64_t llvm_intrinsic_bswap64(uint64_t) __asm__("llvm.bswap.i64");
32
33 /* volatile prevents partial evaluation by llvm */
34 volatile uint16_t i16[] = {0, 0xabcd, 0xdcba, 0xffff};
35 volatile uint32_t i32[] = {0, 0x01234567, 0x12345670, 0xffffffff};
36 volatile uint64_t i64[] = {0, 0x0123456789abcdefll,
37 0x0123456789abcdef0ll, 0xffffffffffffffffll};
38
39 /*
40 * LLVM had a bug generating ARM code with large array offsets. The function
41 * needs a constant offset > 255 to trigger the bug.
42 */
43 volatile uint16_t i16l[257] = {[256] = 0xabcd};
44 volatile uint32_t i32l[257] = {[256] = 0x01234567};
45 volatile uint64_t i64l[257] = {[256] = 0x0123456789abcdefll};
46
47 #define print_op(op, x) \
48 printf("%30s: %u\n", #op " (llvm)", (unsigned) llvm_intrinsic_ ## op(x))
49
50 #define print_op2(op, x, y) \
51 printf("%30s: %u\n", #op " (llvm)", (unsigned) llvm_intrinsic_ ## op(x, y))
52
53 #define print_op_builtin(op, x) \
54 printf("%30s: %u\n", #op " (builtin)", (unsigned) __builtin_ ## op(x))
55
main(int argc,char * argv[])56 int main(int argc, char* argv[]) {
57 int i;
58
59 for (i = 0; i < ARRAY_SIZE_UNSAFE(i16); ++i) {
60 printf("\n%30s: 0x%04hx\n", "i16 value is", i16[i]);
61 printf("%30s: 0x%04hx\n", "bswap (llvm)", llvm_intrinsic_bswap16(i16[i]));
62 printf("%30s: 0x%04hx\n", "bswap (builtin)", __builtin_bswap16(i16[i]));
63 }
64
65 for (i = 0; i < ARRAY_SIZE_UNSAFE(i32); ++i) {
66 printf("\n%30s: 0x%08x\n", "i32 value is", i32[i]);
67 print_op(ctpop, i32[i]);
68 print_op_builtin(popcount, i32[i]);
69
70 print_op2(ctlz, i32[i], 0 /* Don't return undef for 0 input! */);
71 /* 0 gives undefined results for the builtin on x86 */
72 if (i32[i] == 0)
73 printf("%30s: %u\n", "clz (builtin-manual-check)", 32);
74 else
75 print_op_builtin(clz, i32[i]);
76
77 print_op2(cttz, i32[i], 0 /* Don't return undef for 0 input! */);
78 /* 0 gives undefined results for the builtin on x86 */
79 if (i32[i] == 0)
80 printf("%30s: %u\n", "ctz (builtin-manual-check)", 32);
81 else
82 print_op_builtin(ctz, i32[i]);
83
84 printf("%30s: 0x%08x\n", "bswap (llvm)", llvm_intrinsic_bswap32(i32[i]));
85 printf("%30s: 0x%08x\n", "bswap (builtin)", __builtin_bswap32(i32[i]));
86 }
87
88 for (i = 0; i < ARRAY_SIZE_UNSAFE(i64); ++i) {
89 printf("\n%30s: 0x%016llx\n", "i64 value is", i64[i]);
90 print_op(ctpopll, i64[i]);
91 print_op_builtin(popcountll, i64[i]);
92
93 print_op2(ctlzll, i64[i], 0 /* Don't return undef for 0 input! */);
94 /* 0 gives undefined results for the builtin on x86 */
95 if (i64[i] == 0)
96 printf("%30s: %u\n", "clzll (builtin-manual-check)", 64);
97 else
98 print_op_builtin(clzll, i64[i]);
99
100 print_op2(cttzll, i64[i], 0 /* Don't return undef for 0 input! */);
101 /* 0 gives undefined results for the builtin on x86 */
102 if (i64[i] == 0)
103 printf("%30s: %u\n", "ctzll (builtin-manual-check)", 64);
104 else
105 print_op_builtin(ctzll, i64[i]);
106
107 printf("%30s: 0x%016llx\n", "bswapll (llvm)",
108 llvm_intrinsic_bswap64(i64[i]));
109 printf("%30s: 0x%016llx\n", "bswapll (builtin)",
110 __builtin_bswap64(i64[i]));
111 }
112
113 printf("\nLarge offset tests:\n");
114 printf("%30s: 0x%04hx\n", "bswap (llvm)", llvm_intrinsic_bswap16(i16l[256]));
115 printf("%30s: 0x%04hx\n", "bswap (builtin)", __builtin_bswap16(i16l[256]));
116 printf("%30s: 0x%08x\n", "bswap (llvm)", llvm_intrinsic_bswap32(i32l[256]));
117 printf("%30s: 0x%08x\n", "bswap (builtin)", __builtin_bswap32(i32l[256]));
118 printf("%30s: 0x%016llx\n", "bswapll (llvm)",
119 llvm_intrinsic_bswap64(i64l[256]));
120 printf("%30s: 0x%016llx\n", "bswapll (builtin)",
121 __builtin_bswap64(i64l[256]));
122
123 return 0;
124 }
125