diff options
author | Xi Ruoyao <xry111@xry111.site> | 2024-09-06 00:34:55 +0800 |
---|---|---|
committer | Xi Ruoyao <xry111@xry111.site> | 2025-01-18 10:17:03 +0800 |
commit | ce36692f8e10a619563938851f507cdb15567cf8 (patch) | |
tree | a5da9e696bb1253f1643157fd49263f112b5146c | |
parent | cc6176a921cbe3b9db323b1cd557efe4f299171a (diff) | |
download | gcc-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.cc | 27 | ||||
-rw-r--r-- | 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 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}; +} |