https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91812
Bug ID: 91812 Summary: GCC ignores volatile modifier Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: fuchedzhy at google dot com Target Milestone: --- GCC appears to ignore volatile modifier sometimes. C is probably wrong component for the bug, but I'm not sure where else to put it. $ arm-linux-gnueabi-gcc-8 -v Using built-in specs. COLLECT_GCC=arm-linux-gnueabi-gcc-8 COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabi/8/lto-wrapper Target: arm-linux-gnueabi Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-6' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-multiarch --disable-sjlj-exceptions --with-arch=armv5te --with-float=soft --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabi --program-prefix=arm-linux-gnueabi- --includedir=/usr/arm-linux-gnueabi/include Thread model: posix gcc version 8.3.0 (Debian 8.3.0-6) This is a minimal example I could come up with: volatile unsigned register1; volatile unsigned register2; void busy_wait_for_register(int x) { volatile unsigned* ptr; switch(x) { case 0x1111: ptr = ®ister1; break; case 0x2222: ptr = ®ister2; break; default: return; } while (*ptr) {} } If compiled with following command: $ arm-linux-gnueabi-gcc-8 -mcpu=cortex-m7 -Os -c main.c Produces following binary: $ arm-linux-gnueabi-objdump -d main.o main.o: file format elf32-littlearm Disassembly of section .text: 00000000 <busy_wait_for_register>: 0: f241 1211 movw r2, #4369 ; 0x1111 4: 4b08 ldr r3, [pc, #32] ; (28 <busy_wait_for_register+0x28>) 6: 4290 cmp r0, r2 8: 447b add r3, pc a: d004 beq.n 16 <busy_wait_for_register+0x16> c: f242 2222 movw r2, #8738 ; 0x2222 10: 4290 cmp r0, r2 12: d006 beq.n 22 <busy_wait_for_register+0x22> 14: 4770 bx lr 16: 4a05 ldr r2, [pc, #20] ; (2c <busy_wait_for_register+0x2c>) 18: 589b ldr r3, [r3, r2] 1a: 681b ldr r3, [r3, #0] 1c: 2b00 cmp r3, #0 1e: d1fd bne.n 1c <busy_wait_for_register+0x1c> 20: 4770 bx lr 22: 4a03 ldr r2, [pc, #12] ; (30 <busy_wait_for_register+0x30>) 24: e7f8 b.n 18 <busy_wait_for_register+0x18> 26: bf00 nop 28: 0000001c .word 0x0000001c ... Note that generated while loop instructions: 1c: 2b00 cmp r3, #0 1e: d1fd bne.n 1c <busy_wait_for_register+0x1c> never reload the register making this effectively an infinite loop. I believe volatile keyword should have prevented that.