[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] Request: gcrt1.S with empty section .init9
From: |
Marko Mäkelä |
Subject: |
Re: [avr-libc-dev] Request: gcrt1.S with empty section .init9 |
Date: |
Sat, 7 Jan 2017 12:01:53 +0200 |
User-agent: |
NeoMutt/20161126 (1.7.1) |
Hallo Johann,
When you need optimizations at a lever where 2 instructions matter,
then it's very likely you need a project specific start-up code and
linker description anyway. For example, you might truncate the vector
table after the last vector used by the application.
Good idea, thanks! I did think about the interrupt vector table already,
and that approach would allow me to trim it too.
For an easy fix, you can
1) Set up own start-up code omitting .init9
2) Provide own linker description file without input section .init9
3) Or, as a quick fix: 3a) Link with -Wl,--unique=.init9 so that
.init9 becomes an output section, and then 3b) drop it by means
of avr-objcopy --remove-section=.init9 foo.elf
All of these approaches require main in .init8 or earlier.
Right. I successfully had put main in .init3 already before posting.
The quick fix 3) works and shortens the program by 4 words and reduces
stack usage by 2 bytes. The .init9 section would be emitted to the end
of the ELF binary and indeed omitted from the avr-objcopy output.
[snip]
gcrt1.S would need yet another #if __GNUC__ >= 7 or so, and because
toolchain distributors are usually not aware of such subtleties, you
will observe complaints of "brain dead misoptimization" à la
CALL main
JMP exit
CALL main
JMP exit
throughout avr forums all over the net if someone bundles avr-gcc with
the new feature together with avr-libc without conditional removal.
Right, so the risk could be greater than the savings.
One last note: As you are coming straight from asm programming, you
will have a hard time reading the compiler generated code.
Actually I write C and C++ code bigger systems for living.
The 8-bit processors are just a hobby, and my ‘first love’ is the 6502,
not the AVR. I was happy to learn that the avr-llvm changes were
recently merged to the upstream repository. The experimental AVR target
for clang generates some code, but it still needs work. I am hoping that
one day clang generates similar code as avr-gcc. Also clang++ works,
which is nice if you watched the CppCon 2016 talks touting zero-overhead
abstraction, such as these:
https://www.youtube.com/watch?v=zBkNBP00wJE
https://www.youtube.com/watch?v=uzF4u9KgUWI
https://www.youtube.com/watch?v=D7Sd8A6_fYU
Maybe your are shocked enough to jump into contributing to GCC :-)
Not an impossible idea, but I find the idea of LLVM more promising,
because it could be easier to add other 8-bit processor targets there.
So far I found the generated code surprisingly good. I feared that GCC
would target a ‘virtual machine’ with 32-bit registers, but that does
not seem to be the case, or there are good peephole optimizations in
place, and my input is so simple. I am using the Debian package gcc-avr
1:4.9.2+Atmel3.5.3-1.
My only complaint is that avr-gcc does not allow me to assign a pointer
to the Z register even when my simple program does not need that
register for anything else:
register const __flash char* usart_tx_next asm("r28"); // better: r30:31
ISR(USART_TX_vect)
{
char c;
if (!usart_tx_next);
else if ((c = *usart_tx_next++))
UDR0 = c;
else
usart_tx_next = 0;
}
In its current form, this program is generating quite a few push/pop to
preserve the value of the Z register while copying the Y register to it.
I got the impression that LLVM is a 16-bit (or wider) virtual machine.
It could be an acceptable design choice, given that 8-bit processors
usually have a 16-bit or wider address space. But currently llc (the
LLVM-to-AVR translator) is lacking optimizations, generating very
bloated code.
Best regards,
Marko