diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2005-11-20 18:49:18 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2005-11-20 18:49:18 +0000 |
commit | 8b44057d9b7417293c2e9fc81bb0f355cabe83b6 (patch) | |
tree | ced326957170072ff9481ff36ed4bba3a5eb7c8e /gcc | |
parent | 23ffc23579daf0e63042a4952ff47317125279dd (diff) | |
download | gcc-8b44057d9b7417293c2e9fc81bb0f355cabe83b6.zip gcc-8b44057d9b7417293c2e9fc81bb0f355cabe83b6.tar.gz gcc-8b44057d9b7417293c2e9fc81bb0f355cabe83b6.tar.bz2 |
expr.c (expand_expr_real): Use usmul_optab for widening signed * unsigned multiplies.
* 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.
From-SVN: r107258
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/config/bfin/bfin.md | 8 | ||||
-rw-r--r-- | gcc/doc/md.texi | 8 | ||||
-rw-r--r-- | gcc/expr.c | 40 | ||||
-rw-r--r-- | gcc/genopinit.c | 1 | ||||
-rw-r--r-- | gcc/optabs.c | 1 | ||||
-rw-r--r-- | gcc/optabs.h | 3 |
7 files changed, 71 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb1d5ab..b3ab01e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 494b27e..63fc99c 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -908,6 +908,14 @@ "%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 diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 087f444..115de4a 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -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 @@ -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)))) diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 8bf5747..c48d079 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -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$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index d3e1db6..b10dfa4 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -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); diff --git a/gcc/optabs.h b/gcc/optabs.h index 582684f..78cf53b 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -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]) |