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

Reply via email to