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

            Bug ID: 109972
           Summary: RISC-V: Could use umodsi3/udivsi3/divsi3 libcalls for
                    32-bit division/remainder on RV64 without M extension
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: craig.topper at gmail dot com
  Target Milestone: ---

There's an opportunity to improve code size for 32-bit division and remainder
on RV64 without the M extension.

Currently gcc calls the umoddi3/udivdi3/divdi3 functions by zero/sign extending
the operands. In the case of the unsigned functions this requires two shifts to
zero the upper bits. For signed, it's two sext.w if the operands are not
already sign extended.

All 3 functions are followed by a sext.w if the result needs be sign extended.

libgcc contains umodsi3/udivsi3/divsi3 functions that handle the zero extending
of inputs and sign extending the result. Internally they call the di3 functions
to do the computation. These functions could be used to reduce code size at the
caller.

There is no signed modsi3 function in libgcc. Probably because umoddi3(sext(X),
sext(Y)) is guaranteed to produce a result that is sign extended. gcc seems to
not know this and still emits a sext.w after the call to umoddi3.

godbolt https://godbolt.org/z/ax3Khc6cM

unsigned divu(unsigned x, unsigned y) {
  return x / y;
}

unsigned remu(unsigned x, unsigned y) {
  return x % y;
}

int div(int x, int y) {
  return x / y;
}

int rem(int x, int y) {
  return x % y;
}

Reply via email to