This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

genrecog wouldn't emit needed labels within switches


Given the following simplified md file, genrecog will emit a `goto' to
a label that it doesn't emit.  genrecog assumes there are no gotos
into sequences of similar tests that can be reduced to switches, but
this assumption is not valid.  Note that the order of the insn is
relevant, as is the fact that jump_operand (defined below) matches
LABEL_REF but not UNSPEC.  Interestingly, none of the predefined
predicates that match LABEL_REF but not UNSPEC will trigger this
problem, because the predicate evaluation is moved after the switch
for them, so that there's no goto into the switch block.

(define_insn ""
  [(set (pc) (unspec [(const_int 0)] 0))]
  "" "")

(define_insn ""
  [(set (pc) (match_operand:SI 0 "jump_operand" ""))]
  "1" "")

(define_insn ""
  [(set (pc) (label_ref (match_operand 0 "" "")))]
  "" "")


The attached patch arranges for labels to be emitted within the switch
block, as follows (except for the comments):

  switch (GET_CODE (x1))
    {
      case UNSPEC:
        goto ...;
      L10: ATTRIBUTE_UNUSED                    /* These lines */
       if (GET_CODE (x1) == LABEL_REF)         /* are new.    */
      case LABEL_REF:
        goto ...;
      default:
        break;
    }

Index: gcc/genrecog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genrecog.c,v
retrieving revision 1.86
diff -u -p -r1.86 genrecog.c
--- gcc/genrecog.c 2000/09/11 23:54:09 1.86
+++ gcc/genrecog.c 2000/10/16 06:25:37
@@ -190,6 +190,7 @@ static struct pred_table
 #ifdef PREDICATE_CODES
   PREDICATE_CODES
 #endif
+  {"jump_operand", {LABEL_REF, REG}},
   {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
 		       LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
   {"register_operand", {SUBREG, REG}},


Ok to install the following patch?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* genrecog.c (write_switch): Write labels for cases that need
	them.

Index: gcc/genrecog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/genrecog.c,v
retrieving revision 1.86
diff -u -p -r1.86 genrecog.c
--- gcc/genrecog.c 2000/09/11 23:54:09 1.86
+++ gcc/genrecog.c 2000/10/16 06:25:37
@@ -267,7 +268,7 @@ static void print_code
 static void write_afterward
   PARAMS ((struct decision *, struct decision *, const char *));
 static struct decision *write_switch
-  PARAMS ((struct decision *, int));
+  PARAMS ((struct decision *, int, enum routine_type));
 static void write_cond
   PARAMS ((struct decision_test *, int, enum routine_type));
 static void write_action
@@ -1644,9 +1645,10 @@ write_afterward (start, afterward, inden
    nodes at START.  Return the first node yet untested.  */
 
 static struct decision *
-write_switch (start, depth)
+write_switch (start, depth, subroutine_type)
      struct decision *start;
      int depth;
+     enum routine_type subroutine_type;
 {
   struct decision *p = start;
   enum decision_type type = p->tests->type;
@@ -1674,6 +1676,13 @@ write_switch (start, depth)
       code = p->tests->u.code;
       do 
 	{
+	  if (p != start && p->need_label)
+	    {
+	      OUTPUT_LABEL ("    ", p->number);
+	      printf ("      if (");
+	      write_cond (p->tests, depth, subroutine_type);
+	      printf (")\n");
+	    }
 	  printf ("    case ");
 	  print_code (code);
 	  printf (":\n      goto L%d;\n", p->success.first->number);
@@ -1774,6 +1783,13 @@ write_switch (start, depth)
 
       do
 	{
+	  if (p != start && p->need_label)
+	    {
+	      OUTPUT_LABEL ("    ", p->number);
+	      printf ("      if (");
+	      write_cond (p->tests, depth, subroutine_type);
+	      printf (")\n");
+	    }
 	  printf ("    case ");
 	  switch (type)
 	    {
@@ -2056,7 +2072,7 @@ write_tree_1 (head, depth, subroutine_ty
 	OUTPUT_LABEL (" ", p->number);
 
       /* Attempt to write a switch statement for a whole sequence.  */
-      next = write_switch (p, depth);
+      next = write_switch (p, depth, subroutine_type);
       if (p != next)
 	uncond = 0;
       else

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]