[Bug middle-end/71942] [ARM] Zero-extending whats allready zero-extended even when -O3

mikael.rosbacke at gmail dot com gcc-bugzilla@gcc.gnu.org
Tue Nov 7 18:23:00 GMT 2017


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 = &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


More information about the Gcc-bugs mailing list