This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.5/3.4] Fix bug in tree-inline.c
- From: Josef Zlomek <zlomj9am at artax dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 14 Feb 2004 11:15:32 +0100
- Subject: [3.5/3.4] Fix bug in tree-inline.c
Hello,
when compiling attached testcase on x86-64 or powerpc64 with -O3
I get a ICE in verify flow info with error message "Wrong amount of branch edges
after unconditional jump"
because of this insn:
(jump_insn 82 81 83 (set (pc)
(label_ref 0)) -1 (nil)
(nil))
I analyzed how label_ref 0 came there and found the problem.
For some reason, function "b" gets inlined into "a", and then "a" into "b".
In the second inlining, we replace RETURN_STMT with GOTO ret_label
in copy_body_r () as usual.
But when we continue walking through the tree we reach the new
GOTO ret_label and make a copy of the ret_label because
(*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn) == true
because DECL_CONTEXT (*tp) == fn (see lhd_tree_inlining_auto_var_in_fn_p).
The copied ret_label is not of course emitted to code because it is not
elsewhere in the tree and gets expanded to that (label_ref 0).
This happens only when inlining a function into itself via transitivity.
The ret_label should not be copied because we inserted it there
in replacement of RETURN_STMT.
The following patch fixes it.
Bootstrapped/regtested x86-64.
OK for mainline and 3.4 branch?
Josef
-----------testcase-------------
typedef struct xdef xdef;
struct xdef
{
char xtyp;
xdef *next;
int y;
};
extern void b ();
extern void *foo (void *bar);
extern void *foo2 (void *bar1, void *bar2);
extern void *qwe;
static void
c (xdef * xp)
{
b (xp);
}
static void
a (xdef ** xpp)
{
xdef *xp;
xp = *xpp;
foo (xp);
xp = foo2 (xp, qwe);
b (xp->next);
foo (xp);
if (xp->y)
{
foo (xp);
if (xp)
{
xdef *p = foo2 (xp, qwe);
foo2 (xp, p);
xp = foo (p);
}
else
{
foo2 (foo(*xpp), *xpp);
}
}
*xpp = foo2 (xpp, qwe);
}
void
b (xdef ** xpp)
{
xdef *xp = *xpp;
if (!xp)
return;
if (xp->xtyp == 0)
a (xpp);
c (xp);
}
---------------------------------
2004-02-14 Josef Zlomek <zlomekj@suse.cz>
* tree-inline.c (copy_body_r): Do not replace ret_label.
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc-cvs/gcc/gcc/tree-inline.c,v
retrieving revision 1.34.2.17
diff -c -p -c -3 -p -r1.34.2.17 tree-inline.c
*** tree-inline.c 3 Jan 2004 18:13:44 -0000 1.34.2.17
--- tree-inline.c 26 Jan 2004 20:09:30 -0000
*************** copy_body_r (tp, walk_subtrees, data)
*** 490,497 ****
/* Local variables and labels need to be replaced by equivalent
variables. We don't want to copy static variables; there's only
one of those, no matter how many times we inline the containing
! function. */
! else if ((*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn))
{
tree new_decl;
--- 490,500 ----
/* Local variables and labels need to be replaced by equivalent
variables. We don't want to copy static variables; there's only
one of those, no matter how many times we inline the containing
! function.
! We do not also want to copy the label which we put into
! GOTO_STMT which replaced RETURN_STMT. */
! else if (*tp != id->ret_label
! && (*lang_hooks.tree_inlining.auto_var_in_fn_p) (*tp, fn))
{
tree new_decl;