diff options
author | Richard Sandiford <rsandifo@gcc.gnu.org> | 2007-04-24 05:51:57 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2007-04-24 05:51:57 +0000 |
commit | 7f9844caf1ebd513d8720afa3ce857fada9e94c6 (patch) | |
tree | 414ebf4e011654eddd3531c3e652690d778992c9 /gcc/expr.c | |
parent | ec9ac2bc429d48bfd2466d56ddea4244ebfba990 (diff) | |
download | gcc-7f9844caf1ebd513d8720afa3ce857fada9e94c6.zip gcc-7f9844caf1ebd513d8720afa3ce857fada9e94c6.tar.gz gcc-7f9844caf1ebd513d8720afa3ce857fada9e94c6.tar.bz2 |
2007-xx-xx Chao-ying Fu <fu@mips.com> Richard Sandiford <richard@nildram.co.uk>
gcc/
2007-xx-xx Chao-ying Fu <fu@mips.com>
Richard Sandiford <richard@nildram.co.uk>
* doc/md.texi (madd@var{m}@var{n}4, umadd@var{m}@var{n}4): Document.
* optabs.h (OTI_smadd_widen, OTI_umadd_widen): New optab_indexes.
(smadd_widen_optab, umadd_widen_optab): Define.
* optabs.c (init_optabs): Initialize smadd_widen_optab and
umadd_widen_optab.
* genopinit.c (optabs): Fill in smadd_widen_optab and
umadd_widen_optab.
* expr.c (expand_expr_real_1): Try to use smadd_widen_optab
and umadd_widen_optab to implement multiply-add sequences.
* config/mips/mips.md (*<su>mul_acc_di): Rename to...
(<u>maddsidi4): ...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 madd<u>
for TARGET_DSPR2.
* config/mips/mips-dspr2.md (mips_madd, mips_maddu): Convert
to define_expands.
* config/mips/constraints.md (ka): New register constraint.
gcc/testsuite/
2007-xx-xx Richard Sandiford <richard@nildram.co.uk>
* gcc.target/mips/madd-1.c, gcc.target/mips/madd-2.c,
* gcc.target/mips/madd-3.c, gcc.target/mips/madd-4.c,
* gcc.target/mips/maddu-1.c, gcc.target/mips/maddu-2.c,
* gcc.target/mips/maddu-3.c, gcc.target/mips/maddu-4.c: New tests.
From-SVN: r124095
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 43 |
1 files changed, 42 insertions, 1 deletions
@@ -6824,7 +6824,7 @@ static rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, enum expand_modifier modifier, rtx *alt_rtl) { - rtx op0, op1, temp, decl_rtl; + rtx op0, op1, op2, temp, decl_rtl; tree type; int unsignedp; enum machine_mode mode; @@ -7977,6 +7977,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, return op0; case PLUS_EXPR: + /* Check if this is a case for multiplication and addition. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR) + { + tree subsubexp0, subsubexp1; + enum tree_code code0, code1; + + subexp0 = TREE_OPERAND (exp, 0); + subsubexp0 = TREE_OPERAND (subexp0, 0); + subsubexp1 = TREE_OPERAND (subexp0, 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 ? umadd_widen_optab : smadd_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, 1), subtarget, + VOIDmode, 0); + temp = expand_ternary_op (mode, this_optab, op0, op1, op2, + target, unsignedp); + gcc_assert (temp); + return REDUCE_BIT_FIELD (temp); + } + } + } + /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and something else, make sure we add the register to the constant and then to the other thing. This case can occur during strength |