public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug target/67645] New: [SH] Inefficient single bit bitfield operations
@ 2015-09-20  5:35 olegendo at gcc dot gnu.org
  0 siblings, 0 replies; only message in thread
From: olegendo at gcc dot gnu.org @ 2015-09-20  5:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67645

            Bug ID: 67645
           Summary: [SH] Inefficient single bit bitfield operations
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: olegendo at gcc dot gnu.org
  Target Milestone: ---
            Target: sh*-*-*

Ignoring the volatile bitfield double load issue of PR 67644, there seems to be
some room for improvements w.r.t. operations on single bit bitfields.  The
examples below were compiled -m4 -ml -O2.

struct USRSTR
{
  union
  {
    unsigned char BYTE;
    struct
    {
      unsigned char BIT7:1;
      unsigned char BIT6:1;
      unsigned char BIT5:1;
      unsigned char BIT4:1;
      unsigned char BIT3:1;
      unsigned char BIT2:1;
      unsigned char BIT1:1;
      unsigned char BIT0:1;
    }
    BIT;
  }
  ICR0;
};

void test_0 (volatile USRSTR* x)
{
  x->ICR0.BIT.BIT5 |= 0x10;
}

        mov.b   @r4,r0
        mov.b   @r4,r2
        mov     #-5,r1      0b...1111'1011
        and     #4,r0       isolate bit #3 from mem
        and     r2,r1       clear bit #3 from mem
        or      r1,r0       effectively a nop
        mov.b   r0,@r4
        rts
        nop

the equivalent without bitfields:

void test_0_1 (volatile unsigned char* x)
{
  x[0] |= 0;
}

        mov.b   @r4,r1
        mov.b   r1,@r4
        rts     
        nop


void test_2 (volatile USRSTR* x, unsigned char y)
{
  x->ICR0.BIT.BIT5 |= y & 1;
}

        mov.b   @r4,r0
        mov     #1,r2
        mov.b   @r4,r3
        tst     #4,r0
        mov     #-1,r1
        and     r2,r5
        negc    r1,r1
        or      r5,r1
        mov     r3,r5
        mov     #-5,r2
        and     r2,r5
        shll2   r1
        or      r5,r1
        mov.b   r1,@r4
        rts
        nop

the equivalent without bitfields:

void test2_1 (volatile unsigned char* x, unsigned char y)
{
  x[0] |= (y & 1) << 2;
}

        mov.b   @r4,r1
        mov     r5,r0
        shll2   r0
        and     #4,r0
        or      r0,r1
        mov.b   r1,@r4
        rts
        nop

In some cases, a shift sequence as above is a good choice, especially when the
bit positions can be reached with a 1,2,8,16 shift.  Although this particular
case can be slightly improved (reduce R0 reg pressure):

        mov.b   @r4,r1
        shlr    r5        use T bit to do the (x & 1)
        movt    r5
        shll2   r5
        or      r5,r1
        mov.b   r1,@r4
        rts
        nop


In some other cases, it might be better to not use shifts:

void test2_2 (volatile unsigned char* x, unsigned char y)
{
  x[0] |= ((y >> 7) & 1) << 3;
}

currently results in:
        mov     r5,r0
        mov     #-1,r2
        tst     #128,r0
        negc    r2,r1
        mov.b   @r4,r3
        shll2   r1
        add     r1,r1
        or      r3,r1
        mov.b   r1,@r4
        rts
        nop

which could be done as:
        mov     r5,r0
        tst     #128,r0    sign extract bit through T bit...
        subc    r0,r0
        not     r0,r0      ... into r0
        and     #8,r0      punch out one bit at constant position
        mov.b   @r4,r3
        or      r3,r0
        mov.b   r0,@r4
        rts
        nop

Interestingly, when using 'unsigned int' instead of 'unsigned char', the code
tends to be better:

void test2_7 (volatile unsigned int* x, unsigned int y)
{
  x[0] |= ((y >> 7) & 1) << 3;
}

        mov     r5,r0
        shlr2   r0
        mov.l   @r4,r1
        shlr2   r0
        and     #8,r0
        or      r0,r1
        mov.l   r1,@r4
        rts     
        nop


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-09-20  5:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-20  5:35 [Bug target/67645] New: [SH] Inefficient single bit bitfield operations olegendo at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).