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]

Fix PR17513


Hi,

This bug was introduced by the transparent cfg expand patch from
a couple of months ago.  In the tree CFG, we have a flag
EDGE_EXECUTABLE which is set on edges that are executable. This
flag does not have any meaning in the RTL cfg, so cfgexpand has
to clear it on all edges.

But we overlooked a few edges...

The EDGE_EXECUTABLE flag is cleared in epand_gimple_basic_block
by clearing the flag on all edges of the block that is being
expanded.  But we obviously never try to expand ENTRY_BLOCK_PTR,
and so we forgot to clear EDGE_EXECUTABLE on all successors of
the entry block.

This lead to an RTL flow verification error after gcse, which
apparently does a lot of magic with edge splitting and so on, and
one way or another the EDGE_EXECUTABLE flag migrated from an edge
out of the entry block to the edge out of the first "real" basic
block.  This resulte in a miscomputation of the number of outgoing
edges of basic block 0, since in the following,

          if ((e->flags & ~(EDGE_DFS_BACK
                            | EDGE_CAN_FALLTHRU
                            | EDGE_IRREDUCIBLE_LOOP
                            | EDGE_LOOP_EXIT
                            | EDGE_CROSSING)) == 0)
            n_branch++;

n_branch is not incremented if EDGE_EXECUTABLE is set on e->flags.

Fixed by clearing the flag on edges out of ENTRY_BLOCK_PTR in
cfgexpand.c as in the attached patch.

I've bootstrapped the patch on x86_64-unknown-linux-gnu, testing
is in progress.  OK if it passes?

Gr.
Steven

Index: cfgexpand.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgexpand.c,v
retrieving revision 2.23
diff -c -3 -p -r2.23 cfgexpand.c
*** cfgexpand.c	11 Sep 2004 20:07:11 -0000	2.23
--- cfgexpand.c	16 Sep 2004 08:58:33 -0000
*************** static basic_block
*** 1082,1092 ****
  construct_init_block (void)
  {
    basic_block init_block, first_block;
!   edge e;
  
!   for (e = ENTRY_BLOCK_PTR->succ; e; e = e->succ_next)
!     if (e->dest == ENTRY_BLOCK_PTR->next_bb)
!       break;
  
    init_block = create_basic_block (NEXT_INSN (get_insns ()),
  				   get_last_insn (),
--- 1082,1102 ----
  construct_init_block (void)
  {
    basic_block init_block, first_block;
!   edge e = NULL, e2;
  
!   for (e2 = ENTRY_BLOCK_PTR->succ; e2; e2 = e2->succ_next)
!     {
!       /* Clear EDGE_EXECUTABLE.  This flag is never used in the backend.
! 
! 	 For all other blocks this edge flag is cleared while expanding
! 	 a basic block in expand_gimple_basic_block, but there we never
! 	 looked at the successors of the entry block.
! 	 This caused PR17513.  */
!       e2->flags &= ~EDGE_EXECUTABLE;
! 
!       if (e2->dest == ENTRY_BLOCK_PTR->next_bb)
! 	e = e2;
!     }
  
    init_block = create_basic_block (NEXT_INSN (get_insns ()),
  				   get_last_insn (),
Index: testsuite/gcc.dg/20040916-1.c
===================================================================
RCS file: testsuite/gcc.dg/20040916-1.c
diff -N testsuite/gcc.dg/20040916-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/20040916-1.c	16 Sep 2004 08:58:35 -0000
***************
*** 0 ****
--- 1,43 ----
+ /* { dg-do compile } */
+ /* PR17513 - we hit a bug where EDGE_EXECUTABLE was not cleared on
+    successors of the entry block.  This lead to a flow verification
+    error much later in the compilation (after gcse).  */
+ typedef unsigned char uint8; 
+ typedef unsigned int uint32; 
+  
+ uint32 marker = 0; 
+ uint8 *buff = 0; 
+ uint32 bsize = 0; 
+  
+ extern int foo (void); 
+  
+ uint32 
+ bar (void) 
+ { 
+   int len, d; 
+  
+   for (;;) 
+     { 
+       if (foo () == 0) 
+         return (0); 
+  
+       switch (marker) 
+         { 
+         case 0xfe: 
+           { 
+             len |= (*buff++); 
+             bsize -= 2; 
+  
+             while (len > 0) 
+               { 
+                 d = *buff++; 
+                 len--; 
+               } 
+           } 
+           break; 
+         default: 
+           break; 
+         } 
+     } 
+ } 
+ 


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