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

            Bug ID: 103765
           Summary: Missed arithmetic simplification for multiplication +
                    division
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: llvm at rifkin dot dev
  Target Milestone: ---

The following code is optimized strangely:

int foo(int x) {
    return (x * 72) / 3;
}
int bar(int x) {
    x *= 72;
    x /= 3;
    return x;
}

foo(int):
        lea     eax, [rdi+rdi*2]
        sal     eax, 3
        ret
bar(int):
        lea     edx, [rdi+rdi*8]
        sal     edx, 3
        movsx   rax, edx
        imul    rax, rax, 1431655766
        sar     edx, 31
        shr     rax, 32
        sub     eax, edx
        ret

https://godbolt.org/z/13PxxsM8G

For some foo is simplified to return x * 24; but bar is not. It appears the
transformation is done before transformation to gimple.

Another case:

int foo(int x) {
    return (x * 64) / 8;
}
int bar(int x) {
    x *= 64;
    x /= 8;
    return x;
}

foo(int):
        lea     eax, [0+rdi*8]
        ret
bar(int):
        sal     edi, 6
        lea     eax, [rdi+7]
        cmovns  eax, edi
        sar     eax, 3
        ret

https://godbolt.org/z/vfG1TP7oG

Even with powers of 2 (and thus shift operations down the line), it is not
transformed.

This would be a good enhancement, and I'd also be interested to learn why this
strange behavior is occurring.

Reply via email to