This was supposed to go out the door yesterday, but I kept getting
interrupted.
The target bits for rtx costing can't assume the rtl they're given
actually matches a target pattern. It's just kind of inherent in how
the costing routines get called in various places.
In this particular case we're trying to cost a conditional move:
(set (dest) (if_then_else (cond) (true) (false))
On the RISC-V port the backend only allows actual conditionals for COND.
So something like (eq (reg) (const_int 0)). In the costing code for
if-then-else we did something like
(XEXP (XEXP (cond, 0), 0)))
Which fails miserably if COND is a terminal node like (reg) rather than
(ne (reg) (const_int 0)
So this patch tightens up the RTL scanning to ensure that we have a
comparison before we start looking at the comparison's arguments.
Run through my tester without incident, but I'll wait for the pre-commit
tester to run through a cycle before pushing to the trunk.
Jeff
ps. We probably could support a naked REG for the condition and
internally convert it to (ne (reg) (const_int 0)), but I don't think it
likely happens with any regularity.
PR target/116240
gcc/
* config/riscv/riscv.cc (riscv_rtx_costs): Ensure object is a
comparison before looking at its arguments.
gcc/testsuite
* gcc.target/riscv/pr116240.c: New test.
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5fe4273beb7..3d0a1d12b14 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3646,9 +3646,11 @@ riscv_rtx_costs (rtx x, machine_mode mode, int
outer_code, int opno ATTRIBUTE_UN
&& XEXP (x, 2) == CONST0_RTX (GET_MODE (XEXP (x, 1))))
|| (GET_CODE (XEXP (x, 2)) == REG
&& XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 2))))
- || (GET_CODE (XEXP (x, 1)) == REG
+ || (COMPARISON_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == REG
&& rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 0), 0)))
- || (GET_CODE (XEXP (x, 1)) == REG
+ || (COMPARISON_P (XEXP (x, 0))
+ && GET_CODE (XEXP (x, 1)) == REG
&& rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0)))))
{
*total = COSTS_N_INSNS (1);
diff --git a/gcc/testsuite/gcc.target/riscv/pr116240.c
b/gcc/testsuite/gcc.target/riscv/pr116240.c
new file mode 100644
index 00000000000..7e3eaa2f544
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr116240.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fwrapv
-march=rv64imvxtheadcondmov_xventanacondops -mabi=lp64d" } */
+
+int a, b;
+void c() {
+ int e = a >= 2 ? b : a;
+ short d = e * 2;
+ if (d)
+ for (;;)
+ ;
+}
+