https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71942
--- Comment #8 from Mikael Rosbacke <mikael.rosbacke at gmail dot com> --- Previous bug i filed was marked as a duplicate of this. Collecting my information from that report here. Same basic problem, slightly different symptom. --- old text --- I used the following code on arm-gcc 6.3 compiler (using Matt godbolts compiler explorer) #include<cstdint> volatile uint32_t reg32; volatile uint16_t reg16; void test16() { volatile uint16_t* reg_p = ®16; uint16_t mask = 0x800u; *reg_p &= (uint16_t)~mask; } void test32() { volatile uint32_t* reg_p = ®32; uint32_t mask = 0x800u; *reg_p &= (uint32_t)~mask; } And I got the following assembler: (arguments: -std=c99 -mthumb -Os -mcpu=cortex-m4) test16(): ldr r2, .L2 ldrh r3, [r2] bic r3, r3, #2048 lsls r3, r3, #16 lsrs r3, r3, #16 strh r3, [r2] @ movhi bx lr .L2: .word .LANCHOR0 test32(): ldr r2, .L5 ldr r3, [r2, #4] bic r3, r3, #2048 str r3, [r2, #4] bx lr .L5: .word .LANCHOR0 reg16: reg32: The case for 32 bit seems fine. load value, clear bits and then write it back. The second case have 2 extra instructions, lsls/lsrs. I assume these are for clearing bit 16-31. However the value is written using a half word instruction so bit 16-31 should not matter. This particular case is very common on microcontrollers when accessing hardware registers. Using '-Os' to save flash memory and then operating bit field in registers makes this come up often, sometimes in interrupt handlers where timing is important. Would like the lsls/lsrs instructions removed unless there is a good reason to have them there. Thanks in advance, --- Mikael R