linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* sparse -Wptr-subtraction-blows: still needed?
@ 2007-05-01 21:08 Josh Triplett
  2007-05-01 21:43 ` Linus Torvalds
  0 siblings, 1 reply; 11+ messages in thread
From: Josh Triplett @ 2007-05-01 21:08 UTC (permalink / raw)
  To: linux-sparse, linux-kernel; +Cc: Linus Torvalds, Al Viro

[-- Attachment #1: Type: text/plain, Size: 931 bytes --]


Sparse has a warning -Wptr-subtraction-blows (off by default) which generates
a warning for any pointer subtractions.  This warning relates to GCC
shortcomings observed in 2005; the original log message:

> commit 6889bd0f84939675c743229d6fe623513b95e057
> Author: Linus Torvalds <torvalds@ppc970.osdl.org>
> Date:   Fri Jan 7 15:06:24 2005 -0700
>
>     Add option "-Wptr-subtraction-blows" to warn about expensive
>     pointer subtractions.
>     
>     Not only does it generate bad code (that can often be rewritten
>     to not do that), it also causes gcc to go into horrible contortions,
>     and Al Viro reports that it can make a factor of 2.5 difference in
>     kernel build times to have just a few of these in common header
>     file inline functions.

Does this still apply?  Do current versions of GCC still have this problem?
If not, can the option and warning go away?

- Josh Triplett


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 21:08 sparse -Wptr-subtraction-blows: still needed? Josh Triplett
@ 2007-05-01 21:43 ` Linus Torvalds
  2007-05-01 23:59   ` Josh Triplett
                     ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Linus Torvalds @ 2007-05-01 21:43 UTC (permalink / raw)
  To: Josh Triplett; +Cc: linux-sparse, linux-kernel, Al Viro



On Tue, 1 May 2007, Josh Triplett wrote:
> 
> Does this still apply?  Do current versions of GCC still have this problem?
> If not, can the option and warning go away?

Even if current versions of gcc don't triple the build time (and for the 
kernel, I suspect it doesn't, because we've tried to clean up our header 
files), the generated _code_ will invariably suck.

So I'd not want to remove the warning.

		Linus

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 21:43 ` Linus Torvalds
@ 2007-05-01 23:59   ` Josh Triplett
  2007-05-02  0:24     ` Linus Torvalds
  2007-05-02  0:26     ` Al Viro
  2007-05-02  0:02   ` Al Viro
  2007-05-02  2:42   ` Dave Jones
  2 siblings, 2 replies; 11+ messages in thread
From: Josh Triplett @ 2007-05-01 23:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-sparse, linux-kernel, Al Viro

[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]

Linus Torvalds wrote:
> 
> On Tue, 1 May 2007, Josh Triplett wrote:
>> Does this still apply?  Do current versions of GCC still have this problem?
>> If not, can the option and warning go away?
> 
> Even if current versions of gcc don't triple the build time (and for the 
> kernel, I suspect it doesn't, because we've tried to clean up our header 
> files), the generated _code_ will invariably suck.

"invariably"?

Do you know whether the current version of GCC generates poor code for pointer
subtraction?

If so, does anything in particular make this an unfixable problem?

Has anyone reported this poor code generation to the GCC bugzilla?  If so, I
can add a reference to the bug in any (hypothetical) documentation for
-Wptr-subtraction-blows.

> So I'd not want to remove the warning.

Regardless of whether it addresses a current GCC issue or not, I have no
problem leaving the warning in if people want it, given that it requires an
explicit switch.

- Josh Triplett



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 21:43 ` Linus Torvalds
  2007-05-01 23:59   ` Josh Triplett
@ 2007-05-02  0:02   ` Al Viro
  2007-05-02  2:42   ` Dave Jones
  2 siblings, 0 replies; 11+ messages in thread
From: Al Viro @ 2007-05-02  0:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Josh Triplett, linux-sparse, linux-kernel

On Tue, May 01, 2007 at 02:43:30PM -0700, Linus Torvalds wrote:
> 
> 
> On Tue, 1 May 2007, Josh Triplett wrote:
> > 
> > Does this still apply?  Do current versions of GCC still have this problem?
> > If not, can the option and warning go away?
> 
> Even if current versions of gcc don't triple the build time (and for the 
> kernel, I suspect it doesn't, because we've tried to clean up our header 
> files), the generated _code_ will invariably suck.
> 
> So I'd not want to remove the warning.

Note that code *will* blow: in effect, when we have a*2^b as object size,
we have to choose between
	* generic division by a*2^b (dog-slow pretty much on anything)
	* multiplication by such c that a*c == 1 (mod 2^word_size-b), then
shift down by b.
	* shift down by b, then multiplication by such c that a*c == 1
(mod 2^word_size).
And c in the above won't be small or pretty, so doing multiplication as
series of additions won't be short.

FWIW, I've seen very nasty cases (in userland code) where hot path got blown
by factor of 5 or so in size due to that; basically, it started with
#define INDEX(p) ((p)-array)
and that sucker got used a lot in other macros, so it wasn't immediately
obvious what had been going on.  So yes, we do want to be able to see
such cases.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 23:59   ` Josh Triplett
@ 2007-05-02  0:24     ` Linus Torvalds
  2007-05-02  0:35       ` Al Viro
  2007-05-02 12:02       ` Alan Cox
  2007-05-02  0:26     ` Al Viro
  1 sibling, 2 replies; 11+ messages in thread
