https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88253
Bug ID: 88253 Summary: Inlining of function incorrectly deletes volatile register access when using XOR in avr-gcc Product: gcc Version: 5.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: westfw at westfw dot info Target Milestone: --- Created attachment 45116 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45116&action=edit .i pre-processed file from --keep-temps Using avr-gcc (AVR_8_bit_GNU_Toolchain_3.6.1_495) 5.4.0 (bug also occurs in avr-gcc 4.9 and 8.1; does NOT occur in 4.8.1) A rather trivial C program: #include <avr/io.h> uint16_t aRead() { uint8_t h; uint8_t l; l = ADCL; h = ADCH; return (h<<8) | l; } int main() { volatile uint8_t x; x = aRead()^42; } only reads ADCL when aRead() is inlined from main; the read of (volatile) ADCH is apparently removed by an optimization step, which breaks things because that read has side-effects at the hardware level. 00000000 <main>: 0: cf 93 push r28 2: df 93 push r29 4: 1f 92 push r1 6: cd b7 in r28, 0x3d ; 61 8: de b7 in r29, 0x3e ; 62 a: 80 91 78 00 lds r24, 0x0078 ; 0x800078 <__SREG__+0x800039> e: 9a e2 ldi r25, 0x2A ; 42 10: 89 27 eor r24, r25 12: 89 83 std Y+1, r24 ; 0x01 This seems to happen during or slightly before the .combine pass of optimization; the ud_dce output dump shows both volatile accesses, and the combine has only one. Does not happen using inclusive-OR, or a plain store. (yes, I know that the value of ADCH that is read is never actually used. But it's volatile, and has side effects, and should be read.) General compiler command: "avr-gcc -O3 -g adctest.i" Seems to occur regardless of the reason for inlining - happens with "-Os -fto" or with -Os and the always_inline attribute specified. Some discussion at https://www.avrfreaks.net/forum/avr-gcc-optimization-xor-incorrectly-eliminates-volatile-access