https://gcc.gnu.org/g:250a1839a0df109835fdc2c4f10395745995f788
commit 250a1839a0df109835fdc2c4f10395745995f788 Author: Robin Dapp <[email protected]> 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 d09a08b6034e..6083f81618bf 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 } } */
