SB-1 specific MIPS vector instructions.
authorJames E Wilson <wilson@specifixinc.com>
Mon, 13 Sep 2004 19:32:05 +0000 (19:32 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Mon, 13 Sep 2004 19:32:05 +0000 (12:32 -0700)
* config/mips/mips.c (CODE_FOR_mips_sqrt_ps): New.
(sb1_bdesc, bdesc_map, bdesc_arrays): New.
(mips_expand_builtin): Add SB-1 support.  Use bdesc_map and
bdesc_arrays instead of mips_bdesc.
(mips_init_builtins): Likewise.
* config/mips/mips.h (TARGET_SB1): New.
(HAVE_SQRT_P): Delete.
* config/mips/mips.md (divide_condition): Support V2SF.
(sqrt_condition, recip_condition): New.
(div<mode>3): Use ANYF instead of SCALARF.
(*div<mode>3): Use ANYF instead of SCALARF.  Use UNITMODE instead of
MODE.
(*recip<mode>3, *rsqrt<mode>a, *rsqrt<mode>b): Use recip_condition
instead of ISA_HAS_FP4.  Use ANYF instead of SCALARF.  Use UNITMODE
instead of MODE.
(sqrt<mode>2): Use sqrt_condition instead of HAVE_SQRT_P.  Use ANYF
instead of SCALARF.  Use UNITMODE instead of MODE.
* gcc.target/mips/sb1-1.c: New testcase.

From-SVN: r87446

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/sb1-1.c [new file with mode: 0644]

index 72505d641adc37281437e34e5e6d14ba885af81b..6eac4dc471b4bce72e28f81f8e6e6ac4f9c1f0b5 100644 (file)
@@ -1,3 +1,23 @@
+2004-09-13  James E Wilson  <wilson@specifixinc.com>
+
+       * config/mips/mips.c (CODE_FOR_mips_sqrt_ps): New.
+       (sb1_bdesc, bdesc_map, bdesc_arrays): New.
+       (mips_expand_builtin): Add SB-1 support.  Use bdesc_map and
+       bdesc_arrays instead of mips_bdesc.
+       (mips_init_builtins): Likewise.
+       * config/mips/mips.h (TARGET_SB1): New.
+       (HAVE_SQRT_P): Delete.
+       * config/mips/mips.md (divide_condition): Support V2SF.
+       (sqrt_condition, recip_condition): New.
+       (div<mode>3): Use ANYF instead of SCALARF.
+       (*div<mode>3): Use ANYF instead of SCALARF.  Use UNITMODE instead of
+       MODE.
+       (*recip<mode>3, *rsqrt<mode>a, *rsqrt<mode>b): Use recip_condition
+       instead of ISA_HAS_FP4.  Use ANYF instead of SCALARF.  Use UNITMODE
+       instead of MODE.
+       (sqrt<mode>2): Use sqrt_condition instead of HAVE_SQRT_P.  Use ANYF
+       instead of SCALARF.  Use UNITMODE instead of MODE.
+
 2004-09-13  Zack Weinberg  <zack@codesourcery.com>
 
        * config.in: Regenerate after removal of libbanshee.
index f0887d5c5f52af71945a1cfe65b4d02cff84fa20..c564f4e7f186e8ef072f2a980ec4ec179fa75d8b 100644 (file)
@@ -9410,6 +9410,36 @@ static const struct builtin_description mips_bdesc[] =
   MIPS_FP_CONDITIONS (CMP_BUILTINS)
 };
 