From: Linus Torvalds @ 2007-05-02  0:24 UTC (permalink / raw)
  To: Josh Triplett; +Cc: linux-sparse, linux-kernel, Al Viro



On Tue, 1 May 2007, Josh Triplett wrote:
> 
> Do you know whether the current version of GCC generates poor code for pointer
> subtraction?

You _cannot_ generate good code.

When you subtract two pointers, the C definition means that you first 
subtract the values (cheap), and then you *divide* the result by the size 
of the object the pointer points to (expensive!).

So pointer subtraction is by definition expensive, if the size of the 
object is not some kind of nice power-of-two or similar.

Of course, modern CPU's are getting better at divides.

> Has anyone reported this poor code generation to the GCC bugzilla?  If so, I
> can add a reference to the bug in any (hypothetical) documentation for
> -Wptr-subtraction-blows.

The only thing that was gcc-specific about it is that gcc goes to some 
extreme lengths to turn the constant-sized division into a sequence of 
shifts/multiples/subtracts, and can often turn a division into something 
like ten cheaper operations instead.

But that optimization was also what made gcc take such a long time if the 
constant division is very common (ie a header file with an inline 
function, whether that function is actually _used_ or not apparently 
didn't matter to gcc)

So gcc does pretty well on these divisions, and makes them cheaper (except 
on CPU's where divides are really fast and possibly even cheaper than the 
combination of shifts/subtracts, but afaik, that probably won't be until 
the next-generation Intel Core 2 45nm "Penryn" thing)

			Linus

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 23:59   ` Josh Triplett
  2007-05-02  0:24     ` Linus Torvalds
@ 2007-05-02  0:26     ` Al Viro
  1 sibling, 0 replies; 11+ messages in thread
From: Al Viro @ 2007-05-02  0:26 UTC (permalink / raw)
  To: Josh Triplett; +Cc: Linus Torvalds, linux-sparse, linux-kernel

On Tue, May 01, 2007 at 04:59:57PM -0700, Josh Triplett wrote:
> Linus Torvalds wrote:
> > 
> > On Tue, 1 May 2007, Josh Triplett wrote:
> >> Does this still apply?  Do current versions of GCC still have this problem?
> >> If not, can the option and warning go away?
> > 
> > Even if current versions of gcc don't triple the build time (and for the 
> > kernel, I suspect it doesn't, because we've tried to clean up our header 
> > files), the generated _code_ will invariably suck.
> 
> "invariably"?
> 
> Do you know whether the current version of GCC generates poor code for pointer
> subtraction?
> 
> If so, does anything in particular make this an unfixable problem?

Just the fact that calculation itself is nasty.  In the best case you
get (on x86) something like
        sarl    $2, %eax
        imull   $-1431655765, %eax, %eax
(that one is with object size equal to 12).  On other targets it can get
considerably uglier - e.g. on alpha with -O2 the same will result in
        sra $17,2,$17
        s4subq $17,$17,$0
        s8subq $0,$0,$0
        s4addq $0,$17,$0
        sll $0,8,$1
        addq $0,$1,$0
        sll $0,16,$2
        addq $0,$2,$0
        sll $0,32,$1
        addq $0,$1,$0
        addq $0,$0,$0
        addl $0,$17,$0
With -Os it's
        ldah $1,$LC0($29)               !gprelhigh
        sra $0,2,$0
        ldq $1,$LC0($1)         !gprellow
        mull $0,$1,$0
with LC0 in rodata:
$LC0:
        .quad   -6148914691236517205

Now imagine the joy of having a bunch of such wonders in a hot path...

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-02  0:24     ` Linus Torvalds
@ 2007-05-02  0:35       ` Al Viro
  2007-05-02 12:02       ` Alan Cox
  1 sibling, 0 replies; 11+ messages in thread
From: Al Viro @ 2007-05-02  0:35 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Josh Triplett, linux-sparse, linux-kernel

On Tue, May 01, 2007 at 05:24:54PM -0700, Linus Torvalds wrote:
> The only thing that was gcc-specific about it is that gcc goes to some 
> extreme lengths to turn the constant-sized division into a sequence of 
> shifts/multiples/subtracts, and can often turn a division into something 
> like ten cheaper operations instead.
> 
> But that optimization was also what made gcc take such a long time if the 
> constant division is very common (ie a header file with an inline 
> function, whether that function is actually _used_ or not apparently 
> didn't matter to gcc)

There used to be a Dumb Algorithm(tm) in there - basically, gcc went through
all decompositions of constant it was multiplying at and it did it in the
dumbest way possible (== without keeping track of the things like "oh, we'd
already looked at the best way to multiply by 69, no need to redo that
again and again)").  _That_ is what blew the build time to hell for a while.
And yes, that particular idiocy got fixed (they added a moderately-sized
LRU of triplets <constant, price, best way to multiply on it>, which killed
recalculation from scratch for each pointer subtraction and got complexity
of dealing with individual subtraction into tolerable range).

That's separate from runtime issues, of course.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-01 21:43 ` Linus Torvalds
  2007-05-01 23:59   ` Josh Triplett
  2007-05-02  0:02   ` Al Viro
@ 2007-05-02  2:42   ` Dave Jones
  2007-05-02 13:03     ` Andi Kleen
  2 siblings, 1 reply; 11+ messages in thread
From: Dave Jones @ 2007-05-02  2:42 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Josh Triplett, linux-sparse, linux-kernel, Al Viro

On Tue, May 01, 2007 at 02:43:30PM -0700, Linus Torvalds wrote:
 > 
 > 
 > On Tue, 1 May 2007, Josh Triplett wrote:
 > > 
 > > Does this still apply?  Do current versions of GCC still have this problem?
 > > If not, can the option and warning go away?
 > 
 > Even if current versions of gcc don't triple the build time (and for the 
 > kernel, I suspect it doesn't, because we've tried to clean up our header 
 > files), the generated _code_ will invariably suck.

FWIW, I do sparse runs on the fedora development kernels as part of
our daily builds now, and of the latest ones at
http://people.redhat.com/davej/kernels/Fedora/fc7/warnings.txt
(concatenated warning logs from i586/i686/x86_64/ppc/ppc64/s390 builds)
that 'expensive pointer subtraction' turns up 3705 times.
Interestingly, 1873 of those instances are from include/linux/mm.h
on the x86-64 build.

It's complaining about this line...

static __always_inline void *lowmem_page_address(struct page *page)
{
        return __va(page_to_pfn(page) << PAGE_SHIFT);
}

...

unsigned long page_to_pfn(struct page *page)
{
        return __page_to_pfn(page);
}

...

#define __page_to_pfn(page)     ((unsigned long)((page) - mem_map) + \
                                 ARCH_PFN_OFFSET)

