https://gcc.gnu.org/g:ce36692f8e10a619563938851f507cdb15567cf8

commit r15-7012-gce36692f8e10a619563938851f507cdb15567cf8
Author: Xi Ruoyao <xry...@xry111.site>
Date:   Fri Sep 6 00:34:55 2024 +0800

    LoongArch: Fix cost model for alsl
    
    Our cost model for alsl was wrong: it matches (a + b * imm) where imm is
    1, 2, 3, or 4 (should be 2, 4, 8, or 16), and it does not match
    (a + (b << imm)) at all.  For the test case:
    
        a += c << 3;
        b += c << 3;
    
    it caused the compiler to perform a CSE and make one slli and two add,
    but we just want two alsl.
    
    Also add a "code == PLUS" check to prevent matching a - (b << imm) as we
    don't have any "slsl" instruction.
    
    gcc/ChangeLog:
    
            * config/loongarch/loongarch.cc (loongarch_rtx_costs): Fix the
            cost for (a + b * imm) and (a + (b << imm)) which can be
            implemented with a single alsl instruction.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/loongarch/alsl-cost.c: New test.

Diff:
---
 gcc/config/loongarch/loongarch.cc              | 27 +++++++++++++++++++++-----
 gcc/testsuite/gcc.target/loongarch/alsl-cost.c | 14 +++++++++++++
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 9d97f0216f0d..3a8e1297bd3c 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -3929,14 +3929,31 @@ loongarch_rtx_costs (rtx x, machine_mode mode, int 
outer_code,
 
       /* If it's an add + mult (which is equivalent to shift left) and
         it's immediate operand satisfies const_immalsl_operand predicate.  */
-      if ((mode == SImode || (TARGET_64BIT && mode == DImode))
-         && GET_CODE (XEXP (x, 0)) == MULT)
+      if (code == PLUS
+         && (mode == SImode || (TARGET_64BIT && mode == DImode)))
        {
-         rtx op2 = XEXP (XEXP (x, 0), 1);
-         if (const_immalsl_operand (op2, mode))
+         HOST_WIDE_INT shamt = -1;
+         rtx lhs = XEXP (x, 0);
+         rtx_code code_lhs = GET_CODE (lhs);
+
+         switch (code_lhs)
+           {
+           case ASHIFT:
+             if (CONST_INT_P (XEXP (lhs, 1)))
+               shamt = INTVAL (XEXP (lhs, 1));
+             break;
+           case MULT:
+             if (CONST_INT_P (XEXP (lhs, 1)))
+               shamt = exact_log2 (INTVAL (XEXP (lhs, 1)));
+             break;
+           default:
+             break;
+           }
+
+         if (IN_RANGE (shamt, 1, 4))
            {
              *total = (COSTS_N_INSNS (1)
-                       + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed)
+                       + set_src_cost (XEXP (lhs, 0), mode, speed)
                        + set_src_cost (XEXP (x, 1), mode, speed));
              return true;
            }
diff --git a/gcc/testsuite/gcc.target/loongarch/alsl-cost.c 
b/gcc/testsuite/gcc.target/loongarch/alsl-cost.c
new file mode 100644
index 000000000000..a182279015c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/alsl-cost.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=loongarch64" } */
+/* { dg-final { scan-assembler-times "alsl\\\.\[wd\]" 2 } } */
+
+struct P
+{
+  long a, b;
+};
+
+struct P
+t (struct P x, long n)
+{
+  return (struct P){.a = x.a + n * 8, .b = x.b + n * 8};
+}

Reply via email to