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:
parent
23ffc23579
commit
8b44057d9b
7 changed files with 71 additions and 2 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
40
gcc/expr.c
40
gcc/expr.c
|
@ -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))))
|
||||
|
|
|
@ -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$)",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Add table
Reference in a new issue