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".)