clobber problems [Was: Re: Reload patch version 3]

Geoff Keating geoffk@ozemail.com.au
Thu Sep 3 05:25:00 GMT 1998


> Date: Tue, 1 Sep 1998 15:56:45 +0200 (MET DST)
> From: Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

> Couldn't you write 'asm ("" : "=&x" : )' instead to show the compiler that
> CR0 is clobbered? This should have the same effect.

I get `parse error'.  I made, some time ago, a patch to egcs to allow
this syntax, which I attach here in the hope that someone will improve
it and put it in the distribution.  The main target for improvement
would be the function `choose_constraint_mode', which as you can see
could do with some help. The tricky bit is that it is not clear what
of size of operand is being requested, which is of course the problem
in the first place; you can't write 'asm ("" : "=&x"(foo))' because
there is no 4-bit-wide type to use in declaring 'foo'.

I think the code gets it right when the constraint specifies a
register or several registers which hold similar sizes.  Constraints
like 'm' or 'X' will never work very well, nor would you expect them to;
but I'm not sure what, if anything, should be done about constraints
like 'rx' that specify registers of different sizes.

-- 
Geoffrey Keating <geoffk@ozemail.com.au>

===File ~/patches/egcs-asm-1.diff===========================
--- gcc/c-parse.in.orig	Sat Feb  7 14:11:46 1998
+++ gcc/c-parse.in	Sat Feb  7 14:04:25 1998
@@ -2204,6 +2204,8 @@ nonnull_asm_operands:
 asm_operand:
 	  STRING '(' expr ')'
 		{ $$ = build_tree_list ($1, $3); }
+	| STRING
+		{ $$ = build_tree_list ($1, NULL_TREE); }
 	;
 
 asm_clobbers:
--- gcc/c-typeck.c.orig	Sat Sep 27 13:46:33 1997
+++ gcc/c-typeck.c	Fri Feb  6 23:50:00 1998
@@ -6519,7 +6519,7 @@ c_expand_asm_operands (string, outputs, 
 	}
       /* Detect modification of read-only values.
 	 (Otherwise done by build_modify_expr.)  */
-      else
+      else if (o[i] != NULL_TREE)
 	{
 	  tree type = TREE_TYPE (o[i]);
 	  if (TREE_READONLY (o[i])
--- gcc/stmt.c.orig	Fri Feb  6 21:25:08 1998
+++ gcc/stmt.c	Sat Feb  7 14:03:09 1998
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-config.h"
 #include "insn-codes.h"
 #include "expr.h"
+#include "regs.h"
 #include "hard-reg-set.h"
 #include "obstack.h"
 #include "loop.h"
@@ -1383,6 +1384,38 @@ expand_asm (body)
   last_expr_type = 0;
 }
 
+/* Choose a mode that might be suitable for a constraint.
+   If the constraint is too tricky, this can get it wrong.  */
+static enum machine_mode
+choose_constraint_mode(constraint)
+     char *constraint;
+{
+  for (;;)
+    switch (*constraint++)
+      {
+      case '\0': case ',':
+	/* Wild guess.  This is why you shouldn't use this facility
+	   to (for instance) provide a memory location.  */
+	return byte_mode;
+      case 'r': case 'g':
+	/* Assume that general registers can at least hold a byte.  */
+	return byte_mode;
+      default:
+	{
+	  enum reg_class class = REG_CLASS_FROM_LETTER (constraint[-1]);
+	  int regno;
+
+	  if (class == NO_REGS)
+	    continue;
+
+	  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+	    if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))
+	      return reg_raw_mode[regno];
+	  continue;
+	}
+      }
+}
+
 /* Generate RTL for an asm statement with arguments.
    STRING is the instruction template.
    OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
@@ -1455,15 +1488,18 @@ expand_asm_operands (string, outputs, in
   for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
     {
       tree val = TREE_VALUE (tail);
-      tree type = TREE_TYPE (val);
+      tree type;
       tree val1;
       int j;
       int found_equal = 0;
       int found_plus = 0;
       int allows_reg = 0;
 
+      if (val != NULL_TREE)
+	type = TREE_TYPE (val);
+
       /* If there's an erroneous arg, emit no insn.  */
-      if (TREE_TYPE (val) == error_mark_node)
+      if (val != NULL_TREE && type == error_mark_node)
 	return;
 
       /* Make sure constraint has `=' and does not have `+'.  Also, see
@@ -1519,17 +1555,29 @@ expand_asm_operands (string, outputs, in
 	  return;
 	}
 
+      if (found_plus && val == NULL_TREE)
+	{
+	  error ("inout operand to `asm' should have value");
+	  return;
+	}
       /* If an output operand is not a decl or indirect ref and our constraint
 	 allows a register, make a temporary to act as an intermediate.
 	 Make the asm insn write into that, then our caller will copy it to
-	 the real output operand.  Likewise for promoted variables.  */
+	 the real output operand.  Likewise for promoted variables,
+	 and for when we ignore the output (but then we don't want to have
+	 the caller copy it anywhere).  */
 
