Forum Discussion
GCC 4.1.2 Issue. New toolchain soon?
I'm running into a bug where the following code causes a compiler error:
class foo {
public:
virtual const char* name() const throw();
virtual const char* faux_name() const throw();
};
const char* foo::name() const throw()
{
return "bar";
}
const char* foo::faux_name() const throw()
{
return name();
}
Assuming it's named 'foo.cpp': nios2-linux-gnu-g++ -fPIC -O2 -c foo.cpp -o foo.o
foo.cpp: In member function 'virtual const char* foo::faux_name() const':
foo.cpp:15: error: Attempt to delete prologue/epilogue insn:
(insn 44 43 45 0 (set (reg:SI 22 r22)
(plus:SI (reg:SI 22 r22)
(reg:SI 8 r8))) -1 (nil)
(nil))
foo.cpp:15: internal compiler error: in propagate_one_insn, at flow.c:1699
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:...> for instructions.
Normally I'd go to GCC for this, but it's a very outdated compiler version and no longer supported. They don't even use flow.c anymore. This only happens with the nios2-linux-gnu-xxx tools, and not the normal linux tools, even though they're both 4.1.2. Are there any plans on moving toolchain-mmu to a newer version of GCC? Anybody do this themselves? Can I just replace gcc4.3.5 in the gcc4 toolchain build instructions? Thanks.21 Replies
- Altera_Forum
Honored Contributor
The toolchain comes from CodeSourcery. It's the versions stated with many patches applied, most importantly to support the NIOS II architecture. There is actually a slightly newer version out there than the one available on the wiki, but it's still based on the same upstream versions. I haven't seen any sign of a future release based on newer tools unfortunately.
It should theoretically be possible to carry the CodeSourcery patches over to a newer version of GCC but this would require some expertise and a lot of effort. I tried compiling your test with the aforementioned slightly newer version that I'm using and it actually works. I will try to get this published soon on the wiki. - Altera_Forum
Honored Contributor
Thank you for the reply.
Just a note, that the issue only comes up with the above compiler options (-fPIC and any optimizations other than -O0). - Altera_Forum
Honored Contributor
Bringing up an old issue...
Has there been an update? I haven't seen a newer version on the Wiki yet. - Altera_Forum
Honored Contributor
--- Quote Start --- Bringing up an old issue... Has there been an update? I haven't seen a newer version on the Wiki yet. --- Quote End --- A gcc 4.7.3 based toolchain for nios2 is available from Mentor/CodeSourcery at: https://sourcery.mentor.com/gnutoolchain/release2499 ACDS 13.1 will also include a gcc 4.7.3 based nios2 toolchain. - Altera_Forum
Honored Contributor
Does anyone know if they have incorporated my patches (on the wiki) for 'small data' accesses?
I wrote them for gcc 3.4, but they applied to the gcc 4.1 version as well (the only changes I saw between 3.4 and 4.1 were regressions!). gcc 4.1 certainly made a worse job (than 3.4) of compiling my code - although I didn't spend any time trying to work out why. - Altera_Forum
Honored Contributor
--- Quote Start --- Does anyone know if they have incorporated my patches (on the wiki) for 'small data' accesses? I wrote them for gcc 3.4, but they applied to the gcc 4.1 version as well (the only changes I saw between 3.4 and 4.1 were regressions!). gcc 4.1 certainly made a worse job (than 3.4) of compiling my code - although I didn't spend any time trying to work out why. --- Quote End --- 1) Le "they" -- c'est moi. At least, I was hired a few months back as gcc maintainer and liaison to Mentor/CodeSourcery, who do the heavy lifting. (As you may have detected, nios2 toolchain maintainance has been minimal since gcc 4.1.2. We're intending and expecting to do a lot better going forward, starting with the big jump to gcc 4.7.3.) 2) Ghodz you're good! How did you work out all of those?? :-) (If you have any advice/pointers for learning gcc .md stuff I'm all ears. I have a reasonable compiler background -- e.g., I maintain the Mythryl compiler for fun -- but I'm new to gcc+binutils, which have a whole little jargon/world of their own.) 3) I don't see any evidence that your patches have been applied per set, but patches 1,7,8,11,12 have been re-invented. (I managed to find 11,12 on my own, whee.) 4) I'm going to point the Mentor/CodeSourcery folx to your remaining patches. They've re-invented five of them the hard way, they'd probably prefer to do the remaining ones the easy way. :-) 5) My/our informal experience to date is that gcc 4.7.3 generates slightly but significantly better code than gcc 4.1.2, as one might expect and hope. Very roughly 5% smaller, for example, with of course significant variation around the mean. We've had a few teething problems with Nios2 custom instruction generation, but otherwise the new toolchain seems pleasingly solid. - Altera_Forum
Honored Contributor
I'd never looked at gcc (or any other compiler) internals before, so it was a matter of reading the on-line gcc internals docs and the code (and a certain amount of trial and error).
OTOH I've hand written assembler for quite a few cpus over the years. In some places I just hacked the opcode strings in order to see exactly where some common instructions were generated. I was writing a fairly small piece of code (less than 2kb) that is a multi-channel hdlc controller. It has 195 clocks to do a bytes rx and tx on each channel (doing the bit-stuffing and crc in software), so absolutely every clock counts and I needed to minimise the worst-case code paths, not the common ones. I had a moderate incentive to optimise obvious defects in the code generator! The big gain from fixing access to structures 'small data' was reducing 'register pressure' by stopping the compiler allocating a register to contain the start address of the structure - sometimes it sould generate the same pointer twice! Some other stuff I noticed: 1) The gcc 4 config always puts switch statement jump tables directly into the .code segment (something about not having the appropriate relocations for PIC code). I run nios cpu with tightly coupled instruction and data memory (no caches) and without cpu data access to the code memory - so I need the .code to 'pure'. They could probably be written to a .rodata.switch (or .code.switch or ...) section so that the linker script can decide exactly where they end up. 2) The instruction scheduler doesn't know about the delay slots after 'ld' instructions (and a few others). I had to go to great lengths to get delay slots filled in order to avoid any stall cycles. 3) It ought to be possible to generate the switch statement jump table code as a series of rtx to aid instruction scheduling and also to move the 'add' into the load offset removing an instruction. 4) In my code the only references to the stack pointer are in the function prologue where some registers are saved - that seems a waste for a function that doesn't return! The code is compiled in a single unit and all functions are marked __attribute__((always_inline)). 5) The 'global pointer' / 'small data' stuff seems to be based on gcc support for 'page 0' addressing. Although I fixed the code for gp relative access to structures, the code for accessing 'small data' arrays still uses an extra register. I used gp as a register variable pointing to a structure because that generates better code (gcc knows about the 16bit offset in the final memeory reference). 5a) I'd arranged for my nios data areas and the 'small io' to be within a 64k block (to get gp relative addressing for everything), but I'd missed a trick! I should have put the 'small io' below 0x7fff - then it could be accessed by offsets from r0. It would be nice if gcc supported such variables - probably need a gcc attribute (or a special section - attribute is probably cleaner). 6) Add a gcc attribute to mark data an 'io', and generate ldio/stio (etc) for accesses to such data. Unfortunately I can't give you a copy of my sources. - Altera_Forum
Honored Contributor
Another problem I found - which might be in gcc itself, so might be fixed in later versions...
If I read a 'volatile unsigned char' value, the compiler follows the 'ldbu' instruction with one that masks the value with 0xff. (It sometimes does it for non-volatiles as well.) My suspicion is that 'volatile' forces a separate load of the value into a register, then the value from the register is used for the variable reference. Between the two it 'forgets' that the high bits aren't set (they might be set if there was intervening arithmetic). Basically this meant I couldn't mark things as 'volatile', I had to use asm volatile("#comment\n":::"memory") instead - I used a fair number of those to change the instruction scheduling elsewhere. - Altera_Forum
Honored Contributor
Thanks for the pointers and ideas!
--- Quote Start --- The code is compiled in a single unit and all functions are marked __attribute__((always_inline)). . --- Quote End --- Note that in gcc 4.7.3 (at least) always_inline has no effect unless the fn is declared inline. The gcc docs more or less say this. We've tripped over this several times. -Jeff - Altera_Forum
Honored Contributor
The functions are marled 'inline' as well.
However, even though they are static and only called once minor changes would stop the functions being inlined. --- Quote Start --- 5a) I'd arranged for my nios data areas and the 'small io' to be within a 64k block (to get gp relative addressing for everything), but I'd missed a trick! I should have put the 'small io' below 0x7fff - then it could be accessed by offsets from r0. It would be nice if gcc supported such variables - probably need a gcc attribute (or a special section - attribute is probably cleaner). --- Quote End --- Actually I wonder if the linker could modify the instruction to use r0 instead of gp if the offset from gp is out of range but a valid offset from r0? There is a specific error message so there must be some specific code.