public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: "Fu, Chao-Ying" <fu@mips.com>
To: "Richard Sandiford" <richard@codesourcery.com>,
	        "Stephens, Nigel" <nigel@mips.com>
Cc: <gcc@gcc.gnu.org>, "Thekkath, Radhika" <radhika@mips.com>
Subject: RE: [MIPS] MADD issue
Date: Sat, 21 Apr 2007 00:53:00 -0000	[thread overview]
Message-ID: <3CB54817FDF733459B230DD27C690CEC03EE8E54@Exchange.mips.com> (raw)
In-Reply-To: <87ps5zytl5.fsf@firetop.home>

[-- Attachment #1: Type: text/plain, Size: 1931 bytes --]

Hi,

  How about a patch like this to support signed and unsigned
multiplication and addition?  We can extend to MSUB/MSUBU as well.
Thanks!

2007-04-20  Chao-ying Fu  <fu@mips.com>

	* optabs.c (init_optabs): Initialize smadd_widen_optab and umadd_widen_optab.
	* optabs.h (optab_index): Add OTI_smadd_widen and OTI_umadd_widen.
	(smadd_widen_optab, umadd_widen_optab): Define.
	* genopinit.c (optabs): Add smadd_widen_optab and usmadd_widen_optab.
	* expr.c (expand_expr_real_1): Add rtx of op2.
	Process PLUS_EXPR to generate multiplication and add instructions.
	* config/mips/mips-dspr2.md (maddsidi4, umaddsidi4): New patterns.

Ex: (bug72.c)
long long t1 (int a, int b, long long c)
{
  return (long long)a * b + c;
}

unsigned long long t2 (unsigned int a, unsigned int b, unsigned long long c)
{
  return (unsigned long long)a * b + c;
}

# <812> ~/dev/gcc4x/install32/bin/mipsisa32r2-elf-gcc -S -mdspr2 bug72.c -O

t1:
        mtlo    $7
        mthi    $6
        madd    $ac0,$5,$4
        mflo    $7
        mfhi    $6
        move    $2,$6
        j       $31
        move    $3,$7

t2:
        mtlo    $7
        mthi    $6
        maddu   $ac0,$5,$4
        mflo    $7
        mfhi    $6
        move    $2,$6
        j       $31
        move    $3,$7

Regards,
Chao-ying

> -----Original Message-----
> From: gcc-owner@gcc.gnu.org [mailto:gcc-owner@gcc.gnu.org]On Behalf Of
> Richard Sandiford
> Sent: Friday, April 20, 2007 8:05 AM
> To: Stephens, Nigel
> Cc: Fu, Chao-Ying; gcc@gcc.gnu.org; Thekkath, Radhika
> Subject: Re: [MIPS] MADD issue
> 
> 
> Nigel Stephens <nigel@mips.com> writes:
> > OK, so maybe as the person who removed adddi3 from the MIPS 
> backend, and 
> > the main  proponent of the new fused opcodes, you get to 
> volunteer to 
> > implement this? :)
> 
> Hey, I was pretty happy with the status quo ;)
> 
> Richard
> 

[-- Attachment #2: gcc.diff --]
[-- Type: application/octet-stream, Size: 6730 bytes --]

Index: optabs.c
===================================================================
--- optabs.c	(revision 123998)
+++ optabs.c	(working copy)
@@ -5439,6 +5439,8 @@
   smul_widen_optab = init_optab (UNKNOWN);
   umul_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);
   sdivv_optab = init_optabv (DIV);
   sdivmod_optab = init_optab (UNKNOWN);
Index: optabs.h
===================================================================
--- optabs.h	(revision 123998)
+++ optabs.h	(working copy)
@@ -86,6 +86,10 @@
   OTI_umul_widen,
   /* Widening multiply of one unsigned and one signed operand.  */
   OTI_usmul_widen,
+  /* Signed multiply and add with result one machine mode wider than args */
+  OTI_smadd_widen,
+  /* Unigned multiply and add with result one machine mode wider than args */
+  OTI_umadd_widen,
 
   /* Signed divide */
   OTI_sdiv,
@@ -307,6 +311,8 @@
 #define smul_widen_optab (optab_table[OTI_smul_widen])
 #define umul_widen_optab (optab_table[OTI_umul_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 smulv_optab (optab_table[OTI_smulv])
 #define sdivv_optab (optab_table[OTI_sdivv])
Index: genopinit.c
===================================================================
--- genopinit.c	(revision 123998)
+++ genopinit.c	(working copy)
@@ -85,6 +85,8 @@
   "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",
   "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$)",
   "sdivv_optab->handlers[$A].insn_code = CODE_FOR_$(div$V$I$a3$)",
   "udiv_optab->handlers[$A].insn_code = CODE_FOR_$(udiv$I$a3$)",
Index: expr.c
===================================================================
--- expr.c	(revision 123998)
+++ expr.c	(working copy)
@@ -6824,7 +6824,7 @@
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 		    enum expand_modifier modifier, rtx *alt_rtl)
 {
-  rtx op0, op1, temp, decl_rtl;
+  rtx op0, op1, op2, temp, decl_rtl;
   tree type;
   int unsignedp;
   enum machine_mode mode;
@@ -7977,6 +7977,80 @@
       return op0;
 
     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)