looks like the other two variants of __page_to_pfn also use similar arithmatic.

	Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-02  0:24     ` Linus Torvalds
  2007-05-02  0:35       ` Al Viro
@ 2007-05-02 12:02       ` Alan Cox
  2007-05-02 13:19         ` Andi Kleen
  1 sibling, 1 reply; 11+ messages in thread
From: Alan Cox @ 2007-05-02 12:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Josh Triplett, linux-sparse, linux-kernel, Al Viro

On Tue, 1 May 2007 17:24:54 -0700 (PDT)
Linus Torvalds <torvalds@linux-foundation.org> wrote:

> 
> 
> On Tue, 1 May 2007, Josh Triplett wrote:
> > 
> > Do you know whether the current version of GCC generates poor code for pointer
> > subtraction?
> 
> You _cannot_ generate good code.
> 
> When you subtract two pointers, the C definition means that you first 
> subtract the values (cheap), and then you *divide* the result by the size 
> of the object the pointer points to (expensive!).

Good compilers even in the 1990's would defer the divide and try and
propogate it out as a multiply the other side for constants, and they'll
also use shifts when possible.

Thus they'll turn

	(ptr.element - base.element) < NELEM

into
	(ptr.char - base.char) < (constant) [NELEM *sizeof(element) ]


at least for constant operations. Dunno if gcc is that clever

