[gcc(refs/vendors/riscv/heads/gcc-15-with-riscv-opts)] RISC-V: Add min/max patterns for ifcvt.
Jeff Law
law@gcc.gnu.org
Sat Sep 13 16:32:54 GMT 2025
https://gcc.gnu.org/g:7ab6db6a9543bf4b43060620a3db11e97038f4e3
commit 7ab6db6a9543bf4b43060620a3db11e97038f4e3
Author: Robin Dapp <rdapp@ventanamicro.com>
Date: Fri May 31 14:28:00 2024 +0200
RISC-V: Add min/max patterns for ifcvt.
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.
(cherry picked from commit 75cad4640c37afbd22b2025feeea22248e11d530)
Diff:
---
gcc/config/riscv/bitmanip.md | 13 +++++++
gcc/config/riscv/iterators.md | 8 +++++
gcc/config/riscv/riscv.cc | 3 --
gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c | 45 +++++++++++++++++++++++++
4 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 21426f496798..5fd139ac9c14 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -553,6 +553,19 @@
"<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
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index d30022415099..cd8fd7a2b252 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -264,6 +264,14 @@
(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])
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d119538d76bb..89cbf1ffab76 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -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
index 000000000000..3103c96ef2fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zbb-min-max-04.c
@@ -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 } } */
More information about the Gcc-cvs
mailing list