This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/63321] New: [SH] Unused T bit result of shll / shlr insns


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

            Bug ID: 63321
           Summary: [SH] Unused T bit result of shll / shlr insns
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: olegendo at gcc dot gnu.org
            Target: sh*-*-*

The following examples resemble code that is usually used when implementing
pointer tagging (storing meta info in always-zero bits of a pointer variable). 
The shll / shr insns shift the MSB / LSB out into the T bit.  However, the T
bit value is lost and redundant MSB / LSB extractions remain in the code.

unsigned int foo (unsigned int);

unsigned int test2 (unsigned int x)
{
  unsigned int xx = x >> 1;
  if (x & 1)
    return foo (xx);
  else
    return xx;
}

/*
        mov     r4,r1
        shlr    r1
        mov     r4,r0
        tst     #1,r0
        bf/s    .L5
        mov     r1,r0
        rts
        nop
        .align 1
.L5:
        mov.l   .L6,r0
        jmp     @r0
        mov     r1,r4

better:
        shlr    r4
        bt      .L5
        rts
        mov     r4,r0
.L5:
        mov.l   .L6,r0
        jmp     @r0
        nop
*/



void test2_1 (unsigned int x, unsigned int* y)
{
  y[0] = x >> 1;
  y[1] = x & 1;
}

/*
        mov     r4,r1
        mov     r4,r0
        shlr    r1
        and     #1,r0
        mov.l   r1,@r5
        rts
        mov.l   r0,@(4,r5)

better:
        shlr    r4
        movt    r0
        mov.l   r4,@r5
        rts
        mov.l   r0,@(4,r5)
*/

unsigned int test3 (unsigned int x)
{
  unsigned int xx = x << 1;
  if (x & (1 << 31))
    return foo (xx);
  else
    return xx;
}

/*
        cmp/pz  r4
        mov     r4,r0
        bf/s    .L13
        add     r0,r0
        rts
        nop
        .align 1
.L13:
        mov     r0,r4
        mov.l   .L14,r0
        jmp     @r0
        nop

better:
        shll    r4
        bt      .L13
        rts
        mov     r4,r0
.L13:
        mov.l   .L14,r0
        jmp     @r0
        nop
*/

void test3_1 (unsigned int x, unsigned int* y)
{
  y[0] = x << 1;
  y[1] = x >> 31;
}

/*
        mov     r4,r1
        shll    r4
        add     r1,r1
        movt    r4
        mov.l   r1,@r5
        rts
        mov.l   r4,@(4,r5)

better:
        shll    r4
        movt    r0
        mov.l   r4,@r5
        rts
        mov.l   r0,@(4,r5)
*/

It seems that combine doesn't try to combine those adjacent insns into a
parallel, which could be used to implement that kind of patterns.  An
alternative is to do a manual combining/peepholing of insns in the split pass
after combine, as it is done for other insns.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]