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