https://gcc.gnu.org/g:832d5bcef5e49b31358e61525f0d001e776cec34

commit 832d5bcef5e49b31358e61525f0d001e776cec34
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 15c89ff4e3de..259997fef68f 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 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" } 
} */

Reply via email to