summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-20 18:49:18 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2005-11-20 18:49:18 +0000
commit8f0c8a8b1d184a7d759f6736cddd5d7a485a908b (patch)
treeced326957170072ff9481ff36ed4bba3a5eb7c8e /gcc/expr.c
parent77f8ffcbeff911eeb82431db33383c102ee556a5 (diff)
downloadgcc-8f0c8a8b1d184a7d759f6736cddd5d7a485a908b.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@107258 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 13dd782588e..60582c91db6 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))))