So I'm not happy with this entire routine, but after trying to fix things right, I'm back to adjusting the cost routine instead.

The fundamental problem as I see it is the cstore patterns on RISC-V are suboptimal.

Those patterns always have an SI destination.  One expander is used for integer inputs, the other for FP inputs.

In both the integer and FP case we use an iterator to allow different input modes.  But the destination stays fixed in SI.

But it'd be really advantageous to support an output iterator. With the forced SI output we typically end up with subreg copies, zero extensions and moves in sequences involving SCC insns.  That is usually cleaned up by combine, but those extra insns participate in if-conversion costing and sometimes cause us to miss opportunities or force us into a slower/bigger sequence using generalized conditional moves.

Of course the cstore only has one mode, which if I read the docs correctly *should* be the output mode.  RISC-V is using it for the input modes.  So we're doing something a bit dumb there.  To achieve that we'd need to combine the two expanders since they both have integer output modes and we can't have two expanders with the same name.  To combine the expanders the inputs have to accept both integer and FP modes.  That's likely possible but it's going to get ugly (for example, use modeless operands and check modes and FAIL in the expansion code).

So rather than fight that battle, this patch just ignores the trivial copies that can be generated during expansion.  The code was already ignoring certain extensions and promoted subreg copies.   With some in flight if-conversion work we're able to take this testcase (adjusted from a loongarch test):



extern long lm, ln, lr;

void
test_ne ()
{
  if (lm != ln)
    lr += (1 << 2);
  lr += lm;
}



Which previously generated this code for the conditional add

        beq     a5,a2,.L2
        addi    a4,a4,4
.L2:
        add     a5,a5,a4

With the in flight if-converter work alone we'd generate:

        sub     t2,t0,t1
        li      a1,4
        czero.eqz       a0,a1,t2
        add     a6,a3,a0
        add     a7,t0,a6

It's straightline code and probably better due to that alone if the branch has meaningful unpredictability for the hardware.  Add in this patch to send us through a different if-conversion path and we get:

        sub     t2,t0,t1
        snez    a0,t2
        sh2add  a1,a0,a2
        add     a6,t0,a1


For shift counts 1..3 we'll get that shNadd form.  For shift counts 4..11 we'll get sll+add.  For shift counts > 11 the middle block in the if-conversion path has two insns because the constant can't encode into an addi instruction and we can't use the specialized ifcvt paths.

Tested on riscv32-elf and riscv64-elf.  Bootstrap & regression test on k3 is in flight.  Bootstrap and regression test and k1 and c920 will fire up later today.  Obviously I'll wait for pre-commit CI to render its verdict, I expect I'll have k3 data by then as well.

jeff



gcc/

        * config/riscv/riscv.cc (riscv_noce_conversion_profitable_p): Ignore
        reg->reg copies too.

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 873defc5a5b5..3b150d34893d 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -5200,6 +5200,12 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
              riscv_if_info.original_cost += COSTS_N_INSNS (1);
              riscv_if_info.max_seq_cost += COSTS_N_INSNS (1);
            }
+         else if (REG_P (src) && REG_P (dest))
+           {
+             /* Trivial copies likely just get propagated away.  */
+             riscv_if_info.original_cost += COSTS_N_INSNS (1);
+             riscv_if_info.max_seq_cost += COSTS_N_INSNS (1);
+           }
          else
            last_dest = NULL_RTX;
 

Reply via email to