+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.
/* 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))
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,
+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
--- /dev/null
+/* { 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" } } */
--- /dev/null
+/* { 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" } } */