Electronic – Why is the AVR GCC compiler using a full `CALL` even though I have set the `-mshort-calls` flag

avrgcc

I have set the -mshort-calls flag which is documented to replace the 4 byte long CALL instruction with the 2 byte long RCALL instruction when possible to save flash space and and cycles…

-mshort-calls

Assume that RJMP and RCALL can target the whole program memory.

This option is used internally for multilib selection. It is not an
optimization option, and you don’t need to set it by hand.

https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html#index-mshort-calls

…and it set in Atmel Studio here…

enter image description here

Unfortunately the compiler is still using full CALL instructions even for a call that is only 2 bytes away…

    ...
    35f6:   0e 94 fd 1a     call    0x35fa  ; 0x35fa         
    35fa:   f8 94           cli
    ...

What am I doing wrong?

Best Answer

This option was removed in gcc 4.8 but not all the documentation was updated. Atmel Studio also still uses the obsolete flag.

The new option is called -mrelax on the compiler command line or --relax on the linker command line...

https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/AVR-Options.html

After adding that flag, the above code compiled to...

...
3584:   00 d0           rcall   .+0         ; 0x3586 
3586:   f8 94           cli
...

If you are using Atmel Studio, the new flag is misleadingly called "Relax Branches" and is located here...

enter image description here

In my case, enabling relative jumps and calls resulted in significant flash savings. If you are here because you also need to save flash space and/or cycles, I'd also recommend looking into enabling Link Time Optimization which also offers great savings at no cost.