aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXi Ruoyao <xry111@xry111.site>2024-09-06 00:34:55 +0800
committerXi Ruoyao <xry111@xry111.site>2025-01-18 10:17:03 +0800
commitce36692f8e10a619563938851f507cdb15567cf8 (patch)
treea5da9e696bb1253f1643157fd49263f112b5146c
parentcc6176a921cbe3b9db323b1cd557efe4f299171a (diff)
downloadgcc-ce36692f8e10a619563938851f507cdb15567cf8.zip
gcc-ce36692f8e10a619563938851f507cdb15567cf8.tar.gz
gcc-ce36692f8e10a619563938851f507cdb15567cf8.tar.bz2
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.
-rw-r--r--gcc/config/loongarch/loongarch.cc27
-rw-r--r--gcc/testsuite/gcc.target/loongarch/alsl-cost.c14
2 files changed, 36 insertions, 5 deletions
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 9d97f02..3a8e129 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 0000000..a182279
--- /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};
+}