aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2005-11-20 18:49:18 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2005-11-20 18:49:18 +0000
commit8b44057d9b7417293c2e9fc81bb0f355cabe83b6 (patch)
treeced326957170072ff9481ff36ed4bba3a5eb7c8e /gcc
parent23ffc23579daf0e63042a4952ff47317125279dd (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/config/bfin/bfin.md8
-rw-r--r--gcc/doc/md.texi8
-rw-r--r--gcc/expr.c40
-rw-r--r--gcc/genopinit.c1
-rw-r--r--gcc/optabs.c1
-rw-r--r--gcc/optabs.h3
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
diff --git a/gcc/expr.c b/gcc/expr.c
index 13dd782..60582c9 100644
--- a/gcc/expr.c
+++ b/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))))
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])