OSDN Git Service

* expr.c (expand_expr_real): Use usmul_optab for widening
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Nov 2005 18:49:18 +0000 (18:49 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Nov 2005 18:49:18 +0000 (18:49 +0000)
signed * unsigned multiplies.
* genopinit.c (optabs): Add usmul_widen_optab.
* optabs.c (init_optabs): Likewise.
* optabs.h (enum optab_index): Add OTI_usmul_widen.
(usmul_widen_optab): Define.
* config/bfin/bfin.md (usmulhisi3): New pattern.

* doc/md.texi (usmulqihi3, usmulhisi3, usmulsidi3): Document.

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

gcc/ChangeLog
gcc/config/bfin/bfin.md
gcc/doc/md.texi
gcc/expr.c
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h

index bb1d5ab..b3ab01e 100644 (file)
@@ -1,3 +1,15 @@
+2005-11-20  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+       * expr.c (expand_expr_real): Use usmul_optab for widening
+       signed * unsigned multiplies.
+       * genopinit.c (optabs): Add usmul_widen_optab.
+       * optabs.c (init_optabs): Likewise.
+       * optabs.h (enum optab_index): Add OTI_usmul_widen.
+       (usmul_widen_optab): Define.
+       * config/bfin/bfin.md (usmulhisi3): New pattern.
+
+       * doc/md.texi (usmulqihi3, usmulhisi3, usmulsidi3): Document.
+
 2005-11-20  Graham Stott <btinternet.com>
 
        * gensupport.c (std_preds): Fixed extraneous `false` in last change.
index 494b27e..63fc99c 100644 (file)
   "%0 = %h1 * %h2 (FU);"
   [(set_attr "type" "dsp32")])
 
+(define_insn "usmulhisi3"
+  [(set (match_operand:SI 0 "register_operand" "=W")
+       (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "W"))
+                (sign_extend:SI (match_operand:HI 2 "register_operand" "W"))))]
+  ""
+  "%0 = %h2 * %h1 (IS,M);"
+  [(set_attr "type" "dsp32")])
+
 ;; The processor also supports ireg += mreg or ireg -= mreg, but these
 ;; are unusable if we don't ensure that the corresponding lreg is zero.
 ;; The same applies to the add/subtract constant versions involving
index 087f444..115de4a 100644 (file)
@@ -3125,6 +3125,14 @@ Similar widening-multiplication instructions of other widths.
 Similar widening-multiplication instructions that do unsigned
 multiplication.
 
+@cindex @code{usmulqihi3} instruction pattern
+@cindex @code{usmulhisi3} instruction pattern
+@cindex @code{usmulsidi3} instruction pattern
+@item @samp{usmulqihi3}, @samp{usmulhisi3}, @samp{usmulsidi3}
+Similar widening-multiplication instructions that interpret the first
+operand as unsigned and the second operand as signed, then do a signed
+multiplication.
+
 @cindex @code{smul@var{m}3_highpart} instruction pattern
 @item @samp{smul@var{m}3_highpart}
 Perform a signed multiplication of operands 1 and 2, which have mode
index 13dd782..60582c9 100644 (file)
@@ -6543,7 +6543,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
   optab this_optab;
   rtx subtarget, original_target;
   int ignore;
-  tree context;
+  tree context, subexp0, subexp1;
   bool reduce_bit_field = false;
 #define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore              \
                                 ? reduce_to_bit_field_precision ((expr), \
@@ -7824,7 +7824,43 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         from a narrower type.  If this machine supports multiplying
         in that narrower type with a result in the desired type,
         do it that way, and avoid the explicit type-conversion.  */
-      if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
+
+      subexp0 = TREE_OPERAND (exp, 0);
+      subexp1 = TREE_OPERAND (exp, 1);
+      /* First, check if we have a multiplication of one signed and one
+        unsigned operand.  */
+      if (TREE_CODE (subexp0) == NOP_EXPR
+         && TREE_CODE (subexp1) == NOP_EXPR
+         && TREE_CODE (type) == INTEGER_TYPE
+         && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
+             < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
+         && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
+             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subexp1, 0))))
+         && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0)))
+             != TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp1, 0)))))
+       {
+         enum machine_mode innermode
+           = TYPE_MODE (TREE_TYPE (TREE_OPERAND (subexp0, 0)));
+         this_optab = usmul_widen_optab;
+         if (mode == GET_MODE_WIDER_MODE (innermode))
+           {
+             if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+               {
+                 if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subexp0, 0))))
+                   expand_operands (TREE_OPERAND (subexp0, 0),
+                                    TREE_OPERAND (subexp1, 0),
+                                    NULL_RTX, &op0, &op1, 0);
+                 else
+                   expand_operands (TREE_OPERAND (subexp0, 0),
+                                    TREE_OPERAND (subexp1, 0),
+                                    NULL_RTX, &op1, &op0, 0);
+
+                 goto binop2;
+               }
+           }
+       }
+      /* Check for a multiplication with matching signedness.  */
+      else if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
          && TREE_CODE (type) == INTEGER_TYPE
          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
index 8bf5747..c48d079 100644 (file)
@@ -84,6 +84,7 @@ static const char * const optabs[] =
   "smul_highpart_optab->handlers[$A].insn_code = CODE_FOR_$(smul$a3_highpart$)",
   "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",
   "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 d3e1db6..b10dfa4 100644 (file)
@@ -5010,6 +5010,7 @@ init_optabs (void)
   umul_highpart_optab = init_optab (UNKNOWN);
   smul_widen_optab = init_optab (UNKNOWN);
   umul_widen_optab = init_optab (UNKNOWN);
+  usmul_widen_optab = init_optab (UNKNOWN);
   sdiv_optab = init_optab (DIV);
   sdivv_optab = init_optabv (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
index 582684f..78cf53b 100644 (file)
@@ -82,6 +82,8 @@ enum optab_index
   /* Signed multiply with result one machine mode wider than args */
   OTI_smul_widen,
   OTI_umul_widen,
+  /* Widening multiply of one unsigned and one signed operand.  */
+  OTI_usmul_widen,
 
   /* Signed divide */
   OTI_sdiv,
@@ -268,6 +270,7 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define umul_highpart_optab (optab_table[OTI_umul_highpart])
 #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 sdiv_optab (optab_table[OTI_sdiv])
 #define smulv_optab (optab_table[OTI_smulv])
 #define sdivv_optab (optab_table[OTI_sdivv])