When I compile (avr-gcc -Os -c -mmcu=at90s2313) this:
void SIG_PIN_CHANGE0 (void) __attribute__ ((signal)); void SIG_PIN_CHANGE0 (void)
(*(volatile unsigned char *)((0x12) + 0x20)) |= 1;
0: 1f 92 push r1
2: 0f 92 push r0
4: 0f b6 in r0, 0x3f ; 63
6: 0f 92 push r0
8: 11 24 eor r1, r1
a: 90 9a sbi 0x12, 0 ; 18
c: 0f 90 pop r0
e: 0f be out 0x3f, r0 ; 63
10: 0f 90 pop r0
12: 1f 90 pop r1
14: 18 95 reti
If the optimizer?/backend knows that the 'sbi' instruction does not
modify r1 or the status register (0x3f) it could generate this instead:
sbi 0x12, 0
IMHO everyone working on the avr back-end is aware of this problem. The
difficulty is, that the present architecture of the avr back-end does not
easily permit to improve this case: Every instruction pattern (like "multiply
two 16 bit integers" or "sign-extend a 16 bit variable to 32 bits") presently
is free to assume that may overwrite or change r0 and r1 unless it leaves the
"__zero_reg__" with 0 after finishing it's task.
Resolving this issue, IMHO, would require a major refactoring of the
back-end. ... IIUC the keyword is "replace all of the more complex instruction
patterns by RTL expressions."
I suggest to mark this bug as "desired enhancement".
FWIW, confirming that versions 4.3.4 and 4.6.2 still emit these unnecessary saves of r0 and r1 for small ISRs (the generated code is identical to what email@example.com posted, at least for optimization levels >= 1).