Bug 175344
Summary: | fc5t1 gcc won't compile qemu 0.7.1 due to ICE; register spill | ||||||
---|---|---|---|---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Stephen Warren <swarren-tag-rhbugzilla> | ||||
Component: | gcc | Assignee: | Jakub Jelinek <jakub> | ||||
Status: | CLOSED NOTABUG | QA Contact: | |||||
Severity: | medium | Docs Contact: | |||||
Priority: | medium | ||||||
Version: | 5 | ||||||
Target Milestone: | --- | ||||||
Target Release: | --- | ||||||
Hardware: | i386 | ||||||
OS: | Linux | ||||||
Whiteboard: | |||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||
Doc Text: | Story Points: | --- | |||||
Clone Of: | Environment: | ||||||
Last Closed: | 2005-12-10 08:44:05 UTC | Type: | --- | ||||
Regression: | --- | Mount Type: | --- | ||||
Documentation: | --- | CRM: | |||||
Verified Versions: | Category: | --- | |||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
Cloudforms Team: | --- | Target Upstream Version: | |||||
Embargoed: | |||||||
Attachments: |
|
Description
Stephen Warren
2005-12-09 05:32:33 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. 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. |