Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 254577 Details for
Bug 341743
sys-devel/gcc-4.5.1 -fno-strict-overflow causes bad code generation (exercised by sys-devel/patch-2.6.1 on hardened)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
http://gcc.gnu.org/ml/gcc-patches/2010-11/msg01735.html
pr-46315.patch (text/plain), 13.54 KB, created by
Magnus Granberg
on 2010-11-16 23:58:52 UTC
(
hide
)
Description:
http://gcc.gnu.org/ml/gcc-patches/2010-11/msg01735.html
Filename:
MIME Type:
Creator:
Magnus Granberg
Created:
2010-11-16 23:58:52 UTC
Size:
13.54 KB
patch
obsolete
>2010-11-16 Eric Botcazou <ebotcazou@adacore.com> > > PR rtl-optimization/46315 > * rtl.h (remove_reg_equal_equiv_notes_for_regno): Declare. > * rtlanal.c (remove_reg_equal_equiv_notes_for_regno): New function > extracted from... > * dce.c (delete_corresponding_reg_eq_notes): ...here. Rename into... > (remove_reg_equal_equiv_notes_for_defs): ...this. > (delete_unmarked_insns): Adjust to above renaming. > * ifcvt.c (dead_or_predicable): Remove REG_EQUAL and REG_EQUIV notes > referring to registers set in the insns being moved, if any. > > * df-core.c (df_ref_dump): New function extracted from... > (df_refs_chain_dump): ...here. Call it. > (df_regs_chain_dump): Likewise. > * df-problems.c (df_chain_dump): Print 'e' for uses in notes. > * df-scan.c (df_scan_start_dump): Likewise. Fix long line. > > >2010-11-16 Eric Botcazou <ebotcazou@adacore.com> > > * gcc.dg/pr46315.c: New test. > >Index: rtlanal.c >=================================================================== >--- rtlanal.c (revision 166792) >+++ rtlanal.c (working copy) >@@ -1941,6 +1941,33 @@ remove_reg_equal_equiv_notes (rtx insn) > } > } > >+/* Remove all REG_EQUAL and REG_EQUIV notes referring to REGNO. */ >+ >+void >+remove_reg_equal_equiv_notes_for_regno (unsigned int regno) >+{ >+ df_ref eq_use; >+ >+ if (!df) >+ return; >+ >+ /* This loop is a little tricky. We cannot just go down the chain because >+ it is being modified by some actions in the loop. So we just iterate >+ over the head. We plan to drain the list anyway. */ >+ while ((eq_use = DF_REG_EQ_USE_CHAIN (regno)) != NULL) >+ { >+ rtx insn = DF_REF_INSN (eq_use); >+ rtx note = find_reg_equal_equiv_note (insn); >+ >+ /* This assert is generally triggered when someone deletes a REG_EQUAL >+ or REG_EQUIV note by hacking the list manually rather than calling >+ remove_note. */ >+ gcc_assert (note); >+ >+ remove_note (insn, note); >+ } >+} >+ > /* Search LISTP (an EXPR_LIST) for an entry whose first operand is NODE and > return 1 if it is found. A simple equality test is used to determine if > NODE matches. */ >Index: df-scan.c >=================================================================== >--- df-scan.c (revision 166792) >+++ df-scan.c (working copy) >@@ -445,7 +445,7 @@ df_scan_start_dump (FILE *file ATTRIBUTE > } > if (DF_REG_EQ_USE_COUNT (i)) > { >- fprintf (file, "%s%dd", sep, DF_REG_EQ_USE_COUNT (i)); >+ fprintf (file, "%s%de", sep, DF_REG_EQ_USE_COUNT (i)); > ecount += DF_REG_EQ_USE_COUNT (i); > } > fprintf (file, "} "); >@@ -461,8 +461,10 @@ df_scan_start_dump (FILE *file ATTRIBUTE > icount++; > } > >- fprintf (file, "\n;; total ref usage %d{%dd,%du,%de} in %d{%d regular + %d call} insns.\n", >- dcount + ucount + ecount, dcount, ucount, ecount, icount + ccount, icount, ccount); >+ fprintf (file, "\n;; total ref usage %d{%dd,%du,%de}" >+ " in %d{%d regular + %d call} insns.\n", >+ dcount + ucount + ecount, dcount, ucount, ecount, >+ icount + ccount, icount, ccount); > } > > /* Dump the bb_info for a given basic block. */ >Index: df-core.c >=================================================================== >--- df-core.c (revision 166792) >+++ df-core.c (working copy) >@@ -2051,6 +2051,17 @@ df_dump_bottom (basic_block bb, FILE *fi > } > > >+static void >+df_ref_dump (df_ref ref, FILE *file) >+{ >+ fprintf (file, "%c%d(%d)", >+ DF_REF_REG_DEF_P (ref) >+ ? 'd' >+ : (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE) ? 'e' : 'u', >+ DF_REF_ID (ref), >+ DF_REF_REGNO (ref)); >+} >+ > void > df_refs_chain_dump (df_ref *ref_rec, bool follow_chain, FILE *file) > { >@@ -2058,10 +2069,7 @@ df_refs_chain_dump (df_ref *ref_rec, boo > while (*ref_rec) > { > df_ref ref = *ref_rec; >- fprintf (file, "%c%d(%d)", >- DF_REF_REG_DEF_P (ref) ? 'd' : (DF_REF_FLAGS (ref) & DF_REF_IN_NOTE) ? 'e' : 'u', >- DF_REF_ID (ref), >- DF_REF_REGNO (ref)); >+ df_ref_dump (ref, file); > if (follow_chain) > df_chain_dump (DF_REF_CHAIN (ref), file); > ref_rec++; >@@ -2078,10 +2086,7 @@ df_regs_chain_dump (df_ref ref, FILE *f > fprintf (file, "{ "); > while (ref) > { >- fprintf (file, "%c%d(%d) ", >- DF_REF_REG_DEF_P (ref) ? 'd' : 'u', >- DF_REF_ID (ref), >- DF_REF_REGNO (ref)); >+ df_ref_dump (ref, file); > ref = DF_REF_NEXT_REG (ref); > } > fprintf (file, "}"); >Index: ifcvt.c >=================================================================== >--- ifcvt.c (revision 166792) >+++ ifcvt.c (working copy) >@@ -3998,6 +3998,7 @@ dead_or_predicable (basic_block test_bb, > 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, merge_set_noclobber = NULL; > /* Number of pending changes. */ > int n_validated_changes = 0; > >@@ -4086,6 +4087,7 @@ dead_or_predicable (basic_block test_bb, > earliest = jump; > } > #endif >+ > /* Try the NCE path if the CE path did not result in any changes. */ > if (n_validated_changes == 0) > { >@@ -4094,9 +4096,8 @@ dead_or_predicable (basic_block test_bb, > that any registers modified are dead at the branch site. */ > > rtx insn, cond, prev; >- bitmap merge_set, merge_set_noclobber, test_live, test_set; >- unsigned i, fail = 0; >- bitmap_iterator bi; >+ bitmap test_live, test_set; >+ bool intersect = false; > > /* Check for no calls or trapping operations. */ > for (insn = head; ; insn = NEXT_INSN (insn)) >@@ -4138,12 +4139,7 @@ dead_or_predicable (basic_block test_bb, > > merge_set = BITMAP_ALLOC (®_obstack); > merge_set_noclobber = BITMAP_ALLOC (®_obstack); >- test_live = BITMAP_ALLOC (®_obstack); >- test_set = BITMAP_ALLOC (®_obstack); > >- /* ??? bb->local_set is only valid during calculate_global_regs_live, >- so we must recompute usage for MERGE_BB. Not so bad, I suppose, >- since we've already asserted that MERGE_BB is small. */ > /* If we allocated new pseudos (e.g. in the conditional move > expander called from noce_emit_cmove), we must resize the > array first. */ >@@ -4164,17 +4160,22 @@ dead_or_predicable (basic_block test_bb, > if (! reload_completed > && targetm.small_register_classes_for_mode_p (VOIDmode)) > { >+ unsigned i; >+ bitmap_iterator bi; >+ > EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi) > { > if (i < FIRST_PSEUDO_REGISTER > && ! fixed_regs[i] > && ! global_regs[i]) >- fail = 1; >+ goto fail; > } > } > > /* For TEST, we're interested in a range of insns, not a whole block. > Moreover, we're interested in the insns live from OTHER_BB. */ >+ test_live = BITMAP_ALLOC (®_obstack); >+ test_set = BITMAP_ALLOC (®_obstack); > > /* The loop below takes the set of live registers > after JUMP, and calculates the live set before EARLIEST. */ >@@ -4195,23 +4196,21 @@ dead_or_predicable (basic_block test_bb, > /* We can perform the transformation if > MERGE_SET_NOCLOBBER & TEST_SET > and >- MERGE_SET & TEST_LIVE) >+ MERGE_SET & TEST_LIVE > and > TEST_SET & DF_LIVE_IN (merge_bb) > are empty. */ > >- if (bitmap_intersect_p (test_set, merge_set_noclobber) >- || bitmap_intersect_p (test_live, merge_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))) >- fail = 1; >+ intersect = true; > >- BITMAP_FREE (merge_set_noclobber); >- BITMAP_FREE (merge_set); > BITMAP_FREE (test_live); > BITMAP_FREE (test_set); > >- if (fail) >- return FALSE; >+ if (intersect) >+ goto fail; > } > > no_body: >@@ -4261,8 +4260,8 @@ dead_or_predicable (basic_block test_bb, > if (end == BB_END (merge_bb)) > BB_END (merge_bb) = PREV_INSN (head); > >- /* PR 21767: When moving insns above a conditional branch, REG_EQUAL >- notes might become invalid. */ >+ /* PR 21767: when moving insns above a conditional branch, the REG_EQUAL >+ notes being moved might become invalid. */ > insn = head; > do > { >@@ -4279,6 +4278,20 @@ dead_or_predicable (basic_block test_bb, > remove_note (insn, note); > } while (insn != end && (insn = NEXT_INSN (insn))); > >+ /* PR46315: when moving insns above a conditional branch, the REG_EQUAL >+ notes referring to the registers being set might become invalid. */ >+ if (merge_set) >+ { >+ unsigned i; >+ bitmap_iterator 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)); > } > >@@ -4295,6 +4308,12 @@ dead_or_predicable (basic_block test_bb, > > cancel: > cancel_changes (0); >+ fail: >+ if (merge_set) >+ { >+ BITMAP_FREE (merge_set); >+ BITMAP_FREE (merge_set_noclobber); >+ } > return FALSE; > } > >Index: rtl.h >=================================================================== >--- rtl.h (revision 166792) >+++ rtl.h (working copy) >@@ -1892,6 +1892,7 @@ extern rtx alloc_reg_note (enum reg_note > extern void add_reg_note (rtx, enum reg_note, rtx); > extern void remove_note (rtx, const_rtx); > extern void remove_reg_equal_equiv_notes (rtx); >+extern void remove_reg_equal_equiv_notes_for_regno (unsigned int); > extern int side_effects_p (const_rtx); > extern int volatile_refs_p (const_rtx); > extern int volatile_insn_p (const_rtx); >Index: df-problems.c >=================================================================== >--- df-problems.c (revision 166792) >+++ df-problems.c (working copy) >@@ -109,10 +109,13 @@ df_chain_dump (struct df_link *link, FIL > for (; link; link = link->next) > { > fprintf (file, "%c%d(bb %d insn %d) ", >- DF_REF_REG_DEF_P (link->ref) ? 'd' : 'u', >+ DF_REF_REG_DEF_P (link->ref) >+ ? 'd' >+ : (DF_REF_FLAGS (link->ref) & DF_REF_IN_NOTE) ? 'e' : 'u', > DF_REF_ID (link->ref), > DF_REF_BBNO (link->ref), >- DF_REF_IS_ARTIFICIAL (link->ref) ? -1 : DF_REF_INSN_UID (link->ref)); >+ DF_REF_IS_ARTIFICIAL (link->ref) >+ ? -1 : DF_REF_INSN_UID (link->ref)); > } > fprintf (file, "}"); > } >Index: dce.c >=================================================================== >--- dce.c (revision 166792) >+++ dce.c (working copy) >@@ -466,36 +466,16 @@ find_call_stack_args (rtx call_insn, boo > } > > >-/* Delete all REG_EQUAL notes of the registers INSN writes, to prevent >- bad dangling REG_EQUAL notes. */ >+/* Remove all REG_EQUAL and REG_EQUIV notes referring to the registers INSN >+ writes to. */ > > static void >-delete_corresponding_reg_eq_notes (rtx insn) >+remove_reg_equal_equiv_notes_for_defs (rtx insn) > { > df_ref *def_rec; >+ > for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) >- { >- df_ref def = *def_rec; >- unsigned int regno = DF_REF_REGNO (def); >- /* This loop is a little tricky. We cannot just go down the >- chain because it is being modified by the actions in the >- loop. So we just get the head. We plan to drain the list >- anyway. */ >- while (DF_REG_EQ_USE_CHAIN (regno)) >- { >- df_ref eq_use = DF_REG_EQ_USE_CHAIN (regno); >- rtx noted_insn = DF_REF_INSN (eq_use); >- rtx note = find_reg_note (noted_insn, REG_EQUAL, NULL_RTX); >- if (!note) >- note = find_reg_note (noted_insn, REG_EQUIV, NULL_RTX); >- >- /* This assert is generally triggered when someone deletes a >- REG_EQUAL or REG_EQUIV note by hacking the list manually >- rather than calling remove_note. */ >- gcc_assert (note); >- remove_note (noted_insn, note); >- } >- } >+ remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (*def_rec)); > } > > >@@ -544,9 +524,9 @@ delete_unmarked_insns (void) > if (dump_file) > fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); > >- /* Before we delete the insn we have to delete REG_EQUAL notes >+ /* Before we delete the insn we have to remove the REG_EQUAL notes > for the destination regs in order to avoid dangling notes. */ >- delete_corresponding_reg_eq_notes (insn); >+ remove_reg_equal_equiv_notes_for_defs (insn); > > /* If a pure or const call is deleted, this may make the cfg > have unreachable blocks. We rememeber this and call > >/* PR rtl-optimization/46315 */ >/* Reported by Magnus Granberg <zorry@gentoo.org> */ > >/* { dg-do run } */ >/* { dg-options "-O2 -fno-strict-overflow" } */ > >extern void abort (void); > >static char const * >parse_ranged (char const *s, int digits) >{ > int n = 0; > char const *lim = s + digits; > while (s < lim) > { > unsigned d = *s++ - '0'; > if (9 < d) > return 0; > n = 10 * n + d; > } > return s && 0 <= n && n <= 59 ? s : 0; >} > >int main(void) >{ > const char *s = "10092240"; > > s = parse_ranged (s, 2); > s = parse_ranged (s, 2); > s = parse_ranged (s, 2); > s = parse_ranged (s, 2); > > if (!s || *s != '\0') > abort(); > > return 0; >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 341743
:
251223
|
251225
|
251447
| 254577