This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH,MIPS] Add support for the R6 LSA and DLSA instructions
- From: Matthew Fortune <Matthew dot Fortune at imgtec dot com>
- To: "Moore, Catherine (Catherine_Moore at mentor dot com)" <Catherine_Moore at mentor dot com>
- Cc: "'gcc-patches at gcc dot gnu dot org' (gcc-patches at gcc dot gnu dot org)" <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 12 Jan 2015 15:34:58 +0000
- Subject: [PATCH,MIPS] Add support for the R6 LSA and DLSA instructions
- Authentication-results: sourceware.org; auth=none
This patch adds support for the R6 [D]LSA instructions. The support
has been structured to allow MSA (when implemented) to turn on the
same instructions as they are also added by the MSA ASE.
I have continued to use the idea of 'ghost' options in the testsuite to
indicate what features are required rather than arch revisions.
Thanks,
Matthew
gcc/
* config/mips/mips.c (mips_rtx_costs): Set costs for LSA/DLSA.
(mips_print_operand): Support 'y' to print exact log2 in decimal
of a const_int.
* config/mips/mips.h (ISA_HAS_LSA): New define.
(ISA_HAS_DLSA): Likewise.
* config/mips/mips.md (<GPR:d>lsa): New define_insn.
* config/mips/predicates.md (const_immlsa_operand): New predicate.
gcc/testsuite/
* gcc.target/mips/lsa.c: New file.
* gcc.target/mips/mips64-lsa.c: Likewise.
* gcc.target/mips/mulsize-2.c: Require !HAS_LSA.
* gcc.target/mips/mulsize-4.c: Likewise.
* gcc.target/mips/mulsize-5.c: New file.
* gcc.target/mips/mulsize-6.c: Likewise.
* gcc.target/mips/mips.exp (mips_option_groups): Support HAS_LSA
and !HAS_LSA as ghost options.
(mips-dg-options): Require rev 6 for HAS_LSA. Downgrade to rev 5
for !HAS_LSA.
---
gcc/config/mips/mips.c | 30 ++++++++++++++++++++++++++++++
gcc/config/mips/mips.h | 6 ++++++
gcc/config/mips/mips.md | 10 ++++++++++
gcc/config/mips/predicates.md | 4 ++++
gcc/testsuite/gcc.target/mips/lsa.c | 11 +++++++++++
gcc/testsuite/gcc.target/mips/mips.exp | 16 ++++++++++++++--
gcc/testsuite/gcc.target/mips/mips64-lsa.c | 11 +++++++++++
gcc/testsuite/gcc.target/mips/mulsize-2.c | 1 +
gcc/testsuite/gcc.target/mips/mulsize-4.c | 1 +
gcc/testsuite/gcc.target/mips/mulsize-5.c | 13 +++++++++++++
gcc/testsuite/gcc.target/mips/mulsize-6.c | 13 +++++++++++++
11 files changed, 114 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/mips/lsa.c
create mode 100644 gcc/testsuite/gcc.target/mips/mips64-lsa.c
create mode 100644 gcc/testsuite/gcc.target/mips/mulsize-5.c
create mode 100644 gcc/testsuite/gcc.target/mips/mulsize-6.c
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index c2cc76e..a858a84 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4108,6 +4108,22 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return false;
}
+ /* If it's an add + mult (which is equivalent to shift left) and
+ it's immediate operand satisfies const_immlsa_operand predicate. */
+ if (((ISA_HAS_LSA && mode == SImode)
+ || (ISA_HAS_DLSA && mode == DImode))
+ && GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ rtx op2 = XEXP (XEXP (x, 0), 1);
+ if (const_immlsa_operand (op2, mode))
+ {
+ *total = (COSTS_N_INSNS (1)
+ + set_src_cost (XEXP (XEXP (x, 0), 0), speed)
+ + set_src_cost (XEXP (x, 1), speed));
+ return true;
+ }
+ }
+
/* Double-word operations require three single-word operations and
an SLTU. The MIPS16 version then needs to move the result of
the SLTU from $24 to a MIPS16 register. */
@@ -8413,6 +8429,7 @@ mips_print_operand_punct_valid_p (unsigned char code)
'x' Print the low 16 bits of CONST_INT OP in hexadecimal format.
'd' Print CONST_INT OP in decimal.
'm' Print one less than CONST_INT OP in decimal.
+ 'y' Print exact log2 of CONST_INT OP in decimal.
'h' Print the high-part relocation associated with OP, after stripping
any outermost HIGH.
'R' Print the low-part relocation associated with OP.
@@ -8476,6 +8493,19 @@ mips_print_operand (FILE *file, rtx op, int letter)
output_operand_lossage ("invalid use of '%%%c'", letter);
break;
+ case 'y':
+ if (CONST_INT_P (op))
+ {
+ int val = exact_log2 (INTVAL (op));
+ if (val != -1)
+ fprintf (file, "%d", val);
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
+ }
+ else
+ output_operand_lossage ("invalid use of '%%%c'", letter);
+ break;
+
case 'h':
if (code == HIGH)
op = XEXP (op, 0);
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 3d95a58..37d4cb4 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -181,6 +181,12 @@ struct mips_cpu_info {
#define ISA_HAS_DSP_MULT ISA_HAS_DSPR2
#endif
+/* ISA has LSA available. */
+#define ISA_HAS_LSA (mips_isa_rev >= 6)
+
+/* ISA has DLSA available. */
+#define ISA_HAS_DLSA (TARGET_64BIT && mips_isa_rev >= 6)
+
/* The ISA compression flags that are currently in effect. */
#define TARGET_COMPRESSION (target_flags & (MASK_MIPS16 | MASK_MICROMIPS))
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index f7f2687..2fb2786 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -5541,6 +5541,16 @@ (define_insn "*<optab>si3_mips16"
(set_attr "mode" "SI")
(set_attr "extended_mips16" "no,no,yes")])
+(define_insn "<GPR:d>lsa"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (plus:GPR (mult:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand 2 "const_immlsa_operand" ""))
+ (match_operand:GPR 3 "register_operand" "d")))]
+ "ISA_HAS_<GPR:D>LSA"
+ "<GPR:d>lsa\t%0,%1,%3,%y2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<GPR:MODE>")])
+
;; We need separate DImode MIPS16 patterns because of the irregularity
;; of right shifts.
(define_insn "*ashldi3_mips16"
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index ba5c0e3..fa17ac7 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -33,6 +33,10 @@ (define_predicate "arith_operand"
(ior (match_operand 0 "const_arith_operand")
(match_operand 0 "register_operand")))
+(define_predicate "const_immlsa_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (exact_log2 (INTVAL (op)), 1, 4)")))
+
(define_predicate "const_uimm6_operand"
(and (match_code "const_int")
(match_test "UIMM6_OPERAND (INTVAL (op))")))
diff --git a/gcc/testsuite/gcc.target/mips/lsa.c b/gcc/testsuite/gcc.target/mips/lsa.c
new file mode 100644
index 0000000..d7be174
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/lsa.c
@@ -0,0 +1,11 @@
+/* Test MIPS32R6 LSA instruction */
+/* { dg-do compile } */
+/* { dg-options "-mgp32 (HAS_LSA)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+/* { dg-final { scan-assembler "\tlsa\t" } } */
+
+NOMIPS16 signed short test (signed short *a, int index)
+{
+ return a[index];
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 4247cc9..3d6da81 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -253,6 +253,7 @@ set mips_option_groups {
movn "HAS_MOVN"
madd "HAS_MADD"
maddps "HAS_MADDPS"
+ lsa "(|!)HAS_LSA"
}
for { set option 0 } { $option < 32 } { incr option } {
@@ -1061,11 +1062,21 @@ proc mips-dg-options { args } {
# Handle dependencies between the pre-arch options and the arch option.
# This should mirror the arch and post-arch code below.
if { !$arch_test_option_p } {
+ # We need a revision 6 or better ISA for:
+ #
+ # - When the LSA instruction is required
+ if { $isa_rev < 6
+ && ([mips_have_test_option_p options "HAS_LSA"]) } {
+ if { $gp_size == 32 } {
+ mips_make_test_option options "-mips32r6"
+ } else {
+ mips_make_test_option options "-mips64r6"
+ }
# We need a revision 2 or better ISA for:
#
# - the combination of -mgp32 -mfp64
# - the DSP ASE
- if { $isa_rev < 2
+ } elseif { $isa_rev < 2
&& (($gp_size == 32 && [mips_have_test_option_p options "-mfp64"])
|| [mips_have_test_option_p options "-msynci"]
|| [mips_have_test_option_p options "-mdsp"]
@@ -1142,7 +1153,8 @@ proc mips-dg-options { args } {
|| [mips_have_test_option_p options "HAS_MADD"]
|| [mips_have_test_option_p options "-mpaired-single"]
|| [mips_have_test_option_p options "-mnan=legacy"]
- || [mips_have_test_option_p options "-mabs=legacy"]) } {
+ || [mips_have_test_option_p options "-mabs=legacy"]
+ || [mips_have_test_option_p options "!HAS_LSA"]) } {
if { $gp_size == 32 } {
mips_make_test_option options "-mips32r5"
} else {
diff --git a/gcc/testsuite/gcc.target/mips/mips64-lsa.c b/gcc/testsuite/gcc.target/mips/mips64-lsa.c
new file mode 100644
index 0000000..940847e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips64-lsa.c
@@ -0,0 +1,11 @@
+/* Test MIPS64R6 LSA instruction */
+/* { dg-do compile } */
+/* { dg-options "-mabi=64 (HAS_LSA)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+/* { dg-final { scan-assembler "\tdlsa\t" } } */
+
+NOMIPS16 signed long long test (signed long long *a, int index)
+{
+ return a[index];
+}
diff --git a/gcc/testsuite/gcc.target/mips/mulsize-2.c b/gcc/testsuite/gcc.target/mips/mulsize-2.c
index 4cc2224..7c84bfd 100644
--- a/gcc/testsuite/gcc.target/mips/mulsize-2.c
+++ b/gcc/testsuite/gcc.target/mips/mulsize-2.c
@@ -1,3 +1,4 @@
+/* { dg-options "(!HAS_LSA)" } */
/* { dg-final { scan-assembler "\t.globl\tf9" } } */
/* { dg-final { scan-assembler "\tsll\t" } } */
/* { dg-final { scan-assembler "\taddu\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/mulsize-4.c b/gcc/testsuite/gcc.target/mips/mulsize-4.c
index 7694d2c..f8a94a9 100644
--- a/gcc/testsuite/gcc.target/mips/mulsize-4.c
+++ b/gcc/testsuite/gcc.target/mips/mulsize-4.c
@@ -1,3 +1,4 @@
+/* { dg-options "(!HAS_LSA)" } */
/* { dg-final { scan-assembler "\t.globl\tf17" } } */
/* { dg-final { scan-assembler "\tsll\t" } } */
/* { dg-final { scan-assembler "\taddu\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/mulsize-5.c b/gcc/testsuite/gcc.target/mips/mulsize-5.c
new file mode 100644
index 0000000..1c39a7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mulsize-5.c
@@ -0,0 +1,13 @@
+/* { dg-options "(HAS_LSA)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\t.globl\tf9" } } */
+/* { dg-final { scan-assembler "\tlsa\t" } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+/* { dg-final { scan-assembler-not "\taddu\t" } } */
+/* { dg-final { scan-assembler-not "\tli\t" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+int
+f9(int x)
+{
+ return x * 9;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mulsize-6.c b/gcc/testsuite/gcc.target/mips/mulsize-6.c
new file mode 100644
index 0000000..6e9ca00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mulsize-6.c
@@ -0,0 +1,13 @@
+/* { dg-options "(HAS_LSA)" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+/* { dg-final { scan-assembler "\t.globl\tf17" } } */
+/* { dg-final { scan-assembler "\tlsa\t" } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+/* { dg-final { scan-assembler-not "\taddu\t" } } */
+/* { dg-final { scan-assembler-not "\tli\t" } } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+int
+f17(int x)
+{
+ return x * 17;
+}
--
2.2.1