2007-xx-xx Chao-ying Fu <fu@mips.com> Richard Sandiford <richard@nildram.co.uk>
authorRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 24 Apr 2007 05:51:57 +0000 (05:51 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 24 Apr 2007 05:51:57 +0000 (05:51 +0000)
gcc/
2007-xx-xx  Chao-ying Fu  <fu@mips.com>
    Richard Sandiford  <richard@nildram.co.uk>

* doc/md.texi (madd@var{m}@var{n}4, umadd@var{m}@var{n}4): Document.
* optabs.h (OTI_smadd_widen, OTI_umadd_widen): New optab_indexes.
(smadd_widen_optab, umadd_widen_optab): Define.
* optabs.c (init_optabs): Initialize smadd_widen_optab and
umadd_widen_optab.
* genopinit.c (optabs): Fill in smadd_widen_optab and
umadd_widen_optab.
* expr.c (expand_expr_real_1): Try to use smadd_widen_optab
and umadd_widen_optab to implement multiply-add sequences.
* config/mips/mips.md (*<su>mul_acc_di): Rename to...
(<u>maddsidi4): ...this.  Extend condition to include
GENERATE_MADD_MSUB and TARGET_DSPR2.  Change the constraint
of operand 0 to "ka" and use the three-operand form of madd<u>
for TARGET_DSPR2.
* config/mips/mips-dspr2.md (mips_madd, mips_maddu): Convert
to define_expands.
* config/mips/constraints.md (ka): New register constraint.

gcc/testsuite/
2007-xx-xx  Richard Sandiford  <richard@nildram.co.uk>

* gcc.target/mips/madd-1.c, gcc.target/mips/madd-2.c,
* gcc.target/mips/madd-3.c, gcc.target/mips/madd-4.c,
* gcc.target/mips/maddu-1.c, gcc.target/mips/maddu-2.c,
* gcc.target/mips/maddu-3.c, gcc.target/mips/maddu-4.c: New tests.

From-SVN: r124095

18 files changed:
gcc/ChangeLog
gcc/config/mips/constraints.md
gcc/config/mips/mips-dspr2.md
gcc/config/mips/mips.md
gcc/doc/md.texi
gcc/expr.c
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/madd-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/maddu-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/maddu-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/maddu-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/maddu-4.c [new file with mode: 0644]

index 5825eccde0326f843cf1f0bb557a42878daf7e3c..3983b4279381ceb20b64f29d491b57b8739c3c05 100644 (file)
@@ -1,3 +1,24 @@
+2007-04-24  Chao-ying Fu  <fu@mips.com>
+           Richard Sandiford  <richard@nildram.co.uk>
+
+       * doc/md.texi (madd@var{m}@var{n}4, umadd@var{m}@var{n}4): Document.
+       * optabs.h (OTI_smadd_widen, OTI_umadd_widen): New optab_indexes.
+       (smadd_widen_optab, umadd_widen_optab): Define.
+       * optabs.c (init_optabs): Initialize smadd_widen_optab and
+       umadd_widen_optab.
+       * genopinit.c (optabs): Fill in smadd_widen_optab and
+       umadd_widen_optab.
+       * expr.c (expand_expr_real_1): Try to use smadd_widen_optab
+       and umadd_widen_optab to implement multiply-add sequences.
+       * config/mips/mips.md (*<su>mul_acc_di): Rename to...
+       (<u>maddsidi4): ...this.  Extend condition to include
+       GENERATE_MADD_MSUB and TARGET_DSPR2.  Change the constraint
+       of operand 0 to "ka" and use the three-operand form of madd<u>
+       for TARGET_DSPR2.
+       * config/mips/mips-dspr2.md (mips_madd, mips_maddu): Convert
+       to define_expands.
+       * config/mips/constraints.md (ka): New register constraint.
+
 2007-04-24  Jan Hubicka  <j@suse.cz>
 
        Revert:
index a01777dc926c01b9db8cd62e5feec55751c5a53b..1388fc2cca1ed227bbd2b8c705bb2b5261e9cbce 100644 (file)
 (define_register_constraint "D" "COP3_REGS"
   "@internal")
 
+;; Registers that can be used as the target of multiply-accumulate
+;; instructions.  The core MIPS32 ISA provides a hi/lo madd,
+;; but the DSPr2 version allows any accumulator target.
+(define_register_constraint "ka" "TARGET_DSPR2 ? ACC_REGS : MD_REGS")
+
 ;; Integer constraints
 
 (define_constraint "I"
index 948c693c7d83c01d6d400031c49bf2169c1150a8..dd0aab553a1fbdfdbce8561db56f6117dd2b2dfb 100644 (file)
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")])
 
-(define_insn "mips_madd"
-  [(set (match_operand:DI 0 "register_operand" "=a")
+(define_expand "mips_madd<u>"
+  [(set (match_operand:DI 0 "register_operand")
        (plus:DI
-        (mult:DI (sign_extend:DI
-                  (match_operand:SI 2 "register_operand" "d"))
-                 (sign_extend:DI
-                  (match_operand:SI 3 "register_operand" "d")))
-        (match_operand:DI 1 "register_operand" "0")))]
-  "TARGET_DSPR2 && !TARGET_64BIT"
-  "madd\t%q0,%2,%3"
-  [(set_attr "type"    "imadd")
-   (set_attr "mode"    "SI")])
-
-(define_insn "mips_maddu"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (plus:DI
-        (mult:DI (zero_extend:DI
-                  (match_operand:SI 2 "register_operand" "d"))
-                 (zero_extend:DI
-                  (match_operand:SI 3 "register_operand" "d")))
-        (match_operand:DI 1 "register_operand" "0")))]
-  "TARGET_DSPR2 && !TARGET_64BIT"
-  "maddu\t%q0,%2,%3"
-  [(set_attr "type"    "imadd")
-   (set_attr "mode"    "SI")])
+        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
+                 (any_extend:DI (match_operand:SI 3 "register_operand")))
+        (match_operand:DI 1 "register_operand")))]
+  "TARGET_DSPR2 && !TARGET_64BIT")
 
 (define_insn "mips_msub"
   [(set (match_operand:DI 0 "register_operand" "=a")
   "dpsqx_sa.w.ph\t%q0,%z2,%z3"
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")])
-
index 12415e42f998088bc7d75c0b967f51132a71c0ac..e44b919ccb9eb17f1d7983865ff712ceac6b5dd1 100644 (file)
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")])
 
-(define_insn "*<su>mul_acc_di"
-  [(set (match_operand:DI 0 "register_operand" "=x")
+(define_insn "<u>maddsidi4"
+  [(set (match_operand:DI 0 "register_operand" "=ka")
        (plus:DI
         (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
                  (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
         (match_operand:DI 3 "register_operand" "0")))]
-  "(TARGET_MAD || ISA_HAS_MACC)
+  "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || TARGET_DSPR2)
    && !TARGET_64BIT"
 {
   if (TARGET_MAD)
     return "mad<u>\t%1,%2";
-  else if (TARGET_MIPS5500)
+  else if (TARGET_DSPR2)
+    return "madd<u>\t%q0,%1,%2";
+  else if (GENERATE_MADD_MSUB || TARGET_MIPS5500)
     return "madd<u>\t%1,%2";
   else
     /* See comment in *macc.  */
index 01705ad282dff509bc6a562f6069e3810a753cc1..56cc60f2e1e8d7120a029965946f55c33f5d7aea 100644 (file)
@@ -3669,6 +3669,24 @@ The least significant half of the product is discarded.
 @item @samp{umul@var{m}3_highpart}
 Similar, but the multiplication is unsigned.
 
+@cindex @code{madd@var{m}@var{n}4} instruction pattern
+@item @samp{madd@var{m}@var{n}4}
+Multiply operands 1 and 2, sign-extend them to mode @var{n}, add
+operand 3, and store the result in operand 0.  Operands 1 and 2
+have mode @var{m} and operands 0 and 3 have mode @var{n}.
+Both modes must be integer modes and @var{n} must be twice
+the size of @var{m}.
+
+In other words, @code{madd@var{m}@var{n}4} is like
+@code{mul@var{m}@var{n}3} except that it also adds operand 3.
+
+These instructions are not allowed to @code{FAIL}.
+
+@cindex @code{umadd@var{m}@var{n}4} instruction pattern
+@item @samp{umadd@var{m}@var{n}4}
+Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication
+operands instead of sign-extending them.
+
 @cindex @code{divmod@var{m}4} instruction pattern
 @item @samp{divmod@var{m}4}
 Signed division that produces both a quotient and a remainder.
index e239f4c69b54a511e815c15a14617054422c2d6a..34cc0aa6553a28ca2662c5232b30af3c2b4ea6bd 100644 (file)
@@ -6824,7 +6824,7 @@ static rtx
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    enum expand_modifier modifier, rtx *alt_rtl)
 {
-  rtx op0, op1, temp, decl_rtl;
+  rtx op0, op1, op2, temp, decl_rtl;
   tree type;
   int unsignedp;
   enum machine_mode mode;
@@ -7977,6 +7977,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return op0;
 
     case PLUS_EXPR:
+      /* Check if this is a case for multiplication and addition.  */
+      if (TREE_CODE (type) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
+       {
+         tree subsubexp0, subsubexp1;
+         enum tree_code code0, code1;
+
+         subexp0 = TREE_OPERAND (exp, 0);
+         subsubexp0 = TREE_OPERAND (subexp0, 0);
+         subsubexp1 = TREE_OPERAND (subexp0, 1);
+         code0 = TREE_CODE (subsubexp0);
+         code1 = TREE_CODE (subsubexp1);
+         if (code0 == NOP_EXPR && code1 == NOP_EXPR
+             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+                 < TYPE_PRECISION (TREE_TYPE (subsubexp0)))
+             && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+                 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))
+             && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
+                 == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))))
+           {
+             tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
+             enum machine_mode innermode = TYPE_MODE (op0type);
+             bool zextend_p = TYPE_UNSIGNED (op0type);
+             this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
+             if (mode == GET_MODE_2XWIDER_MODE (innermode)
+                 && (this_optab->handlers[(int) mode].insn_code
+                     != CODE_FOR_nothing))
+               {
+                 expand_operands (TREE_OPERAND (subsubexp0, 0),
+                                  TREE_OPERAND (subsubexp1, 0),
+                                  NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+                 op2 = expand_expr (TREE_OPERAND (exp, 1), subtarget,
+                                    VOIDmode, 0);
+                 temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
+                                           target, unsignedp);
+                 gcc_assert (temp);
+                 return REDUCE_BIT_FIELD (temp);
+               }
+           }
+       }
+
       /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
         something else, make sure we add the register to the constant and
         then to the other thing.  This case can occur during strength
index 0e6d419bcbe4e1ea590728b3998ebbac9f013c17..992981aa8c02ee3e30a84ea5cc7b8cfec3f2015b 100644 (file)
@@ -85,6 +85,8 @@ static const char * const optabs[] =
   "smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N",
   "umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N",
   "usmul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(usmul$a$b3$)$N",
+  "smadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(madd$a$b4$)$N",
+  "umadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umadd$a$b4$)$N",
   "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)",
   "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)",
   "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
index b45a9b3abadf30ba2c0d2354fccb35ef4d6541b3..49e01217414eb8633ffdf054b60a7f69d7d3c018 100644 (file)
@@ -5439,6 +5439,8 @@ init_optabs (void)
   smul_widen_optab = init_optab (UNKNOWN);
   umul_widen_optab = init_optab (UNKNOWN);
   usmul_widen_optab = init_optab (UNKNOWN);
+  smadd_widen_optab = init_optab (UNKNOWN);
+  umadd_widen_optab = init_optab (UNKNOWN);
   sdiv_optab = init_optab (DIV);
   sdivv_optab = init_optabv (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
index 62a69c742fbff4f5bde8b8847e96cd66574d01b9..e5bbef89e4c035e01e6cb020b3a0faafe8ba2e2a 100644 (file)
@@ -86,6 +86,12 @@ enum optab_index
   OTI_umul_widen,
   /* Widening multiply of one unsigned and one signed operand.  */
   OTI_usmul_widen,
+  /* Signed multiply and add with the result and addend one machine mode
+     wider than the multiplicand and multiplier.  */
+  OTI_smadd_widen,
+  /* Unigned multiply and add with the result and addend one machine mode
+     wider than the multiplicand and multiplier.  */
+  OTI_umadd_widen,
 
   /* Signed divide */
   OTI_sdiv,
@@ -309,6 +315,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define smul_widen_optab (optab_table[OTI_smul_widen])
 #define umul_widen_optab (optab_table[OTI_umul_widen])
 #define usmul_widen_optab (optab_table[OTI_usmul_widen])
+#define smadd_widen_optab (optab_table[OTI_smadd_widen])
+#define umadd_widen_optab (optab_table[OTI_umadd_widen])
 #define sdiv_optab (optab_table[OTI_sdiv])
 #define smulv_optab (optab_table[OTI_smulv])
 #define sdivv_optab (optab_table[OTI_sdivv])
index 5c9223922bba5c0a3e2e59d1c0fa8d5581d4e373..d94dc90c33d5e9834e7a87c7d937f1f577990265 100644 (file)
@@ -1,3 +1,10 @@
+2007-04-24  Richard Sandiford  <richard@nildram.co.uk>
+
+       * gcc.target/mips/madd-1.c, gcc.target/mips/madd-2.c,
+       * gcc.target/mips/madd-3.c, gcc.target/mips/madd-4.c,
+       * gcc.target/mips/maddu-1.c, gcc.target/mips/maddu-2.c,
+       * gcc.target/mips/maddu-3.c, gcc.target/mips/maddu-4.c: New tests.
+
 2007-04-23  Simon Baldwin  <simonb@google.com>
 
        * g++.dg/other/error15.C: New.
diff --git a/gcc/testsuite/gcc.target/mips/madd-1.c b/gcc/testsuite/gcc.target/mips/madd-1.c
new file mode 100644 (file)
index 0000000..e522339
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr4130 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmacc\t\\\$1," 3 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return (long long) x * y + z;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  return z + (long long) y * x;
+}
+
+long long
+f3 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/madd-2.c b/gcc/testsuite/gcc.target/mips/madd-2.c
new file mode 100644 (file)
index 0000000..4c761ed
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return (long long) x * y + z;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  return z + (long long) y * x;
+}
+
+long long
+f3 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/madd-3.c b/gcc/testsuite/gcc.target/mips/madd-3.c
new file mode 100644 (file)
index 0000000..6fc30e5
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return (long long) x * y + z;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  return z + (long long) y * x;
+}
+
+long long
+f3 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/madd-4.c b/gcc/testsuite/gcc.target/mips/madd-4.c
new file mode 100644 (file)
index 0000000..28b5534
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmadd\t\\\$ac" 3 } } */
+
+long long
+f1 (int x, int y, long long z)
+{
+  return (long long) x * y + z;
+}
+
+long long
+f2 (int x, int y, long long z)
+{
+  return z + (long long) y * x;
+}
+
+long long
+f3 (int x, int y, long long z)
+{
+  long long t = (long long) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/maddu-1.c b/gcc/testsuite/gcc.target/mips/maddu-1.c
new file mode 100644 (file)
index 0000000..961e49b
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr4130 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmaccu\t\\\$1," 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/maddu-2.c b/gcc/testsuite/gcc.target/mips/maddu-2.c
new file mode 100644 (file)
index 0000000..2add974
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/maddu-3.c b/gcc/testsuite/gcc.target/mips/maddu-3.c
new file mode 100644 (file)
index 0000000..d89c450
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/maddu-4.c b/gcc/testsuite/gcc.target/mips/maddu-4.c
new file mode 100644 (file)
index 0000000..f208713
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
+/* { dg-final { scan-assembler-times "\tmaddu\t\\\$ac" 3 } } */
+
+typedef unsigned int ui;
+typedef unsigned long long ull;
+
+ull
+f1 (ui x, ui y, ull z)
+{
+  return (ull) x * y + z;
+}
+
+ull
+f2 (ui x, ui y, ull z)
+{
+  return z + (ull) y * x;
+}
+
+ull
+f3 (ui x, ui y, ull z)
+{
+  ull t = (ull) x * y;
+  int temp = 5;
+  if (temp == 5)
+    z += t;
+  return z;
+}