Add support for the R6 LSA and DLSA instructions
authorMatthew Fortune <matthew.fortune@imgtec.com>
Thu, 15 Jan 2015 10:44:57 +0000 (10:44 +0000)
committerMatthew Fortune <mpf@gcc.gnu.org>
Thu, 15 Jan 2015 10:44:57 +0000 (10:44 +0000)
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.

From-SVN: r219638

13 files changed:
gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/lsa.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mips.exp
gcc/testsuite/gcc.target/mips/mips64-lsa.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mulsize-2.c
gcc/testsuite/gcc.target/mips/mulsize-4.c
gcc/testsuite/gcc.target/mips/mulsize-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mulsize-6.c [new file with mode: 0644]

index 388bc84ac724791243587091ce58d17575454fd5..356422321c43a842f664afcd5069cd558e34a2fc 100644 (file)
@@ -1,3 +1,13 @@
+2015-01-14  Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * 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.
+
 2015-01-15  Martin Liska  <mliska@suse.cz>
 
        PR target/64377
index 327aa290ec2c9a7453e88bcc55504476e726aed7..00801bb3ce868778a7f5c2334099028ee3bc6aea 100644 (file)
@@ -4114,6 +4114,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.  */
@@ -8419,6 +8435,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.
@@ -8482,6 +8499,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);
index f6f785393f51d7ccb18e7e1387433b10a6bf8017..c5ea2401a17a00fba5860ae809f2ec4ff0a8f61d 100644 (file)
@@ -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))
 
index f7f2687026637813038082c3e545970caed82941..2fb278650ca946a465a048e0885d70a45d728318 100644 (file)
    (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"
index ba5c0e3e81f007f838daf2c1fa9821d99cc97581..fa17ac7ca4b3f1ec5162e3ca5e34884afdc762df 100644 (file)
   (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))")))
index ba1cd3101e45857ead7c89d146019814f2df4062..6b73d3159fb1ce2dddec961118b9a4b0cf1fd78f 100644 (file)
@@ -1,3 +1,16 @@
+2015-01-14  Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * 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.
+
 2015-01-15  Matthew Wahab  <matthew.wahab@arm.com>
 
        * g++.dg/torture/20141013.c: Set -fno-short-enums.
diff --git a/gcc/testsuite/gcc.target/mips/lsa.c b/gcc/testsuite/gcc.target/mips/lsa.c
new file mode 100644 (file)
index 0000000..d7be174
--- /dev/null
@@ -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];
+}
index 4247cc9f8da4213d7860d0d02ebfba03d05a8e98..3d6da815c49d10a3759f14a64b2c7e4d937ea39a 100644 (file)
@@ -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 (file)
index 0000000..940847e
--- /dev/null
@@ -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];
+}
index 4cc2224dff9f9cb15d437f8648b41aa7d8bd1989..7c84bfd9cddaefc8cce78a54ec75f3655eca7c8f 100644 (file)
@@ -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" } } */
index 7694d2c03dc27ce2afd2fdf4b8db0b6eff2548e8..f8a94a9588e94294002dbb4fb9709602254b9506 100644 (file)
@@ -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 (file)
index 0000000..1c39a7e
--- /dev/null
@@ -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 (file)
index 0000000..6e9ca00
--- /dev/null
@@ -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;
+}