Commit 7f9844ca by Richard Sandiford

2007-xx-xx Chao-ying Fu <fu@mips.com> Richard Sandiford <richard@nildram.co.uk>

gcc/
2007-xx-xx  Chao-ying Fu  <fu@mips.com>
	    Richard Sandiford  <richard@nildram.co.uk>

	* doc/md.texi (madd@var{m}@var{n}4, umadd@var{m}@var{n}4): Document.
	* optabs.h (OTI_smadd_widen, OTI_umadd_widen): New optab_indexes.
	(smadd_widen_optab, umadd_widen_optab): Define.
	* optabs.c (init_optabs): Initialize smadd_widen_optab and
	umadd_widen_optab.
	* genopinit.c (optabs): Fill in smadd_widen_optab and
	umadd_widen_optab.
	* expr.c (expand_expr_real_1): Try to use smadd_widen_optab
	and umadd_widen_optab to implement multiply-add sequences.
	* config/mips/mips.md (*<su>mul_acc_di): Rename to...
	(<u>maddsidi4): ...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 madd<u>
	for TARGET_DSPR2.
	* config/mips/mips-dspr2.md (mips_madd, mips_maddu): Convert
	to define_expands.
	* config/mips/constraints.md (ka): New register constraint.

gcc/testsuite/
2007-xx-xx  Richard Sandiford  <richard@nildram.co.uk>

	* gcc.target/mips/madd-1.c, gcc.target/mips/madd-2.c,
	* gcc.target/mips/madd-3.c, gcc.target/mips/madd-4.c,
	* gcc.target/mips/maddu-1.c, gcc.target/mips/maddu-2.c,
	* gcc.target/mips/maddu-3.c, gcc.target/mips/maddu-4.c: New tests.

