diff options
author | Jim Wilson <jimw@sifive.com> | 2018-05-17 22:37:38 +0000 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 2018-05-17 15:37:38 -0700 |
commit | 7bbce9b50302959286381d9177818642bceaf301 (patch) | |
tree | 0ce4f20f1d1ab9a42ba1843c8d03e69332f11446 | |
parent | 4e0684beff1fcd8398425b1fbe237cdbcb34c359 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.c | 14 | ||||
-rw-r--r-- | gcc/expr.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/switch-qi.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/switch-si.c | 15 |
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)) @@ -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" } } */ |