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 threading bug with computed gotos


The pass reorganization I've been working on exposed a bug in the
jump threader that causes an ICE in gcc.dg/tree-ssa/20030821-1.c.
The IL is now sufficiently cleaned up, that we ICE in DOM1
because of this bug.

This test case reproduces the ICE in today's mainline:

-----------------------------------------------------------------------------
void bar (int k)
{
  void *label = (k) ? &&x : &&y;
  if (k)
    goto *label;

x:
  if (k)
    dont_remove ();
y:
  return;
}

$ ./cc1 -O1 thread-bug.c
 bar

thread-bug.c: In function 'bar':
thread-bug.c:2: internal compiler error: in tree_redirect_edge_and_branch, at tree-cfg.c:4549
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
-----------------------------------------------------------------------------

The problem is that we try to redirect the edges on a block that
ends in a GOTO_EXPR:

-----------------------------------------------------------------------------
bar (k)
{
  [ ... ]
  # BLOCK 8
  # PRED:
<L12>:;
  goto <bb 5> (<L6>);
  # SUCC: 5 (fallthru)
}
-----------------------------------------------------------------------------

Jeff had suggested looking at create_block_for_threading because
that's where we remove the control statements at the end of
blocks.  However, when block 8 is created, the original block
looks like this:

-----------------------------------------------------------------------------
;; basic block 8, loop depth 0, count 0
;; prev block 7, next block -2
;; pred:
;; succ:       5 (true,exec) 6 (false,exec)
<bb 8>:
if (k_2 != 0) goto <L6>; else goto y;
-----------------------------------------------------------------------------

When we later get to redirect_edges, the block has been changed to:

-----------------------------------------------------------------------------
;; basic block 8, loop depth 0, count 0
;; prev block 7, next block -2
;; pred:
;; succ:       5 (fallthru)
<L12>:;
goto <bb 5> (<L6>);
-----------------------------------------------------------------------------

I am not sure what transforms the block into this, but I also
don't think it's doing the wrong thing.  What I did is copy the
call to remove_ctrl_stmt_and_useless_edges from
create_block_for_threading into redirect_edges.

My vague notion is that we also need to remove the useless
expressions right before redirecting the edges to account for
optimizations we may have done on the duplicate block.

Jeff, I don't really know if I am fixing or papering over the
problem.  Is this right?

With this patch, the test now works and DOM1 converts it into:

bar (k)
{
  if (k_2 != 0) goto <L2>; else goto <L11>;

  # label_1 = PHI <&x(0)>;
<L2>:;
  goto label_1;

x:;
<L6>:;
  dont_remove ();

y:;
<L9>:;
  return;

  # label_4 = PHI <&y(0)>;
<L11>:;
}


Bootstrap/testing in progress.


Thanks.  Diego.

Index: tree-ssa-threadupdate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-threadupdate.c,v
retrieving revision 2.25
diff -d -u -p -r2.25 tree-ssa-threadupdate.c
--- tree-ssa-threadupdate.c     6 May 2005 16:43:52 -0000       2.25
+++ tree-ssa-threadupdate.c     10 May 2005 15:04:09 -0000
@@ -595,6 +595,12 @@ redirect_edges (void **slot, void *data)
            fprintf (dump_file, "  Threaded jump %d --> %d to %d\n",
                     e->src->index, e->dest->index, rd->dup_block->index);

+         /* The duplicate block will have all the original COND_EXPR
+            and SWITCH_EXPRs from the original block.  These
+            expresions and the original outgoing edges are now
+            useless and can be removed.  */
+         remove_ctrl_stmt_and_useless_edges (rd->dup_block, NULL);
+
          /* Redirect the incoming edge to the appropriate duplicate
             block.  */
          e2 = redirect_edge_and_branch (e, rd->dup_block);


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