Bug 109910 - GCC prologue/epilogue saves/restores callee-saved registers that are never changed
Summary: GCC prologue/epilogue saves/restores callee-saved registers that are never ch...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: other (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2023-05-19 16:38 UTC by Georg-Johann Lay
Modified: 2023-08-04 19:19 UTC (History)
0 users

See Also:
Host:
Target: avr
Build:
Known to work:
Known to fail:
Last reconfirmed: 2023-08-04 00:00:00


Attachments
args.c: C test case. (132 bytes, text/plain)
2023-05-19 16:38 UTC, Georg-Johann Lay
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Georg-Johann Lay 2023-05-19 16:38:14 UTC
Created attachment 55120 [details]
args.c: C test case.

There are targets like AVR that can pass values in callee-saved registers.  There is no need to save / restore them if a caller never changes them.  Example:

$ avr-gcc args.c -dp -mmcu=atmega128 -S -Os

typedef __UINT64_TYPE__ uint64_t;

void callee_ld (long double, long double);
void callee_ull (uint64_t, uint64_t);

void noop_ld (long double x, long double y)
{
    callee_ld (x, y);
}

void noop_ull (uint64_t x, uint64_t y)
{
    callee_ull (x, y);
}

y is passed in R10...R17 which are callee-saved:

noop_ld:
	push r10		 ;  73	[c=4 l=1]  pushqi1/0
	push r11		 ;  74	[c=4 l=1]  pushqi1/0
	push r12		 ;  75	[c=4 l=1]  pushqi1/0
	push r13		 ;  76	[c=4 l=1]  pushqi1/0
	push r14		 ;  77	[c=4 l=1]  pushqi1/0
	push r15		 ;  78	[c=4 l=1]  pushqi1/0
	push r16		 ;  79	[c=4 l=1]  pushqi1/0
	push r17		 ;  80	[c=4 l=1]  pushqi1/0
	call callee_ld	 ;  39	[c=0 l=2]  call_insn/1
	pop r17		 ;  83	[c=4 l=1]  popqi
	pop r16		 ;  84	[c=4 l=1]  popqi
	pop r15		 ;  85	[c=4 l=1]  popqi
	pop r14		 ;  86	[c=4 l=1]  popqi
	pop r13		 ;  87	[c=4 l=1]  popqi
	pop r12		 ;  88	[c=4 l=1]  popqi
	pop r11		 ;  89	[c=4 l=1]  popqi
	pop r10		 ;  90	[c=4 l=1]  popqi
	ret		 ;  91	[c=0 l=1]  return_from_epilogue

There is no need to save R10..R17 because they are never changed.  If any of these regs is changed by callee_ld, that function will take care of it because these regs are callee-saved.

No need to mention that this adds considerably to code size, compute and stack usage.

The AVR backend uses df_regs_ever_live_p to determine whether a register must be saved / restored in lack of a better alternative like non-existing df_regs_ever_changed_p.

Configured with: ../../source/gcc-master/configure --target=avr --disable-nls --with-dwarf2 --with-gnu-as --with-gnu-ld --disable-shared --enable-languages=c,c++

gcc version 14.0.0 20230518 (experimental) (GCC)
Comment 1 Georg-Johann Lay 2023-05-19 19:43:48 UTC
Note that df_regs_ever_live_p may be used before reload_completed, for example in INITIAL_ELIMINATION_OFFSET.

Hence, scanning the insns by hand using, say, note_stores, does not work because reload might still be in progress.