Bug 23422 - Sign extension removed even when inline assembly uses variable
Summary: Sign extension removed even when inline assembly uses variable
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.0.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-08-16 14:03 UTC by Anton Blanchard
Modified: 2005-08-18 03:20 UTC (History)
1 user (show)

See Also:
Host:
Target: powerpc64-*-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anton Blanchard 2005-08-16 14:03:30 UTC
When using the recent debian 4.0 build (gcc version 4.0.2 20050806 (prerelease)
(Debian 4.0.1-4)) I had some problems with a 64bit kernel.

A cut down test case is:

#define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" (x));

static inline int bar(int val)
{
        return val + 1;
}

int foo;

void baz()
{
        BUG_ON(bar(foo));
}

gcc 3.4 sign extends before passing it to the inline assembly:

.baz:
        ld 11,.LC0@toc(2)
        lwa 9,0(11)
        addi 9,9,1
        extsw 9,9
        tdnei 9,0

But gcc 4.0 has removed the sign extension:

.baz:
        ld 11,.LC0@toc(2)
        lwz 9,0(11)
        addi 9,9,1
        tdnei 9,0

gcc 4.0 does get it right with -fno-inline.
Comment 1 Andrew Pinski 2005-08-16 14:16:20 UTC
This is not a bug.
The code you gave is equivalant to as that is what inlining does (3.4 had a bug in that it had an extra 
overhead as you noticed, which you thought was a feature):
#define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" (x));
int foo;
void baz()
{
        BUG_ON(foo+1);
}

So it will pick the SImode (32bit part) for the "r" selector.  If you want the BUG_ON to take a signed 
extended (DImode) for the "r", use something like the following:
#define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" ((long long)x));
static inline int bar(int val)
{
        return val + 1;
}

int foo;

void baz()
{
        BUG_ON(bar(foo));
}


That will both work on 3.4 and 4.0.0 with no asm changes in both.  
Comment 2 Anton Blanchard 2005-08-17 01:04:21 UTC
Thanks, after applying the suggested fix the kernel works.