While min/minu/max/maxu instructions are provided for XLEN only, these can safely operate on GPRs (i.e. SImode or DImode for RV64): SImode is always sign-extended, which ensures that the XLEN-wide instructions can be used for signed and unsigned comparisons on SImode yielding a correct ordering of value.
This commit - relaxes the minmax pattern to express for GPR (instead of X only), providing both a si3 and di3 expansion on RV64 - adds a sign-extending form for thee si3 pattern for RV64 to all REE to eliminate redundant extensions - adds test-cases for both gcc/ChangeLog: * config/riscv/bitmanip.md: Relax minmax to GPR (i.e SImode or DImode) on RV64. * config/riscv/bitmanip.md (<bitmanip_optab>si3_sext): Add pattern for REE. gcc/testsuite/ChangeLog: * gcc.target/riscv/zbb-min-max.c: Add testcases for SImode operands checking that no redundant sign- or zero-extensions are emitted. Signed-off-by: Philipp Tomsich <philipp.toms...@vrull.eu> --- gcc/config/riscv/bitmanip.md | 14 +++++++++++--- gcc/testsuite/gcc.target/riscv/zbb-min-max.c | 20 +++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 000deb48b16..2a28f78f5f6 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -260,13 +260,21 @@ (define_insn "bswap<mode>2" [(set_attr "type" "bitmanip")]) (define_insn "<bitmanip_optab><mode>3" - [(set (match_operand:X 0 "register_operand" "=r") - (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r") - (match_operand:X 2 "register_operand" "r")))] + [(set (match_operand:GPR 0 "register_operand" "=r") + (bitmanip_minmax:GPR (match_operand:GPR 1 "register_operand" "r") + (match_operand:GPR 2 "register_operand" "r")))] "TARGET_ZBB" "<bitmanip_insn>\t%0,%1,%2" [(set_attr "type" "bitmanip")]) +(define_insn "<bitmanip_optab>si3_sext" + [(set (match_operand:DI 0 "register_operand" "=r") + (sign_extend:DI (bitmanip_minmax:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_64BIT && TARGET_ZBB" + "<bitmanip_insn>\t%0,%1,%2" + [(set_attr "type" "bitmanip")]) + ;; orc.b (or-combine) is added as an unspec for the benefit of the support ;; for optimized string functions (such as strcmp). (define_insn "orcb<mode>2" diff --git a/gcc/testsuite/gcc.target/riscv/zbb-min-max.c b/gcc/testsuite/gcc.target/riscv/zbb-min-max.c index f44c398ea08..7169e873551 100644 --- a/gcc/testsuite/gcc.target/riscv/zbb-min-max.c +++ b/gcc/testsuite/gcc.target/riscv/zbb-min-max.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zbb -mabi=lp64 -O2" } */ +/* { dg-options "-march=rv64gc_zba_zbb -mabi=lp64 -O2" } */ long foo1 (long i, long j) @@ -25,7 +25,21 @@ foo4 (unsigned long i, unsigned long j) return i > j ? i : j; } +unsigned int +foo5(unsigned int a, unsigned int b) +{ + return a > b ? a : b; +} + +int +foo6(int a, int b) +{ + return a > b ? a : b; +} + /* { dg-final { scan-assembler-times "min" 3 } } */ -/* { dg-final { scan-assembler-times "max" 3 } } */ +/* { dg-final { scan-assembler-times "max" 4 } } */ /* { dg-final { scan-assembler-times "minu" 1 } } */ -/* { dg-final { scan-assembler-times "maxu" 1 } } */ +/* { dg-final { scan-assembler-times "maxu" 3 } } */ +/* { dg-final { scan-assembler-not "zext.w" } } */ +/* { dg-final { scan-assembler-not "sext.w" } } */ -- 2.32.0