public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* asm clobbers, !SMALL_REGISTER_CLASSES patch.
@ 1998-02-12 19:36 Geoffrey KEATING
  1998-02-12 20:24 ` David Edelsohn
  0 siblings, 1 reply; 14+ messages in thread
From: Geoffrey KEATING @ 1998-02-12 19:36 UTC (permalink / raw)
  To: egcs; +Cc: David Edelsohn

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

From the earlier discussion about how to avoid problems with asm
clobbers, on machines with small register classes on which
SMALL_REGISTER_CLASSES is not defined, I have produced this patch.

The patch affects all ports.  I believe that it works and is good on
PowerPC/RS6000.  I believe that it has no effect on machines that
don't have any register classes containing only one register, like
sparc.

I have absolutely no idea what effect it will have on machines like
x86.  I'm willing to believe anything from 'stops egcs crashing in
reload and causes better code generation' to the reverse.  Thus, it
needs some testing, preferably on some pieces of code that use lots of
complex asm() statements (c-torture doesn't).

--
Geoff Keating <Geoff.Keating@anu.edu.au>


[-- Attachment #2: egcs-asm-2.diff --]
[-- Type: text/x-diff, Size: 5751 bytes --]

Fri Feb 13 13:48:25 1998  Geoffrey KEATING  <geoffk@ozemail.com.au>

	* stmt.c (expand_asm_operands): When an asm statement
	clobbers a register that is in a class of its own, and there
	is space remaining for an extra output, turn the clobber into
	an output to a dummy pseudo.  At present, don't do this if
	there are constraints that have alternatives.

--- stmt.c.orig-2	Sat Feb  7 18:07:55 1998
+++ stmt.c	Sat Feb  7 19:43:18 1998
@@ -1444,6 +1444,7 @@ expand_asm_operands (string, outputs, in
   int noutputs = list_length (outputs);
   int ninout = 0;
   int nclobbers;
+  int n_promoted_clobbers;
   tree tail;
   register int i;
   /* Vector of RTX's of evaluated output operands.  */
@@ -1453,6 +1454,10 @@ expand_asm_operands (string, outputs, in
     = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
   /* The insn we have emitted.  */
   rtx insn;
+  /* The class letters for each promoted clobber, or '\0' if the clobber
+     won't be promoted.  */
+  char *clobber_class;
+  int constraint_alternatives = 0;
 
   /* An ASM with no outputs needs to be treated as volatile.  */
   if (noutputs == 0)
@@ -1527,12 +1532,16 @@ expand_asm_operands (string, outputs, in
 	    found_equal = 1;
 	    break;
 
+	  case ',':
+	    constraint_alternatives = 1;
+	    break;
+
 	  case '?':  case '!':  case '*':  case '%':  case '&':
 	  case 'V':  case 'm':  case 'o':  case '<':  case '>':
 	  case 'E':  case 'F':  case 'G':  case 'H':  case 'X':
 	  case 's':  case 'i':  case 'n':
 	  case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-	  case 'N':  case 'O':  case 'P':  case ',':
+	  case 'N':  case 'O':  case 'P':
 #ifdef EXTRA_CONSTRAINT
 	  case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':
 #endif
@@ -1609,6 +1618,47 @@ expand_asm_operands (string, outputs, in
       return;
     }
 
+  n_promoted_clobbers = 0;
+  clobber_class = (char *) alloca (nclobbers * sizeof (char));
+  for (i = -1, tail = clobbers; tail; tail = TREE_CHAIN (tail))
+    {
+      char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+      int regno = decode_reg_name (regname);
+
+      if (regno <= 0 && regno != -4)
+	continue;
+
+      clobber_class[++i] = '\0';
+
+      /* We can't promote clobbers to output operands if that produces
+	 too many output operands.  Perhaps we should print a warning
+	 in this case?
+
+	 Also, at present we don't try if the constraints contain commas.
+	 */
+      if (ninputs + noutputs + n_promoted_clobbers >= MAX_RECOG_OPERANDS
+	  || constraint_alternatives)
+	continue;
+
+      if (reg_class_size[REGNO_REG_CLASS(regno)] == 1)
+	{
+	  int class;
+	  if (REGNO_REG_CLASS(regno) == GENERAL_REGS)
+	    {
+	      ++n_promoted_clobbers;
+	      clobber_class[i] = 'r';
+	      continue;
+	    }
+	  for (class = 'a'; class <= 'z'; class++)
+	    if (REG_CLASS_FROM_LETTER(class) == REGNO_REG_CLASS(regno))
+	      {
+		++n_promoted_clobbers;
+		clobber_class[i] = class;
+		break;
+	      }
+	}
+    }
+
   /* Make vectors for the expression-rtx and constraint strings.  */
 
   argvec = rtvec_alloc (ninputs);
@@ -1763,10 +1813,12 @@ expand_asm_operands (string, outputs, in
     }
   else
     {
+      int clobb_counter;
       rtx obody = body;
-      int num = noutputs;
+      int num = noutputs + n_promoted_clobbers;
       if (num == 0) num = 1;
-      body = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num + nclobbers));
+      body = gen_rtx (PARALLEL, VOIDmode,
+		      rtvec_alloc (num + nclobbers - n_promoted_clobbers));
 
       /* For each output operand, store a SET.  */
 
@@ -1783,14 +1835,49 @@ expand_asm_operands (string, outputs, in
 	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
 	}
 
-      /* If there are no outputs (but there are some clobbers)
-	 store the bare ASM_OPERANDS into the PARALLEL.  */
+      /* Store a SET for each promoted clobber.  */
+      
+      clobb_counter = -1;
+      for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
+	{
+	  char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
+	  int regno = decode_reg_name (regname);
+
+	  if (regno <= 0 && regno != -4)
+	    continue;
+
+	  if (clobber_class[++clobb_counter] != '\0')
+	    {
+	      extern struct obstack *rtl_obstack;
+	      char *constraint;
+	      
+	      constraint = obstack_alloc (rtl_obstack, 4);
+	      constraint[0] = '=';
+	      constraint[1] = '&';
+	      constraint[2] = clobber_class[clobb_counter];
+	      constraint[3] = '\0';
+	      XVECEXP (body, 0, i)
+		= gen_rtx (SET, VOIDmode,
+			   gen_reg_rtx(reg_raw_mode[regno]),
+			   gen_rtx (ASM_OPERANDS, VOIDmode,
+				    TREE_STRING_POINTER (string),
+				    constraint,
+				    i, argvec, constraints,
+				    filename, line));
+	      MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
+	      i++;
+	    }
+	}
+
+      /* If there are no outputs or promoted clobbers store the bare
+	 ASM_OPERANDS into the PARALLEL.  */
 
       if (i == 0)
 	XVECEXP (body, 0, i++) = obody;
 
-      /* Store (clobber REG) for each clobbered register specified.  */
+      /* Store (clobber REG) for each non-promoted clobbered register.  */
 
+      clobb_counter = 0;
       for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
 	{
 	  char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
@@ -1807,12 +1894,16 @@ expand_asm_operands (string, outputs, in
 		    = gen_rtx (CLOBBER, VOIDmode,
 			       gen_rtx (MEM, BLKmode,
 					gen_rtx (SCRATCH, VOIDmode, 0)));
+		  clobb_counter++;
 		  continue;
 		}
 
 	      /* Ignore unknown register, error already signalled.  */
 	      continue;
 	    }
+
+	  if (clobber_class[clobb_counter++] != '\0')
+	      continue;
 
 	  /* Use QImode since that's guaranteed to clobber just one reg.  */
 	  XVECEXP (body, 0, i++)

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

end of thread, other threads:[~1998-02-15 18:47 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-02-12 19:36 asm clobbers, !SMALL_REGISTER_CLASSES patch Geoffrey KEATING
1998-02-12 20:24 ` David Edelsohn
1998-02-12 20:24   ` Geoffrey KEATING
1998-02-13  2:28   ` Richard Henderson
1998-02-13 10:34     ` David Edelsohn
1998-02-13 10:58       ` Richard Henderson
1998-02-13 10:58         ` David Edelsohn
1998-02-14 20:23         ` Geoffrey KEATING
1998-02-13  2:28   ` Jeffrey A Law
1998-02-13  2:28     ` Geoffrey KEATING
1998-02-14  0:32       ` Jeffrey A Law
1998-02-14 21:14         ` Geoffrey KEATING
1998-02-15 11:33           ` Jeffrey A Law
1998-02-15 18:47             ` David Edelsohn

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