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
This commit is contained in:
Chao-ying Fu 2007-05-08 22:51:14 +00:00 committed by Chao-ying Fu
parent 10050f74a3
commit 14661f36f8
8 changed files with 103 additions and 28 deletions

View file

@ -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

View file

@ -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")
(define_expand "mips_msub<u>"
[(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
(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

View file

@ -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";

View file

@ -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.

View file

@ -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. */

View file

@ -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$)",

View file

@ -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);

View file

@ -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])