This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix threading bug with computed gotos
- From: Diego Novillo <dnovillo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Jeff Law <law at redhat dot com>
- Date: Tue, 10 May 2005 11:05:53 -0400
- Subject: 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);