Re: [PATCH] document optimizing macro for translating PROT_ to VM_ bits

From: Muli Ben-Yehuda
Date: Tue Sep 30 2003 - 04:42:42 EST


On Tue, Sep 30, 2003 at 04:59:56PM +0900, Miles Bader wrote:
> Muli Ben-Yehuda <mulix@xxxxxxxxx> 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

Attachment: signature.asc
Description: Digital signature