So I was looking at a performance regression in spec with Ventana's internal tree. Ultimately the problem was a bad interaction with an internal patch (REP_MODE_EXTENDED), fwprop and ext-dce. The details of that problem aren't particularly important.
Removal of the local patch went reasonably well. But I did see some secondary cases where we had redundant sign extensions. The most notable cases come from the integer sCC insns.
Expansion of those cases for rv64 can be improved using Jivan's trick. ie, if the target is not DImode, then create a DImode temporary for the result and copy the low bits out with a promoted subreg to the real target.
With the change in expansion the final code we generate is slightly different for a few tests at -O1/-Og, but should perform the same. The key for the affected tests is we're not seeing the introduction of unnecessary extensions. Rather than adjust the regexps to handle the -O1/-Og output, skipping for those seemed OK to me. I didn't extract a testcase. I'm a bit fried from digging through LTO'd code right now ;-)
Anyway, this has gone through my tester on rv32 and rv64. I'll let it spin in the pre-commit tester before taking further action.
Jeff
gcc/ * config/riscv/riscv.cc (riscv_expand_int_scc): For rv64, use a DI temporary for the output and a promoted subreg to extract it into SI target. gcc/testsuite/ * gcc.target/riscv/sge.c: Skip for -O1 and -Og. * gcc.target/riscv/sgeu.c: Likewise. * gcc.target/riscv/sle.c: Likewise. * gcc.target/riscv/sleu.c: Likewise. diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f82e64a6fec..ad8bcd3e959 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -4891,13 +4891,31 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *in riscv_extend_comparands (code, &op0, &op1); op0 = force_reg (word_mode, op0); + /* For sub-word targets on rv64, do the computation in DImode + then extract the lowpart for the final target, marking it + as sign extended. Note that it's also properly zero extended, + but it's probably more profitable to expose it as sign extended. */ + rtx t; + if (TARGET_64BIT && GET_MODE (target) == SImode) + t = gen_reg_rtx (DImode); + else + t = target; + if (code == EQ || code == NE) { rtx zie = riscv_zero_if_equal (op0, op1); - riscv_emit_binary (code, target, zie, const0_rtx); + riscv_emit_binary (code, t, zie, const0_rtx); } else - riscv_emit_int_order_test (code, invert_ptr, target, op0, op1); + riscv_emit_int_order_test (code, invert_ptr, t, op0, op1); + + if (t != target) + { + t = gen_lowpart (SImode, t); + SUBREG_PROMOTED_VAR_P (t) = 1; + SUBREG_PROMOTED_SET (t, SRP_SIGNED); + emit_move_insn (target, t); + } } /* Like riscv_expand_int_scc, but for floating-point comparisons. */ diff --git a/gcc/testsuite/gcc.target/riscv/sge.c b/gcc/testsuite/gcc.target/riscv/sge.c index 5f7e7ae82db..ab278d18d3b 100644 --- a/gcc/testsuite/gcc.target/riscv/sge.c +++ b/gcc/testsuite/gcc.target/riscv/sge.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ -/* { dg-skip-if "" { *-*-* } { "-O0" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ int sge (int x, int y) diff --git a/gcc/testsuite/gcc.target/riscv/sgeu.c b/gcc/testsuite/gcc.target/riscv/sgeu.c index 234b9aa52bd..38c2272a55f 100644 --- a/gcc/testsuite/gcc.target/riscv/sgeu.c +++ b/gcc/testsuite/gcc.target/riscv/sgeu.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ -/* { dg-skip-if "" { *-*-* } { "-O0" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ int sgeu (unsigned int x, unsigned int y) diff --git a/gcc/testsuite/gcc.target/riscv/sle.c b/gcc/testsuite/gcc.target/riscv/sle.c index 3259c191598..4371068c50e 100644 --- a/gcc/testsuite/gcc.target/riscv/sle.c +++ b/gcc/testsuite/gcc.target/riscv/sle.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ -/* { dg-skip-if "" { *-*-* } { "-O0" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ int sle (int x, int y) diff --git a/gcc/testsuite/gcc.target/riscv/sleu.c b/gcc/testsuite/gcc.target/riscv/sleu.c index 301b8c32eb7..8d4ee50b07c 100644 --- a/gcc/testsuite/gcc.target/riscv/sleu.c +++ b/gcc/testsuite/gcc.target/riscv/sleu.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target rv64 } */ -/* { dg-skip-if "" { *-*-* } { "-O0" } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-Og" } } */ int sleu (unsigned int x, unsigned int y)