History

Add builtins ffs, clz, ctz, clrsb, popcount, parity

Add new file lib/builtin.c Modify include/tccdefs.h, lib/Makefile to compile it. Update tests/tcctest.c to test it.

herman ten brugge committed 3 years ago

Commit dd691431 parent ea0c57e4 files · +193 −5Browse files

Unified · Split

4 files
  1. include/tccdefs.h +15 −0
  2. lib/Makefile +5 −5
  3. lib/builtin.c +124 −0
  4. tests/tcctest.c +49 −0
include/tccdefs.h+15−0
@@ -309,4 +309,19 @@ · 308 unmodified lines
309 #undef __MAYBE_REDIR309 #undef __MAYBE_REDIR
310 #undef __RENAME310 #undef __RENAME
311 311
312#if !defined _WIN32
313 #define __BUILTIN_EXTERN(name,u) \
314 int __builtin_##name(u int); \
315 int __builtin_##name##l(u long); \
316 int __builtin_##name##ll(u long long);
317
318 __BUILTIN_EXTERN(ffs,)
319 __BUILTIN_EXTERN(clz, unsigned)
320 __BUILTIN_EXTERN(ctz, unsigned)
321 __BUILTIN_EXTERN(clrsb,)
322 __BUILTIN_EXTERN(popcount, unsigned)
323 __BUILTIN_EXTERN(parity, unsigned)
324 #undef __BUILTIN_EXTERN
325#endif
326
312 #endif /* ndef __TCC_PP__ */327 #endif /* ndef __TCC_PP__ */
lib/Makefile+5−5
@@ -42,11 +42,11 @@ $(X)BT_O += tcov.o · 41 unmodified lines
42 42
43DSO_O = dsohandle.o43DSO_O = dsohandle.o
44 44
45I386_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o $(BT_O)45I386_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O)
46X86_64_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o $(BT_O)46X86_64_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O)
47ARM_O = libtcc1.o armeabi.o alloca.o armflush.o stdatomic.o atomic.o $(BT_O)47ARM_O = libtcc1.o armeabi.o alloca.o armflush.o stdatomic.o atomic.o builtin.o $(BT_O)
48ARM64_O = lib-arm64.o stdatomic.o atomic.o $(BT_O)48ARM64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O)
49RISCV64_O = lib-arm64.o stdatomic.o atomic.o $(BT_O)49RISCV64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O)
50WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o50WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
51 51
52OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)52OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
lib/builtin.c+124−0
@@ -0,0 +1,124 @@
1/* ---------------------------------------------- */
2/* This file implements:
3 * __builtin_ffs
4 * __builtin_clz
5 * __builtin_ctz
6 * __builtin_clrsb
7 * __builtin_popcount
8 * __builtin_parity
9 * for int, long and long long
10 */
11
12static const unsigned char table_1_32[] = {
13 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
14 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
15};
16static const unsigned char table_2_32[32] = {
17 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
18 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
19};
20static const unsigned char table_1_64[] = {
21 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
22 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
23 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
24 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
25};
26static const unsigned char table_2_64[] = {
27 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2,
28 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1,
29 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18,
30 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0
31};
32
33#define FFSI(x) \
34 return table_1_32[((x & -x) * 0x077cb531u) >> 27] + (x != 0);
35#define FFSL(x) \
36 return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58] + (x != 0);
37#define CTZI(x) \
38 return table_1_32[((x & -x) * 0x077cb531u) >> 27];
39#define CTZL(x) \
40 return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58];
41#define CLZI(x) \
42 x |= x >> 1; \
43 x |= x >> 2; \
44 x |= x >> 4; \
45 x |= x >> 8; \
46 x |= x >> 16; \
47 return table_2_32[(x * 0x07c4acddu) >> 27];
48#define CLZL(x) \
49 x |= x >> 1; \
50 x |= x >> 2; \
51 x |= x >> 4; \
52 x |= x >> 8; \
53 x |= x >> 16; \
54 x |= x >> 32; \
55 return table_2_64[x * 0x03f79d71b4cb0a89ull >> 58];
56#define POPCOUNTI(x, m) \
57 x = x - ((x >> 1) & 0x55555555); \
58 x = (x & 0x33333333) + ((x >> 2) & 0x33333333); \
59 x = (x + (x >> 4)) & 0xf0f0f0f; \
60 return ((x * 0x01010101) >> 24) & m;
61#define POPCOUNTL(x, m) \
62 x = x - ((x >> 1) & 0x5555555555555555ull); \
63 x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull); \
64 x = (x + (x >> 4)) & 0xf0f0f0f0f0f0f0full; \
65 return ((x * 0x0101010101010101ull) >> 56) & m;
66
67/* Returns one plus the index of the least significant 1-bit of x,
68 or if x is zero, returns zero. */
69int __builtin_ffs (int x) { FFSI(x) }
70#if __SIZEOF_LONG__ == 4
71int __builtin_ffsl (long x) { FFSI(x) }
72#else
73int __builtin_ffsl (long x) { FFSL(x) }
74#endif
75int __builtin_ffsll (long long x) { FFSL(x) }
76
77/* Returns the number of leading 0-bits in x, starting at the most significant
78 bit position. If x is 0, the result is undefined. */
79int __builtin_clz (unsigned int x) { CLZI(x) }
80#if __SIZEOF_LONG__ == 4
81int __builtin_clzl (unsigned long x) { CLZI(x) }
82#else
83int __builtin_clzl (unsigned long x) { CLZL(x) }
84#endif
85int __builtin_clzll (unsigned long long x) { CLZL(x) }
86
87/* Returns the number of trailing 0-bits in x, starting at the least
88 significant bit position. If x is 0, the result is undefined. */
89int __builtin_ctz (unsigned int x) { CTZI(x) }
90#if __SIZEOF_LONG__ == 4
91int __builtin_ctzl (unsigned long x) { CTZI(x) }
92#else
93int __builtin_ctzl (unsigned long x) { CTZL(x) }
94#endif
95int __builtin_ctzll (unsigned long long x) { CTZL(x) }
96
97/* Returns the number of leading redundant sign bits in x, i.e. the number
98 of bits following the most significant bit that are identical to it.
99 There are no special cases for 0 or other values. */
100int __builtin_clrsb (int x) { if (x < 0) x = ~x; x <<= 1; CLZI(x) }
101#if __SIZEOF_LONG__ == 4
102int __builtin_clrsbl (long x) { if (x < 0) x = ~x; x <<= 1; CLZI(x) }
103#else
104int __builtin_clrsbl (long x) { if (x < 0) x = ~x; x <<= 1; CLZL(x) }
105#endif
106int __builtin_clrsbll (long long x) { if (x < 0) x = ~x; x <<= 1; CLZL(x) }
107
108/* Returns the number of 1-bits in x.*/
109int __builtin_popcount (unsigned int x) { POPCOUNTI(x, 0x3f) }
110#if __SIZEOF_LONG__ == 4
111int __builtin_popcountl (unsigned long x) { POPCOUNTI(x, 0x3f) }
112#else
113int __builtin_popcountl (unsigned long x) { POPCOUNTL(x, 0x7f) }
114#endif
115int __builtin_popcountll (unsigned long long x) { POPCOUNTL(x, 0x7f) }
116
117/* Returns the parity of x, i.e. the number of 1-bits in x modulo 2. */
118int __builtin_parity (unsigned int x) { POPCOUNTI(x, 0x01) }
119#if __SIZEOF_LONG__ == 4
120int __builtin_parityl (unsigned long x) { POPCOUNTI(x, 0x01) }
121#else
122int __builtin_parityl (unsigned long x) { POPCOUNTL(x, 0x01) }
123#endif
124int __builtin_parityll (unsigned long long x) { POPCOUNTL(x, 0x01) }
tests/tcctest.c+49−0
@@ -3844,6 +3844,36 @@ int constant_p_var; · 3843 unmodified lines
3844 3844
3845int func(void);3845int func(void);
3846 3846
3847#if !defined _WIN32
3848/* __builtin_clz and __builtin_ctz return random values for 0 */
3849static void builtin_test_bits(unsigned long long x, int cnt[])
3850{
3851 cnt[0] += __builtin_ffs(x);
3852 cnt[1] += __builtin_ffsl(x);
3853 cnt[2] += __builtin_ffsll(x);
3854
3855 if ((unsigned int) x) cnt[3] += __builtin_clz(x);
3856 if ((unsigned long) x) cnt[4] += __builtin_clzl(x);
3857 if ((unsigned long long) x) cnt[5] += __builtin_clzll(x);
3858
3859 if ((unsigned int) x) cnt[6] += __builtin_ctz(x);
3860 if ((unsigned long) x) cnt[7] += __builtin_ctzl(x);
3861 if ((unsigned long long) x) cnt[8] += __builtin_ctzll(x);
3862
3863 cnt[9] += __builtin_clrsb(x);
3864 cnt[10] += __builtin_clrsbl(x);
3865 cnt[11] += __builtin_clrsbll(x);
3866
3867 cnt[12] += __builtin_popcount(x);
3868 cnt[13] += __builtin_popcountl(x);
3869 cnt[14] += __builtin_popcountll(x);
3870
3871 cnt[15] += __builtin_parity(x);
3872 cnt[16] += __builtin_parityl(x);
3873 cnt[17] += __builtin_parityll(x);
3874}
3875#endif
3876
3847void builtin_test(void)3877void builtin_test(void)
3848{3878{
3849 short s;3879 short s;
@@ -3897,6 +3927,25 @@ void builtin_test(void) · 47 unmodified lines
3897 printf("bce: %d\n", i);3927 printf("bce: %d\n", i);
3898 3928
3899 //printf("bera: %p\n", __builtin_extract_return_addr((void*)43));3929 //printf("bera: %p\n", __builtin_extract_return_addr((void*)43));
3930
3931#if !defined _WIN32
3932 {
3933 int cnt[18];
3934 unsigned long long r = 0;
3935
3936 memset(cnt, 0, sizeof(cnt));
3937 builtin_test_bits(0, cnt);
3938 builtin_test_bits(0xffffffffffffffffull, cnt);
3939 for (i = 0; i < 64; i++)
3940 builtin_test_bits(1ull << i, cnt);
3941 for (i = 0; i < 1000; i++) {
3942 r = 0x5851f42d4c957f2dull * r + 0x14057b7ef767814full;
3943 builtin_test_bits(r, cnt);
3944 }
3945 for (i = 0; i < 18; i++)
3946 printf ("%d %d\n", i, cnt[i]);
3947 }
3948#endif
3900}3949}
3901 3950
3902#if defined _WIN323951#if defined _WIN32

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t