=head1 LIBECB You suck, we don't(tm) =head2 ABOUT THE HEADER - how to include it - it includes inttypes.h - no .a - whats a bool - function mean macro or function - macro means untyped =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. =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 optimsied 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) [MACRO] 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) [MACRO] 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 (bool) [MACRO] =item bool ecb_unlikely (bool) [MACRO] 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 0-ptr 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) - eahc 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) [MACRO] 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 supressing a warning in some cases, this function can be used to implement C or similar functions. =item bool ecb_prefetch (addr, rw, locality) [MACRO] 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 prefethces 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 () =item int ecb_ctz32 (uint32_t x) =item int ecb_popcount32 (uint32_t x) =item uint32_t ecb_bswap16 (uint32_t x) =item uint32_t ecb_bswap32 (uint32_t x) =item uint32_t ecb_rotr32 (uint32_t x, unsigned int count) =item uint32_t ecb_rotl32 (uint32_t x, unsigned int count) =back =head2 ARITHMETIC =over 4 =item x = ecb_mod (m, n) [MACRO] =back =head2 UTILITY =over 4 =item element_count = ecb_array_length (name) [MACRO] =back