This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Combine versus updating of liveness
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, gcc-pdo at atrey dot karlin dot mff dot cuni dot cz
- Date: Wed, 6 Mar 2002 18:42:16 +0100
- Subject: Combine versus updating of liveness
Hi,
this cfg-branch crashes in bootstrap after updating to mainline. The purpose
is latent bug in updating liveness after combine. What happends is an condjump
converted to noop (set (pc) (pc)) on the end of basic block, where given register
is live only on the impossible branching path.
Combine knows how to update liveness in local cases and is happy here - and
correct according to current CFG. Later delete_noop_moves is called that
should not need updating of cfg, but it detects the dead edge and removes it
via purge_dead_edges causing liveness to be inconsistent. Later we care
updating the liveness after purge_all_dead_edges, but it is not enought, since
we no longer have this particular dead edge.
Fixing for mainline and branch is probably the attached patch that converts
all three beasts to use BB_DIRTY flags for updating instead of maitaining
their own bitmaps. The liveness is updated once after all three passes iterate.
Problem is how to fix this porperly for the 3.1 branch?
Unfortunately I don't have testcase that reproduce w/o superblock formation...
Bootstrapped/regtested i386 on mainline, installed to cfg-branch.
OK for mainline?
Honza
Wed Mar 6 18:36:03 CET 2002 Jan Hubicka <jh@suse.cz>
* cfgrtl.c (purge_dead_edges): Set BB_DRITY flags if edge has been removed;
fix return value.
* combine.c (combine_instructions): Dirtify blocks where we failed to
update liveness; purge dead edges; use update_life_info_in_dirty_blocks.
* toplev.c (rest_of_compilation): Do not purge_dead_edges after combine.
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cfgrtl.c,v
retrieving revision 1.10.2.28
diff -c -3 -p -r1.10.2.28 cfgrtl.c
*** cfgrtl.c 2002/03/06 10:04:34 1.10.2.28
--- cfgrtl.c 2002/03/06 17:03:52
*************** purge_dead_edges (bb)
*** 2153,2158 ****
--- 2153,2159 ----
if (e->flags & EDGE_EH)
{
remove_edge (e);
+ bb->flags |= BB_DIRTY;
purged = true;
}
}
*************** purge_dead_edges (bb)
*** 2166,2172 ****
if (!any_condjump_p (insn)
&& !returnjump_p (insn)
&& !simplejump_p (insn))
! return false;
/* Branch probability/prediction notes are defined only for
condjumps. We've possibly turned condjump into simplejump. */
--- 2167,2173 ----
if (!any_condjump_p (insn)
&& !returnjump_p (insn)
&& !simplejump_p (insn))
! return purged;
/* Branch probability/prediction notes are defined only for
condjumps. We've possibly turned condjump into simplejump. */
*************** purge_dead_edges (bb)
*** 2199,2210 ****
&& returnjump_p (insn))
continue;
purged = true;
remove_edge (e);
}
if (!bb->succ || !purged)
! return false;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
--- 2200,2212 ----
&& returnjump_p (insn))
continue;
+ bb->flags |= BB_DIRTY;
purged = true;
remove_edge (e);
}
if (!bb->succ || !purged)
! return purged;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Purged edges from bb %i\n", bb->index);
*************** purge_dead_edges (bb)
*** 2251,2257 ****
{
next = e->succ_next;
if (!(e->flags & EDGE_FALLTHRU))
! remove_edge (e), purged = true;
}
if (!bb->succ || bb->succ->succ_next)
--- 2253,2263 ----
{
next = e->succ_next;
if (!(e->flags & EDGE_FALLTHRU))
! {
! bb->flags |= BB_DIRTY;
! remove_edge (e);
! purged = true;
! }
}
if (!bb->succ || bb->succ->succ_next)
Index: combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.241.2.10
diff -c -3 -p -r1.241.2.10 combine.c
*** combine.c 2002/03/05 18:58:04 1.241.2.10
--- combine.c 2002/03/06 17:03:59
*************** combine_instructions (f, nregs)
*** 739,752 ****
;
}
}
delete_noop_moves (f);
! if (need_refresh)
! {
! update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
! PROP_DEATH_NOTES);
! }
/* Clean up. */
sbitmap_free (refresh_blocks);
--- 739,754 ----
;
}
}
+ clear_bb_flags ();
+ EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, this_basic_block,
+ BASIC_BLOCK (this_basic_block)->flags |= BB_DIRTY);
+ new_direct_jump_p |= purge_all_dead_edges (0);
delete_noop_moves (f);
! update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
! PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
! | PROP_KILL_DEAD_CODE);
/* Clean up. */
sbitmap_free (refresh_blocks);
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.537.2.47
diff -c -3 -p -r1.537.2.47 toplev.c
*** toplev.c 2002/03/06 10:04:40 1.537.2.47
--- toplev.c 2002/03/06 17:04:01
*************** rest_of_compilation (decl)
*** 3247,3256 ****
rebuild_jump_labels_after_combine
= combine_instructions (insns, max_reg_num ());
-
- /* Always purge dead edges, as we may eliminate an insn throwing
- exception. */
- rebuild_jump_labels_after_combine |= purge_all_dead_edges (true);
/* Combining insns may have turned an indirect jump into a
direct jump. Rebuid the JUMP_LABEL fields of jumping
--- 3247,3252 ----