Alan

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-02  2:42   ` Dave Jones
@ 2007-05-02 13:03     ` Andi Kleen
  0 siblings, 0 replies; 11+ messages in thread
From: Andi Kleen @ 2007-05-02 13:03 UTC (permalink / raw)
  To: Dave Jones
  Cc: Linus Torvalds, Josh Triplett, linux-sparse, linux-kernel,
	Al Viro

Dave Jones <davej@redhat.com> writes:
> 
> #define __page_to_pfn(page)     ((unsigned long)((page) - mem_map) + \
>                                  ARCH_PFN_OFFSET)
> 
> looks like the other two variants of __page_to_pfn also use similar arithmatic.

No way around this. The only way to turn a page into a pfn is to do 
a constant division.  Should be fairly cheap here though.

-Andi (who thinks the sparse warning is dumb; better to look at oprofiles
of hot paths)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: sparse -Wptr-subtraction-blows: still needed?
  2007-05-02 12:02       ` Alan Cox
@ 2007-05-02 13:19         ` Andi Kleen
  0 siblings, 0 replies; 11+ messages in thread
From: Andi Kleen @ 2007-05-02 13:19 UTC (permalink / raw)
  To: Alan Cox; +Cc: Linus Torvalds, Josh Triplett, linux-sparse, linux-kernel,
	Al Viro

Alan Cox <alan@lxorguk.ukuu.org.uk> writes:
> 
> Good compilers even in the 1990's would defer the divide and try and
> propogate it out as a multiply the other side for constants, and they'll
> also use shifts when possible.

gcc has an algorithm that tends to generate a near perfect shift/add etc.
code sequence and also knows the obvious x / y ==> x*1/y

However it doesn't do that with -Os, prefering smaller code on x86
(idiv is fairly small compared to the expanded sequences for non power
of two dividends) and kernels are usually compiled with -Os these
days.

We've had a few cases in the past where this showed up as regression
against older kernels that still used -O2.
 
> Thus they'll turn
> 
> 	(ptr.element - base.element) < NELEM
> 
> into
> 	(ptr.char - base.char) < (constant) [NELEM *sizeof(element) ]
> 
> 
> at least for constant operations. Dunno if gcc is that clever

It is. However a few more complex transformations I would have liked
in the past are missing -- in particular 

x / (cond ? const1 : const2) ==> cond ? (x / const1) : (x / const2)

-Andi

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2007-05-02 12:21 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-01 21:08 sparse -Wptr-subtraction-blows: still needed? Josh Triplett
2007-05-01 21:43 ` Linus Torvalds
2007-05-01 23:59   ` Josh Triplett
2007-05-02  0:24     ` Linus Torvalds
2007-05-02  0:35       ` Al Viro
2007-05-02 12:02       ` Alan Cox
2007-05-02 13:19         ` Andi Kleen
2007-05-02  0:26     ` Al Viro
2007-05-02  0:02   ` Al Viro
2007-05-02  2:42   ` Dave Jones
2007-05-02 13:03     ` Andi Kleen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).