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 = &reg16;
    uint16_t mask = 0x800u;
    *reg_p &= (uint16_t)~mask;
}

void test32()
{
    volatile uint32_t* reg_p = &reg32;
    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

Reply via email to