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.