On Wed, Apr 27, 2011 at 6:27 PM, Ulrich Weigand <uweig...@de.ibm.com> wrote: > Hello, > > PR middle-end/43085 is a crash of cc1plus when building libstdc++ during > make profiledbootstrap on the 4.5 branch. The crash is caused by a > mis-compile of the add_method routine with -fprofile-use due to a > dataflow bug during the final if-conversion pass. For more detailed > analysis see the PR. > > The dataflow bug was fixed on mainline (already for 4.6) by a series of > patches by Bernd Schmidt, who noticed the bug in a different context. > > The patch below is a backport of those fixes to the 4.5 branch, which > fixes the profiled-bootstrap failure for me. (Note that on current > mainling, the ifcvt.c dead_or_predictable routine has been significantly > rewritten beyond what was done by those patches. These additional > changes do not appear to be necessary to fix the PR ...) > > Tested on 4.5 on i386-linux with no regression; make profiledbootstrap > works again (and the resulting compiler also passes the testsuite with > no regressions). > > OK for the 4.5 branch?
Looks ok to me from a RM perspective, once the branch is unfrozen again. Richard. > Bye, > Ulrich > > > 2011-04-27 Ulrich Weigand <ulrich.weig...@linaro.org> > > PR middle-end/43085 > Backport from mainline: > > 2010-04-29 Bernd Schmidt <ber...@codesourcery.com> > > From Dominique d'Humieres <domi...@lps.ens.fr> > PR bootstrap/43858 > * ifcvt.c (dead_or_predicable): Use df_simulate_find_defs to compute > test_set. > > 2010-04-26 Bernd Schmidt <ber...@codesourcery.com> > > * df-problems.c (df_simulate_initialize_forwards): Set, don't clear, > bits for artificial defs at the top of the block. > * fwprop.c (single_def_use_enter_block): Don't call it. > > 2010-04-22 Bernd Schmidt <ber...@codesourcery.com> > > * ifcvt.c (dead_or_predicable): Use df_simulate_find_defs and > df_simulate_find_noclobber_defs as appropriate. Keep track of an > extra set merge_set_noclobber, and use it to relax the final test > slightly. > * df.h (df_simulate_find_noclobber_defs): Declare. > * df-problems.c (df_simulate_find_defs): Don't ignore partial or > conditional defs. > (df_simulate_find_noclobber_defs): New function. > > > Index: gcc/fwprop.c > =================================================================== > --- gcc/fwprop.c (revision 172641) > +++ gcc/fwprop.c (working copy) > @@ -228,8 +228,11 @@ > > process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP); > process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP); > - df_simulate_initialize_forwards (bb, local_lr); > > + /* We don't call df_simulate_initialize_forwards, as it may overestimate > + the live registers if there are unused artificial defs. We prefer > + liveness to be underestimated. */ > + > FOR_BB_INSNS (bb, insn) > if (INSN_P (insn)) > { > Index: gcc/ifcvt.c > =================================================================== > --- gcc/ifcvt.c (revision 172641) > +++ gcc/ifcvt.c (working copy) > @@ -3818,7 +3818,7 @@ > basic_block other_bb, basic_block new_dest, int reversep) > { > rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX; > - bitmap merge_set = NULL; > + bitmap merge_set = NULL, merge_set_noclobber = NULL; > /* Number of pending changes. */ > int n_validated_changes = 0; > > @@ -3951,11 +3951,14 @@ > > /* Collect: > MERGE_SET = set of registers set in MERGE_BB > + MERGE_SET_NOCLOBBER = like MERGE_SET, but only includes registers > + that are really set, not just clobbered. > TEST_LIVE = set of registers live at EARLIEST > - TEST_SET = set of registers set between EARLIEST and the > - end of the block. */ > + TEST_SET = set of registers set between EARLIEST and the > + end of the block. */ > > merge_set = BITMAP_ALLOC (®_obstack); > + merge_set_noclobber = BITMAP_ALLOC (®_obstack); > > /* If we allocated new pseudos (e.g. in the conditional move > expander called from noce_emit_cmove), we must resize the > @@ -3967,13 +3970,8 @@ > { > if (NONDEBUG_INSN_P (insn)) > { > - unsigned int uid = INSN_UID (insn); > - df_ref *def_rec; > - for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) > - { > - df_ref def = *def_rec; > - bitmap_set_bit (merge_set, DF_REF_REGNO (def)); > - } > + df_simulate_find_defs (insn, merge_set); > + df_simulate_find_noclobber_defs (insn, merge_set_noclobber); > } > } > > @@ -3984,7 +3982,7 @@ > unsigned i; > bitmap_iterator bi; > > - EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi) > + EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi) > { > if (i < FIRST_PSEUDO_REGISTER > && ! fixed_regs[i] > @@ -4015,12 +4013,14 @@ > } > > /* We can perform the transformation if > - MERGE_SET & (TEST_SET | TEST_LIVE) > + MERGE_SET_NOCLOBBER & TEST_SET > and > + MERGE_SET & TEST_LIVE > + and > TEST_SET & DF_LIVE_IN (merge_bb) > are empty. */ > > - if (bitmap_intersect_p (merge_set, test_set) > + if (bitmap_intersect_p (merge_set_noclobber, test_set) > || bitmap_intersect_p (merge_set, test_live) > || bitmap_intersect_p (test_set, df_get_live_in (merge_bb))) > intersect = true; > @@ -4104,10 +4104,11 @@ > unsigned i; > bitmap_iterator bi; > > - EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi) > + EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi) > remove_reg_equal_equiv_notes_for_regno (i); > > BITMAP_FREE (merge_set); > + BITMAP_FREE (merge_set_noclobber); > } > > reorder_insns (head, end, PREV_INSN (earliest)); > @@ -4128,7 +4129,10 @@ > cancel_changes (0); > fail: > if (merge_set) > - BITMAP_FREE (merge_set); > + { > + BITMAP_FREE (merge_set); > + BITMAP_FREE (merge_set_noclobber); > + } > return FALSE; > } > > Index: gcc/df.h > =================================================================== > --- gcc/df.h (revision 172641) > +++ gcc/df.h (working copy) > @@ -978,6 +978,7 @@ > extern void df_md_add_problem (void); > extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap); > extern void df_md_simulate_one_insn (basic_block, rtx, bitmap); > +extern void df_simulate_find_noclobber_defs (rtx, bitmap); > extern void df_simulate_find_defs (rtx, bitmap); > extern void df_simulate_defs (rtx, bitmap); > extern void df_simulate_uses (rtx, bitmap); > Index: gcc/df-problems.c > =================================================================== > --- gcc/df-problems.c (revision 172641) > +++ gcc/df-problems.c (working copy) > @@ -3748,9 +3748,22 @@ > for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) > { > df_ref def = *def_rec; > - /* If the def is to only part of the reg, it does > - not kill the other defs that reach here. */ > - if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL))) > + bitmap_set_bit (defs, DF_REF_REGNO (def)); > + } > +} > + > +/* Find the set of real DEFs, which are not clobbers, for INSN. */ > + > +void > +df_simulate_find_noclobber_defs (rtx insn, bitmap defs) > +{ > + df_ref *def_rec; > + unsigned int uid = INSN_UID (insn); > + > + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) > + { > + df_ref def = *def_rec; > + if (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))) > bitmap_set_bit (defs, DF_REF_REGNO (def)); > } > } > @@ -3903,13 +3916,9 @@ > the block, starting with the first one. > > ----------------------------------------------------------------------------*/ > > -/* Apply the artificial uses and defs at the top of BB in a forwards > - direction. ??? This is wrong; defs mark the point where a pseudo > - becomes live when scanning forwards (unless a def is unused). Since > - there are no REG_UNUSED notes for artificial defs, passes that > - require artificial defs probably should not call this function > - unless (as is the case for fwprop) they are correct when liveness > - bitmaps are *under*estimated. */ > +/* Initialize the LIVE bitmap, which should be copied from DF_LIVE_IN or > + DF_LR_IN for basic block BB, for forward scanning by marking artificial > + defs live. */ > > void > df_simulate_initialize_forwards (basic_block bb, bitmap live) > @@ -3921,7 +3930,7 @@ > { > df_ref def = *def_rec; > if (DF_REF_FLAGS (def) & DF_REF_AT_TOP) > - bitmap_clear_bit (live, DF_REF_REGNO (def)); > + bitmap_set_bit (live, DF_REF_REGNO (def)); > } > } > > @@ -3942,7 +3951,7 @@ > while here the scan is performed forwards! So, first assume that the > def is live, and if this is not true REG_UNUSED notes will rectify the > situation. */ > - df_simulate_find_defs (insn, live); > + df_simulate_find_noclobber_defs (insn, live); > > /* Clear all of the registers that go dead. */ > for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) > -- > Dr. Ulrich Weigand > GNU Toolchain for Linux on System z and Cell BE > ulrich.weig...@de.ibm.com >