* [KERNEL]: Avoid divide in IS_ALIGN
@ 2007-11-20 13:56 Herbert Xu
2007-11-20 18:17 ` Joe Perches
2007-11-20 21:43 ` linux-os (Dick Johnson)
0 siblings, 2 replies; 6+ messages in thread
From: Herbert Xu @ 2007-11-20 13:56 UTC (permalink / raw)
To: Linus Torvalds, Andrew Morton, Linux Kernel Mailing List
Hi:
[KERNEL]: Avoid divide in IS_ALIGN
I was happy to discover the brand new IS_ALIGN macro and quickly
used it in my code. To my dismay I found that the generated code
used division to perform the test.
This patch fixes it by changing the % test to an &. This avoids
the division.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 94bc996..39b3fa6 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -35,7 +35,7 @@ extern const char linux_proc_banner[];
#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
-#define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0)
+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [KERNEL]: Avoid divide in IS_ALIGN 2007-11-20 13:56 [KERNEL]: Avoid divide in IS_ALIGN Herbert Xu @ 2007-11-20 18:17 ` Joe Perches 2007-11-20 20:22 ` Andrew Morton 2007-11-20 21:43 ` linux-os (Dick Johnson) 1 sibling, 1 reply; 6+ messages in thread From: Joe Perches @ 2007-11-20 18:17 UTC (permalink / raw) To: Herbert Xu; +Cc: Linus Torvalds, Andrew Morton, Linux Kernel Mailing List On Tue, 2007-11-20 at 21:56 +0800, Herbert Xu wrote: > [KERNEL]: Avoid divide in IS_ALIGN > I was happy to discover the brand new IS_ALIGN macro and quickly > used it in my code. To my dismay I found that the generated code > used division to perform the test. > This patch fixes it by changing the % test to an &. This avoids > the division. Perhaps this should use is_power_of_2? #define IS_ALIGNED(x, a) \ ({ typeof(x) _a = (typeof(x))(a); \ is_power_of_2(_a) ? (((x) & (_a - 1)) == 0) \ : (((x) % _a == 0); }) gcc -o2/oS seems to do the right thing. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [KERNEL]: Avoid divide in IS_ALIGN 2007-11-20 18:17 ` Joe Perches @ 2007-11-20 20:22 ` Andrew Morton 0 siblings, 0 replies; 6+ messages in thread From: Andrew Morton @ 2007-11-20 20:22 UTC (permalink / raw) To: Joe Perches; +Cc: herbert, torvalds, linux-kernel On Tue, 20 Nov 2007 10:17:15 -0800 Joe Perches <joe@perches.com> wrote: > On Tue, 2007-11-20 at 21:56 +0800, Herbert Xu wrote: > > [KERNEL]: Avoid divide in IS_ALIGN > > I was happy to discover the brand new IS_ALIGN macro and quickly > > used it in my code. To my dismay I found that the generated code > > used division to perform the test. > > This patch fixes it by changing the % test to an &. This avoids > > the division. > > Perhaps this should use is_power_of_2? > > #define IS_ALIGNED(x, a) \ > ({ typeof(x) _a = (typeof(x))(a); \ > is_power_of_2(_a) ? (((x) & (_a - 1)) == 0) \ > : (((x) % _a == 0); }) > > gcc -o2/oS seems to do the right thing. The other *ALIGN* macros in there are only good for power-of-2 alignments so I guess Herbert's change is OK. The whole thing's a bit crufty really - there's no reason why it _can't_ work on non-power-of-2 numbers 9via an implementation such as you suggest) and there's no commentary in there explaining that this will presently break things. Those macros are sufficiently obscure, risky and undocumented as to make them of dubious value IMO. I mean, anything which forces you to go and stare at the definition for a while when reviewing a callsite isn't worth it. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [KERNEL]: Avoid divide in IS_ALIGN 2007-11-20 13:56 [KERNEL]: Avoid divide in IS_ALIGN Herbert Xu 2007-11-20 18:17 ` Joe Perches @ 2007-11-20 21:43 ` linux-os (Dick Johnson) 2007-11-21 13:06 ` linux-os (Dick Johnson) 1 sibling, 1 reply; 6+ messages in thread From: linux-os (Dick Johnson) @ 2007-11-20 21:43 UTC (permalink / raw) To: Herbert Xu; +Cc: Linus Torvalds, Andrew Morton, Linux Kernel Mailing List On Tue, 20 Nov 2007, Herbert Xu wrote: > Hi: > > [KERNEL]: Avoid divide in IS_ALIGN > > I was happy to discover the brand new IS_ALIGN macro and quickly > used it in my code. To my dismay I found that the generated code > used division to perform the test. > > This patch fixes it by changing the % test to an &. This avoids > the division. > > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> > > Cheers, > -- > Visit Openswan at http://www.openswan.org/ > Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> > Home Page: http://gondor.apana.org.au/~herbert/ > PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt > -- > diff --git a/include/linux/kernel.h b/include/linux/kernel.h > index 94bc996..39b3fa6 100644 > --- a/include/linux/kernel.h > +++ b/include/linux/kernel.h > @@ -35,7 +35,7 @@ extern const char linux_proc_banner[]; > #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) > #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) > #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) > -#define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) > +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) > Your macro modification is wrong. Take 0x12345600, which is aligned on a 16-byte boundary. Now, with your macro, we have for a 0x10 alignment: (0x12345600 & 0x0f) = (0x00 == 0) == TRUE (correct) For an 0x20 alignment: (0x12345600 & 0x1f) = (0x00 == 0) == TRUE (incorrect) In other words, the macro may work for some alignments, but not all. It is therefore wrong. You need the modulus, the remainder after division. Anything else is broken. Cheers, Dick Johnson Penguin : Linux version 2.6.22.1 on an i686 machine (5588.30 BogoMips). My book : http://www.AbominableFirebug.com/ _ **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [KERNEL]: Avoid divide in IS_ALIGN 2007-11-20 21:43 ` linux-os (Dick Johnson) @ 2007-11-21 13:06 ` linux-os (Dick Johnson) 2007-11-21 13:35 ` Andreas Schwab 0 siblings, 1 reply; 6+ messages in thread From: linux-os (Dick Johnson) @ 2007-11-21 13:06 UTC (permalink / raw) To: Herbert Xu; +Cc: Linus Torvalds, Andrew Morton, Linux Kernel Mailing List On Tue, 20 Nov 2007, Richard B. Johnson wrote: > On Tue, 20 Nov 2007, Herbert Xu wrote: > >> Hi: >> >> [KERNEL]: Avoid divide in IS_ALIGN >> >> I was happy to discover the brand new IS_ALIGN macro and quickly >> used it in my code. To my dismay I found that the generated code >> used division to perform the test. >> >> This patch fixes it by changing the % test to an &. This avoids >> the division. >> >> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> >> >> Cheers, >> -- >> Visit Openswan at http://www.openswan.org/ >> Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> >> Home Page: http://gondor.apana.org.au/~herbert/ >> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt >> -- >> diff --git a/include/linux/kernel.h b/include/linux/kernel.h >> index 94bc996..39b3fa6 100644 >> --- a/include/linux/kernel.h >> +++ b/include/linux/kernel.h >> @@ -35,7 +35,7 @@ extern const char linux_proc_banner[]; >> #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) >> #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) >> #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), >> (a))) >> -#define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) >> +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) >> > > Your macro modification is wrong. There was a brain fart on the explaination of why it's wrong. Here is a better explaination. Executing this script............. cat <<EOF >/tmp/xxx.c #include <stdio.h> #define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) #define _IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) int main() { int i; long p = 0x12345678; for(i=1; i< 0x11; i++) printf("Old = %d, new = %d\n", IS_ALIGNED(p, i), _IS_ALIGNED(p, i)); return 0; } EOF gcc -Wall -o /tmp/xxx /tmp/xxx.c /tmp/xxx ... produces: Old = 1, new = 1 Old = 1, new = 1 Old = 1, new = 1 Old = 1, new = 1 Old = 0, new = 1 Old = 1, new = 1 Old = 0, new = 1 Old = 1, new = 1 Old = 1, new = 0 Old = 0, new = 0 Old = 0, new = 0 Old = 1, new = 0 Old = 0, new = 0 Old = 0, new = 0 Old = 0, new = 0 Old = 0, new = 0 Which is clearly different. Cheers, Dick Johnson Penguin : Linux version 2.6.22.1 on an i686 machine (5588.30 BogoMips). My book : http://www.AbominableFirebug.com/ _ **************************************************************** The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to DeliveryErrors@analogic.com - and destroy all copies of this information, including any attachments, without reading or disclosing them. Thank you. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [KERNEL]: Avoid divide in IS_ALIGN 2007-11-21 13:06 ` linux-os (Dick Johnson) @ 2007-11-21 13:35 ` Andreas Schwab 0 siblings, 0 replies; 6+ messages in thread From: Andreas Schwab @ 2007-11-21 13:35 UTC (permalink / raw) To: linux-os (Dick Johnson) Cc: Herbert Xu, Linus Torvalds, Andrew Morton, Linux Kernel Mailing List "linux-os (Dick Johnson)" <linux-os@analogic.com> writes: > Executing this script............. > > cat <<EOF >/tmp/xxx.c > #include <stdio.h> > > #define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) > #define _IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) > > int main() > { > int i; > long p = 0x12345678; > for(i=1; i< 0x11; i++) > printf("Old = %d, new = %d\n", IS_ALIGNED(p, i), _IS_ALIGNED(p, i)); Alignment is only defined for powers of two. Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2007-11-21 13:35 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-11-20 13:56 [KERNEL]: Avoid divide in IS_ALIGN Herbert Xu 2007-11-20 18:17 ` Joe Perches 2007-11-20 20:22 ` Andrew Morton 2007-11-20 21:43 ` linux-os (Dick Johnson) 2007-11-21 13:06 ` linux-os (Dick Johnson) 2007-11-21 13:35 ` Andreas Schwab
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox