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

            Bug ID: 113680
           Summary: Missed optimization: Redundant cmp/test instructions
                    when comparing (x - y) > 0
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Explorer09 at gmail dot com
  Target Milestone: ---

Note: This issue is not limited to x86-64. I also tested it with ARM64 gcc in
Compiler Explorer (https://godbolt.org/) and it has the same "redundant cmp
instruction" problem.

This may be related to bug #3507 but I can't make sure it's the same bug. I
apologize if I reported a duplicate.

== Test code ==

```c
#include <stdio.h>

void func1(int x, int y) {
    int diff = x - y;
    if (diff > 0)
        putchar('>');
    if (diff < 0)
        putchar('<');
}

void func2(int x, int y) {
    if ((x - y) > 0)
        putchar('>');
    if ((x - y) < 0)
        putchar('<');
}

void func3(int x, int y) {
    if (x > y)
        putchar('>');
    if (x < y) {
        putchar('<');
}

void func4(int x, int y) {
    int diff = x - y;
    if (diff > 0)
        putchar('>');
    if (x < y) {
        putchar('<');
}
```

== Actual result ==

With x86-64 "gcc -Os" it generates the following.

In short, gcc can recognize func1() and func2() as completely identical, but
didn't recognize func1() and func2() can both optimize to func3().

func4() currently generates the worst assembly, but it might be another issue
to address (something messes up the register allocation algorithm).

```x86asm
func1:
        subl    %esi, %edi
        testl   %edi, %edi
        jle     .L2
        movl    $62, %edi
        jmp     .L4
.L2:
        je      .L1
        movl    $60, %edi
.L4:
        jmp     putchar
.L1:
        ret
func2:
        jmp     func1
func3:
        cmpl    %esi, %edi
        jle     .L8
        movl    $62, %edi
        jmp     .L10
.L8:
        jge     .L7
        movl    $60, %edi
.L10:
        jmp     putchar
.L7:
        ret
func4:
        pushq   %rbp
        movl    %edi, %ebp
        pushq   %rbx
        movl    %esi, %ebx
        pushq   %rcx
        cmpl    %esi, %edi
        jle     .L12
        movl    $62, %edi
        call    putchar
.L12:
        cmpl    %ebx, %ebp
        jge     .L11
        popq    %rdx
        movl    $60, %edi
        popq    %rbx
        popq    %rbp
        jmp     putchar
.L11:
        popq    %rax
        popq    %rbx
        popq    %rbp
        ret
```

== Expected result ==

func1(), func2(), func3() and func4() are all identical. With the func3() as
the example for the best assembly. (No redundant "test" instruction; the "sub"
instruction can simplify into a "cmp".)

Reply via email to