diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index 2844cb02ff09526c9f69615f5becfc4b0427fed4..872c542e90652a92b2947fdb9ff42700838b4bf6 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -233,6 +233,8 @@ (define_code_iterator any_ge [ge geu]) (define_code_iterator any_lt [lt ltu]) (define_code_iterator any_le [le leu]) +;; Iterators for conditions we can emit a sCC against 0 or a reg directly +(define_code_iterator scc_0 [eq ne gt gtu]) ; atomics code iterator (define_code_iterator any_atomic [plus ior xor and]) diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md index 3876be7f9d297511474676d07b2029172aa42c7d..ab1a5337ee53822c2b8f44c7f991e60a89004b99 100644 --- a/gcc/config/riscv/zicond.md +++ b/gcc/config/riscv/zicond.md @@ -124,3 +124,115 @@ { operands[2] = GEN_INT (1 << UINTVAL(operands[2])); }) + +;; In some cases gimple can give us a sequence with a logical and +;; of two sCC insns. This can be implemented an sCC feeding a +;; conditional zero. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (ne:X (match_operand:X 1 "register_operand") (const_int 0)) + (scc_0:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "reg_or_0_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (scc_0:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + +;; Similarly but GE/GEU which requires (const_int 1) as an operand. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (ne:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_ge:X (match_operand:X 2 "register_operand") + (const_int 1)))) + (clobber (match_operand:X 3 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 3) (any_ge:X (match_dup 2) (const_int 1))) + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 3)))]) + +;; Similarly but LU/LTU which allows an arith_operand +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (ne:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_lt:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "arith_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (any_lt:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + +;; Finally LE/LEU which requires sle_operand. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (ne:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_le:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "sle_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (any_le:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (eq:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + + +;; Inverted versions from above. I tried to get this to work with +;; iterators, but didn't have any success disambiguating the code attr +;; for the eq/ne flip we have to do. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (eq:X (match_operand:X 1 "register_operand") (const_int 0)) + (scc_0:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "reg_or_0_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (scc_0:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (ne:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + +;; Similarly but GE/GEU which requires (const_int 1) as an operand. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (eq:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_ge:X (match_operand:X 2 "register_operand") + (const_int 1)))) + (clobber (match_operand:X 3 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 3) (any_ge:X (match_dup 2) (const_int 1))) + (set (match_dup 0) (if_then_else:X (ne:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 3)))]) + +;; Similarly but LU/LTU which allows an arith_operand +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (eq:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_lt:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "arith_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (any_lt:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (ne:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + +;; Finally LE/LEU which requires sle_operand. +(define_split + [(set (match_operand:X 0 "register_operand") + (and:X (eq:X (match_operand:X 1 "register_operand") (const_int 0)) + (any_le:X (match_operand:X 2 "register_operand") + (match_operand:X 3 "sle_operand")))) + (clobber (match_operand:X 4 "register_operand"))] + "TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV" + [(set (match_dup 4) (any_le:X (match_dup 2) (match_dup 3))) + (set (match_dup 0) (if_then_else:X (ne:X (match_dup 1) (const_int 0)) + (const_int 0) + (match_dup 4)))]) + + + diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c b/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c index 1a3e7104bd8c1b5ab25bf811ad443efe5c83f556..6e9f8cc61de09e6f73a53ebfebda6e83befcf2a6 100644 --- a/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c +++ b/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ -/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ -/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ -/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O1" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fno-ssa-phiopt -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fno-ssa-phiopt -fdump-rtl-ce1" { target { rv64 } } } */ int foo (long a, long b) @@ -22,7 +22,7 @@ foo (long a, long b) 1: */ -/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" { xfail { rv32 && { any-opts "-O1" } } } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" } } /* { dg-final { scan-assembler-times "\\ssnez\\s" 1 } } */ -/* { dg-final { scan-assembler-times "\\sbne\\s\[^\\s\]+\\s# movcc\\s" 1 { xfail { rv32 && { any-opts "-O1" } } } } } */ -/* { dg-final { scan-assembler-not "\\sbeq\\s" { xfail { rv32 && { any-opts "-O1" } } } } } */ +/* { dg-final { scan-assembler-times "\\sbne\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sbeq\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c b/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c index 45b94704aaf6f17948f751b3f5097517855f109b..74cae71d7a0bb21c4d689df74977701759140a5d 100644 --- a/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c +++ b/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ /* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ -/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1" } */ int foo (long a, long b) @@ -20,7 +20,6 @@ foo (long a, long b) th.mveqz a0,zero,a1 */ -/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" } } */ /* { dg-final { scan-assembler-times "\\ssnez\\s" 1 } } */ /* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ /* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-ventana.c b/gcc/testsuite/gcc.target/riscv/cset-sext-ventana.c index eac1e1376cb4e119b7f7bb6fe11dda3fa4608cbe..8c3ca98bc2fcec9118556968e850db4a2d09cb0f 100644 --- a/gcc/testsuite/gcc.target/riscv/cset-sext-ventana.c +++ b/gcc/testsuite/gcc.target/riscv/cset-sext-ventana.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ /* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ -/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=1" } */ int foo (long a, long b) @@ -20,7 +20,6 @@ foo (long a, long b) vt.maskc a0,a0,a1 */ -/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" } } */ /* { dg-final { scan-assembler-times "\\ssnez\\s" 1 } } */ /* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ /* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-zicond.c b/gcc/testsuite/gcc.target/riscv/cset-sext-zicond.c index a526b0c3d5a68570354f7abf2ce316d0dd534805..ec715254d4e21c52d693e351243dbd78808d1013 100644 --- a/gcc/testsuite/gcc.target/riscv/cset-sext-zicond.c +++ b/gcc/testsuite/gcc.target/riscv/cset-sext-zicond.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ -/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=1" { target { rv32 } } } */ int foo (long a, long b) @@ -20,7 +20,6 @@ foo (long a, long b) czero.eqz a0,a0,a1 */ -/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" { xfail { rv32 && { any-opts "-O1" "-Os" "-Oz" } } } } } */ /* { dg-final { scan-assembler-times "\\ssnez\\s" 1 } } */ -/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 { xfail { rv32 && { any-opts "-O1" "-Os" "-Oz" } } } } } */ -/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail { rv32 && { any-opts "-O1" "-Os" "-Oz" } } } } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext.c b/gcc/testsuite/gcc.target/riscv/cset-sext.c index a1293cd62ea7eae5fd262a8603dd0732d303d383..e1c3239d146107fc10f23584a6e4e74fa7bf0542 100644 --- a/gcc/testsuite/gcc.target/riscv/cset-sext.c +++ b/gcc/testsuite/gcc.target/riscv/cset-sext.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ -/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ -/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=1 -mmovcc" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=1 -mmovcc" { target { rv64 } } } */ int foo (long a, long b) @@ -17,11 +17,10 @@ foo (long a, long b) /* Expect branchless assembly like: snez a1,a1 - neg a1,a1 snez a0,a0 and a0,a1,a0 */ -/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove_arith" 1 "ce1" { xfail { rv32 && { any-opts "-O1" } } } } } */ -/* { dg-final { scan-assembler-times "\\ssnez\\s" 2 { xfail { rv32 && { any-opts "-O1" } } } } } */ -/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail { rv32 && { any-opts "-O1" } } } } } */ +/* { dg-final { scan-assembler-times "\\ssnez\\s" 2 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sneg\\s" } } */