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

            Bug ID: 122911
           Summary: Redundant code when calculating / 10 and %10 for
                    signed/unsigned mixture
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tkoenig at gcc dot gnu.org
  Target Milestone: ---

Consider

void bar(unsigned long, long);

void foo(unsigned long u1)
{
  long u3;
  u1 = u1 / 10;
  u3 = u1 % 10;
  bar(u1,u3);
}


which yields, with a reasonably recent trunk at -O2,

foo:
.LFB0:
        .cfi_startproc
        movabsq $-3689348814741910323, %rcx
        movq    %rdi, %rax
        mulq    %rcx
        movq    %rdx, %rdi
        shrq    $3, %rdi
        movq    %rdi, %rax
        movq    %rdi, %rsi
        mulq    %rcx
        shrq    $3, %rdx
        leaq    (%rdx,%rdx,4), %rax
        addq    %rax, %rax
        subq    %rax, %rsi
        jmp     bar

which calculates u1/10 twice.

POWER has (compiled with godbolt)

foo:
.LCF0:
0:      addis 2,12,.TOC.-.LCF0@ha
        addi 2,2,.TOC.-.LCF0@l
        mflr 0
        lis 9,0xcccc
        lis 10,0xcccc
        ori 9,9,0xcccd
        ori 10,10,0xcccc
        rldimi 9,10,32,0
        mulhdu 3,3,9
        std 0,16(1)
        stdu 1,-32(1)
        srdi 3,3,3
        mulhdu 9,3,9
        srdi 9,9,3
        mulli 9,9,10
        subf 4,9,3
        bl bar
        nop
        addi 1,1,32
        ld 0,16(1)
        mtlr 0
        blr

so it shows a similar problem.

Dividing an unsigned long number by 10 will always yield a
valid long, so this could be improved.

Reply via email to