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.

Jeff

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.

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 15c89ff4e3d..259997fef68 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3173,15 +3173,25 @@ (define_insn_and_split 
"*branch<ANYI:mode>_shiftedarith_equals_zero"
   "#"
   "&& 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 00000000000..fe560a78ce1
--- /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