https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121268
Bug ID: 121268 Summary: RISC-V: Possible optimization when manipulating rightmost bits with zbb enabled Product: gcc Version: 16.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: dusan.stojko...@rt-rk.com Target Milestone: --- Hello, Consider the following three functions: ``` unsigned int f1(unsigned int x) { return ~(x | -x); } unsigned int f2(unsigned int x) { return ~x & (x - 1); } unsigned int f3(unsigned int x) { return (x & -x) - 1; } ``` The functions effectively create ones in the trailing 0s in x and 0s elsewhere, producing 0 if none (ex. 0x00100000 → 0x000fffff). They are equivalent logically, but GCC produces different assembly code for each one: ``` f1(unsigned int): negw a5,a0 or a0,a5,a0 not a0,a0 ret f2(unsigned int): addiw a5,a0,-1 andn a0,a5,a0 ret f3(unsigned int): negw a5,a0 and a0,a5,a0 addiw a0,a0,-1 ret ``` Compiled with -O3 -march=rv64gc_zbb. Could GCC match f1 and f3 combinations and transform them into f2? For -O3 -march=rv32gc_zbb we get: ``` f1(unsigned int): addi a5,a0,-1 andn a0,a5,a0 ret f2(unsigned int): addi a5,a0,-1 andn a0,a5,a0 ret f3(unsigned int): neg a5,a0 and a0,a5,a0 addi a0,a0,-1 ret ``` Here, f3 could be combined to f1 or f2.