From 14661f36f8ef69c15d8a78a3c0ecbb03611df078 Mon Sep 17 00:00:00 2001 From: Chao-ying Fu Date: Tue, 8 May 2007 22:51:14 +0000 Subject: 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_di): Rename to... (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 for TARGET_DSPR2. * config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert to define_expands. From-SVN: r124558 --- gcc/ChangeLog | 19 +++++++++++++++++++ gcc/config/mips/mips-dspr2.md | 30 ++++++------------------------ gcc/config/mips/mips.md | 10 ++++++---- gcc/doc/md.texi | 19 +++++++++++++++++++ gcc/expr.c | 41 +++++++++++++++++++++++++++++++++++++++++ gcc/genopinit.c | 2 ++ gcc/optabs.c | 2 ++ gcc/optabs.h | 8 ++++++++ 8 files changed, 103 insertions(+), 28 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d0e905..4c7ba63 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2007-05-08 Chao-ying Fu + + * 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_di): Rename to... + (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 + for TARGET_DSPR2. + * config/mips/mips-dspr2.md (mips_msub, mips_msubu): Convert + to define_expands. + 2007-05-08 Kaz Kojima PR rtl-optimization/28011 diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md index dd0aab5..2019008 100644 --- a/gcc/config/mips/mips-dspr2.md +++ b/gcc/config/mips/mips-dspr2.md @@ -162,31 +162,13 @@ (match_operand:DI 1 "register_operand")))] "TARGET_DSPR2 && !TARGET_64BIT") -(define_insn "mips_msub" - [(set (match_operand:DI 0 "register_operand" "=a") - (minus:DI - (match_operand:DI 1 "register_operand" "0") - (mult:DI (sign_extend:DI - (match_operand:SI 2 "register_operand" "d")) - (sign_extend:DI - (match_operand:SI 3 "register_operand" "d")))))] - "TARGET_DSPR2 && !TARGET_64BIT" - "msub\t%q0,%2,%3" - [(set_attr "type" "imadd") - (set_attr "mode" "SI")]) - -(define_insn "mips_msubu" - [(set (match_operand:DI 0 "register_operand" "=a") +(define_expand "mips_msub" + [(set (match_operand:DI 0 "register_operand") (minus:DI - (match_operand:DI 1 "register_operand" "0") - (mult:DI (zero_extend:DI - (match_operand:SI 2 "register_operand" "d")) - (zero_extend:DI - (match_operand:SI 3 "register_operand" "d")))))] - "TARGET_DSPR2 && !TARGET_64BIT" - "msubu\t%q0,%2,%3" - [(set_attr "type" "imadd") - (set_attr "mode" "SI")]) + (match_operand:DI 1 "register_operand") + (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) + (any_extend:DI (match_operand:SI 3 "register_operand")))))] + "TARGET_DSPR2 && !TARGET_64BIT") (define_insn "mulv2hi3" [(parallel diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index e44b919..de592b9 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1649,16 +1649,18 @@ [(set_attr "type" "imul") (set_attr "mode" "SI")]) -(define_insn "*msac_di" - [(set (match_operand:DI 0 "register_operand" "=x") +(define_insn "msubsidi4" + [(set (match_operand:DI 0 "register_operand" "=ka") (minus:DI (match_operand:DI 3 "register_operand" "0") (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] - "!TARGET_64BIT && ISA_HAS_MSAC" + "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || TARGET_DSPR2)" { - if (TARGET_MIPS5500) + if (TARGET_DSPR2) + return "msub\t%q0,%1,%2"; + else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB) return "msub\t%1,%2"; else return "msac\t$0,%1,%2"; diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 56cc60f..53c5769 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3687,6 +3687,25 @@ These instructions are not allowed to @code{FAIL}. Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication operands instead of sign-extending them. +@cindex @code{msub@var{m}@var{n}4} instruction pattern +@item @samp{msub@var{m}@var{n}4} +Multiply operands 1 and 2, sign-extend them to mode @var{n}, subtract the +result from operand 3, and store the result in operand 0. Operands 1 and 2 +have mode @var{m} and operands 0 and 3 have mode @var{n}. +Both modes must be integer modes and @var{n} must be twice +the size of @var{m}. + +In other words, @code{msub@var{m}@var{n}4} is like +@code{mul@var{m}@var{n}3} except that it also subtracts the result +from operand 3. + +These instructions are not allowed to @code{FAIL}. + +@cindex @code{umsub@var{m}@var{n}4} instruction pattern +@item @samp{umsub@var{m}@var{n}4} +Like @code{msub@var{m}@var{n}4}, but zero-extend the multiplication +operands instead of sign-extending them. + @cindex @code{divmod@var{m}4} instruction pattern @item @samp{divmod@var{m}4} Signed division that produces both a quotient and a remainder. diff --git a/gcc/expr.c b/gcc/expr.c index 5a618c9..ce26ba6 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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. */ diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 992981a..a137750 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -87,6 +87,8 @@ static const char * const optabs[] = "usmul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(usmul$a$b3$)$N", "smadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(madd$a$b4$)$N", "umadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umadd$a$b4$)$N", + "smsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(msub$a$b4$)$N", + "umsub_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umsub$a$b4$)$N", "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)", "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)", "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index b63accc..416c4d4 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5442,6 +5442,8 @@ init_optabs (void) usmul_widen_optab = init_optab (UNKNOWN); smadd_widen_optab = init_optab (UNKNOWN); umadd_widen_optab = init_optab (UNKNOWN); + smsub_widen_optab = init_optab (UNKNOWN); + umsub_widen_optab = init_optab (UNKNOWN); sdiv_optab = init_optab (DIV); sdivv_optab = init_optabv (DIV); sdivmod_optab = init_optab (UNKNOWN); diff --git a/gcc/optabs.h b/gcc/optabs.h index e5bbef8..60dcc15 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -92,6 +92,12 @@ enum optab_index /* Unigned multiply and add with the result and addend one machine mode wider than the multiplicand and multiplier. */ OTI_umadd_widen, + /* Signed multiply and subtract the result and minuend one machine mode + wider than the multiplicand and multiplier. */ + OTI_smsub_widen, + /* Unigned multiply and subtract the result and minuend one machine mode + wider than the multiplicand and multiplier. */ + OTI_umsub_widen, /* Signed divide */ OTI_sdiv, @@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define usmul_widen_optab (optab_table[OTI_usmul_widen]) #define smadd_widen_optab (optab_table[OTI_smadd_widen]) #define umadd_widen_optab (optab_table[OTI_umadd_widen]) +#define smsub_widen_optab (optab_table[OTI_smsub_widen]) +#define umsub_widen_optab (optab_table[OTI_umsub_widen]) #define sdiv_optab (optab_table[OTI_sdiv]) #define smulv_optab (optab_table[OTI_smulv]) #define sdivv_optab (optab_table[OTI_sdivv]) -- cgit v1.1