diff options
author | Jeff Law <jlaw@ventanamicro.com> | 2025-05-06 19:20:14 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2025-05-06 19:21:55 -0600 |
commit | 2c46a74d4707bd1e67561ed8514c67efc6164832 (patch) | |
tree | 9bf5473cf21ae673f4eba60a25895e0e43bd4bb5 /gcc | |
parent | d4da4474dd3b76d82bf1c9dc79548b708322cb46 (diff) | |
download | gcc-2c46a74d4707bd1e67561ed8514c67efc6164832.zip gcc-2c46a74d4707bd1e67561ed8514c67efc6164832.tar.gz gcc-2c46a74d4707bd1e67561ed8514c67efc6164832.tar.bz2 |
[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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.md | 20 | ||||
-rw-r--r-- | 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 15c89ff..259997f 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3173,15 +3173,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 0000000..fe560a7 --- /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" } } */ |