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:
parent
10050f74a3
commit
14661f36f8
8 changed files with 103 additions and 28 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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.
|
||||
|
|
41
gcc/expr.c
41
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. */
|
||||
|
|
|
@ -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$)",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Add table
Reference in a new issue