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