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) (nil))) /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): gcc-4.0.2-6 How reproducible: Always 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)
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.
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 Variables": """ 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.
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.
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?
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.
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 statements? * Something else? Obviously, it's possible to generate correct working assembly for this C source code, because gcc 3.2.x did.