From-SVN: r124095
parent ec9ac2bc
2007-04-24 Chao-ying Fu <fu@mips.com>
Richard Sandiford <richard@nildram.co.uk>
* doc/md.texi (madd@var{m}@var{n}4, umadd@var{m}@var{n}4): Document.
* optabs.h (OTI_smadd_widen, OTI_umadd_widen): New optab_indexes.
(smadd_widen_optab, umadd_widen_optab): Define.
* optabs.c (init_optabs): Initialize smadd_widen_optab and
umadd_widen_optab.
* genopinit.c (optabs): Fill in smadd_widen_optab and
umadd_widen_optab.
* expr.c (expand_expr_real_1): Try to use smadd_widen_optab
and umadd_widen_optab to implement multiply-add sequences.
* config/mips/mips.md (*<su>mul_acc_di): Rename to...
(<u>maddsidi4): ...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 madd<u>
for TARGET_DSPR2.
* config/mips/mips-dspr2.md (mips_madd, mips_maddu): Convert
to define_expands.
* config/mips/constraints.md (ka): New register constraint.
2007-04-24 Jan Hubicka <j@suse.cz> 2007-04-24 Jan Hubicka <j@suse.cz>
Revert: Revert:
......
...@@ -78,6 +78,11 @@ ...@@ -78,6 +78,11 @@
(define_register_constraint "D" "COP3_REGS" (define_register_constraint "D" "COP3_REGS"
"@internal") "@internal")
;; Registers that can be used as the target of multiply-accumulate
;; instructions. The core MIPS32 ISA provides a hi/lo madd,
;; but the DSPr2 version allows any accumulator target.
(define_register_constraint "ka" "TARGET_DSPR2 ? ACC_REGS : MD_REGS")
;; Integer constraints ;; Integer constraints
(define_constraint "I" (define_constraint "I"
......
...@@ -154,31 +154,13 @@ ...@@ -154,31 +154,13 @@
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "mips_madd" (define_expand "mips_madd<u>"
[(set (match_operand:DI 0 "register_operand" "=a") [(set (match_operand:DI 0 "register_operand")
(plus:DI (plus:DI
(mult:DI (sign_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")))
(sign_extend:DI (match_operand:DI 1 "register_operand")))]
(match_operand:SI 3 "register_operand" "d"))) "TARGET_DSPR2 && !TARGET_64BIT")
(match_operand:DI 1 "register_operand" "0")))]
"TARGET_DSPR2 && !TARGET_64BIT"
"madd\t%q0,%2,%3"
[(set_attr "type" "imadd")
(set_attr "mode" "SI")])
(define_insn "mips_maddu"
[(set (match_operand:DI 0 "register_operand" "=a")
(plus:DI
(mult:DI (zero_extend:DI
(match_operand:SI 2 "register_operand" "d"))
(zero_extend:DI
(match_operand:SI 3 "register_operand" "d")))
(match_operand:DI 1 "register_operand" "0")))]
"TARGET_DSPR2 && !TARGET_64BIT"
"maddu\t%q0,%2,%3"
[(set_attr "type" "imadd")
(set_attr "mode" "SI")])
(define_insn "mips_msub" (define_insn "mips_msub"
[(set (match_operand:DI 0 "register_operand" "=a") [(set (match_operand:DI 0 "register_operand" "=a")
...@@ -623,4 +605,3 @@ ...@@ -623,4 +605,3 @@
"dpsqx_sa.w.ph\t%q0,%z2,%z3" "dpsqx_sa.w.ph\t%q0,%z2,%z3"
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
...@@ -1767,18 +1767,20 @@ ...@@ -1767,18 +1767,20 @@
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "*<su>mul_acc_di" (define_insn "<u>maddsidi4"
[(set (match_operand:DI 0 "register_operand" "=x") [(set (match_operand:DI 0 "register_operand" "=ka")
(plus:DI (plus:DI
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (mult:DI (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")))
(match_operand:DI 3 "register_operand" "0")))] (match_operand:DI 3 "register_operand" "0")))]
"(TARGET_MAD || ISA_HAS_MACC) "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || TARGET_DSPR2)
&& !TARGET_64BIT" && !TARGET_64BIT"
{ {
if (TARGET_MAD) if (TARGET_MAD)
return "mad<u>\t%1,%2"; return "mad<u>\t%1,%2";
else if (TARGET_MIPS5500) else if (TARGET_DSPR2)
return "madd<u>\t%q0,%1,%2";
else if (GENERATE_MADD_MSUB || TARGET_MIPS5500)
return "madd<u>\t%1,%2"; return "madd<u>\t%1,%2";
else else
/* See comment in *macc. */ /* See comment in *macc. */
......
...@@ -3669,6 +3669,24 @@ The least significant half of the product is discarded. ...@@ -3669,6 +3669,24 @@ The least significant half of the product is discarded.
@item @samp{umul@var{m}3_highpart} @item @samp{umul@var{m}3_highpart}
Similar, but the multiplication is unsigned. Similar, but the multiplication is unsigned.
@cindex @code{madd@var{m}@var{n}4} instruction pattern
@item @samp{madd@var{m}@var{n}4}
Multiply operands 1 and 2, sign-extend them to mode @var{n}, add
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{madd@var{m}@var{n}4} is like
@code{mul@var{m}@var{n}3} except that it also adds operand 3.
These instructions are not allowed to @code{FAIL}.
@cindex @code{umadd@var{m}@var{n}4} instruction pattern
@item @samp{umadd@var{m}@var{n}4}
Like @code{madd@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.
......
...@@ -6824,7 +6824,7 @@ static rtx ...@@ -6824,7 +6824,7 @@ static rtx
expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
enum expand_modifier modifier, rtx *alt_rtl) enum expand_modifier modifier, rtx *alt_rtl)
{ {
rtx op0, op1, temp, decl_rtl; rtx op0, op1, op2, temp, decl_rtl;
tree type; tree type;
int unsignedp; int unsignedp;
enum machine_mode mode; enum machine_mode mode;
...@@ -7977,6 +7977,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -7977,6 +7977,47 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return op0; return op0;
case PLUS_EXPR: case PLUS_EXPR:
/* Check if this is a case for multiplication and addition. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
{
tree subsubexp0, subsubexp1;
enum tree_code code0, code1;
subexp0 = TREE_OPERAND (exp, 0);
subsubexp0 = TREE_OPERAND (subexp0, 0);
subsubexp1 = TREE_OPERAND (subexp0, 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 ? umadd_widen_optab : smadd_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, 1), subtarget,
VOIDmode, 0);
temp = expand_ternary_op (mode, this_optab, op0, op1, op2,
target, unsignedp);
gcc_assert (temp);
return REDUCE_BIT_FIELD (temp);
}
}
}
/* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
something else, make sure we add the register to the constant and something else, make sure we add the register to the constant and
then to the other thing. This case can occur during strength then to the other thing. This case can occur during strength
......
...@@ -85,6 +85,8 @@ static const char * const optabs[] = ...@@ -85,6 +85,8 @@ static const char * const optabs[] =
"smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N", "smul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(mul$a$b3$)$N",
"umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N", "umul_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umul$a$b3$)$N",
"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",
"umadd_widen_optab->handlers[$B].insn_code = CODE_FOR_$(umadd$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$)",
......
...@@ -5439,6 +5439,8 @@ init_optabs (void) ...@@ -5439,6 +5439,8 @@ init_optabs (void)
smul_widen_optab = init_optab (UNKNOWN); smul_widen_optab = init_optab (UNKNOWN);
umul_widen_optab = init_optab (UNKNOWN); umul_widen_optab = init_optab (UNKNOWN);
usmul_widen_optab = init_optab (UNKNOWN); usmul_widen_optab = init_optab (UNKNOWN);
smadd_widen_optab = init_optab (UNKNOWN);
umadd_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);
......
...@@ -86,6 +86,12 @@ enum optab_index ...@@ -86,6 +86,12 @@ enum optab_index
OTI_umul_widen, OTI_umul_widen,
/* Widening multiply of one unsigned and one signed operand. */ /* Widening multiply of one unsigned and one signed operand. */
OTI_usmul_widen, OTI_usmul_widen,
/* Signed multiply and add with the result and addend one machine mode
wider than the multiplicand and multiplier. */
OTI_smadd_widen,
/* Unigned multiply and add with the result and addend one machine mode
wider than the multiplicand and multiplier. */
OTI_umadd_widen,
/* Signed divide */ /* Signed divide */
OTI_sdiv, OTI_sdiv,
...@@ -309,6 +315,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; ...@@ -309,6 +315,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define smul_widen_optab (optab_table[OTI_smul_widen]) #define smul_widen_optab (optab_table[OTI_smul_widen])
#define umul_widen_optab (optab_table[OTI_umul_widen]) #define umul_widen_optab (optab_table[OTI_umul_widen])
#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 umadd_widen_optab (optab_table[OTI_umadd_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])
......
2007-04-24 Richard Sandiford <richard@nildram.co.uk>
* gcc.target/mips/madd-1.c, gcc.target/mips/madd-2.c,
* gcc.target/mips/madd-3.c, gcc.target/mips/madd-4.c,
* gcc.target/mips/maddu-1.c, gcc.target/mips/maddu-2.c,
* gcc.target/mips/maddu-3.c, gcc.target/mips/maddu-4.c: New tests.
2007-04-23 Simon Baldwin <simonb@google.com> 2007-04-23 Simon Baldwin <simonb@google.com>
* g++.dg/other/error15.C: New. * g++.dg/other/error15.C: New.
/* { dg-do compile } */
/* { dg-mips-options "-O2 -march=vr4130 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmacc\t\\\$1," 3 } } */
long long
f1 (int x, int y, long long z)
{
return (long long) x * y + z;
}
long long
f2 (int x, int y, long long z)
{
return z + (long long) y * x;
}
long long
f3 (int x, int y, long long z)
{
long long t = (long long) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
long long
f1 (int x, int y, long long z)
{
return (long long) x * y + z;
}
long long
f2 (int x, int y, long long z)
{
return z + (long long) y * x;
}
long long
f3 (int x, int y, long long z)
{
long long t = (long long) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
long long
f1 (int x, int y, long long z)
{
return (long long) x * y + z;
}
long long
f2 (int x, int y, long long z)
{
return z + (long long) y * x;
}
long long
f3 (int x, int y, long long z)
{
long long t = (long long) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmadd\t\\\$ac" 3 } } */
long long
f1 (int x, int y, long long z)
{
return (long long) x * y + z;
}
long long
f2 (int x, int y, long long z)
{
return z + (long long) y * x;
}
long long
f3 (int x, int y, long long z)
{
long long t = (long long) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -march=vr4130 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmaccu\t\\\$1," 3 } } */
typedef unsigned int ui;
typedef unsigned long long ull;
ull
f1 (ui x, ui y, ull z)
{
return (ull) x * y + z;
}
ull
f2 (ui x, ui y, ull z)
{
return z + (ull) y * x;
}
ull
f3 (ui x, ui y, ull z)
{
ull t = (ull) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -march=vr5500 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
typedef unsigned int ui;
typedef unsigned long long ull;
ull
f1 (ui x, ui y, ull z)
{
return (ull) x * y + z;
}
ull
f2 (ui x, ui y, ull z)
{
return z + (ull) y * x;
}
ull
f3 (ui x, ui y, ull z)
{
ull t = (ull) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
typedef unsigned int ui;
typedef unsigned long long ull;
ull
f1 (ui x, ui y, ull z)
{
return (ull) x * y + z;
}
ull
f2 (ui x, ui y, ull z)
{
return z + (ull) y * x;
}
ull
f3 (ui x, ui y, ull z)
{
ull t = (ull) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
/* { dg-do compile } */
/* { dg-mips-options "-O2 -mips32r2 -mdspr2 -mgp32" } */
/* { dg-final { scan-assembler-times "\tmaddu\t\\\$ac" 3 } } */
typedef unsigned int ui;
typedef unsigned long long ull;
ull
f1 (ui x, ui y, ull z)
{
return (ull) x * y + z;
}
ull
f2 (ui x, ui y, ull z)
{
return z + (ull) y * x;
}
ull
f3 (ui x, ui y, ull z)
{
ull t = (ull) x * y;
int temp = 5;
if (temp == 5)
z += t;
return z;
}
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