fix ARCH_HAS_PREFETCH
PATCH 4/21 fix ARCH_HAS_PREFETCH
include/linux/prefetch.h does a strange thing: if the arch doesn't have the prefectch functions, this header defines no-op version of them and then defines ARCH_HAS_PREFETCH. So there's no way for mainline code to know if the architecture *really* has prefetch instructions.
This information loss is unfortunate. Examples:
for (i = 0; i < N; i++) prefetch(foo[i]);
Problem is, if `prefetch' is a no-op, the compiler will still generate an empty busy-wait loop. Which it must do. We need to know the truth about ARCH_HAS_PREFETCH to correctly elide that loop.
#ifdef ARCH_HAS_PREFETCH
#define prefetch_prev_lru_page(_page, _base, _field) \
do { \
if ((_page)->lru.prev != _base) { \
struct page *prev; \
\
prev = list_entry(_page->lru.prev, \
struct page, lru); \
prefetch(&prev->_field); \
} \
} while (0)#else
#define prefetch_prev_lru_page(_page, _base, _field) do { } while (0) #endif
Which needs a working ARCH_HAS_PREFETCH to avoid probable extra code generation on CPUs which don't have prefetch.
prefetch.h | 3 --- 1 files changed, 3 deletions(-)
include/linux/prefetch.h renamed from include/linux/prefetch.h~arch_has_prefetchw +0 -3
@@ -39,17 +39,14 @@*/ #ifndef ARCH_HAS_PREFETCH -#define ARCH_HAS_PREFETCH static inline void prefetch (const void *x) {;}#endif #ifndef ARCH_HAS_PREFETCHW -#define ARCH_HAS_PREFETCHW static inline void prefetchw (const void *x) {;}#endif #ifndef ARCH_HAS_SPINLOCK_PREFETCH -#define ARCH_HAS_SPINLOCK_PREFETCH #define spin_lock_prefetch (x) prefetchw(x)#endif
.
Quoted 7 lines · Andrew Morton
This information loss is unfortunate. Examples:
for (i = 0; i < N; i++) prefetch(foo[i]);Problem is, if `prefetch' is a no-op, the compiler will still generate an empty busy-wait loop. Which it must do.
Why - nothing there is volatile
Quoted 11 lines · Alan Cox
Quoted 7 lines · Andrew Morton
This information loss is unfortunate. Examples:
for (i = 0; i < N; i++) prefetch(foo[i]);Problem is, if `prefetch' is a no-op, the compiler will still generate an empty busy-wait loop. Which it must do.
Why - nothing there is volatile
Because the compiler sees:
for (i = 0; i < N; i++) ;
and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Quoted 15 lines · Andrew Morton
Quoted 11 lines · Alan Cox
Quoted 7 lines · Andrew Morton
This information loss is unfortunate. Examples:
for (i = 0; i < N; i++) prefetch(foo[i]);Problem is, if `prefetch' is a no-op, the compiler will still generate an empty busy-wait loop. Which it must do.
Why - nothing there is volatile
Because the compiler sees:
Quoted 7 lines
for (i = 0; i < N; i++) ;and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Good lord. If anyone depends all versions of GCC to not optimize this away, they are going to hate life. Since GCC doesn't seem to do cross file optimization (does it?) I've found the following works well:
cat > use_result.c
int dummy; // can't be static, the compiler will see it's not read
use_result(int i)
{
dummy = i;
}
^D
for (i = 0; i < N; ++i) use_result(i);I'm positive we do stuff like this in LMbench, which is fairly well supported on a pile of different platforms/compilers.
Signature · 2 lines
--- Larry McVoy lm at bitmover.com http://www.bitmover.com/lm
Quoted 3 lines · Andrew Morton
It's actually a special-case inside the compiler to not optimise away such constructs.
I thought that special case was removed long ago, because it is untenable in C++ etc (where such empty loops happen due to various abstraction issues, and not optimizing them away is just silly).
But testing shows that you're right at least for 2.95 and 2.96. Argh
Linus
GCC still keeps empty loops? (was: [patch 4/21] fix ARCH_HAS_PREFETCH)
Quoted 5 lines · Linus Torvalds
I thought that special case was removed long ago, because it is untenable in C++ etc (where such empty loops happen due to various abstraction issues, and not optimizing them away is just silly).
But testing shows that you're right at least for 2.95 and 2.96. Argh
Unbelievably, 3.1 doesn't remove empty loops either.
I think there's a case for a compiler flag, `-fremove-empty-loops'.
Empty loop delays aren't portable acrosss compilers in general. If you _really_ want an empty loop that must always work with GCC, it's easy enough to write:
for (i = 0; i < 100000; i++)
__asm__ __volatile__ ("");-- Jamie
Re: GCC still keeps empty loops? (was: [patch 4/21] fix ARCH_HAS_PREFETCH)
Quoted 2 lines · Jamie Lokier
Unbelievably, 3.1 doesn't remove empty loops either.
I think there's a case for a compiler flag, `-fremove-empty-loops'.
Indeed ... It's sad having to scatter ifdefs over the code just because gcc lacks this optimization ...
Ralf
Quoted 15 lines · Andrew Morton
Quoted 11 lines · Alan Cox
Quoted 7 lines · Andrew Morton
This information loss is unfortunate. Examples:
for (i = 0; i < N; i++) prefetch(foo[i]);Problem is, if `prefetch' is a no-op, the compiler will still generate an empty busy-wait loop. Which it must do.
Why - nothing there is volatile
Because the compiler sees:
Quoted 7 lines
for (i = 0; i < N; i++) ;and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Why is this a special case? As long as a compiler can't prove that the computed value of i isn't used later it mustn't optimize it away.
Kernighan/Ritchie (German translation of the second edition) contains the following example program that shows why the compiler mustn't optimize it away:
<-- snip -->
#include <stdio.h>
main()
{
double nc;
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%.0f\n", nc);
}
<-- snip -->
cu
Adrian
Signature · 3 lines
You only think this is a free country. Like the US the UK spends a lot of time explaining its a free country because its a police state. Alan Cox
Followup to: <Pine.NEB.4.44.0208132322340.1351-100000@mimas.fachschaften.tu-muenchen.de> By author: Adrian Bunk <[email protected]> In newsgroup: linux.dev.kernel
Quoted 6 lines
Quoted 6 lines
Because the compiler sees:
for (i = 0; i < N; i++) ;
Quoted 8 lines
Quoted 4 lines
and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Why is this a special case? As long as a compiler can't prove that the computed value of i isn't used later it mustn't optimize it away.
Bullsh*t. It can legitimately transform it into:
i = N;
Quoted 12 lines
Kernighan/Ritchie (German translation of the second edition) contains the following example program that shows why the compiler mustn't optimize it away:
<-- snip -->
#include <
stdio.h>
main()
{
double nc;
Quoted 6 lines
for (nc = 0;
getchar()!= EOF; ++nc);
printf("%.0f\n", nc);}
getchar() has side effects.
-hpa
Signature · 3 lines
<[email protected]> at work, <[email protected]> in private! "Unix gives you enough rope to shoot yourself in the foot." http://www.zytor.com/~hpa/puzzle.txt <[email protected]>
Quoted 11 lines · H. Peter Anvin
...
Quoted 10 lines
Quoted 9 lines
Because the compiler sees:
for (i = 0; i < N; i++) ;and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Quoted 7 lines
Quoted 2 lines
Why is this a special case? As long as a compiler can't prove that the computed value of i isn't used later it mustn't optimize it away.
Bullsh*t. It can legitimately transform it into:
i = N;...
Ah, my misunderstanding:
"optimize away" didn't mean "completely remove it" but "transform it to something semantically equivalent".
Quoted 1 line
-hpa
Thanks
Adrian
Signature · 3 lines
You only think this is a free country. Like the US the UK spends a lot of time explaining its a free country because its a police state. Alan Cox
Quoted 5 lines · Adrian Bunk
Ah, my misunderstanding:
"optimize away" didn't mean "completely remove it" but "transform it to something semantically equivalent".
The thing is that gcc has a special rule that keeps it from optimizing it into something with less than O(n) time.
-=hpa
Quoted 14 lines · H. Peter Anvin
Followup to: <Pine.NEB.4.44.0208132322340.1351-100000@mimas.fachschaften.tu-muenchen.de> By author: Adrian Bunk <[email protected]> In newsgroup: linux.dev.kernelQuoted 11 lines
Quoted 10 lines
Because the compiler sees:
for (i = 0; i < N; i++) ;and it says "ah ha. A busy wait delay loop" and leaves it alone.
It's actually a special-case inside the compiler to not optimise away such constructs.
Quoted 7 lines
Quoted 3 lines
Why is this a special case? As long as a compiler can't prove that the computed value of i isn't used later it mustn't optimize it away.
Bullsh*t. It can legitimately transform it into:
i = N;
Right! But people are confusing "practise", "published interface", and "spec" again.
Published interface in this case is that gcc will not optimize an empty loop away, as it is often used to generate a timing loop.
Roger.
Signature · 4 lines
** [email protected] ** http://www.BitWizard.nl/ ** +31-15-2600998 ** *-- BitWizard writes Linux device drivers for any device you may have! --* * There are old pilots, and there are bold pilots. * There are also old, bald pilots.
Quoted 11 lines · Rogier Wolff
Quoted 4 lines
Bullsh*t. It can legitimately transform it into:
i = N;Right! But people are confusing "practise", "published interface", and "spec" again.
Published interface in this case is that gcc will not optimize an empty loop away, as it is often used to generate a timing loop.
Yes. This is a gcc-specific wart, a bad idea from the start, and apparently one which has caught up with them to the point that they've had to abandon it.
-hpa
Quoted 3 lines · H. Peter Anvin
Yes. This is a gcc-specific wart, a bad idea from the start, and apparently one which has caught up with them to the point that they've had to abandon it.
It's still there in GCC 3.1.
-- Jamie
Quoted 6 lines · Jamie Lokier
Quoted 3 lines · H. Peter Anvin
Yes. This is a gcc-specific wart, a bad idea from the start, and apparently one which has caught up with them to the point that they've had to abandon it.
It's still there in GCC 3.1.
Yes. If you check out the tree-ssa-branch, however (and use appropriate commandline arguments), I think you'll find that it's no longer there. That's the future of GCC's optimizer, but most of it won't make even GCC 3.3.
Signature · 2 lines
Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer
Quoted 10 lines · H. Peter Anvin
Quoted 9 lines · Rogier Wolff
Quoted 4 lines
Bullsh*t. It can legitimately transform it into:
i = N;Right! But people are confusing "practise", "published interface", and "spec" again.
Quoted 7 lines
Quoted 3 lines
Published interface in this case is that gcc will not optimize an empty loop away, as it is often used to generate a timing loop.
Yes. This is a gcc-specific wart, a bad idea from the start, and apparently one which has caught up with them to the point that they've had to abandon it.
There would be a solution to tell gcc not to optimize things, which may not require too much work from gcc people. Basically, we would need to implement a __builtin_nop() function that would respect dependencies but not generate any code. This way, we could have :
for (i=0; i<N, i++);
optimized as i=N
and
for (i=0; i<N; i++) __builtin_nop(); or even for (i=0; i<N; __builtin_nop(i++));
do the real work.
This way, some loops could be optimized, and the developpers could explicitely tell the compiler when they need to prevent any optimization.
Cheers,
Willy
Quoted 10 lines · Willy Tarreau
There would be a solution to tell gcc not to optimize things, which may not require too much work from gcc people. Basically, we would need to implement a
__builtin_nop()function that would respect dependencies but not generate any code. This way, we could have :for (i=0; i<N, i++);optimized as i=N
and
Quoted 9 lines
for (i=0; i<N; i++) __builtin_nop(); or even for (i=0; i<N; __builtin_nop(i++));do the real work.
This way, some loops could be optimized, and the developpers could explicitely tell the compiler when they need to prevent any optimization.
#define __nop() asm volatile("")
Since some processors now have "busy wait delay" instructions, this would also make it possible to do:
#if defined(__i386__) || defined(__x86_64__)
#define __busy_wait() asm volatile("rep;nop")
#else
#define __busy_wait() asm volatile("")
#endif
Quoted 6 lines · H. Peter Anvin
Quoted 3 lines · Willy Tarreau
This way, some loops could be optimized, and the developpers could explicitely tell the compiler when they need to prevent any optimization.
#define
__nop()asmvolatile("")
and if you want to pass arguments, to guarantee that no optimization will be done, even on loop constants ?
eg:
for (i = 0; i < N; i++) {
j++;
__nop();}
-> might be optimized this way :
j = N;
for (i = 0; i < N; i++) {
__nop();}
Perhaps using a volatile for j ?
Cheers,
Willy
Quoted 12 lines · Willy Tarreau
Quoted 3 lines
Quoted 1 line
#define
__nop()asmvolatile("")and if you want to pass arguments, to guarantee that no optimization will be done, even on loop constants ?
eg:for (i = 0; i < N; i++) { j++; __nop();}
Quoted 8 lines
-> might be optimized this way :
j = N;for (i = 0; i < N; i++) { __nop();}
Perhaps using a volatile for j ?
OK, what are you trying to accomplish by this?
But if you wanted to, you could do:
for ( i = 0 ; i < N ; i++ ) {
j++;
asm volatile("" : "=g" (j));
}Quoted 3 lines · H. Peter Anvin
Since some processors now have "busy wait delay" instructions, this would also make it possible to do:
Nobody should be using an empty busy loop. If its a short timed busy loop then they should be using udelay, if its a long one schedule_timeout()
If its polling hardware then it isnt an empty loop
Quoted 10 lines · Alan Cox
Quoted 2 lines · H. Peter Anvin
Since some processors now have "busy wait delay" instructions, this would also make it possible to do:
Nobody should be using an empty busy loop. If its a short timed busy loop then they should be using udelay, if its a long one
schedule_timeout()
Indeed.
Quoted 1 line
If its polling hardware then it isnt an empty loop
True indeed as well, although we should still have a busy_wait(); macro that can insert whatever hint instruction the architecture might or might not have.
-hpa
Quoted 3 lines · H. Peter Anvin
True indeed as well, although we should still have a
busy_wait(); macro that can insert whatever hint instruction the architecture might or might not have.
We have one - its called cpu_relax()
why are you useing loops for delays in the first place? it's a solution that will fail as clock speeds keep improving (if for no other reason then your loop counter will end up needing to be a larger int to achieve the desired delay!!)
rather then debating how to convince gcc how to not optimize them away and messing up the timing we should be talking about how to eliminate such loops in the first place.
David Lang
Quoted 52 lines · Willy Tarreau
Date: Wed, 14 Aug 2002 22:45:56 +0200
From: Willy Tarreau <[email protected]>
To: H. Peter Anvin <[email protected]>
Cc: Rogier Wolff <[email protected]>, [email protected]
Subject: Re: [patch 4/21] fixARCH_HAS_PREFETCHQuoted 10 lines · H. Peter Anvin
Quoted 9 lines · Rogier Wolff
Quoted 4 lines
Bullsh*t. It can legitimately transform it into:
i = N;Right! But people are confusing "practise", "published interface", and "spec" again.
Quoted 7 lines
Quoted 3 lines
Published interface in this case is that gcc will not optimize an empty loop away, as it is often used to generate a timing loop.
Yes. This is a gcc-specific wart, a bad idea from the start, and apparently one which has caught up with them to the point that they've had to abandon it.
There would be a solution to tell gcc not to optimize things, which may not require too much work from gcc people. Basically, we would need to implement a
__builtin_nop()function that would respect dependencies but not generate any code. This way, we could have :for (i=0; i<N, i++);optimized as i=N
andfor (i=0; i<N; i++) __builtin_nop(); or even for (i=0; i<N; __builtin_nop(i++));do the real work.
This way, some loops could be optimized, and the developpers could explicitely tell the compiler when they need to prevent any optimization.
Cheers,
Willy-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Quoted 3 lines · David Lang
rather then debating how to convince gcc how to not optimize them away and messing up the timing we should be talking about how to eliminate such loops in the first place.
You misunderstand. We _do_ want gcc to optimize away empty loops.
-- Jamie
Quoted 8 lines · David Lang
why are you useing loops for delays in the first place? it's a solution that will fail as clock speeds keep improving (if for no other reason then your loop counter will end up needing to be a larger int to achieve the desired delay!!)
rather then debating how to convince gcc how to not optimize them away and messing up the timing we should be talking about how to eliminate such loops in the first place.
I'm NEVER using loops for delays, I find this awful and always a waste of time. But sometimes, you want to benchmark some algorithms, and the compiler makes this difficult by eliminating things it thinks are useless. I once had this problem when comparing several linked lists algorithms, for example.
Moreover, some people complain about the fact that gcc doesn't optimize everything because of people using loops for delays. If we provide convenient ways to help the user tell gcc when not to optimize, gcc could optimize everything possible by default.
Cheers,
Willy
Quoted 6 lines · Willy Tarreau
Moreover, some people complain about the fact that gcc doesn't optimize everything because of people using loops for delays. If we provide convenient ways to help the user tell gcc when not to optimize, gcc could optimize everything possible by default.
Well, again, such ways already exist.
-hpa