]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Add min/max patterns for ifcvt.
authorRobin Dapp <rdapp@ventanamicro.com>
Fri, 31 May 2024 12:28:00 +0000 (14:28 +0200)
committerRobin Dapp <rdapp@ventanamicro.com>
Thu, 11 Sep 2025 08:20:15 +0000 (10:20 +0200)
ifcvt likes to emit

(set
  (if_then_else)
    (ge (reg 1) (reg2))
    (reg 1)
    (reg 2))

which can be recognized as min/max patterns in the backend.
This patch adds such patterns and the respective iterators as well as a
test.

gcc/ChangeLog:

* config/riscv/bitmanip.md (*<bitmanip_minmax_cmp_insn>_cmp_<mode>3):
New min/max ifcvt pattern.
* config/riscv/iterators.md (minu): New iterator.
* config/riscv/riscv.cc (riscv_noce_conversion_profitable_p):
Remove riscv-specific adjustment.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zbb-min-max-04.c: New test.

gcc/config/riscv/bitmanip.md
gcc/config/riscv/iterators.md
gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c [new file with mode: 0644]

index 21426f496798f04748a579033f15939d64a6f5c4..5fd139ac9c14d913ea96244fc54abd2800465693 100644 (file)
   "<bitmanip_insn>\t%0,%1,%z2"
   [(set_attr "type" "<bitmanip_insn>")])
 
+;; Provide a minmax pattern for ifcvt to match.
+(define_insn "*<bitmanip_minmax_cmp_insn>_cmp_<mode>3"
+  [(set (match_operand:X 0 "register_operand" "=r")
+       (if_then_else:X
+           (bitmanip_minmax_cmp_op
+               (match_operand:X 1 "register_operand" "r")
+               (match_operand:X 2 "register_operand" "r"))
+           (match_dup 1)
+           (match_dup 2)))]
+  "TARGET_ZBB"
+  "<bitmanip_minmax_cmp_insn>\t%0,%1,%z2"
+  [(set_attr "type" "<bitmanip_minmax_cmp_insn>")])
+
 ;; Optimize the common case of a SImode min/max against a constant
 ;; that is safe both for sign- and zero-extension.
 (define_split
index d300224150991d88f99aa5e4ffdecd4761055c56..cd8fd7a2b25293c6bb63fe5af47e8d84738ea947 100644 (file)
 
 (define_code_iterator bitmanip_minmax [smin umin smax umax])
 
+(define_code_iterator bitmanip_minmax_cmp_op [lt ltu le leu ge geu gt gtu])
+
+; Map a comparison operator to a min or max.
+(define_code_attr bitmanip_minmax_cmp_insn [(lt "min") (ltu "minu")
+                                           (le "min") (leu "minu")
+                                           (ge "max") (geu "maxu")
+                                           (gt "max") (gtu "maxu")])
+
 (define_code_iterator clz_ctz_pcnt [clz ctz popcount])
 
 (define_code_iterator bitmanip_rotate [rotate rotatert])
index bfd43fba10138c6729bc54db995c280b98c7b9fa..17eb45aacf01a422ae6ccdb5856650b7eac15de4 100644 (file)
@@ -4641,9 +4641,6 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
 {
   struct noce_if_info riscv_if_info = *if_info;
 
-  riscv_if_info.original_cost -= COSTS_N_INSNS (2);
-  riscv_if_info.original_cost += insn_cost (if_info->jump, if_info->speed_p);
-
   /* Hack alert!  When `noce_try_store_flag_mask' uses `cstore<mode>4'
      to emit a conditional set operation on DImode output it comes up
      with a sequence such as:
diff --git a/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c b/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c
new file mode 100644 (file)
index 0000000..3103c96
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zicond_zbb -mabi=lp64d" } */
+/* { dg-skip-if "" { *-*-* } { "-finline-functions" "-funroll-loops" "-ftracer" } } */
+
+int
+remove_one_fast (int *move_ordering, const int num_moves, int mark)
+{
+  int i, best = -1000000;
+  int tmp = 0;
+
+  for (i = mark; i < num_moves; i++)
+    {
+      if (move_ordering[i] > best)
+        {
+          best = move_ordering[i];
+          tmp = i;
+        }
+    }
+
+  return tmp;
+}
+
+/* { dg-final { scan-assembler-times "max\t" 1 } }  */
+/* { dg-final { scan-assembler-times "czero.nez" 2 } }  */
+/* { dg-final { scan-assembler-times "czero.eqz" 2 } }  */
+
+int
+remove_one_fast2 (int *move_ordering, const int num_moves, int mark)
+{
+  int i, best = -1000000;
+  int tmp = 0;
+
+  for (i = mark; i < num_moves; i++)
+    {
+      if (move_ordering[i] < best)
+        {
+          best = move_ordering[i];
+          tmp = i;
+        }
+    }
+
+  return tmp;
+}
+
+/* { dg-final { scan-assembler-times "min\t" 1 } }  */