=head1 LIBECB - e-C-Builtins =head2 ABOUT LIBECB Libecb is currently a simple header file that doesn't require any configuration to use or include in your project. It's part of the e-suite of libraries, other memembers of which include libev and libeio. Its homepage can be found here: http://software.schmorp.de/pkg/libecb It mainly provides a number of wrappers around GCC built-ins, together with replacement functions for other compilers. In addition to this, it provides a number of other lowlevel C utilities, such endienness detection, byte swapping or bit rotations. More might come. =head2 ABOUT THE HEADER At the moment, all you have to do is copy F somewhere where your compiler can find it and include it: #include The header should work fine for both C and C++ compilation, and gives you all of F in addition to the ECB symbols. There are currently no objetc files to link to - future versions might come with an (optional) object code library to link against, to reduce code size or gain access to additional features. It also currently includes everything from F. =head2 ABOUT THIS MANUAL / CONVENTIONS This manual mainly describes each (public) function available after including the F header. The header might define other symbols than these, but these are not part of the public API, and not supported in any way. When the manual mentions a "function" then this could be defined either as as inline function, a macro, or an external symbol. When functions use a concrete standard type, such as C or C, then the corresponding function works only with that type. If only a generic name is used (C, C, C and so on), then the corresponding function relies on C to implement the correct types, and is usually implemented as a macro. Specifically, a "bool" in this manual refers to any kind of boolean value, not a specific type. =head2 GCC ATTRIBUTES blabla where to put, what others =over 4 =item ecb_attribute ((attrs...)) A simple wrapper that expands to C<__attribute__((attrs))> on GCC, and to nothing on other compilers, so the effect is that only GCC sees these. Example: use the C attribute on a function. ecb_attribute((__deprecated__)) void do_not_use_me_anymore (void); =item ecb_unused Marks a function or a variable as "unused", which simply suppresses a warning by GCC when it detects it as unused. This is useful when you e.g. declare a variable but do not always use it: { int var ecb_unused; #ifdef SOMECONDITION var = ...; return var; #else return 0; #endif } =item ecb_noinline Prevent a function from being inlined - it might be optimised away, but not inlined into other functions. This is useful if you know your function is rarely called and large enough for inlining not to be helpful. =item ecb_noreturn =item ecb_const =item ecb_pure =item ecb_hot =item ecb_cold =item ecb_artificial =back =head2 OPTIMISATION HINTS =over 4 =item bool ecb_is_constant(expr) Returns true iff the expression can be deduced to be a compile-time constant, and false otherwise. For example, when you have a C function that returns a 16 bit random number, and you have a function that maps this to a range from 0..n-1, then you could use this inline function in a header file: ecb_inline uint32_t rndm (uint32_t n) { return (n * (uint32_t)rndm16 ()) >> 16; } However, for powers of two, you could use a normal mask, but that is only worth it if, at compile time, you can detect this case. This is the case when the passed number is a constant and also a power of two (C): ecb_inline uint32_t rndm (uint32_t n) { return is_constant (n) && !(n & (n - 1)) ? rndm16 () & (num - 1) : (n * (uint32_t)rndm16 ()) >> 16; } =item bool ecb_expect (expr, value) Evaluates C and returns it. In addition, it tells the compiler that the C evaluates to C a lot, which can be used for static branch optimisations. Usually, you want to use the more intuitive C and C functions instead. =item bool ecb_likely (cond) =item bool ecb_unlikely (cond) These two functions expect a expression that is true or false and return C<1> or C<0>, respectively, so when used in the condition of an C or other conditional statement, it will not change the program: /* these two do the same thing */ if (some_condition) ...; if (ecb_likely (some_condition)) ...; However, by using C, you tell the compiler that the condition is likely to be true (and for C, that it is unlikely to be true). For example, when you check for a null pointer and expect this to be a rare, exceptional, case, then use C: void my_free (void *ptr) { if (ecb_unlikely (ptr == 0)) return; } Consequent use of these functions to mark away exceptional cases or to tell the compiler what the hot path through a function is can increase performance considerably. A very good example is in a function that reserves more space for some memory block (for example, inside an implementation of a string stream) - each time something is added, you have to check for a buffer overrun, but you expect that most checks will turn out to be false: /* make sure we have "size" extra room in our buffer */ ecb_inline void reserve (int size) { if (ecb_unlikely (current + size > end)) real_reserve_method (size); /* presumably noinline */ } =item bool ecb_assume (cond) Try to tell the compiler that some condition is true, even if it's not obvious. This can be used to teach the compiler about invariants or other conditions that might improve code generation, but which are impossible to deduce form the code itself. For example, the example reservation function from the C description could be written thus (only C was added): ecb_inline void reserve (int size) { if (ecb_unlikely (current + size > end)) real_reserve_method (size); /* presumably noinline */ ecb_assume (current + size <= end); } If you then call this function twice, like this: reserve (10); reserve (1); Then the compiler I be able to optimise out the second call completely, as it knows that C<< current + 1 > end >> is false and the call will never be executed. =item bool ecb_unreachable () This function does nothing itself, except tell the compiler that it will never be executed. Apart from suppressing a warning in some cases, this function can be used to implement C or similar functions. =item bool ecb_prefetch (addr, rw, locality) Tells the compiler to try to prefetch memory at the given Cess for either reading (C = 0) or writing (C = 1). A C of C<0> means that there will only be one access later, C<3> means that the data will likely be accessed very often, and values in between mean something... in between. The memory pointed to by the address does not need to be accessible (it could be a null pointer for example), but C and C must be compile-time constants. An obvious way to use this is to prefetch some data far away, in a big array you loop over. This prefetches memory some 128 array elements later, in the hope that it will be ready when the CPU arrives at that location. int sum = 0; for (i = 0; i < N; ++i) { sum += arr [i] ecb_prefetch (arr + i + 128, 0, 0); } It's hard to predict how far to prefetch, and most CPUs that can prefetch are often good enough to predict this kind of behaviour themselves. It gets more interesting with linked lists, especially when you do some fair processing on each list element: for (node *n = start; n; n = n->next) { ecb_prefetch (n->next, 0, 0); ... do medium amount of work with *n } After processing the node, (part of) the next node might already be in cache. =back =head2 BIT FIDDLING / BITSTUFFS =over 4 =item bool ecb_big_endian () =item bool ecb_little_endian () These two functions return true if the byte order is big endian (most-significant byte first) or little endian (least-significant byte first) respectively. =item int ecb_ctz32 (uint32_t x) Returns the index of the least significant bit set in C (or equivalently the number of bits set to 0 before the least significant bit set), starting from 0. If C is 0 the result is undefined. A common use case is to compute the integer binary logarithm, i.e., floor(log2(n)). For example: ecb_ctz32 (3) = 0 ecb_ctz32 (6) = 1 =item int ecb_popcount32 (uint32_t x) Returns the number of bits set to 1 in C. For example: ecb_popcount32 (7) = 3 ecb_popcount32 (255) = 8 =item uint32_t ecb_bswap16 (uint32_t x) =item uint32_t ecb_bswap32 (uint32_t x) These two functions return the value of the 16-bit (32-bit) variable C after reversing the order of bytes. =item uint32_t ecb_rotr32 (uint32_t x, unsigned int count) =item uint32_t ecb_rotl32 (uint32_t x, unsigned int count) These two functions return the value of C after shifting all the bits by C positions to the right or left respectively. =back =head2 ARITHMETIC =over 4 =item x = ecb_mod (m, n) Returns the positive remainder of the modulo operation between C and C. Unlike the C moduloe operator C<%>, this function ensures that the return value is always positive). C must be strictly positive (i.e. C<< >1 >>), while C must be negatable, that is, both C and C<-m> must be representable in its type. =back =head2 UTILITY =over 4 =item element_count = ecb_array_length (name) [MACRO] Returns the number of elements in the array C. For example: int primes[] = { 2, 3, 5, 7, 11 }; int sum = 0; for (i = 0; i < ecb_array_length (primes); i++) sum += primes [i]; =back