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

            Bug ID: 119178
           Summary: Optimization: (x != C) comparison can utilize (x - C)
                    or (x ^ C) result
           Product: gcc
           Version: 14.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Explorer09 at gmail dot com
  Target Milestone: ---

This is an optimization opportunity that can benefit RISC-V, MIPS and other
processors that don't use condition codes for their compare-and-branch
instructions.

```c

#include <stdlib.h>
unsigned int func1_a(unsigned int x) {
    if (x != 0x555)
        return (x ^ 0x555);
    abort();
}

unsigned int func1_c(unsigned int x) {
    unsigned int tmp = x ^ 0x555;
    __asm__ ("" : "+r" (tmp));
    if (tmp == 0)
        abort();
    return tmp;
}

unsigned int func2_a(unsigned int x) {
    if (x != 0x555)
        return (x - 0x555);
    abort();
}

unsigned int func2_c(unsigned int x) {
    unsigned int tmp = x - 0x555;
    __asm__ ("" : "+r" (tmp));
    if (tmp == 0)
        abort();
    return tmp;
}

```

The example code above can be tested in Compiler Explorer (godbolt.org).

func1_c() and func2_c() are the results I expected for func1_a() and func2_a()
to optimize to when using the `-Os` option.

* The second operand for `==` or `!=` comparison is a compile-time constant.
* The constant is small enough to fit the immediate operands of the "sub" and
"xor" instructions.
* The compare-and-branch instructions of RISC-V have only register operands
(cannot compare with immediate), and for these particular examples it's better
to calculate `(x - 0x555)` or `(x ^ 0x555)` first and compare that result with
zero.

Reply via email to