Messages in this thread | ![/](/images/icornerl.gif) | | Date | Tue, 30 Sep 2003 12:24:03 +0300 | From | Muli Ben-Yehuda <> | Subject | Re: [PATCH] document optimizing macro for translating PROT_ to VM_ bits |
| |
On Tue, Sep 30, 2003 at 04:59:56PM +0900, Miles Bader wrote: > Muli Ben-Yehuda <mulix@mulix.org> writes: > > Ok, that's a pretty convincing argument for scraping that > > version. I'll rewrite it to evaluate the arguments at compile time if > > they're constants, which they are, in our case. Unless someone else > > beats me to it, of course ;-) > > What's wrong with the macro version? The presence of a __ prefix > suggests that it's only used in controlled circumstances anyway, so is > validity-checking on the bit arguments really worthwhile?
I like code that is "future proof", especially when it doesn't cost anything. These examples generate identical code for me with gcc-3.3 and almost identical code with gcc-2.96 (one instruction difference, and I can't tell which is faster), and the inline function barfs when its arguments are incorrect during compile time, whereas the macro will silently give you the wrong results. How does it fare on your arch?
#include <stdio.h> #include <assert.h>
#define BUG_ON(x) assert(x)
/* compiler trap for assert_single_bit. */ extern void __assert_single_bit_failed_dont_exist(void);
/* * assert that only a single bit is on in 'bit' */ #define assert_single_bit(bit) do { \ if (__builtin_constant_p(bit)) { \ if ((bit & (bit -1))) \ __assert_single_bit_failed_dont_exist(); \ } else \ BUG_ON(!(bit & (bit - 1))); \ } while(0) /* * Optimisation function. It is equivalent to: * (x & bit1) ? bit2 : 0 * but this version is faster. * ("bit1" and "bit2" must be single bits). */ static inline unsigned long inline_calc_vm_trans(unsigned long x, unsigned long bit1, unsigned long bit2) { assert_single_bit(bit1); assert_single_bit(bit2);
return ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) : ((x) & (bit1)) / ((bit1) / (bit2))); }
/* Optimisation macro. */ #define macro_calc_vm_trans(x,bit1,bit2) \ ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \ : ((x) & (bit1)) / ((bit1) / (bit2)))
int test3(unsigned long arg) { return macro_calc_vm_trans(arg, 0x20, 0x80); }
int test4(unsigned long arg) { return inline_calc_vm_trans(arg, 0x20, 0x80); }
int main(void) { int l1 = test4(~0UL); int l2 = test3(~0UL); return l1 & l2; /* don't optimize them out */ }
gcc-2.96:
test3: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax andl $32, %eax sall $2, %eax popl %ebp ret
test4: pushl %ebp movl %esp, %ebp subl $8, %esp movl 8(%ebp), %eax andl $32, %eax sall $2, %eax leave ret -- Muli Ben-Yehuda http://www.mulix.org
[unhandled content-type:application/pgp-signature] | ![\](/images/icornerr.gif) |