aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTorbjorn Granlund <tege@gnu.org>1995-12-17 16:39:58 +0000
committerTorbjorn Granlund <tege@gnu.org>1995-12-17 16:39:58 +0000
commitb10af0c8206f7ff2aefd13b3d7d20accf4c9a33c (patch)
tree2e15ad493ad1e91ed65c980f89a7854ca51b29e3 /gcc
parent97cf2138f807ae2a631f7908227570a5cabfd8ac (diff)
downloadgcc-b10af0c8206f7ff2aefd13b3d7d20accf4c9a33c.zip
gcc-b10af0c8206f7ff2aefd13b3d7d20accf4c9a33c.tar.gz
gcc-b10af0c8206f7ff2aefd13b3d7d20accf4c9a33c.tar.bz2
(expand_expr...
(expand_expr, case MULT_EXPR): Generalize code for widening multiply to handle signed widening multiply when only unsigned optab is defined, and vice versa. From-SVN: r10788
Diffstat (limited to 'gcc')
-rw-r--r--gcc/expr.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index b7860c0..5297ae2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5430,20 +5430,46 @@ expand_expr (exp, target, tmode, modifier)
{
enum machine_mode innermode
= TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
+ optab other_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
+ ? smul_widen_optab : umul_widen_optab);
this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
? umul_widen_optab : smul_widen_optab);
- if (mode == GET_MODE_WIDER_MODE (innermode)
- && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ if (mode == GET_MODE_WIDER_MODE (innermode))
{
- op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
- NULL_RTX, VOIDmode, 0);
- if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
- op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
- VOIDmode, 0);
- else
- op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
- NULL_RTX, VOIDmode, 0);
- goto binop2;
+ if (this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ NULL_RTX, VOIDmode, 0);
+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
+ VOIDmode, 0);
+ else
+ op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
+ NULL_RTX, VOIDmode, 0);
+ goto binop2;
+ }
+ else if (other_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
+ && innermode == word_mode)
+ {
+ rtx htem;
+ op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
+ NULL_RTX, VOIDmode, 0);
+ if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
+ op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
+ VOIDmode, 0);
+ else
+ op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
+ NULL_RTX, VOIDmode, 0);
+ temp = expand_binop (mode, other_optab, op0, op1, target,
+ unsignedp, OPTAB_LIB_WIDEN);
+ htem = expand_mult_highpart_adjust (innermode,
+ gen_highpart (innermode, temp),
+ op0, op1,
+ gen_highpart (innermode, temp),
+ unsignedp);
+ emit_move_insn (gen_highpart (innermode, temp), htem);
+ return temp;
+ }
}
}
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);