]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Also handle sign extension in branch costing
authorMaciej W. Rozycki <macro@embecosm.com>
Wed, 10 Jan 2024 16:34:24 +0000 (16:34 +0000)
committerMaciej W. Rozycki <macro@embecosm.com>
Wed, 10 Jan 2024 16:34:24 +0000 (16:34 +0000)
Complement commit c1e8cb3d9f94 ("RISC-V: Rework branch costing model for
if-conversion") and also handle extraneous sign extend operations that
are sometimes produced by `noce_try_cmove_arith' instead of zero extend
operations, making branch costing consistent.  It is unclear what the
condition is for the middle end to choose between the zero extend and
sign extend operation, but the test case included uses sign extension
with 64-bit targets, preventing if-conversion from triggering across all
the architectural variants.

There are further anomalies revealed by the test case, specifically the
exceedingly high branch cost of 6 required for the `-mmovcc' variant
despite that the final branchless sequence only uses 4 instructions, the
missed conversion at -O1 for 32-bit targets even though code is machine
word size agnostic, and the missed conversion at -Os and -Oz for 32-bit
Zicond targets even though the branchless sequence would be shorter than
the branched one.  These will have to be handled separately.

gcc/
* config/riscv/riscv.cc (riscv_noce_conversion_profitable_p):
Also handle sign extension.

gcc/testsuite/
* gcc.target/riscv/cset-sext-sfb.c: New test.
* gcc.target/riscv/cset-sext-thead.c: New test.
* gcc.target/riscv/cset-sext-ventana.c: New test.
* gcc.target/riscv/cset-sext-zicond.c: New test.
* gcc.target/riscv/cset-sext.c: New test.

gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/cset-sext-thead.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/cset-sext-ventana.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/cset-sext-zicond.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/cset-sext.c [new file with mode: 0644]

index 32183d63180f1af058eddccc96fc096858760dc6..2620e3e7b7905172548e71b29f265efb090f1812 100644 (file)
@@ -3555,7 +3555,7 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
      this redundant zero extend operation counts towards the cost of
      the replacement sequence.  Compensate for that by incrementing the
      cost of the original sequence as well as the maximum sequence cost
-     accordingly.  */
+     accordingly.  Likewise for sign extension.  */
   rtx last_dest = NULL_RTX;
   for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
     {
@@ -3567,8 +3567,9 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
          && GET_CODE (x) == SET)
        {
          rtx src = SET_SRC (x);
+         enum rtx_code code = GET_CODE (src);
          if (last_dest != NULL_RTX
-             && GET_CODE (src) == ZERO_EXTEND
+             && (code == SIGN_EXTEND || code == ZERO_EXTEND)
              && REG_P (XEXP (src, 0))
              && REGNO (XEXP (src, 0)) == REGNO (last_dest))
            {
diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c b/gcc/testsuite/gcc.target/riscv/cset-sext-sfb.c
new file mode 100644 (file)
index 0000000..1a3e710
--- /dev/null
@@ -0,0 +1,28 @@
+/* { 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 } } } */
+
+int
+foo (long a, long b)
+{
+  if (!b)
+    return 0;
+  else if (a)
+    return 1;
+  else
+    return 0;
+}
+
+/* Expect short forward branch assembly like:
+
+       snez    a0,a0
+       bne     a1,zero,1f      # movcc
+       mv      a0,zero
+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-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" } } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c b/gcc/testsuite/gcc.target/riscv/cset-sext-thead.c
new file mode 100644 (file)
index 0000000..45b9470
--- /dev/null
@@ -0,0 +1,26 @@
+/* { 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" } */
+
+int
+foo (long a, long b)
+{
+  if (!b)
+    return 0;
+  else if (a)
+    return 1;
+  else
+    return 0;
+}
+
+/* Expect branchless assembly like:
+
+       snez    a0,a0
+       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
new file mode 100644 (file)
index 0000000..eac1e13
--- /dev/null
@@ -0,0 +1,26 @@
+/* { 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" } */
+
+int
+foo (long a, long b)
+{
+  if (!b)
+    return 0;
+  else if (a)
+    return 1;
+  else
+    return 0;
+}
+
+/* Expect branchless assembly like:
+
+       snez    a0,a0
+       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
new file mode 100644 (file)
index 0000000..a526b0c
--- /dev/null
@@ -0,0 +1,26 @@
+/* { 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 } } } */
+
+int
+foo (long a, long b)
+{
+  if (!b)
+    return 0;
+  else if (a)
+    return 1;
+  else
+    return 0;
+}
+
+/* Expect branchless assembly like:
+
+       snez    a0,a0
+       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" } } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cset-sext.c b/gcc/testsuite/gcc.target/riscv/cset-sext.c
new file mode 100644 (file)
index 0000000..a1293cd
--- /dev/null
@@ -0,0 +1,27 @@
+/* { 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 } } } */
+
+int
+foo (long a, long b)
+{
+  if (!b)
+    return 0;
+  else if (a)
+    return 1;
+  else
+    return 0;
+}
+
+/* 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" } } } } } */