Commit 14661f36 by Chao-ying Fu Committed by Chao-ying Fu

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
parent 10050f74
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> 2007-05-08 Kaz Kojima <kkojima@gcc.gnu.org>
PR rtl-optimization/28011 PR rtl-optimization/28011
......
...@@ -162,31 +162,13 @@ ...@@ -162,31 +162,13 @@
(match_operand:DI 1 "register_operand")))] (match_operand:DI 1 "register_operand")))]
"TARGET_DSPR2 && !TARGET_64BIT") "TARGET_DSPR2 && !TARGET_64BIT")
(define_insn "mips_msub" (define_expand "mips_msub<u>"
[(set (match_operand:DI 0 "register_operand" "=a") [(set (match_operand:DI 0 "register_operand")
(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")
(minus:DI (minus:DI
(match_operand:DI 1 "register_operand" "0") (match_operand:DI 1 "register_operand")
(mult:DI (zero_extend:DI (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand"))
(match_operand:SI 2 "register_operand" "d")) (any_extend:DI (match_operand:SI 3 "register_operand")))))]
(zero_extend:DI "TARGET_DSPR2 && !TARGET_64BIT")
(match_operand:SI 3 "register_operand" "d")))))]
"TARGET_DSPR2 && !TARGET_64BIT"
"msubu\t%q0,%2,%3"
[(set_attr "type" "imadd")
(set_attr "mode" "SI")])
(define_insn "mulv2hi3" (define_insn "mulv2hi3"
[(parallel [(parallel
......
...@@ -1649,16 +1649,18 @@ ...@@ -1649,16 +1649,18 @@
[(set_attr "type" "imul") [(set_attr "type" "imul")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "*msac<u>_di" (define_insn "<u>msubsidi4"
[(set (match_operand:DI 0 "register_operand" "=x") [(set (match_operand:DI 0 "register_operand" "=ka")
(minus:DI (minus:DI
(match_operand:DI 3 "register_operand" "0") (match_operand:DI 3 "register_operand" "0")
(mult:DI (mult:DI
(any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "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"; return "msub<u>\t%1,%2";
else else
return "msac<u>\t$0,%1,%2"; return "msac<u>\t$0,%1,%2";
......
...@@ -3687,6 +3687,25 @@ These instructions are not allowed to @code{FAIL}. ...@@ -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 Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication
operands instead of sign-extending them. 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 @cindex @code{divmod@var{m}4} instruction pattern
@item @samp{divmod@var{m}4} @item @samp{divmod@var{m}4}
Signed division that produces both a quotient and a remainder. 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, ...@@ -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)); return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
case MINUS_EXPR: 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 /* For initializers, we are allowed to return a MINUS of two
symbolic constants. Here we handle all cases when both operands symbolic constants. Here we handle all cases when both operands
are constant. */ are constant. */
......
...@@ -87,6 +87,8 @@ static const char * const optabs[] = ...@@ -87,6 +87,8 @@ static const char * const optabs[] =
"usmul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(usmul$a$b3$)$N", "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", "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", "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$)", "sdiv_optab->handlers[$A].insn_code = CODE_FOR_$(div$a3$)",
"sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)", "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)",
"udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)", "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
......
...@@ -5442,6 +5442,8 @@ init_optabs (void) ...@@ -5442,6 +5442,8 @@ init_optabs (void)
usmul_widen_optab = init_optab (UNKNOWN); usmul_widen_optab = init_optab (UNKNOWN);
smadd_widen_optab = init_optab (UNKNOWN); smadd_widen_optab = init_optab (UNKNOWN);
umadd_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); sdiv_optab = init_optab (DIV);
sdivv_optab = init_optabv (DIV); sdivv_optab = init_optabv (DIV);
sdivmod_optab = init_optab (UNKNOWN); sdivmod_optab = init_optab (UNKNOWN);
......
...@@ -92,6 +92,12 @@ enum optab_index ...@@ -92,6 +92,12 @@ enum optab_index
/* Unigned multiply and add with the result and addend one machine mode /* Unigned multiply and add with the result and addend one machine mode
wider than the multiplicand and multiplier. */ wider than the multiplicand and multiplier. */
OTI_umadd_widen, 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 */ /* Signed divide */
OTI_sdiv, OTI_sdiv,
...@@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; ...@@ -317,6 +323,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define usmul_widen_optab (optab_table[OTI_usmul_widen]) #define usmul_widen_optab (optab_table[OTI_usmul_widen])
#define smadd_widen_optab (optab_table[OTI_smadd_widen]) #define smadd_widen_optab (optab_table[OTI_smadd_widen])
#define umadd_widen_optab (optab_table[OTI_umadd_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 sdiv_optab (optab_table[OTI_sdiv])
#define smulv_optab (optab_table[OTI_smulv]) #define smulv_optab (optab_table[OTI_smulv])
#define sdivv_optab (optab_table[OTI_sdivv]) #define sdivv_optab (optab_table[OTI_sdivv])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment