diff options
author | Chao-ying Fu <fu@mips.com> | 2007-05-08 22:51:14 +0000 |
---|---|---|
committer | Chao-ying Fu <chaoyingfu@gcc.gnu.org> | 2007-05-08 22:51:14 +0000 |
commit | 14661f36f8ef69c15d8a78a3c0ecbb03611df078 (patch) | |
tree | 4f99bbafe98aff39b7f5885c910746129d4e95e8 /gcc/expr.c | |
parent | 10050f74a3151e7aa333bbbffb38dde95cb5e001 (diff) | |
download | gcc-14661f36f8ef69c15d8a78a3c0ecbb03611df078.zip gcc-14661f36f8ef69c15d8a78a3c0ecbb03611df078.tar.gz gcc-14661f36f8ef69c15d8a78a3c0ecbb03611df078.tar.bz2 |
md.texi (msub@var{m}@var{n}4, [...]): Document.
* doc/md.texi (msub@var{m}@var{n}4, usub@var{m}@var{n}4): Document.
* optabs.h (OTI_smsub_widen, OTI_umsub_widen): New optab_indexes.
(smsub_widen_optab, umsub_widen_optab): Define.
* optabs.c (init_optabs): Initialize smsub_widen_optab and
umsub_widen_optab.
* genopinit.c (optabs): Fill in smsub_widen_optab and
umsub_widen_optab.
* expr.c (expand_expr_real_1): Try to use smsub_widen_optab
and umsub_widen_optab to implement multiply-subtract sequences.
* config/mips/mips.md (*msac<u>_di): Rename to...
(<u>msubsidi4): ...this. Extend condition to include
GENERATE_MADD_MSUB and TARGET_DSPR2. Change the constraint
of operand 0 to "ka" and use the three-operand form of msub<u>
for TARGET_DSPR2.
* config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert
to define_expands.
From-SVN: r124558
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -8133,6 +8133,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1)); case MINUS_EXPR: + /* Check if this is a case for multiplication and subtraction. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR) + { + tree subsubexp0, subsubexp1; + enum tree_code code0, code1; + + subexp1 = TREE_OPERAND (exp, 1); + subsubexp0 = TREE_OPERAND (subexp1, 0); + subsubexp1 = TREE_OPERAND (subexp1, 1); + code0 = TREE_CODE (subsubexp0); + code1 = TREE_CODE (subsubexp1); + if (code0 == NOP_EXPR && code1 == NOP_EXPR + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + < TYPE_PRECISION (TREE_TYPE (subsubexp0))) + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp1, 0)))) + && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp0, 0))) + == TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (subsubexp1, 0))))) + { + tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0)); + enum machine_mode innermode = TYPE_MODE (op0type); + bool zextend_p = TYPE_UNSIGNED (op0type); + this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab; + if (mode == GET_MODE_2XWIDER_MODE (innermode) + && (this_optab->handlers[(int) mode].insn_code + != CODE_FOR_nothing)) + { + expand_operands (TREE_OPERAND (subsubexp0, 0), + TREE_OPERAND (subsubexp1, 0), + NULL_RTX, &op0, &op1, EXPAND_NORMAL); + op2 = expand_expr (TREE_OPERAND (exp, 0), subtarget, + VOIDmode, 0); + temp = expand_ternary_op (mode, this_optab, op0, op1, op2, + target, unsignedp); + gcc_assert (temp); + return REDUCE_BIT_FIELD (temp); + } + } + } + /* For initializers, we are allowed to return a MINUS of two symbolic constants. Here we handle all cases when both operands are constant. */ |