https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65371
Bug ID: 65371 Summary: arm loop with volatile variable Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: gcc-bugzilla at enginuities dot com Target: arm-none-eabi (Cortex-M3) I've found this behaviour with gcc 4.8.4, 4.9.2, and 5.0.0 (20150308) (all compiled with the same flags) on Arch Linux (3.18.2-2-ARCH x86_64). I've also had the same behaviour using the precompiled gcc-arm-embedded toolchain from Launchpad (gcc-arm-none-eabi-4_9-2014q4). Compiling func.c: #define PERIPH_BASE 0x4001000 #define PERIPH ((PERIPH_TypeDef *) PERIPH_BASE) typedef struct { volatile unsigned long REG1; } PERIPH_TypeDef; void func() { PERIPH->REG1 |= 0x00010000; while (!(PERIPH->REG1 & 0x00020000)) { } PERIPH->REG1 |= 0x01000000; } With: arm-none-eabi-gcc -mthumb -mcpu=cortex-m3 -Os -c func.c Results in the following disassembly of func.o: 00000000 <func>: 0: 4b06 ldr r3, [pc, #24] ; (1c <func+0x1c>) 2: 681a ldr r2, [r3, #0] 4: f442 3280 orr.w r2, r2, #65536 ; 0x10000 8: 601a str r2, [r3, #0] a: 6819 ldr r1, [r3, #0] c: 4a03 ldr r2, [pc, #12] ; (1c <func+0x1c>) e: 0389 lsls r1, r1, #14 10: d5fb bpl.n a <func+0xa> 12: 6813 ldr r3, [r2, #0] 14: f043 7380 orr.w r3, r3, #16777216 ; 0x1000000 18: 6013 str r3, [r2, #0] 1a: 4770 bx lr 1c: 04001000 streq r1, [r0], #-0 The last line in func.c (PERIPH->REG1 |= 0x01000000;) causes the compiled code to load the address of PERIPH->REG1 in to r2 during the loop at <func+0x0c> (ldr r2, [pc, #12]) and then use r2 after the loop even though the address contained in r2 was loaded in to r3 at <func+0x00> (ldr r3, [pc, #24]) and doesn't change. As such I would expect something like this disassembly of func.o: 00000000 <func>: 0: 4b06 ldr r3, [pc, #24] ; (1c <func+0x1c>) 2: 681a ldr r2, [r3, #0] 4: f442 3280 orr.w r2, r2, #65536 ; 0x10000 8: 601a str r2, [r3, #0] a: 681a ldr r2, [r3, #0] c: 0392 lsls r2, r2, #14 e: d5fc bpl.n a <func+0xa> 10: 681a ldr r2, [r3, #0] 12: f042 7280 orr.w r2, r2, #16777216 ; 0x1000000 16: 601a str r2, [r3, #0] 18: 4770 bx lr 1a: bf00 nop 1c: 04001000 streq r1, [r0], #-0 arm-none-eabi-gcc -v: Using built-in specs. COLLECT_GCC=arm-none-eabi-gcc COLLECT_LTO_WRAPPER=/home/test_user/toolchain/libexec/gcc/arm-none-eabi/5.0.0/lto-wrapper Target: arm-none-eabi Configured with: /home/test_user/temp/gcc-5-20150308/gcc-5-20150308/configure --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --enable-languages=c,c++ --prefix=/home/test_user/toolchain --target=arm-none-eabi --with-gmp=/home/test_user/toolchain --with-gnu-as --with-gnu-ld --with-mpc=/home/test_user/toolchain --with-mpfr=/home/test_user/toolchain --with-newlib --without-headers Thread model: single gcc version 5.0.0 20150308 (experimental) (GCC)