https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70676
--- Comment #2 from night_ghost at ykoctpa dot ru --- *** testcase for call+ret: (all code from https://github.com/night-ghost/minimosd-extra/tree/master/MinimOsd_Extra), compile with -fno-optimize-sibling-calls #include <Arduino.h> class SPI { public: SPI(void); static byte transfer(byte); }; SPI::SPI() { #define SCK_PIN 13 #define MISO_PIN 12 #define MOSI_PIN 11 // initialize the SPI pins pinMode(SCK_PIN, OUTPUT); pinMode(MOSI_PIN, OUTPUT); pinMode(MISO_PIN, INPUT); } byte SPI::transfer(byte value){ SPDR = value; while (!(SPSR & (1<<SPIF))) ; return SPDR; } byte MAX_read(byte addr){ SPI::transfer(addr); return SPI::transfer(0xff); } *** testcase of splitting tail, compile without -fno-optimize-sibling-calls #include <Arduino.h> #define NOINLINE __attribute__ ((noinline)) struct Point { byte x; byte y; }; typedef struct Point point; static boolean inline is_alt(point p){ return (p.y & 0x40); } static void NOINLINE osd_printf_1(PGM_P fmt, float f){ Serial.printf_P(fmt, f); } static void NOINLINE osd_printf_2(PGM_P fmt, float f, byte c){ Serial.printf_P(fmt, f); Serial.write(c); } static void panBatteryPercent(point p){ float val=2.0; if (is_alt(p)) osd_printf_1(PSTR("%2.0f%%"),val); else osd_printf_2(PSTR("%4.0f\x01"),val,0x15); } } >Provided you use -mrelax (or link with -Wl,--relax), the linker tries to >replace [R]CALL+RET by [R]JMP instruction Thanks for good key, it saves 700bytes of code (from 30642 to 29942)