So this is the second part to pr108031.
Originally I thought this was going to be related to Shreya's work on
fixing various cost model goofs in the RISC-V backend and that if we
fixed the cost modeling that the right things would just happen.
Essentially what I've had her focused on is cases where we have a single
cycle ALU insn, but the reported cost is anything but 4. Lots of these
issues have been clustered around embedded extensions, complex RTL for
bitmanip instructions, symbolic addresses, etc. I figured the costing
issue with 108031 would be related.
But it'd been a while since I did that very quick triage, so I went back
and took a closer look at the behavior inside CSE; that's when it became
clear that the LO_SUM expression and related value equivalent were
reporting the same cost. In that scenario CSE (reasonably) chooses to
keep things as-is to avoid gratuitous IL changes.
So we need the LO_SUM expression to cost higher than a simple PLUS, even
though they both collapse into addi/add insns. It's not as crazy at it
might seem as anytime we can get rid of the LO_SUM form, we're likely
going to get rid of the HIGH expression as well. Other ports cost
symbolics much higher and the RISC-V port may want to follow suit at
some point, but for now we can just add a single unit to the LO_SUM
expression cost and all the right things happen -- hopefully with no
fallout.
This has been tested on riscv32-elf and riscv64-elf. Bootstraps on the
K3 and c920 will run overnight, but I don't expect any issues. Pushing
to the trunk.
Jeff
commit 0cfd3de946cedafc0948fe4fde5a015c63b8993c
Author: Jeff Law <[email protected]>
Date: Thu Aug 13 21:22:57 2026 -0600
[RISC-V][PR target/108031] Adjust cost of LO_SUM expression slightly
So this is the second part to pr108031.
Originally I thought this was going to be related to Shreya's work on fixing
various cost model goofs in the RISC-V backend and that if we fixed the cost
modeling that the right things would just happen. Essentially what I've had
her focused on is cases where we have a single cycle ALU insn, but the
reported
cost is anything but 4. Lots of these issues have been clustered around
embedded extensions, complex RTL for bitmanip instructions, symbolic
addresses,
etc. I figured the costing issue with 108031 would be related.
But it'd been a while since I did that very quick triage, so I went back and
took a closer look at the behavior inside CSE; that's when it became clear
that
the LO_SUM expression and related value equivalent were reporting the same
cost. In that scenario CSE (reasonably) chooses to keep things as-is to
avoid
gratuitous IL changes.
So we need the LO_SUM expression to cost higher than a simple PLUS, even
though
they both collapse into addi/add insns. It's not as crazy at it might seem
as
anytime we can get rid of the LO_SUM form, we're likely going to get rid of
the
HIGH expression as well. Other ports cost symbolics much higher and the
RISC-V
port may want to follow suit at some point, but for now we can just add a
single unit to the LO_SUM expression cost and all the right things happen --
hopefully with no fallout.
This has been tested on riscv32-elf and riscv64-elf. Bootstraps on the K3
and
c920 will run overnight, but I don't expect any issues. Pushing to the
trunk.
PR target/108031
gcc/
* config/riscv/riscv.cc (riscv_rtx_costs): Bump the cost of a LO_SUM
by one unit to encourage use of related values instead of the
symbolic
form.
gcc/testsuite
* gcc.target/riscv/pr108031-2.c: New test.
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f79b55a0c70..a2a51c019ec 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -4773,8 +4773,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
return false;
case LO_SUM:
+ /* The +1 at the end is to make this ever-so-slightly more
+ expensive than a simple PLUS to encourage CSE-ing the
+ symbolic expression with related symbolic expressions.
+
+ While both PLUS and LO_SUM will turn into an add insn, if
+ we can convert the LO_SUM to a constant offset from another
+ expression, then we'll be able to eliminate the HIGH
+ insn. */
*total = (set_src_cost (XEXP (x, 0), mode, speed)
- + set_src_cost (XEXP (x, 1), mode, speed));
+ + set_src_cost (XEXP (x, 1), mode, speed)
+ + 1);
return true;
case LT:
diff --git a/gcc/testsuite/gcc.target/riscv/pr108031-2.c
b/gcc/testsuite/gcc.target/riscv/pr108031-2.c
new file mode 100644
index 00000000000..423334df8ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr108031-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d " { target { rv64 } } } */
+/* { dg-options "-march=rv32gc -mabi=ilp32d " { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+#include "pr108031.c"
+
+/* { dg-final { scan-assembler-times "%hi" 2 } } */
+/* { dg-final { scan-assembler-times "%lo" 2 } } */