Blame SOURCES/gcc32-tablejump-cleanup.patch

6f1b0c
2005-01-03  Jakub Jelinek  <jakub@redhat.com>
6f1b0c
6f1b0c
	* cfgrtl.c (try_redirect_by_replacing_jump): Add 2 arguments to
6f1b0c
	tablejump_p.
6f1b0c
6f1b0c
	* gcc.c-torture/compile/20050103-1.c: New test.
6f1b0c
6f1b0c
2003-07-20  Josef Zlomek  <zlomekj@suse.cz>
6f1b0c
6f1b0c
	* cfgcleanup.c (merge_blocks_move_successor_nojumps): Use tablejump_p.
6f1b0c
	* ifcvt.c (find_if_block): Added 2 arguments to tablejump_p.
6f1b0c
	* jump.c (tablejump_p): Added 2 arguments.
6f1b0c
	* rtl.h (tablejump_p): Likewise.
6f1b0c
6f1b0c
--- gcc/rtl.h.jj	2003-06-11 14:58:17.000000000 +0200
6f1b0c
+++ gcc/rtl.h	2005-01-03 17:32:46.113937897 +0100
6f1b0c
@@ -1793,7 +1793,7 @@ extern rtx pc_set			PARAMS ((rtx));
6f1b0c
 extern rtx condjump_label		PARAMS ((rtx));
6f1b0c
 extern int simplejump_p			PARAMS ((rtx));
6f1b0c
 extern int returnjump_p			PARAMS ((rtx));
6f1b0c
-extern int tablejump_p			PARAMS ((rtx));
6f1b0c
+extern int tablejump_p			PARAMS ((rtx, rtx *, rtx *));
6f1b0c
 extern int onlyjump_p			PARAMS ((rtx));
6f1b0c
 extern int only_sets_cc0_p		PARAMS ((rtx));
6f1b0c
 extern int sets_cc0_p			PARAMS ((rtx));
