aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
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 /gcc/expr.c
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
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c19
1 files changed, 17 insertions, 2 deletions
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,