Bug 175344 - fc5t1 gcc won't compile qemu 0.7.1 due to ICE; register spill
Summary: fc5t1 gcc won't compile qemu 0.7.1 due to ICE; register spill
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc   
(Show other bugs)
Version: 5
Hardware: i386
OS: Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact:
Depends On:
TreeView+ depends on / blocked
Reported: 2005-12-09 05:32 UTC by Stephen Warren
Modified: 2007-11-30 22:11 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2005-12-10 08:44:05 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)
Pre-processed content of failing source file (25.65 KB, application/x-bzip)
2005-12-10 03:04 UTC, Stephen Warren
no flags Details

Description Stephen Warren 2005-12-09 05:32:33 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8) Gecko/20051129 Fedora/1.5-1 Firefox/1.5

Description of problem:
The build of qemu fails with this error message:

gcc -Wall -O2 -g -fno-strict-aliasing -fomit-frame-pointer -mpreferred-stack-boundary=2 -falign-functions=0 -fno-gcse -fno-reorder-blocks -fno-optimize-sibling-calls -I. -I/home/swarren/qemu-0.7.1/target-i386 -I/home/swarren/qemu-0.7.1 -I/home/swarren/qemu-0.7.1/linux-user -I/home/swarren/qemu-0.7.1/linux-user/i386 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I/home/swarren/qemu-0.7.1/fpu -I/home/swarren/qemu-0.7.1/slirp -c -o op.o /home/swarren/qemu-0.7.1/target-i386/op.c
/home/swarren/qemu-0.7.1/target-i386/ops_sse.h: In function op_pshufw_mmx:
/home/swarren/qemu-0.7.1/target-i386/ops_sse.h:574: error: unable to find a register to spill in class GENERAL_REGS
/home/swarren/qemu-0.7.1/target-i386/ops_sse.h:574: error: this is the insn:
(insn:HI 18 17 19 0 /home/swarren/qemu-0.7.1/target-i386/ops_sse.h:569 (set (strict_low_part (subreg:HI (reg/v:DI 63 [ r ]) 0))
        (mem/s/j:HI (plus:SI (mult:SI (reg:SI 64)
                    (const_int 2 [0x2]))
                (reg/v/f:SI 59 [ s ])) [0 <variable>._w S2 A16])) 41 {*movstricthi_1} (insn_list:REG_DEP_TRUE 16 (insn_list:REG_DEP_TRUE 12 (insn_list:REG_DEP_TRUE 53 (nil))))
    (expr_list:REG_DEAD (reg:SI 64)
/home/swarren/qemu-0.7.1/target-i386/ops_sse.h:574: confused by earlier errors, bailing out
make[1]: *** [op.o] Error 1
make[1]: Leaving directory `/home/swarren/qemu-0.7.1/i386-user'
make: *** [all] Error 1

The code in question (ops_sse.h:569) is this:

void OPPROTO glue(op_pshufw, SUFFIX) (void)
    Reg r, *d, *s;
    int order;
    d = (Reg *)((char *)env + PARAM1);
    s = (Reg *)((char *)env + PARAM2);
    order = PARAM3;
    r.W(0) = s->W(order & 3);
    r.W(1) = s->W((order >> 2) & 3);
    r.W(2) = s->W((order >> 4) & 3);
    r.W(3) = s->W((order >> 6) & 3);
    *d = r;

so this doesn't seem to have anything to do with the other gcc bugs referencing register spill, which were due to the code specify too many register variables.

Version-Release number of selected component (if applicable):

How reproducible:

Steps to Reproduce:
1. Download/untar qemu-0.7.1
2. ./configure --disable-kqemu --enable-adlib
3. make

Actual Results:  Compile succeeds.

Expected Results:  Compile fails with error above.

Additional info:

Latest updates to fc3 build this fine - I just did it recently (albeit perhaps without the --enable-adlib and --disable-kqemu)

Comment 1 Jakub Jelinek 2005-12-09 07:36:54 UTC
That's qemu bug, it uses too many global register variables on already heavily
register starved i386, leaving not enough registers for the compiler to really
do anything.  In older GCCs it build by pure luck.

Comment 2 Stephen Warren 2005-12-09 17:32:00 UTC
I still believe that this is a gcc bug.

The function that's failing to compile doesn't define any register variables.

I already checked the other gcc bug reports in RH Bugzilla to ensure that this
wasn't the same issue - in the other cases, the ICE happens when attempting to
compile a function that declares register variables, but not in my case, that I
can tell.

Besides, the register keyword just a hint to the compiler. If the compiler can't
actually honor all the register variables, then it's supposed to ignore as many
as it needs and compile the code anyway.

I quote from "The C Programming Language" 2nd edition. Section 4.7 "Register

A register declaration advises the compiler that the variable in question will
be heavily used. The idea is that register variables are to be placed in machine
registers, which may result in smaller and faster programs. But compilers are
free to ignore the advice.

So, whilst the qemu code may be misguided, the ICE is still a gcc bug.

Comment 3 Jakub Jelinek 2005-12-09 17:38:11 UTC
register keyword can GCC ignore only unless the variable has __asm ("reg")
attached to it.  And last time I looked, qemu used 4 global register variables,
which means 4 variables are kept in the 4 selected registers and no function
can use those registers.
If you preprocess the file on which it errored (note, GCC is issuing normal
error for this, not an ICE and only afterwards bails out) and attach it here
(just add -save-temps to the gcc options used), I can tell you for sure.

Comment 4 Stephen Warren 2005-12-10 03:04:35 UTC
Created attachment 122094 [details]
Pre-processed content of failing source file

OK - I do see the 4 global register definitions - they're just nowhere near the
function that was failing, no doubt from some header.

But, I still don't understand why previous gcc releases worked fine - did they
ignore the register keyword even with the extra asm statement or something?

Comment 5 Jakub Jelinek 2005-12-10 08:44:05 UTC
What kind of "global register variable" thing you don't understand?
The 4 registers are globally occupied, so instead of being able to allocate
up to 7 registers in every function (with -fomit-frame-pointer; even 7 is
terribly small number, i386 is one of the most register starved targets),
you suddenly have up to 3 registers, %eax, %ecx and %edx for all the code.
That means if you are lucky, almost everything is spilled all the time to
the stack and for almost every single instruction you have to load all their
arguments from the stack and after it store it to the stack again.
And if you aren't lucky because the compiler chose say a different pattern that
really needs 4 registers for some reason (there are several such in i386 machine
description), the compiler can't do anything but give up.
QEMU folks really need to get a clue.

Comment 6 Stephen Warren 2005-12-10 17:05:21 UTC
It is obvious what I don't understand:

gcc 3.2.x compiles this code without a problem (I just downloaded compat-gcc32
and proved this)

gcc 4.0.x does not compile this code.

That is a regression in gcc.

Yes, the regression is caused by stupid code, I accept that.

Still, I want to know *why* the regression occured - it is a severe
inconvenience to users of gcc, as evidenced by the number of gcc bug reports
this gcc change causes.

I ask again: What changed in gcc?

* Did the code generation quality get lower, so it *has* to use more registers,
and so can't cope when there are 4 global registers defined?

* Did earlier versions of gcc ignore the supposedly not-ignorable register

* Something else?

Obviously, it's possible to generate correct working assembly for this C source
code, because gcc 3.2.x did.

Note You need to log in before you can comment on or make changes to this bug.