https://gcc.gnu.org/g:5408f5d2f9dbcec62b995f52cd064b459ec69c74
commit 5408f5d2f9dbcec62b995f52cd064b459ec69c74 Author: Jeff Law <j...@ventanamicro.com> Date: Tue May 6 19:20:14 2025 -0600 [RISC-V] Avoid unnecessary andi with -1 argument I was preparing to do some testing of Shreya's next patch on spec and stumbled across another "andi dst,src,-1" case. I fixed some stuff like this in the gcc-15 cycle, but this one slipped through. It's probably about 100M instructions on deepsjeng. So tiny, but there's no good reason to leave the clearly extraneous instructions in the output. As with the other cases, it's a post-reload splitter that's not being careful enough about the code it generates. This has gone through my tester successfully. Waiting on the pre-commit tester before going forward. gcc/ * config/riscv/riscv.md (*branch<ANYI:mode>_shiftedarith_equals_zero): Avoid generating unnecessary andi. Fix formatting. gcc/testsuite * g++.target/riscv/redundant-andi.C: New test. (cherry picked from commit 2c46a74d4707bd1e67561ed8514c67efc6164832) Diff: --- gcc/config/riscv/riscv.md | 20 ++++++++++++++----- gcc/testsuite/g++.target/riscv/redundant-andi.C | 26 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 8cc82f58e696..f6621ea53e6e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3181,15 +3181,25 @@ "#" "&& reload_completed" [(set (match_dup 4) (lshiftrt:X (subreg:X (match_dup 2) 0) (match_dup 6))) - (set (match_dup 4) (and:X (match_dup 4) (match_dup 7))) + (set (match_dup 4) (match_dup 8)) (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)]) (label_ref (match_dup 0)) (pc)))] { - HOST_WIDE_INT mask = INTVAL (operands[3]); - int trailing = ctz_hwi (mask); + HOST_WIDE_INT mask = INTVAL (operands[3]); + int trailing = ctz_hwi (mask); + + operands[6] = GEN_INT (trailing); + operands[7] = GEN_INT (mask >> trailing); - operands[6] = GEN_INT (trailing); - operands[7] = GEN_INT (mask >> trailing); + /* This splits after reload, so there's little chance to clean things + up. Rather than emit a ton of RTL here, we can just make a new + operand for that RHS and use it. For the case where the AND would + have been redundant, we can make it a NOP move, which does get + cleaned up. */ + if (operands[7] == CONSTM1_RTX (word_mode)) + operands[8] = operands[4]; + else + operands[8] = gen_rtx_AND (word_mode, operands[4], operands[7]); } [(set_attr "type" "branch")]) diff --git a/gcc/testsuite/g++.target/riscv/redundant-andi.C b/gcc/testsuite/g++.target/riscv/redundant-andi.C new file mode 100644 index 000000000000..fe560a78ce17 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/redundant-andi.C @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcb -mabi=lp64" { target rv64 } } */ +/* { dg-options "-O2 -march=rv32gcb -mabi=ilp32" { target rv32 } } */ + + +typedef int move_s; +struct state_t +{ + int npieces[13]; +}; +typedef struct state_t state_t; +int +search (state_t *s, int alpha, int beta, int depth, int is_null, int cutnode, + int extend, int wpcs, int bpcs, move_s moves[240]) +{ + int i; + if ((((moves[i]) >> 19) & 0x0F) != 13 + && (((moves[i]) >> 19) & 0x0F) != 1 && (((moves[i]) >> 19) & 0x0F) != 2) + if ((wpcs + bpcs) == 1) + extend += 4; + return extend; +} + +/* A splitter was generating an unnecessary andi instruction. Verify it's + not in our output. */ +/* { dg-final { scan-assembler-not "andi\t\[a-z\]\[0-9\],\[a-z\]\[0-9\],-1" } } */