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

            Bug ID: 123884
           Summary: Missed bit manipulation on RISC-V
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: law at gcc dot gnu.org
  Target Milestone: ---

int foo( int dst, int i_denom) {
    dst ^= 1<<i_denom;
    return dst;
}

int x264_macroblock_encode_p8x8( int dst, int a) {
    dst &= ~(1<<a);
    return dst;
}

These show two examples where we're generating an unnecessary sign extension on
rv64.  I'm confident another example could be generated for single bit sets.

When compiled with -O2 -march=rv64gcb will fail to generate bset/bclr/binv
style instructions.

The key issue is (of course) the fact that the single bit manipulation
instructions do not sign extend from bit 31..63 and the ABI mandates that
return values smaller than a word get sign extended.

We might be able to do something with these two combine opportunities:

Trying 7, 8 -> 10:
    7: r140:SI=0x1
    8: r141:DI=sign_extend(r140:SI<<r145:DI#0)
      REG_DEAD r145:DI
      REG_DEAD r140:SI
   10: r142:DI=r144:DI^r141:DI
      REG_DEAD r144:DI
      REG_DEAD r141:DI
Failed to match this instruction:
(set (reg:DI 142)
    (xor:DI (sign_extend:DI (ashift:SI (const_int 1 [0x1])
                (subreg:QI (reg:DI 145 [ i_denom ]) 0)))
        (reg:DI 144 [ dst ])))


I think that's binv+sext iff we know that bits 32..63 are don't care bits --
they just need to be a copy of the sign bit becuase of the ABI.  Nothing is
going to care about them other than possibly assuming they are copies of the
sign bit.

There's a similar case if you dive into the combine dump for the second
example.  I'm sure with a bit of poking a case could be constructed for bset.

Reply via email to