source: trunk/lib/builtins.hpp @ 5715

Last change on this file since 5715 was 3392, checked in by cameron, 6 years ago

Return int rather than uint32_t saves a conversion

File size: 2.8 KB
Line 
1#ifndef BUILTINS_HPP_
2#define BUILTINS_HPP_
3
4/*=============================================================================
5    builtin - Compiler dependent builtin function wrappers.
6
7    Copyright (C) 2011, Robert D. Cameron, Kenneth S. Herdy.
8    Licensed to the public under the Open Software License 3.0.
9    Licensed to International Characters Inc.
10       under the Academic Free License version 3.0.
11=============================================================================*/
12
13#include "config.hpp"
14
15static IDISA_ALWAYS_INLINE long likely(long x);
16static IDISA_ALWAYS_INLINE long unlikely(long x);
17
18#if defined (_MSC_VER)
19        IDISA_ALWAYS_INLINE long likely(long x) {
20                return x;
21        }
22        IDISA_ALWAYS_INLINE long unlikely(long x) {
23                return x;
24        }
25
26#elif defined (__GNUC__)
27
28        IDISA_ALWAYS_INLINE long likely(long x) {
29                return __builtin_expect(x, 1);
30        }
31
32        IDISA_ALWAYS_INLINE long unlikely(long x) {
33                return __builtin_expect(x, 0);
34        }
35
36#endif
37
38#include <stdint.h>
39#if defined (_MSC_VER)
40        #include <intrin.h>
41
42        #ifdef _M_X64
43        typedef unsigned __int64 ScanWord;
44        #define ScanForwardIntrinsic _BitScanForward64
45        #define ScanReverseIntrinsic _BitScanReverse64
46        #else
47        typedef unsigned __int32 ScanWord;
48        #define ScanForwardIntrinsic _BitScanForward
49        #define ScanReverseIntrinsic _BitScanReverse
50        #endif
51
52        #pragma intrinsic(ScanForwardIntrinsic)
53        #pragma intrinsic(ScanReverseIntrinsic)
54        IDISA_ALWAYS_INLINE uint32_t scan_forward_zeroes(ScanWord x) { // Precondition: x != 0
55                unsigned long zeroes;
56                ScanForwardIntrinsic(&zeroes, x);
57                return (uint32_t) zeroes;
58        }
59
60        IDISA_ALWAYS_INLINE uint32_t scan_backward_zeroes(ScanWord x) { // Precondition: x != 0
61                unsigned long pos;
62                ScanReverseIntrinsic(&pos, x);
63                return (uint32_t) (8* sizeof(ScanWord) - pos - 1);
64        }
65
66        #undef ScanForwardIntrinsic
67        #undef ScanReverseIntrinsic
68
69#elif defined (__GNUC__)
70
71        #if __x86_64__ /* 64-bit architecture */
72        typedef uint64_t ScanWord;
73        #define ScanForwardIntrinsic __builtin_ctzll
74        #define ScanReverseIntrinsic __builtin_clzll
75
76        #else
77        typedef uint32_t ScanWord;
78        #define ScanForwardIntrinsic __builtin_ctzl
79        #define ScanReverseIntrinsic __builtin_clzl
80        #endif
81
82        IDISA_ALWAYS_INLINE int scan_forward_zeroes(ScanWord x) { // Precondition: x != 0
83                return ScanForwardIntrinsic((ScanWord) x);
84        }
85
86        IDISA_ALWAYS_INLINE int scan_backward_zeroes(ScanWord x) { // Precondition: x != 0
87                return ScanReverseIntrinsic((ScanWord) x);
88        }
89
90        #undef ScanForwardIntrinsic
91        #undef ScanReverseIntrinsic
92
93#else
94  #warning "Neither _MSC_VER nor __GNUC__ defined: scan_forward/backward_zeroes not implemented."
95#endif
96
97#endif // BUILTINS_HPP
Note: See TracBrowser for help on using the repository browser.