https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82871
Bug ID: 82871 Summary: Unneeded lsls lsrs instructions generated on half word access for arm cortex-m4 target. Product: gcc Version: 6.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: mikael.rosbacke at gmail dot com Target Milestone: --- 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