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

            Bug ID: 89018
           Summary: common subexpression present in both branches of
                    condition is not factored out
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wojciech_mula at poczta dot onet.pl
  Target Milestone: ---

A common transformation used in a C condition expression is not detected and
code is duplicated. Below are a few examples:

---condition.c---
long transform(long);

long negative_max(long a, long b) {
    return (a >= b) ? -a : -b;
}

long fun_max(long a, long b) {
    return (a >= b) ? 47*a : 47*b;
}

long transform_max(long a, long b) {
    return (a >= b) ? transform(a) : transform(b);
}
---eof---

In both branches a scalar value is a part of the same expression. So, it
would be more profitable when, for instance "(a >= b) ? -a : -b" would be
compiled as "-((a >= b) ? a : b))". Of course, a programmer might factor it
out, but in case of macros or auto-generated code such silly repetition
might occur.

Below is assembly code generated for x86 by a pretty fresh GCC 9.
BTW the jump instruction from `fun_max` and `transform_max` can
be replaced with a condition move.

$ gcc --version
gcc (GCC) 9.0.0 20190117 (experimental)

$ gcc -O3 -march=skylake -c -S condition.c && cat condition.s

negative_max:
        movq    %rdi, %rdx
        movq    %rsi, %rax
        negq    %rdx
        negq    %rax
        cmpq    %rsi, %rdi
        cmovge  %rdx, %rax
        ret

fun_max:
        cmpq    %rsi, %rdi
        jl      .L6
        imulq   $47, %rdi, %rax
        ret
.L6:
        imulq   $47, %rsi, %rax
        ret

transform_max:
        cmpq    %rsi, %rdi
        jge     .L11
        movq    %rsi, %rdi
.L11:
        jmp     transform

Reply via email to