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]
Other format: [Raw text]

[PATCH] Expand unreachable WHILE_STMTs like DO_STMTs.


The following patch should fix the failure of gcc.dg/duff-2.c on
all platforms.  This regression is caused by unreachable RTL between
the switch statement and the first case label.  This is caused by
GCC's RTL expansion routines that attempt to rotate while loops, so
that normally we initially unconditionally jump to the loop condition
at the bottom of the loop.  This unconditional jump occurs before
the loop label and is therefore always unreachable, which triggers
the unexpected warning.

The solution is to realize that if the start of the while loop is
unreachable, there's no need/advantage to rotate it, and instead
the construct can be expanded as a do-loop.  Indeed, the behaviour
of Duff's device is identical when implemented as either a do loop
or as a while loop.

Fortunately, my recent patch to introduce expand_unreachable_stmt
provides the perfect mechanism to solve this problem, avoiding the
current bogus warning and producing better initial RTL.


The following patch has been tested on i686-pc-linux-gnu with a
complete bootstrap, all languages except treelang (including Ada),
and regression tested with a top-level "make -k check" with no
new failures.

Ok for mainline?


2003-05-28  Roger Sayle  <roger@eyesopen.com>

	* c-semantics.c (expand_unreachable_while_stmt): New function
	to generate RTL for an unreachable while statement.
	(expand_unreachable_stmt):  Use it to handle WHILE_STMT.

	* gcc.dg/duff-4.c: New test case.


Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.61
diff -c -3 -p -r1.61 c-semantics.c
*** c-semantics.c	17 May 2003 22:21:25 -0000	1.61
--- c-semantics.c	27 May 2003 19:21:28 -0000
*************** void (*lang_expand_decl_stmt) PARAMS ((t
*** 54,61 ****

  static tree find_reachable_label_1	PARAMS ((tree *, int *, void *));
  static tree find_reachable_label	PARAMS ((tree));
! static bool expand_unreachable_if_stmt	PARAMS ((tree));
! static tree expand_unreachable_stmt	PARAMS ((tree, int));

  /* Create an empty statement tree rooted at T.  */

--- 54,62 ----

  static tree find_reachable_label_1	PARAMS ((tree *, int *, void *));
  static tree find_reachable_label	PARAMS ((tree));
! static bool expand_unreachable_if_stmt		PARAMS ((tree));
! static void expand_unreachable_while_stmt	PARAMS ((tree));
! static tree expand_unreachable_stmt		PARAMS ((tree, int));

  /* Create an empty statement tree rooted at T.  */

*************** expand_unreachable_if_stmt (t)
*** 1001,1006 ****
--- 1002,1056 ----
    return n != NULL_TREE;
  }

+ /* Expand an unreachable while statement, T.  If the start of a
+    WHILE_STMT is unreachable, there's no reason to rotate the loop
+    and it can be treated like a DO_STMT.  */
+
+ static void
+ expand_unreachable_while_stmt (t)
+     tree t;
+ {
+   tree cond = WHILE_COND (t);
+
+   if (find_reachable_label (cond) != NULL_TREE)
+     {
+       genrtl_while_stmt (t);
+       return;
+     }
+
+   if (!cond || integer_zerop (cond))
+     {
+       expand_start_null_loop ();
+       expand_stmt (WHILE_BODY (t));
+       expand_end_null_loop ();
+     }
+   else if (integer_nonzerop (cond))
+     {
+       emit_nop ();
+       emit_line_note (input_filename, input_line);
+       expand_start_loop (1);
+
+       expand_stmt (WHILE_BODY (t));
+
+       emit_line_note (input_filename, input_line);
+       expand_end_loop ();
+     }
+   else
+     {
+       emit_nop ();
+       emit_line_note (input_filename, input_line);
+       expand_start_loop_continue_elsewhere (1);
+
+       expand_stmt (WHILE_BODY (t));
+
+       expand_loop_continue_here ();
+       cond = expand_cond (cond);
+       emit_line_note (input_filename, input_line);
+       expand_exit_loop_if_false (0, cond);
+       expand_end_loop ();
+     }
+ }
+
  /* Expand an unreachable statement list.  This function skips all
     statements preceding the first potentially reachable label and
     then returns the label (or, in same cases, the statement after
*************** expand_unreachable_stmt (t, warn)
*** 1058,1063 ****
--- 1108,1117 ----
  	  if (expand_unreachable_if_stmt (t))
  	    return TREE_CHAIN (t);
  	  break;
+
+ 	case WHILE_STMT:
+ 	  expand_unreachable_while_stmt (t);
+ 	  return TREE_CHAIN (t);

  	case COMPOUND_STMT:
  	  {


/* Duff's device is legal C; test to make sure the compiler
   doesn't complain about it.

   Roger Sayle <roger@eyesopen.com>
   Derived from duff-2.c.  */

/* { dg-do run } */
/* { dg-options "-O2" } */

extern void abort (void);
extern void exit (int);

#if __INT_MAX__ >= 2147483647
/* At least 32-bit integers. */
typedef int type32;
#else
typedef long type32;
#endif

type32
cksum (const unsigned char *src, unsigned long size)
{
  type32 ck = 0;

  switch (size & 3)
    {
    do
      {
    case 0:
	ck ^= (type32)*src++ << 24;
	--size;
    case 3:
	ck ^= (type32)*src++ << 16;
	--size;
    case 2:
	ck ^= (type32)*src++ << 8;
	--size;
    case 1:
	ck ^= (type32)*src++;
	--size;
      }
    while (size > 0);
    }

  return ck;
}

const char testpat[] = "The quick brown fox jumped over the lazy dog.";

int
main()
{
  type32 ck;

  ck = cksum ((const unsigned char *) testpat, sizeof (testpat));
  if (ck != 925902908)
    abort ();

  exit (0);
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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