+/* Builtin functions for the SB-1 processor.  */
+
+#define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
+
+static const struct builtin_description sb1_bdesc[] =
+{
+  DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE)
+};
+
+/* This helps provide a mapping from builtin function codes to bdesc
+   arrays.  */
+
+struct bdesc_map
+{
+  /* The builtin function table that this entry describes.  */
+  const struct builtin_description *bdesc;
+
+  /* The number of entries in the builtin function table.  */
+  unsigned int size;
+
+  /* The target processor that supports these builtin functions.
+     PROCESSOR_DEFAULT means we enable them for all processors.  */
+  enum processor_type proc;
+};
+
+static const struct bdesc_map bdesc_arrays[] =
+{
+  { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_DEFAULT },
+  { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 }
+};
 
 /* Take the head of argument list *ARGLIST and convert it into a form
    suitable for input operand OP of instruction ICODE.  Return the value
@@ -9457,15 +9487,28 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
   enum mips_builtin_type type;
   tree fndecl, arglist;
   unsigned int fcode;
+  const struct builtin_description *bdesc;
+  const struct bdesc_map *m;
 
   fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   arglist = TREE_OPERAND (exp, 1);
   fcode = DECL_FUNCTION_CODE (fndecl);
-  if (fcode >= ARRAY_SIZE (mips_bdesc))
+
+  bdesc = NULL;
+  for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
+    {
+      if (fcode < m->size)
+       {
+         bdesc = m->bdesc;
+         icode = bdesc[fcode].icode;
+         type = bdesc[fcode].builtin_type;
+         break;
+       }
+      fcode -= m->size;
+    }
+  if (bdesc == NULL)
     return 0;
 
-  icode = mips_bdesc[fcode].icode;
-  type = mips_bdesc[fcode].builtin_type;
   switch (type)
     {
     case MIPS_BUILTIN_DIRECT:
@@ -9473,7 +9516,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
 
     case MIPS_BUILTIN_MOVT:
     case MIPS_BUILTIN_MOVF:
-      return mips_expand_builtin_movtf (type, icode, mips_bdesc[fcode].cond,
+      return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond,
                                        target, arglist);
 
     case MIPS_BUILTIN_CMP_ANY:
@@ -9481,7 +9524,7 @@ mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case MIPS_BUILTIN_CMP_UPPER:
     case MIPS_BUILTIN_CMP_LOWER:
     case MIPS_BUILTIN_CMP_SINGLE:
-      return mips_expand_builtin_compare (type, icode, mips_bdesc[fcode].cond,
+      return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
                                          target, arglist);
 
     default:
@@ -9495,8 +9538,10 @@ void
 mips_init_builtins (void)
 {
   const struct builtin_description *d;
+  const struct bdesc_map *m;
   tree types[(int) MIPS_MAX_FTYPE_MAX];
   tree V2SF_type_node;
+  unsigned int offset;
 
   /* We have only builtins for -mpaired-single and -mips3d.  */
   if (!TARGET_PAIRED_SINGLE_FLOAT)
@@ -9561,10 +9606,20 @@ mips_init_builtins (void)
     = build_function_type_list (double_type_node,
                                double_type_node, double_type_node, NULL_TREE);
 
-  for (d = mips_bdesc; d < &mips_bdesc[ARRAY_SIZE (mips_bdesc)]; d++)
-    if ((d->target_flags & target_flags) == d->target_flags)
-      lang_hooks.builtin_function (d->name, types[d->function_type],
-                                  d - mips_bdesc, BUILT_IN_MD, NULL, NULL);
+  /* Iterate through all of the bdesc arrays, initializing all of the
+     builtin functions.  */
+
+  offset = 0;
+  for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
+    {
+      if (m->proc == PROCESSOR_DEFAULT || (m->proc == mips_arch))
+       for (d = m->bdesc; d < &m->bdesc[m->size]; d++)
+         if ((d->target_flags & target_flags) == d->target_flags)
+           lang_hooks.builtin_function (d->name, types[d->function_type],
+                                        d - m->bdesc + offset,
+                                        BUILT_IN_MD, NULL, NULL);
+      offset += m->size;
+    }
 }
 
 /* Expand a MIPS_BUILTIN_DIRECT function.  ICODE is the code of the
index 3428ac9a4fee457e355038042d9f929709632f34..ddca621abfcca791fb0af8d414c532b1a104734b 100644 (file)
@@ -302,6 +302,7 @@ extern const struct mips_cpu_info *mips_tune_info;
 #define TARGET_MIPS5500             (mips_arch == PROCESSOR_R5500)
 #define TARGET_MIPS7000             (mips_arch == PROCESSOR_R7000)
 #define TARGET_MIPS9000             (mips_arch == PROCESSOR_R9000)
+#define TARGET_SB1                  (mips_arch == PROCESSOR_SB1)
 #define TARGET_SR71K                (mips_arch == PROCESSOR_SR71000)
 
 /* Scheduling target defines.  */