+	{
+	  subexp0 = TREE_OPERAND (exp, 0);
+	  tree subsubexp0 = TREE_OPERAND (subexp0, 0);
+	  tree subsubexp1 = TREE_OPERAND (subexp0, 1);
+	  enum tree_code code0 = TREE_CODE (subsubexp0);
+	  enum tree_code 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 (subsubexp1, 0)))
+		 < TYPE_PRECISION (TREE_TYPE (subsubexp1))
+	      && 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)
+		{
+		  int icode = this_optab->handlers[(int) mode].insn_code;
+		  enum machine_mode target_mode, mode0, mode1, mode2;
+		  rtx xop0, xop1, xop2;
+		  rtx last, pat, temp;
+
+		  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);
+		  target_mode = insn_data[icode].operand[0].mode;
+		  mode0 = insn_data[icode].operand[1].mode;
+		  mode1 = insn_data[icode].operand[2].mode;
+		  mode2 = insn_data[icode].operand[3].mode;
+		  xop0 = op0;
+		  xop1 = op1;
+		  xop2 = op2;
+		  last = get_last_insn ();
+
+		  if (target && modifier != EXPAND_STACK_PARM)
+		    temp = target;
+		  else
+		    temp = gen_reg_rtx (mode);
+
+		  if (!insn_data[icode].operand[0].predicate (temp,
+							      target_mode))
+		    temp = gen_reg_rtx (target_mode);
+		  if (!insn_data[icode].operand[1].predicate (xop0, mode0)
+		      && mode0 != VOIDmode)
+		    xop0 = copy_to_mode_reg (mode0, xop0);
+		  if (!insn_data[icode].operand[2].predicate (xop1, mode1)
+		      && mode1 != VOIDmode)
+		    xop1 = copy_to_mode_reg (mode1, xop1);
+		  if (!insn_data[icode].operand[3].predicate (xop2, mode2)
+		      && mode2 != VOIDmode)
+		    xop2 = copy_to_mode_reg (mode2, xop2);
+		  pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
+		  if (pat)
+		    {
+		      emit_insn (pat);
+		      return REDUCE_BIT_FIELD (temp);
+		    }
+		  else
+		    delete_insns_since (last);
+		}
+	    }
+	}
+
+
       /* 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
 	 then to the other thing.  This case can occur during strength
Index: config/mips/mips-dspr2.md
===================================================================
--- config/mips/mips-dspr2.md	(revision 123998)
+++ config/mips/mips-dspr2.md	(working copy)
@@ -624,3 +624,29 @@
   [(set_attr "type"	"imadd")
    (set_attr "mode"	"SI")])
 
+(define_insn "maddsidi4"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(plus:DI
+	 (mult:DI (sign_extend:DI
+		   (match_operand:SI 1 "register_operand" "d"))
+		  (sign_extend:DI
+		   (match_operand:SI 2 "register_operand" "d")))
+	 (match_operand:DI 3 "register_operand" "0")))]
+  "TARGET_DSPR2 && !TARGET_64BIT"
+  "madd\t%q0,%1,%2"
+  [(set_attr "type"	"imadd")
+   (set_attr "mode"	"SI")])
+
+(define_insn "umaddsidi4"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(plus:DI
+	 (mult:DI (zero_extend:DI
+		   (match_operand:SI 1 "register_operand" "d"))
+		  (zero_extend:DI
+		   (match_operand:SI 2 "register_operand" "d")))
+	 (match_operand:DI 3 "register_operand" "0")))]
+  "TARGET_DSPR2 && !TARGET_64BIT"
+  "maddu\t%q0,%1,%2"
+  [(set_attr "type"	"imadd")
+   (set_attr "mode"	"SI")])
+

  reply	other threads:[~2007-04-20 23:59 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-13  0:26 Fu, Chao-Ying
2007-04-13 13:07 ` Paolo Bonzini
2007-04-13 17:05   ` Ian Lance Taylor
2007-04-13 18:10     ` Paolo Bonzini
2007-04-13 18:33       ` Richard Sandiford
2007-04-13 14:25 ` Richard Sandiford
2007-04-13 15:23   ` Nigel Stephens
2007-04-13 15:34     ` Richard Sandiford
2007-04-13 16:19       ` Nigel Stephens
2007-04-20 14:32       ` Nigel Stephens
2007-04-20 14:44         ` Richard Sandiford
2007-04-20 15:05           ` Nigel Stephens
2007-04-20 16:38             ` Richard Sandiford
2007-04-21  0:53               ` Fu, Chao-Ying [this message]
2007-04-20 16:46           ` Ian Lance Taylor
2007-04-20 16:57             ` Richard Sandiford
2007-04-20 17:00               ` Ian Lance Taylor
2007-04-20 17:06                 ` Richard Sandiford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3CB54817FDF733459B230DD27C690CEC03EE8E54@Exchange.mips.com \
    --to=fu@mips.com \
    --cc=gcc@gcc.gnu.org \
    --cc=nigel@mips.com \
    --cc=radhika@mips.com \
    --cc=richard@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).