Currently, the cost of the LO_SUM expression is based on
the cost of calculating the first subexpression. When the
first subexpression is a register, the cost result will
be zero. It seems a bit unreasonable for a SET expression
to have a zero cost when its source is LO_SUM. Moreover,
having a cost of zero for the expression will lead the
loop invariant pass to calculate its benefits of being
moved outside the loop as zero, thus preventing the
out-of-loop placement of the loop invariant.

As an example, consider the following test case:
  long a;
  long b[];
  long *c;
  foo () {
    for (;;)
      *c = b[a];
  }

When compiling with -march=rv64gc -mabi=lp64d -Os, the following code is 
generated:
        .cfi_startproc
        lui     a5,%hi(c)
        ld      a4,%lo(c)(a5)
        lui     a2,%hi(b)
        lui     a1,%hi(a)
.L2:
        ld      a5,%lo(a)(a1)
        addi    a3,a2,%lo(b)
        slli    a5,a5,3
        add     a5,a5,a3
        ld      a5,0(a5)
        sd      a5,0(a4)
        j       .L2

After adjust the cost of the LO_SUM expression, the instruction addi will be
moved outside the loop:
        .cfi_startproc
        lui     a5,%hi(c)
        ld      a3,%lo(c)(a5)
        lui     a4,%hi(b)
        lui     a2,%hi(a)
        addi    a4,a4,%lo(b)
.L2:
        ld      a5,%lo(a)(a2)
        slli    a5,a5,3
        add     a5,a5,a4
        ld      a5,0(a5)
        sd      a5,0(a3)
        j       .L2

gcc/
        * config/riscv/riscv.cc (riscv_rtx_costs): Optimize
        the cost of the LO_SUM expression.
---
 gcc/config/riscv/riscv.cc | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 1b4a5c39c667..cb9692dad715 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3994,7 +3994,10 @@ riscv_rtx_costs (rtx x, machine_mode mode, int 
outer_code, int opno ATTRIBUTE_UN
       return false;
 
     case LO_SUM:
-      *total = set_src_cost (XEXP (x, 0), mode, speed);
+      if (outer_code == SET && REG_P (XEXP (x, 0)))
+       *total = COSTS_N_INSNS (1);
+      else
+       *total = set_src_cost (XEXP (x, 0), mode, speed);
       return true;
 
     case LT:
-- 
2.43.0

Reply via email to