OSDN Git Service

* doc/md.texi (msub@var{m}@var{n}4, usub@var{m}@var{n}4): Document.
authorchaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 May 2007 22:51:14 +0000 (22:51 +0000)
committerchaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 May 2007 22:51:14 +0000 (22:51 +0000)
* optabs.h (OTI_smsub_widen, OTI_umsub_widen): New optab_indexes.
(smsub_widen_optab, umsub_widen_optab): Define.
* optabs.c (init_optabs): Initialize smsub_widen_optab and
umsub_widen_optab.
* genopinit.c (optabs): Fill in smsub_widen_optab and
umsub_widen_optab.
* expr.c (expand_expr_real_1): Try to use smsub_widen_optab
and umsub_widen_optab to implement multiply-subtract sequences.
* config/mips/mips.md (*msac<u>_di): Rename to...
(<u>msubsidi4): ...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 msub<u>
for TARGET_DSPR2.
* config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert
to define_expands.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124558 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
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

index 1d0e905..4c7ba63 100644 (file)
@@ -1,3 +1,22 @@
+2007-05-08  Chao-ying Fu  <fu@mips.com>
+
+       * doc/md.texi (msub@var{m}@var{n}4, usub@var{m}@var{n}4): Document.
+       * optabs.h (OTI_smsub_widen, OTI_umsub_widen): New optab_indexes.
+       (smsub_widen_optab, umsub_widen_optab): Define.
+       * optabs.c (init_optabs): Initialize smsub_widen_optab and
+       umsub_widen_optab.
+       * genopinit.c (optabs): Fill in smsub_widen_optab and
+       umsub_widen_optab.
+       * expr.c (expand_expr_real_1): Try to use smsub_widen_optab
+       and umsub_widen_optab to implement multiply-subtract sequences.
+       * config/mips/mips.md (*msac<u>_di): Rename to...
+       (<u>msubsidi4): ...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 msub<u>
+       for TARGET_DSPR2.
+       * config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert
+       to define_expands.
+
 2007-05-08  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        PR rtl-optimization/28011
index dd0aab5..2019008 100644 (file)
         (match_operand:DI 1 "register_operand")))]
   "TARGET_DSPR2 && !TARGET_64BIT")
 
