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 | |
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
-rw-r--r-- | gcc/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/config/mips/mips-dspr2.md | 30 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 10 | ||||
-rw-r--r-- | gcc/doc/md.texi | 19 | ||||
-rw-r--r-- | gcc/expr.c | 41 | ||||
-rw-r--r-- | gcc/genopinit.c | 2 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | 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 <fu@mips.com> + + * 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. + 2007-05-08 Kaz Kojima <kkojima@gcc.gnu.org> 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<u>" + [(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<u>_di" - [(set (match_operand:DI 0 "register_operand" "=x") +(define_insn "<u>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<u>\t%q0,%1,%2"; + else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB) return "msub<u>\t%1,%2"; else return "msac<u>\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. @@ -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]) |