public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch] 1/2 Expand sync_sub as sync_add if predicates don't match.
@ 2007-08-20 16:46 David Daney
  2007-08-20 17:06 ` [Patch] 2/2 MIPS atomic memory operations David Daney
  2007-08-21  9:02 ` [Patch] 1/2 Expand sync_sub as sync_add if predicates don't match Richard Sandiford
  0 siblings, 2 replies; 14+ messages in thread
From: David Daney @ 2007-08-20 16:46 UTC (permalink / raw)
  To: GCC Patches; +Cc: Richard Sandiford

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

While implementing the atomic memory operations for MIPS, I came across 
a problem where immediate operands were forced into a register when 
sync_sub* insns were expanded.  On MIPS there is no minus instruction 
for immediate operands, instead this should be expanded as plus with the 
negative value of the immediate operand.

In expand_sync_operation() and expand_sync_fetch_operation() there is 
code to handle conversion to plus if the minus insn does not exits.  I 
enhanced this slightly so that it also does the conversion if the 
predicate for sync_sub* does not match, but it does match for the 
corresponding sync_add*.  This allows me to write sync_sub* insns with a 
register predicate and have them used for non-immediate operands, but an 
immediate operand results in conversion to sync_add*.

Tested on x86_64-pc-linux-gnu all default languages both native and -m32 
with no regressions.  Also tested mips64-linux C only.

:ADDPATCH middle-end:

OK to commit?

2007-08-20  David Daney  <ddaney@avtrex.com>

    * optabs.c (expand_sync_operation):  Use plus insn if minus insn
    predicate does not match val.
    (expand_sync_fetch_operation):  Ditto.


[-- Attachment #2: optabs.diff --]
[-- Type: text/x-patch, Size: 2688 bytes --]

Index: optabs.c
===================================================================
--- optabs.c	(revision 127356)
+++ optabs.c	(working copy)
@@ -6420,7 +6420,7 @@ rtx
 expand_sync_operation (rtx mem, rtx val, enum rtx_code code)
 {
   enum machine_mode mode = GET_MODE (mem);
-  enum insn_code icode;
+  enum insn_code icode, plus_icode;
   rtx insn;
 
   /* Look to see if the target supports the operation directly.  */
@@ -6444,9 +6444,17 @@ expand_sync_operation (rtx mem, rtx val,
 
     case MINUS:
       icode = sync_sub_optab[mode];
-      if (icode == CODE_FOR_nothing)
+      plus_icode = sync_add_optab[mode];
+
+      /* Change sign and add either if there is no insn for MINUS, or
+         if the MINUS insn cannot directly handle VAL and the PLUS
+         insn can.  */
+      if (icode == CODE_FOR_nothing
+          || (!insn_data[icode].operand[1].predicate (val, mode)
+              && plus_icode != CODE_FOR_nothing
+              && insn_data[plus_icode].operand[1].predicate (val, mode)))
 	{
-	  icode = sync_add_optab[mode];
+          icode = plus_icode;
 	  if (icode != CODE_FOR_nothing)
 	    {
 	      val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);
@@ -6513,7 +6521,7 @@ expand_sync_fetch_operation (rtx mem, rt
 			     bool after, rtx target)
 {
   enum machine_mode mode = GET_MODE (mem);
-  enum insn_code old_code, new_code, icode;
+  enum insn_code old_code, new_code, plus_old_code, plus_new_code, icode;
   bool compensate;
   rtx insn;
 
@@ -6544,10 +6552,20 @@ expand_sync_fetch_operation (rtx mem, rt
     case MINUS:
       old_code = sync_old_sub_optab[mode];
       new_code = sync_new_sub_optab[mode];
-      if (old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
+      plus_old_code = sync_old_add_optab[mode];
+      plus_new_code = sync_new_add_optab[mode];
+
+      /* Change sign and add either if there are no insns for MINUS, or
+         if the MINUS insns cannot directly handle VAL and the PLUS
+         insns can.  */
+      if ((old_code == CODE_FOR_nothing && new_code == CODE_FOR_nothing)
+          || (after && !insn_data[new_code].operand[1].predicate (val, mode)
+              && insn_data[plus_new_code].operand[1].predicate (val, mode))
+          || (!after && !insn_data[old_code].operand[1].predicate (val, mode)
+              && insn_data[plus_old_code].operand[1].predicate (val, mode)))
 	{
-	  old_code = sync_old_add_optab[mode];
-	  new_code = sync_new_add_optab[mode];
+          old_code = plus_old_code;
+          new_code = plus_new_code;
 	  if (old_code != CODE_FOR_nothing || new_code != CODE_FOR_nothing)
 	    {
 	      val = expand_simple_unop (mode, NEG, val, NULL_RTX, 1);

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2007-09-09 11:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-20 16:46 [Patch] 1/2 Expand sync_sub as sync_add if predicates don't match David Daney
2007-08-20 17:06 ` [Patch] 2/2 MIPS atomic memory operations David Daney
2007-08-21  9:02   ` Richard Sandiford
2007-09-03  6:02     ` David Daney
2007-09-03  8:30       ` Richard Sandiford
2007-09-03  9:39   ` Maxim Kuvyrkov
2007-09-03 15:35     ` Richard Sandiford
2007-09-06 21:33   ` David Daney
2007-08-21  9:02 ` [Patch] 1/2 Expand sync_sub as sync_add if predicates don't match Richard Sandiford
2007-08-22  6:47   ` David Daney
2007-08-24  0:41     ` David Daney
2007-09-05 18:16       ` Ping: " David Daney
2007-09-09 11:23         ` Ping^3: use sync_add rather than sync_sub for CONST_INTs Richard Sandiford
2007-09-09 13:47           ` Richard Guenther

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