-(define_insn "mips_msub"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-       (minus:DI
-        (match_operand:DI 1 "register_operand" "0")
-        (mult:DI (sign_extend:DI
-                  (match_operand:SI 2 "register_operand" "d"))
-                 (sign_extend:DI
-                  (match_operand:SI 3 "register_operand" "d")))))]
-  "TARGET_DSPR2 && !TARGET_64BIT"
-  "msub\t%q0,%2,%3"
-  [(set_attr "type"    "imadd")
-   (set_attr "mode"    "SI")])
-
-(define_insn "mips_msubu"
-  [(set (match_operand:DI 0 "register_operand" "=a")
+(define_expand "mips_msub<u>"
+  [(set (match_operand:DI 0 "register_operand")
        (minus:DI
-        (match_operand:DI 1 "register_operand" "0")
-        (mult:DI (zero_extend:DI
-                  (match_operand:SI 2 "register_operand" "d"))
-                 (zero_extend:DI
-                  (match_operand:SI 3 "register_operand" "d")))))]
-  "TARGET_DSPR2 && !TARGET_64BIT"
-  "msubu\t%q0,%2,%3"
-  [(set_attr "type"    "imadd")
-   (set_attr "mode"    "SI")])
+        (match_operand:DI 1 "register_operand")
+        (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
+                 (any_extend:DI (match_operand:SI 3 "register_operand")))))]
+  "TARGET_DSPR2 && !TARGET_64BIT")
 
 (define_insn "mulv2hi3"
   [(parallel
index e44b919..de592b9 100644 (file)
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
 
-(define_insn "*msac<u>_di"
-  [(set (match_operand:DI 0 "register_operand" "=x")
+(define_insn "<u>msubsidi4"
+  [(set (match_operand:DI 0 "register_operand" "=ka")
         (minus:DI
           (match_operand:DI 3 "register_operand" "0")
           (mult:DI
              (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
              (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
-  "!TARGET_64BIT && ISA_HAS_MSAC"
+  "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || TARGET_DSPR2)"
 {
-  if (TARGET_MIPS5500)
+  if (TARGET_DSPR2)
+    return "msub<u>\t%q0,%1,%2";
+  else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB)
     return "msub<u>\t%1,%2";
   else
     return "msac<u>\t$0,%1,%2";
index 56cc60f..53c5769 100644 (file)
@@ -3687,6 +3687,25 @@ These instructions are not allowed to @code{FAIL}.
 Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication
 operands instead of sign-extending them.
 
+@cindex @code{msub@var{m}@var{n}4} instruction pattern
+@item @samp{msub@var{m}@var{n}4}
+Multiply operands 1 and 2, sign-extend them to mode @var{n}, subtract the
+result from 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{msub@var{m}@var{n}4} is like
+@code{mul@var{m}@var{n}3} except that it also subtracts the result
+from operand 3.
+
+These instructions are not allowed to @code{FAIL}.
+
+@cindex @code{umsub@var{m}@var{n}4} instruction pattern
+@item @samp{umsub@var{m}@var{n}4}
+Like @code{msub@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 5a618c9..ce26ba6 100644 (file)
@@ -8133,6 +8133,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
 
     case MINUS_EXPR:
+      /* Check if this is a case for multiplication and subtraction.  */
+      if (TREE_CODE (type) == INTEGER_TYPE
+         && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
+       {
+         tree subsubexp0, subsubexp1;
+         enum tree_code code0, code1;
+
+         subexp1 = TREE_OPERAND (exp, 1);
+         subsubexp0 = TREE_OPERAND (subexp1, 0);
+         subsubexp1 = TREE_OPERAND (subexp1, 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 ? umsub_widen_optab : smsub_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, 0), subtarget,
+                                    VOIDmode, 0);
+                 temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
+                                           target, unsignedp);
+                 gcc_assert (temp);
+                 return REDUCE_BIT_FIELD (temp);
+               }
+           }
+       }
+
       /* For initializers, we are allowed to return a MINUS of two
         symbolic constants.  Here we handle all cases when both operands
         are constant.  */
index 992981a..a137750 100644 (file)
@@ -87,6 +87,8 @@ static const char * const optabs[] =
   "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",
+  "smsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(msub$a$b4$)$N",
+  "umsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umsub$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 b63accc..416c4d4 100644 (file)
@@ -5442,6 +5442,8 @@ init_optabs (void)
   usmul_widen_optab = init_optab (UNKNOWN);
   smadd_widen_optab = init_optab (UNKNOWN);
   umadd_widen_optab = init_optab (UNKNOWN);
+  smsub_widen_optab = init_optab (UNKNOWN);
+  umsub_widen_optab = init_optab (UNKNOWN);
   sdiv_optab = init_optab (DIV);
   sdivv_optab = init_optabv (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
index e5bbef8..60dcc15 100644 (file)
@@ -92,6 +92,12 @@ enum optab_index
   /* Unigned multiply and add with the result and addend one machine mode
      wider than the multiplicand and multiplier.  */
   OTI_umadd_widen,
+  /* Signed multiply and subtract the result and minuend one machine mode
+     wider than the multiplicand and multiplier.  */
+  OTI_smsub_widen,
+  /* Unigned multiply and subtract the result and minuend one machine mode
+     wider than the multiplicand and multiplier.  */
+  OTI_umsub_widen,
 
   /* Signed divide */
   OTI_sdiv,
@@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #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 smsub_widen_optab (optab_table[OTI_smsub_widen])
+#define umsub_widen_optab (optab_table[OTI_umsub_widen])
 #define sdiv_optab (optab_table[OTI_sdiv])
 #define smulv_optab (optab_table[OTI_smulv])
 #define sdivv_optab (optab_table[OTI_sdivv])