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
This commit is contained in:
Bernd Schmidt 2005-11-20 18:49:18 +00:00 committed by Bernd Schmidt
parent 23ffc23579
commit 8b44057d9b
7 changed files with 71 additions and 2 deletions

View 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.

View File

@ -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

View 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

View 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))))

View 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$)",

View 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);

View 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])