This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix latent bug in crossjuping
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com
- Date: Tue, 31 Dec 2002 17:25:57 +0100
- Subject: fix latent bug in crossjuping
Hi,
the trace scheduling on cfgbranch uncovered another latent problem in crossjumping.
WHen we merge two blocks, one containing clobber, it is necesary to remove the clobber in order to avoid
the other computation patch from loosing the computation.
It may be better to move the clobber to the edge but that can futher complicate
flowgraph and I don't think liveness in functions just prtially returning value
is that important.
Bootstrapped/regtested rtlopt branch. OK for mainline?
Tue Dec 31 17:20:47 CET 2002 Jan Hubicka <jh@suse.cz>
* cfgcleanup.c (try_crossjump_to_edge): Remove bohus clobbers.
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.63.2.6
diff -c -3 -p -r1.63.2.6 cfgcleanup.c
*** cfgcleanup.c 18 Dec 2002 10:35:02 -0000 1.63.2.6
--- cfgcleanup.c 31 Dec 2002 16:25:14 -0000
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1348,1353 ****
--- 1348,1354 ----
basic_block redirect_to, redirect_from, to_remove;
rtx newpos1, newpos2;
edge s;
+ rtx insn;
/* Search backward through forwarder blocks. We don't need to worry
about multiple entry or chained forwarders, as they will be optimized
*************** try_crossjump_to_edge (mode, e1, e2)
*** 1480,1485 ****
--- 1481,1512 ----
to_remove = redirect_from->succ->dest;
redirect_edge_and_branch_force (redirect_from->succ, redirect_to);
+
+ /* The redirect_to may contain clobbers missing in to_remove. This
+ is commonly the case when return value is undefined in some paths.
+ We must wallk trought the clobbers and remove these that clobber values
+ live in beggining of to_remove and not in the beggining of redirect_to.
+
+ If needed the same trick can be done without liveness information by
+ comparing clobbers and uses present in both blocks. */
+ if (!(mode & CLEANUP_POST_REGSTACK))
+ {
+ if (!(mode & CLEANUP_UPDATE_LIFE))
+ abort ();
+ for (insn = redirect_to->head; insn != NEXT_INSN (redirect_to->end);
+ insn = NEXT_INSN (insn))
+ if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == CLOBBER
+ && REG_P (XEXP (PATTERN (insn), 0)))
+ {
+ unsigned int regno = REGNO (XEXP (PATTERN (insn), 0));
+ if (REGNO_REG_SET_P (to_remove->global_live_at_start, regno)
+ && !REGNO_REG_SET_P (redirect_to->global_live_at_start, regno))
+ delete_insn (insn);
+ }
+ IOR_REG_SET (redirect_to->global_live_at_start,
+ to_remove->global_live_at_start);
+ }
+
flow_delete_block (to_remove);
update_forwarder_flag (redirect_from);