-      if (TREE_CODE (val) == INDIRECT_REF
-	  || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
-	      && ! (GET_CODE (DECL_RTL (val)) == REG
-		    && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
-	  || ! allows_reg
-	  || found_plus)
+      if (val == NULL_TREE)
+	{
+	  char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
+	  output_rtx[i] = gen_reg_rtx (choose_constraint_mode(constraint));
+	}
+      else if (TREE_CODE (val) == INDIRECT_REF
+	       || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
+		   && ! (GET_CODE (DECL_RTL (val)) == REG
+			 && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
+	       || ! allows_reg
+	       || found_plus)
 	{
 	  if (! allows_reg)
 	    mark_addressable (TREE_VALUE (tail));
@@ -1579,6 +1627,13 @@ expand_asm_operands (string, outputs, in
     {
       int j;
       int allows_reg = 0;
+
+      /* Null inputs make little sense.  */
+      if (TREE_VALUE (tail) == NULL_TREE)
+	{
+	  error ("input operand to `asm' should have value");
+	  return;
+	}
 
       /* If there's an erroneous arg, emit no insn,
 	 because the ASM_INPUT would get VOIDmode
--- gcc/cp/parse.y.orig	Sat Feb  7 14:12:50 1998
+++ gcc/cp/parse.y	Sat Feb  7 14:12:33 1998
@@ -4065,6 +4065,8 @@ nonnull_asm_operands:
 asm_operand:
 	  STRING '(' expr ')'
 		{ $$ = build_tree_list ($$, $3); }
+	| STRING
+		{ $$ = build_tree_list ($1, NULL_TREE); }
 	;
 
 asm_clobbers:
--- gcc/ChangeLog~	Sun Jan 25 00:35:52 1998
+++ gcc/ChangeLog	Sat Feb  7 14:21:05 1998
@@ -1,3 +1,12 @@
+Fri Feb  6 22:15:24 1998  Geoff Keating  (geoffk@ozemail.com.au)
+
+	* c-parse.in (asm_operand): Add new `ignore output' syntax.
+	* c-typeck.c (c_expand_asm_operands): If we are ignoring the
+	output, don't copy it anywhere.
+	* stmt.c (choose_constraint_mode): New function.
+	(expand_asm_operands): Handle `ignore output' syntax by creating a
+	dummy pseudo to output to.
+
 Fri Jan  2 23:40:09 1998  Jim Wilson  (wilson@cygnus.com)
 			  Jeffrey A Law  (law@cygnus.com)
 
--- gcc/cp/ChangeLog~	Sun Jan 25 00:36:04 1998
+++ gcc/cp/ChangeLog	Sat Feb  7 14:21:35 1998
@@ -1,3 +1,7 @@
+Fri Feb  6 22:21:27 1998  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* parse.y (asm_operand): Add new `ignore output' syntax.
+
 Sat Dec 20 13:00:30 1997  Jason Merrill  <jason@yorick.cygnus.com>
 
 	* pt.c (instantiate_decl): Defer all templates but inline functions.
--- gcc/extend.texi.orig	Sat Feb  7 14:50:39 1998
+++ gcc/extend.texi	Sat Feb  7 15:33:02 1998
@@ -2430,6 +2430,28 @@
 and therefore they cannot take account of them when deciding how to
 optimize.
 
+In some of these more complex @code{asm} statements, you need temporary
+registers.  You could just choose a register at random (and specify it
+as clobbered), but it is usually better to instead make the temporary an
+`output' of the @code{asm}; that way the register allocator can pick the
+most convenient temporary.  There is a special syntax to simplify using
+such temporaries: if you omit the C expression specifying the output
+destination, the output will be ignored.  For instance, the following
+example implements test-and-set on RS6000, using a temporary
+condition code register:
+
+@example
+asm volatile("0:  lwarx %0,0,%3;"
+             "    cmpwi %1,%0,0;"
+             "    bne %1,1f;"
+             "    stwcx. %4,0,%3;"
+             "    bne- 0b;"
+             "1: "
+     : "=&r"(oldvalue), "=y", "=x"
+     : "r"(address), "r"(1)
+     : "memory");
+@end example
+
 @cindex macros containing @code{asm}
 Usually the most convenient way to use these @code{asm} instructions is to
 encapsulate them in macros that look like functions.  For example,
============================================================



More information about the Gcc-patches mailing list