]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[RISC-V] Avoid unnecessary andi with -1 argument
authorJeff Law <jlaw@ventanamicro.com>
Wed, 7 May 2025 01:20:14 +0000 (19:20 -0600)
committerJeff Law <jlaw@ventanamicro.com>
Wed, 7 May 2025 01:21:55 +0000 (19:21 -0600)
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.

gcc/config/riscv/riscv.md
gcc/testsuite/g++.target/riscv/redundant-andi.C [new file with mode: 0644]

index 15c89ff4e3de4047116434f77c5476c1bbb53cb7..259997fef68f4b7a4962e0d266092407844f9ef4 100644 (file)
   "#"
   "&& 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 (file)
index 0000000..fe560a7
--- /dev/null
@@ -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" } } */