aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2018-05-17 22:37:38 +0000
committerJim Wilson <wilson@gcc.gnu.org>2018-05-17 15:37:38 -0700
commit7bbce9b50302959286381d9177818642bceaf301 (patch)
tree0ce4f20f1d1ab9a42ba1843c8d03e69332f11446
parent4e0684beff1fcd8398425b1fbe237cdbcb34c359 (diff)
downloadgcc-7bbce9b50302959286381d9177818642bceaf301.zip
gcc-7bbce9b50302959286381d9177818642bceaf301.tar.gz
gcc-7bbce9b50302959286381d9177818642bceaf301.tar.bz2
RISC-V: Optimize switch with sign-extended index.
gcc/ * expr.c (do_tablejump): When converting index to Pmode, if we have a sign extended promoted subreg, and the range does not have the sign bit set, then do a sign extend. * config/riscv/riscv.c (riscv_extend_comparands): In unsigned QImode test, check for sign extended subreg and/or constant operands, and do a sign extend in that case. gcc/testsuite/ * gcc.target/riscv/switch-qi.c: New. * gcc.target/riscv/switch-si.c: New. From-SVN: r260340
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/riscv/riscv.c14
-rw-r--r--gcc/expr.c19
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/riscv/switch-qi.c15
-rw-r--r--gcc/testsuite/gcc.target/riscv/switch-si.c15
6 files changed, 74 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e027c17..cc71c8b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2018-05-17 Jim Wilson <jimw@sifive.com>
+
+ * expr.c (do_tablejump): When converting index to Pmode, if we have a
+ sign extended promoted subreg, and the range does not have the sign bit
+ set, then do a sign extend.
+
+ * config/riscv/riscv.c (riscv_extend_comparands): In unsigned QImode
+ test, check for sign extended subreg and/or constant operands, and
+ do a sign extend in that case.
+
2018-05-17 Steve Ellcey <sellcey@cavium.com>
* config/aarch64/thunderx2t99.md (thunderx2t99_ls_both): Delete.
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 2a8f87d..b497588 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -2002,8 +2002,18 @@ riscv_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
/* Comparisons consider all XLEN bits, so extend sub-XLEN values. */
if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)))
{
- /* It is more profitable to zero-extend QImode values. */
- if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode)
+ /* It is more profitable to zero-extend QImode values. But not if the
+ first operand has already been sign-extended, and the second one is
+ is a constant or has already been sign-extended also. */
+ if (unsigned_condition (code) == code
+ && (GET_MODE (*op0) == QImode
+ && ! (GET_CODE (*op0) == SUBREG
+ && SUBREG_PROMOTED_VAR_P (*op0)
+ && SUBREG_PROMOTED_SIGNED_P (*op0)
+ && (CONST_INT_P (*op1)
+ || (GET_CODE (*op1) == SUBREG
+ && SUBREG_PROMOTED_VAR_P (*op1)
+ && SUBREG_PROMOTED_SIGNED_P (*op1))))))
{
*op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0);
if (CONST_INT_P (*op1))
diff --git a/gcc/expr.c b/gcc/expr.c
index 9dd0e60..00a802c 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11782,11 +11782,26 @@ do_tablejump (rtx index, machine_mode mode, rtx range, rtx table_label,
emit_cmp_and_jump_insns (index, range, GTU, NULL_RTX, mode, 1,
default_label, default_probability);
-
/* If index is in range, it must fit in Pmode.
Convert to Pmode so we can index with it. */
if (mode != Pmode)
- index = convert_to_mode (Pmode, index, 1);
+ {
+ unsigned int width;
+
+ /* We know the value of INDEX is between 0 and RANGE. If we have a
+ sign-extended subreg, and RANGE does not have the sign bit set, then
+ we have a value that is valid for both sign and zero extension. In
+ this case, we get better code if we sign extend. */
+ if (GET_CODE (index) == SUBREG
+ && SUBREG_PROMOTED_VAR_P (index)
+ && SUBREG_PROMOTED_SIGNED_P (index)
+ && ((width = GET_MODE_PRECISION (as_a <scalar_int_mode> (mode)))
+ <= HOST_BITS_PER_WIDE_INT)
+ && ! (UINTVAL (range) & (HOST_WIDE_INT_1U << (width - 1))))
+ index = convert_to_mode (Pmode, index, 0);
+ else
+ index = convert_to_mode (Pmode, index, 1);
+ }
/* Don't let a MEM slip through, because then INDEX that comes
out of PIC_CASE_VECTOR_ADDRESS won't be a valid address,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2dd0340..7442eb4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-05-17 Jim Wilson <jimw@sifive.com>
+
+ * gcc.target/riscv/switch-qi.c: New.
+ * gcc.target/riscv/switch-si.c: New.
+
2018-05-17 Pat Haugen <pthaugen@us.ibm.com>
PR target/85698
diff --git a/gcc/testsuite/gcc.target/riscv/switch-qi.c b/gcc/testsuite/gcc.target/riscv/switch-qi.c
new file mode 100644
index 0000000..973d09a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/switch-qi.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2" } */
+
+/* Test for riscv_extend_comparands patch. */
+extern void asdf(int);
+void foo(signed char x) {
+ switch (x) {
+ case 0: asdf(10); break;
+ case 1: asdf(11); break;
+ case 2: asdf(12); break;
+ case 3: asdf(13); break;
+ case 4: asdf(14); break;
+ }
+}
+/* { dg-final { scan-assembler-not "andi" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/switch-si.c b/gcc/testsuite/gcc.target/riscv/switch-si.c
new file mode 100644
index 0000000..de4d68f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/switch-si.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* Test for do_tablejump patch. */
+extern void asdf(int);
+void foo(int x) {
+ switch (x) {
+ case 0: asdf(10); break;
+ case 1: asdf(11); break;
+ case 2: asdf(12); break;
+ case 3: asdf(13); break;
+ case 4: asdf(14); break;
+ }
+}
+/* { dg-final { scan-assembler-not "srli" } } */