]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[V2][PR target/125387][RISC-V] Properly cost mulh for RISC-V
authorRaphael Zinsly <raphael.zinsly@oss.qualcomm.com>
Thu, 4 Jun 2026 13:08:08 +0000 (07:08 -0600)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Thu, 4 Jun 2026 13:08:08 +0000 (07:08 -0600)
Bah.  Sent the wrong version.  The integer multiply cost in the tuning
structure already has COSTS_N_INSNS applied, so no need to apply it again
(which causes the costs to skyrocket and the code generation we want to see not
happen).

--

This is a patch Raphael wrote a few years back, but which never got upstreamed.
I can vaguely recall evaluating the patch and concluding to drop it both
internally and from the queue of things to upstream.  But the details of how I
reached that conclusion are lost.

The core problem is we didn't recognize the fairly complex widening multiply
RTL, so it got costed by recursion which is painful on its own.  To add insult
to injury the input operands are TI mode which, IIRC, also increased the cost
of the mulh insn.

The net was a totally bogus cost, it was totally off the charts which in turn
discouraged using multiplies for division-by-constant operations as can be seen
in the BZ.

This patch from Raphael fixes recognition of the mulh RTL and uses the integer
multiply cost out of the costing structure.  This results in sensible costs for
the multiply and using a multiply-by-reciprocal instead of division in more
cases.

It's been tested on riscv32-elf and riscv64-elf without regressions.  I haven't
bootstrapped it as I had my system disabled yesterday for "reasons".  I'll
obviously wait for the pre-commit verdict.

PR target/125387
gcc/
* config/riscv/riscv.cc (riscv_rtx_costs): Recognize and properly cost
mulh instructions.

gcc/testsuite
* gcc.target/riscv/pr125387.c: New test.

Co-authored-by: Jeff Law <jeffrey.law@oss.qualcomm.com>
gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/pr125387.c [new file with mode: 0644]

index 238f64d6411cba40a5a0d863f50b64ae28f7fe4b..623aaa83b0ecda2af7b46b31434acc111eb37cef 100644 (file)
@@ -4701,8 +4701,26 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
          return true;
        }
       gcc_fallthrough ();
-    case ASHIFTRT:
     case LSHIFTRT:
+      /* mulh[u] pattern */
+      if (GET_CODE (x) == LSHIFTRT
+         && TARGET_MUL
+         && mode == GET_MODE_2XWIDER_MODE (word_mode).require ()
+         && outer_code == TRUNCATE
+         && (GET_CODE (XEXP (x, 0)) == MULT)
+            && (GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND
+                || GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND)
+            && (GET_CODE (XEXP (XEXP (x, 0), 1)) == ZERO_EXTEND
+                || GET_CODE (XEXP (XEXP (x, 0), 1)) == SIGN_EXTEND)
+         && (GET_CODE (XEXP (x, 1)) == CONST_INT
+             && INTVAL (XEXP (x, 1)) == BITS_PER_WORD))
+       {
+         *total = tune_param->int_mul[mode == TImode];
+         return true;
+       }
+       /* Fall through.  */
+
+    case ASHIFTRT:
       *total = riscv_binary_cost (x, SINGLE_SHIFT_COST,
                                  CONSTANT_P (XEXP (x, 1)) ? 4 : 9);
       return false;
diff --git a/gcc/testsuite/gcc.target/riscv/pr125387.c b/gcc/testsuite/gcc.target/riscv/pr125387.c
new file mode 100644 (file)
index 0000000..c381b7a
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile { target rv64} } */
+/* { dg-additional-options "-mtune=tt-ascalon-d8 -march=rv64gc" } 
+/* { dg-skip-if "" { *-*-* } { "-Os" "-Oz" } } */
+
+long foo1 (long x) { return x / 10000L; }
+long foo2 (long x) { return x / 30; }
+
+/* { dg-final { scan-assembler-times "mulh" 2 } } */
+/* { dg-final { scan-assembler-not "\tdiv\t" } } */