@@ -822,11 +823,6 @@ extern const struct mips_cpu_info *mips_tune_info;
 #define GENERATE_MULT3_DI       ((TARGET_MIPS3900)                      \
                                 && !TARGET_MIPS16)
 
-/* Macros to decide whether certain features are available or not,
-   depending on the instruction set architecture level.  */
-
-#define HAVE_SQRT_P()          (!ISA_MIPS1)
-
 /* True if the ABI can only work with 64-bit integer registers.  We
    generally allow ad-hoc variations for TARGET_SINGLE_FLOAT, but
    otherwise floating-point registers must also be 64-bit.  */
index 9390ed03b2170073bf13cebc7c7b6277b1d1ab7d..fb50b3bdab276b36b9e76aa625a6e14828ab58a6 100644 (file)
 ;; Therefore, we only allow div.s if not working around SB-1 rev2
 ;; errata or if a slight loss of precision is OK.
 (define_mode_attr divide_condition
-  [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations")])
+  [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations")
+   (V2SF "TARGET_SB1 && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)")])
+
+; This attribute gives the condition for which sqrt instructions exist.
+(define_mode_attr sqrt_condition
+  [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
+
+; This attribute gives the condition for which recip and rsqrt instructions
+; exist.
+(define_mode_attr recip_condition
+  [(SF "ISA_HAS_FP4") (DF "ISA_HAS_FP4") (V2SF "TARGET_SB1")])
 
 ;; This code macro allows all branch instructions to be generated from
 ;; a single define_expand template.
 ;;
 
 (define_expand "div<mode>3"
-  [(set (match_operand:SCALARF 0 "register_operand")
-       (div:SCALARF (match_operand:SCALARF 1 "reg_or_1_operand")
-                    (match_operand:SCALARF 2 "register_operand")))]
+  [(set (match_operand:ANYF 0 "register_operand")
+       (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand")
+                 (match_operand:ANYF 2 "register_operand")))]
   "<divide_condition>"
 {
   if (const_1_operand (operands[1], <MODE>mode))
 ;; long latency op destination register.
 
 (define_insn "*div<mode>3"
-  [(set (match_operand:SCALARF 0 "register_operand" "=f")
-       (div:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
-                    (match_operand:SCALARF 2 "register_operand" "f")))]
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
+                 (match_operand:ANYF 2 "register_operand" "f")))]
   "<divide_condition>"
 {
   if (TARGET_FIX_SB1)
     return "div.<fmt>\t%0,%1,%2";
 }
   [(set_attr "type" "fdiv")
-   (set_attr "mode" "<MODE>")
+   (set_attr "mode" "<UNITMODE>")
    (set (attr "length")
         (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
                       (const_int 8)
                       (const_int 4)))])
 
 (define_insn "*recip<mode>3"
-  [(set (match_operand:SCALARF 0 "register_operand" "=f")
-       (div:SCALARF (match_operand:SCALARF 1 "const_1_operand" "")
-                    (match_operand:SCALARF 2 "register_operand" "f")))]
-  "ISA_HAS_FP4 && flag_unsafe_math_optimizations"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+                 (match_operand:ANYF 2 "register_operand" "f")))]
+  "<recip_condition> && flag_unsafe_math_optimizations"
 {
   if (TARGET_FIX_SB1)
     return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
     return "recip.<fmt>\t%0,%2";
 }
   [(set_attr "type" "frdiv")
-   (set_attr "mode" "<MODE>")
+   (set_attr "mode" "<UNITMODE>")
    (set (attr "length")
         (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
                       (const_int 8)
 ;; "*div[sd]f3" comment for details).
 
 (define_insn "sqrt<mode>2"
-  [(set (match_operand:SCALARF 0 "register_operand" "=f")
-       (sqrt:SCALARF (match_operand:SCALARF 1 "register_operand" "f")))]
-  "HAVE_SQRT_P()"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
+  "<sqrt_condition>"
 {
   if (TARGET_FIX_SB1)
     return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0";
     return "sqrt.<fmt>\t%0,%1";
 }
   [(set_attr "type" "fsqrt")
-   (set_attr "mode" "<MODE>")
+   (set_attr "mode" "<UNITMODE>")
    (set (attr "length")
         (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
                       (const_int 8)
                       (const_int 4)))])
 
 (define_insn "*rsqrt<mode>a"
-  [(set (match_operand:SCALARF 0 "register_operand" "=f")
-       (div:SCALARF
-        (match_operand:SCALARF 1 "const_1_operand" "")
-        (sqrt:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))))]
-  "ISA_HAS_FP4 && flag_unsafe_math_optimizations"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+                 (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))]
+  "<recip_condition> && flag_unsafe_math_optimizations"
 {
   if (TARGET_FIX_SB1)
     return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
     return "rsqrt.<fmt>\t%0,%2";
 }
   [(set_attr "type" "frsqrt")
-   (set_attr "mode" "<MODE>")
+   (set_attr "mode" "<UNITMODE>")
    (set (attr "length")
         (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
                       (const_int 8)
                       (const_int 4)))])
 
 (define_insn "*rsqrt<mode>b"
-  [(set (match_operand:SCALARF 0 "register_operand" "=f")
-       (sqrt:SCALARF
-        (div:SCALARF (match_operand:SCALARF 1 "const_1_operand" "")
-                     (match_operand:SCALARF 2 "register_operand" "f"))))]
-  "ISA_HAS_FP4 && flag_unsafe_math_optimizations"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+                            (match_operand:ANYF 2 "register_operand" "f"))))]
+  "<recip_condition> && flag_unsafe_math_optimizations"
 {
   if (TARGET_FIX_SB1)
     return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
     return "rsqrt.<fmt>\t%0,%2";
 }
   [(set_attr "type" "frsqrt")
-   (set_attr "mode" "<MODE>")
+   (set_attr "mode" "<UNITMODE>")
    (set (attr "length")
         (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
                       (const_int 8)
index ae42e1bf8b3d5811634eda8b3b862b8faae0c343..4736e13e528c7470775061d08954dd029952693d 100644 (file)
@@ -1,3 +1,7 @@
+2004-09-13  James E Wilson  <wilson@specifixinc.com>
+
+       * gcc.target/mips/sb1-1.c: New testcase.
+
 2004-09-12  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * lib/g77-dg.exp: Remove unused file.
diff --git a/gcc/testsuite/gcc.target/mips/sb1-1.c b/gcc/testsuite/gcc.target/mips/sb1-1.c
new file mode 100644 (file)
index 0000000..b6d671b
--- /dev/null
@@ -0,0 +1,29 @@
+/* Test SB-1 v2sf extensions.  */
+/* { dg-do compile { target mipsisa64*-*-* } } */ 
+/* { dg-options "-march=sb1 -O2 -mpaired-single -mhard-float -mfp64 -ffast-math" } */ 
+/* { dg-final { scan-assembler "div.ps" } } */ 
+/* { dg-final { scan-assembler "recip.ps" } } */ 
+/* { dg-final { scan-assembler "sqrt.ps" } } */ 
+/* { dg-final { scan-assembler "rsqrt.ps" } } */ 
+
+typedef float v2sf __attribute__ ((vector_size (8)));
+
+v2sf divide (v2sf a, v2sf b)
+{
+  return a / b;
+}
+
+v2sf recip (v2sf a)
+{
+  return ((v2sf) {1.0, 1.0}) / a;
+}
+
+v2sf squareroot (v2sf a)
+{
+  return __builtin_mips_sqrt_ps (a);
+}
+
+v2sf rsqrt (v2sf a)
+{
+  return ((v2sf) {1.0, 1.0}) / __builtin_mips_sqrt_ps (a);
+}