Bug in identical code folding?

Georg-Johann Lay avr@gjlay.de
Tue Dec 2 20:44:50 GMT 2025


Playing with a new avr function attribute, I stumbled upon this problem:

On avr, all varargs arguments are passed on the stack, even the named 
ones. So I added a "rargs" function attribute that passes named args in 
registers if possible.  One test case looks like this:

#define RA __attribute__((rargs))

void call_rafun_cast1 (void (*f)(char, ...))
{
     ((RA void(*)(char,...)) f) (10);
}

void call_rafun_cast0 (RA void (*f)(char, ...))
{
     ((void(*)(char,...)) f) (20);
}

The code compiles as expected:

// rargs: no push/pop
call_rafun_cast1:
	movw r30,r24	 ;  20	[c=4 l=1]  *movhi/0
	ldi r24,lo8(10)	 ;  14	[c=4 l=1]  movqi_insn/1
	ijmp		 ;  7	[c=0 l=1]  call_insn/2

// default: push/pop.
call_rafun_cast0:
	ldi r18,lo8(20)	 ;  15	[c=4 l=1]  movqi_insn/1
	push r18		 ;  7	[c=4 l=1]  pushqi1/0
	movw r30,r24	 ;  23	[c=4 l=1]  *movhi/0
	icall		 ;  8	[c=0 l=1]  call_insn/0
	 ; SP += 1	 ;  9	[c=8 l=1]  *addhi3_sp
	pop __tmp_reg__
	ret		 ;  19	[c=0 l=1]  return

Notice that cast0 has a push / pop of the argument as expected, while 
cast1 hasn't, also as expected. This is all fine.  Now change the code 
slightly so that the function bodies become the same (pass 10 instead of 
20):

void call_rafun_cast0 (RA void (*f)(char, ...))
{
     ((void(*)(char,...)) f) (10);
}

The code compiles to:

call_rafun_cast0:
	rjmp call_rafun_cast1	 ;  7	[c=0 l=1]  call_insn/3

which is wrong IMO.  The bodies of the functions are the same, but the
prototypes are not, so performing ICF is wrong.

I am not completely sure about a function pointer cast adding / removing 
a function attribute.  Though GCC seems to compile it as expected 
without ICF.

So is this an ICF bug or am I missing some target hook?
For now I only changed the cumulative args hooks, but there are some 
VA_LIST and VA_ARG hooks in 
https://gcc.gnu.org/onlinedocs/gccint/Register-Arguments.html where I 
don't know what to do with them.

All unnamed args are passed the same way in either case; the attribute 
only affects passing of named args.

GCC is current trunk.

Johann



More information about the Gcc mailing list