diff options
author | Torbjorn Granlund <tege@gnu.org> | 1995-12-17 16:39:58 +0000 |
---|---|---|
committer | Torbjorn Granlund <tege@gnu.org> | 1995-12-17 16:39:58 +0000 |
commit | b10af0c8206f7ff2aefd13b3d7d20accf4c9a33c (patch) | |
tree | 2e15ad493ad1e91ed65c980f89a7854ca51b29e3 /gcc | |
parent | 97cf2138f807ae2a631f7908227570a5cabfd8ac (diff) | |
download | gcc-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.c | 48 |
1 files changed, 37 insertions, 11 deletions
@@ -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); |