6f1b0c
--- gcc/cfgrtl.c.jj	2003-04-08 15:50:58.000000000 +0200
6f1b0c
+++ gcc/cfgrtl.c	2005-01-03 17:37:59.150837447 +0100
6f1b0c
@@ -674,7 +674,7 @@ try_redirect_by_replacing_jump (e, targe
6f1b0c
   if (tmp || !onlyjump_p (insn))
6f1b0c
     return false;
6f1b0c
 
6f1b0c
-  if ((!optimize || flow2_completed) && tablejump_p (insn))
6f1b0c
+  if ((!optimize || flow2_completed) && tablejump_p (insn, NULL, NULL))
6f1b0c
     return false;
6f1b0c
 
6f1b0c
   /* Avoid removing branch with side effects.  */
6f1b0c
--- gcc/cfgcleanup.c.jj	2003-08-02 01:18:22.000000000 +0200
6f1b0c
+++ gcc/cfgcleanup.c	2005-01-03 17:32:10.010407336 +0100
6f1b0c
@@ -691,25 +691,20 @@ merge_blocks_move_successor_nojumps (a, 
6f1b0c
      basic_block a, b;
6f1b0c
 {
6f1b0c
   rtx barrier, real_b_end;
6f1b0c
+  rtx label, table;
6f1b0c
 
6f1b0c
   real_b_end = b->end;
6f1b0c
-  barrier = NEXT_INSN (b->end);
6f1b0c
 
6f1b0c
-  /* Recognize a jump table following block B.  */
6f1b0c
-  if (barrier
6f1b0c
-      && GET_CODE (barrier) == CODE_LABEL
6f1b0c
-      && NEXT_INSN (barrier)
6f1b0c
-      && GET_CODE (NEXT_INSN (barrier)) == JUMP_INSN
6f1b0c
-      && (GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_VEC
6f1b0c
-	  || GET_CODE (PATTERN (NEXT_INSN (barrier))) == ADDR_DIFF_VEC))
6f1b0c
+  /* If there is a jump table following block B temporarily add the jump table
6f1b0c
+     to block B so that it will also be moved to the correct location.  */
6f1b0c
+  if (tablejump_p (b->end, &label, &table)
6f1b0c
+      && prev_active_insn (label) == b->end)
6f1b0c
     {
6f1b0c
-      /* Temporarily add the table jump insn to b, so that it will also
6f1b0c
-	 be moved to the correct location.  */
6f1b0c
-      b->end = NEXT_INSN (barrier);
6f1b0c
-      barrier = NEXT_INSN (b->end);
6f1b0c
+      b->end = table;
6f1b0c
     }
6f1b0c
 
6f1b0c
   /* There had better have been a barrier there.  Delete it.  */
6f1b0c
+  barrier = NEXT_INSN (b->end);
6f1b0c
   if (barrier && GET_CODE (barrier) == BARRIER)
6f1b0c
     delete_insn (barrier);
6f1b0c
 
6f1b0c
--- gcc/jump.c.jj	2003-08-01 22:38:45.000000000 +0200
6f1b0c
+++ gcc/jump.c	2005-01-03 17:36:59.744484787 +0100
6f1b0c
@@ -1099,20 +1099,32 @@ simplejump_p (insn)
6f1b0c
 	  && GET_CODE (SET_DEST (PATTERN (insn))) == PC
6f1b0c
 	  && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
6f1b0c
 }
6f1b0c
-/* Return 1 if INSN is an tablejump.  */
6f1b0c
+
6f1b0c
+/* If INSN is a tablejump return 1 and store the label (before jump table) to
6f1b0c
+   *LABELP and the jump table to *TABLEP.  LABELP and TABLEP may be NULL.  */
6f1b0c
 
6f1b0c
 int
6f1b0c
-tablejump_p (insn)
6f1b0c
+tablejump_p (insn, labelp, tablep)
6f1b0c
      rtx insn;
6f1b0c
+     rtx *labelp;
6f1b0c
+     rtx *tablep;
6f1b0c
 {
6f1b0c
-  rtx table;
6f1b0c
-  return (GET_CODE (insn) == JUMP_INSN
6f1b0c
-	  && JUMP_LABEL (insn)
6f1b0c
-	  && NEXT_INSN (JUMP_LABEL (insn))
6f1b0c
-	  && (table = next_active_insn (JUMP_LABEL (insn)))
6f1b0c
-	  && GET_CODE (table) == JUMP_INSN
6f1b0c
-	  && (GET_CODE (PATTERN (table)) == ADDR_VEC
6f1b0c
-	      || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC));
6f1b0c
+  rtx label, table;
6f1b0c
+  
6f1b0c
+  if (GET_CODE (insn) == JUMP_INSN
6f1b0c
+      && (label = JUMP_LABEL (insn)) != NULL_RTX
6f1b0c
+      && (table = next_active_insn (label)) != NULL_RTX
6f1b0c
+      && GET_CODE (table) == JUMP_INSN
6f1b0c
+      && (GET_CODE (PATTERN (table)) == ADDR_VEC
6f1b0c
+	  || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
6f1b0c
+    {
6f1b0c
+      if (labelp)
6f1b0c
+	*labelp = label;
6f1b0c
+      if (tablep)
6f1b0c
+	*tablep = table;
6f1b0c
+      return 1;
6f1b0c
+    }
6f1b0c
+  return 0;
6f1b0c
 }
6f1b0c
 
6f1b0c
 /* Return nonzero if INSN is a (possibly) conditional jump
6f1b0c
--- gcc/ifcvt.c.jj	2003-03-25 17:42:24.000000000 +0100
6f1b0c
+++ gcc/ifcvt.c	2005-01-03 17:32:10.012406978 +0100
6f1b0c
@@ -2046,7 +2046,7 @@ find_if_block (test_bb, then_edge, else_
6f1b0c
   if (then_succ != NULL_EDGE
6f1b0c
       && (then_succ->succ_next != NULL_EDGE
6f1b0c
           || (then_succ->flags & EDGE_COMPLEX)
6f1b0c
-	  || (flow2_completed && tablejump_p (then_bb->end))))
6f1b0c
+	  || (flow2_completed && tablejump_p (then_bb->end, NULL, NULL))))
6f1b0c
     return FALSE;
6f1b0c
 
6f1b0c
   /* If the THEN block has no successors, conditional execution can still
6f1b0c
@@ -2094,7 +2094,7 @@ find_if_block (test_bb, then_edge, else_
6f1b0c
 	   && else_bb->pred->pred_next == NULL_EDGE
6f1b0c
 	   && else_succ->succ_next == NULL_EDGE
6f1b0c
 	   && ! (else_succ->flags & EDGE_COMPLEX)
6f1b0c
-	   && ! (flow2_completed && tablejump_p (else_bb->end)))
6f1b0c
+	   && ! (flow2_completed && tablejump_p (else_bb->end, NULL, NULL)))
6f1b0c
     join_bb = else_succ->dest;
6f1b0c
 
6f1b0c
   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
6f1b0c
--- gcc/testsuite/gcc.c-torture/compile/20050103-1.c.jj	2004-12-09 13:34:01.422415552 +0100
6f1b0c
+++ gcc/testsuite/gcc.c-torture/compile/20050103-1.c	2005-01-03 15:21:18.146431991 +0100
6f1b0c
@@ -0,0 +1,83 @@
6f1b0c
+extern void abort (void);
6f1b0c
+
6f1b0c
+struct S
6f1b0c
+{
6f1b0c
+  char *s1;
6f1b0c
+  int s2;
6f1b0c
+};
6f1b0c
+struct T
6f1b0c
+{
6f1b0c
+  int t1;
6f1b0c
+  struct S *t2;
6f1b0c
+} *s1;
6f1b0c
+
6f1b0c
+extern int bar (const struct T *, unsigned int, unsigned int,
6f1b0c
+		const struct T *, unsigned int, unsigned int);
6f1b0c
+
6f1b0c
+extern inline void *
6f1b0c
+baz (void *x, const void *y, unsigned int z)
6f1b0c
+{
6f1b0c
+  unsigned char *s1 = x;
6f1b0c
+  const unsigned char *s2 = y;
6f1b0c
+
6f1b0c
+  if (z > 4 || __builtin_constant_p (z))
6f1b0c
+    __builtin_memcpy (x, y, z);
6f1b0c
+  else
6f1b0c
+    switch (z)
6f1b0c
+      {
6f1b0c
+      case 4:
6f1b0c
+	s1[3] = s2[3];
6f1b0c
+      case 3:
6f1b0c
+	s1[2] = s2[2];
6f1b0c
+      case 2:
6f1b0c
+	s1[1] = s2[1];
6f1b0c
+      case 1:
6f1b0c
+	s1[0] = s2[0];
6f1b0c
+      case 0:
6f1b0c
+	break;
6f1b0c
+      }
6f1b0c
+
6f1b0c
+  return x;
6f1b0c
+}
6f1b0c
+
6f1b0c
+extern inline int
6f1b0c
+foo (struct T *b, unsigned int x, const void *y, unsigned int z)
6f1b0c
+{
6f1b0c
+  if (!b || !z)
6f1b0c
+    return 0;
6f1b0c
+  if (x == b->t1)
6f1b0c
+    {
6f1b0c
+      struct S *r = b->t2;
6f1b0c
+      baz (r->s1 + r->s2, y, z);
6f1b0c
+      return 1;
6f1b0c
+    }
6f1b0c
+
6f1b0c
+  return 0;
6f1b0c
+}
6f1b0c
+
6f1b0c
+int
6f1b0c
+test (struct T *a, struct T *b, struct T *c, struct T *d)
6f1b0c
+{
6f1b0c
+  if (!a)
6f1b0c
+    abort ();
6f1b0c
+  if (!b)
6f1b0c
+    abort ();
6f1b0c
+
6f1b0c
+  if (bar (a, 1, a->t1, b, 1, b->t1) > 0)
6f1b0c
+    abort ();
6f1b0c
+  if (bar (a, 41, a->t1 - 40, b, 1, b->t1) > 0)
6f1b0c
+    abort ();
6f1b0c
+
6f1b0c
+  if (!c)
6f1b0c
+    abort ();
6f1b0c
+  if (!d)
6f1b0c
+    abort ();
6f1b0c
+
6f1b0c
+  if (bar (c, 1, c->t1, d, 1, d->t1) < 0)
6f1b0c
+    abort ();
6f1b0c
+  if (bar (c, 41, c->t1 - 40, d, 1, d->t1) < 0)
6f1b0c
+    abort ();
6f1b0c
+
6f1b0c
+  foo (s1, 0, "abcd", 4);
6f1b0c
+  return 0;
6f1b0c
+}