From: Andrey Belevantsev Date: Mon, 20 Jun 2011 11:56:08 +0000 (+0400) Subject: backport: re PR target/43603 (gcc-4.4.3 ICE on ia64 with -O3) X-Git-Tag: releases/gcc-4.4.7~354 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3c4f93533ee748c39cab18317134f1abd9c6da5;p=thirdparty%2Fgcc.git backport: re PR target/43603 (gcc-4.4.3 ICE on ia64 with -O3) Backport from mainline 2010-12-07 Andrey Belevantsev PR target/43603 * haifa-sched.c (sched_create_recovery_edges): Update dominator info. * sel-sched-ir.c (maybe_tidy_empty_bb): Update dominator info after deleting an empty block, verify dominators. (sel_remove_bb): Update dominator info after removing a block. (sel_redirect_edge_and_branch_force): Assert that no unreachable blocks will be created. Update dominator info. (sel_redirect_edge_and_branch): Update dominator info when basic blocks do not become unreachable. (sel_remove_loop_preheader): Update dominator info. 2010-10-14 Andrey Belevantsev * sel-sched-ir.c (maybe_tidy_empty_bb): Simplify comment. (tidy_control_flow): Tidy vertical space. (sel_remove_bb): New variable idx. Use it to remember the basic block index before deleting the block. (sel_remove_empty_bb): Remove dead code, simplify and insert to ... (sel_merge_blocks): ... here. Add forward declaration. * sel-sched-ir.h (sel_remove_empty_bb): Remove prototype. (sel_merge_blocks): Likewise. 2011-06-20 Andrey Belevantsev Backport from mainline 2010-12-07 Andrey Belevantsev PR target/43603 * gcc.target/ia64/pr43603.c: New. * gcc/testsuite/g++.dg/opt/pr46640.C: New. From-SVN: r175207 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 09164bed7a37..8dafef711f74 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2011-06-20 Andrey Belevantsev + + Backport from mainline + 2010-12-07 Andrey Belevantsev + PR target/43603 + * haifa-sched.c (sched_create_recovery_edges): Update + dominator info. + * sel-sched-ir.c (maybe_tidy_empty_bb): Update dominator info + after deleting an empty block, verify dominators. + (sel_remove_bb): Update dominator info after removing a block. + (sel_redirect_edge_and_branch_force): Assert that no unreachable + blocks will be created. Update dominator info. + (sel_redirect_edge_and_branch): Update dominator info when + basic blocks do not become unreachable. + (sel_remove_loop_preheader): Update dominator info. + + 2010-10-14 Andrey Belevantsev + + * sel-sched-ir.c (maybe_tidy_empty_bb): Simplify comment. + (tidy_control_flow): Tidy vertical space. + (sel_remove_bb): New variable idx. Use it to remember the basic + block index before deleting the block. + (sel_remove_empty_bb): Remove dead code, simplify and insert to ... + (sel_merge_blocks): ... here. Add forward declaration. + * sel-sched-ir.h (sel_remove_empty_bb): Remove prototype. + (sel_merge_blocks): Likewise. + 2011-06-17 Hans-Peter Nilsson Backport from mainline diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 09dc233c2537..a3931a591b59 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -3918,7 +3918,9 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec, else edge_flags = 0; - make_single_succ_edge (rec, second_bb, edge_flags); + make_single_succ_edge (rec, second_bb, edge_flags); + if (dom_info_available_p (CDI_DOMINATORS)) + set_immediate_dominator (CDI_DOMINATORS, rec, first_bb); } /* This function creates recovery code for INSN. If MUTATE_P is nonzero, diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c index a6b73b997d00..ab2742fd871b 100644 --- a/gcc/sel-sched-ir.c +++ b/gcc/sel-sched-ir.c @@ -152,6 +152,7 @@ static void free_history_vect (VEC (expr_history_def, heap) **); static void move_bb_info (basic_block, basic_block); static void remove_empty_bb (basic_block, bool); +static void sel_merge_blocks (basic_block, basic_block); static void sel_remove_loop_preheader (void); static bool insn_is_the_only_one_in_bb_p (insn_t); @@ -3539,6 +3540,7 @@ static bool maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p) { basic_block succ_bb, pred_bb; + VEC (basic_block, heap) *dom_bbs; edge e; edge_iterator ei; bool rescan_p; @@ -3574,6 +3576,7 @@ maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p) succ_bb = single_succ (bb); rescan_p = true; pred_bb = NULL; + dom_bbs = NULL; /* Redirect all non-fallthru edges to the next bb. */ while (rescan_p) @@ -3586,6 +3589,12 @@ maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p) if (!(e->flags & EDGE_FALLTHRU)) { + /* We will update dominators here only when we'll get + an unreachable block when redirecting, otherwise + sel_redirect_edge_and_branch will take care of it. */ + if (e->dest != bb + && single_pred_p (e->dest)) + VEC_safe_push (basic_block, heap, dom_bbs, e->dest); recompute_toporder_p |= sel_redirect_edge_and_branch (e, succ_bb); rescan_p = true; break; @@ -3593,13 +3602,11 @@ maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p) } } - /* If it is possible - merge BB with its predecessor. */ if (can_merge_blocks_p (bb->prev_bb, bb)) sel_merge_blocks (bb->prev_bb, bb); else - /* Otherwise this is a block without fallthru predecessor. - Just delete it. */ { + /* This is a block without fallthru predecessor. Just delete it. */ gcc_assert (pred_bb != NULL); if (in_current_region_p (pred_bb)) @@ -3607,11 +3614,19 @@ maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p) remove_empty_bb (bb, true); } + if (!VEC_empty (basic_block, dom_bbs)) + { + VEC_safe_push (basic_block, heap, dom_bbs, succ_bb); + iterate_fix_dominators (CDI_DOMINATORS, dom_bbs, false); + VEC_free (basic_block, heap, dom_bbs); + } + if (recompute_toporder_p) sel_recompute_toporder (); #ifdef ENABLE_CHECKING verify_backedges (); + verify_dominators (CDI_DOMINATORS); #endif return true; @@ -4985,16 +5000,23 @@ sel_add_bb (basic_block bb) static void sel_remove_bb (basic_block bb, bool remove_from_cfg_p) { + unsigned idx = bb->index; + gcc_assert (bb != NULL && BB_NOTE_LIST (bb) == NULL_RTX); remove_bb_from_region (bb); return_bb_to_pool (bb); - bitmap_clear_bit (blocks_to_reschedule, bb->index); + bitmap_clear_bit (blocks_to_reschedule, idx); if (remove_from_cfg_p) - delete_and_free_basic_block (bb); + { + basic_block succ = single_succ (bb); + delete_and_free_basic_block (bb); + set_immediate_dominator (CDI_DOMINATORS, succ, + recompute_dominator (CDI_DOMINATORS, succ)); + } - rgn_setup_region (CONTAINING_RGN (bb->index)); + rgn_setup_region (CONTAINING_RGN (idx)); } /* Concatenate info of EMPTY_BB to info of MERGE_BB. */ @@ -5009,50 +5031,6 @@ move_bb_info (basic_block merge_bb, basic_block empty_bb) } -/* Remove an empty basic block EMPTY_BB. When MERGE_UP_P is true, we put - EMPTY_BB's note lists into its predecessor instead of putting them - into the successor. When REMOVE_FROM_CFG_P is true, also remove - the empty block. */ -void -sel_remove_empty_bb (basic_block empty_bb, bool merge_up_p, - bool remove_from_cfg_p) -{ - basic_block merge_bb; - - gcc_assert (sel_bb_empty_p (empty_bb)); - - if (merge_up_p) - { - merge_bb = empty_bb->prev_bb; - gcc_assert (EDGE_COUNT (empty_bb->preds) == 1 - && EDGE_PRED (empty_bb, 0)->src == merge_bb); - } - else - { - edge e; - edge_iterator ei; - - merge_bb = bb_next_bb (empty_bb); - - /* Redirect incoming edges (except fallthrough one) of EMPTY_BB to its - successor block. */ - for (ei = ei_start (empty_bb->preds); - (e = ei_safe_edge (ei)); ) - { - if (! (e->flags & EDGE_FALLTHRU)) - sel_redirect_edge_and_branch (e, merge_bb); - else - ei_next (&ei); - } - - gcc_assert (EDGE_COUNT (empty_bb->succs) == 1 - && EDGE_SUCC (empty_bb, 0)->dest == merge_bb); - } - - move_bb_info (merge_bb, empty_bb); - remove_empty_bb (empty_bb, remove_from_cfg_p); -} - /* Remove EMPTY_BB. If REMOVE_FROM_CFG_P is false, remove EMPTY_BB from region, but keep it in CFG. */ static void @@ -5352,12 +5330,16 @@ sel_create_recovery_block (insn_t orig_insn) } /* Merge basic block B into basic block A. */ -void +static void sel_merge_blocks (basic_block a, basic_block b) { - sel_remove_empty_bb (b, true, false); - merge_blocks (a, b); + gcc_assert (sel_bb_empty_p (b) + && EDGE_COUNT (b->preds) == 1 + && EDGE_PRED (b, 0)->src == b->prev_bb); + move_bb_info (b->prev_bb, b); + remove_empty_bb (b, false); + merge_blocks (a, b); change_loops_latches (b, a); } @@ -5367,11 +5349,15 @@ sel_merge_blocks (basic_block a, basic_block b) void sel_redirect_edge_and_branch_force (edge e, basic_block to) { - basic_block jump_bb, src; + basic_block jump_bb, src, orig_dest = e->dest; int prev_max_uid; rtx jump; - gcc_assert (!sel_bb_empty_p (e->src)); + /* This function is now used only for bookkeeping code creation, where + we'll never get the single pred of orig_dest block and thus will not + hit unreachable blocks when updating dominator info. */ + gcc_assert (!sel_bb_empty_p (e->src) + && !single_pred_p (orig_dest)); src = e->src; prev_max_uid = get_max_uid (); @@ -5389,6 +5375,10 @@ sel_redirect_edge_and_branch_force (edge e, basic_block to) jump = find_new_jump (src, jump_bb, prev_max_uid); if (jump) sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP); + set_immediate_dominator (CDI_DOMINATORS, to, + recompute_dominator (CDI_DOMINATORS, to)); + set_immediate_dominator (CDI_DOMINATORS, orig_dest, + recompute_dominator (CDI_DOMINATORS, orig_dest)); } /* A wrapper for redirect_edge_and_branch. Return TRUE if blocks connected by @@ -5397,11 +5387,12 @@ bool sel_redirect_edge_and_branch (edge e, basic_block to) { bool latch_edge_p; - basic_block src; + basic_block src, orig_dest = e->dest; int prev_max_uid; rtx jump; edge redirected; bool recompute_toporder_p = false; + bool maybe_unreachable = single_pred_p (orig_dest); latch_edge_p = (pipelining_p && current_loop_nest @@ -5432,6 +5423,15 @@ sel_redirect_edge_and_branch (edge e, basic_block to) if (jump) sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP); + /* Only update dominator info when we don't have unreachable blocks. + Otherwise we'll update in maybe_tidy_empty_bb. */ + if (!maybe_unreachable) + { + set_immediate_dominator (CDI_DOMINATORS, to, + recompute_dominator (CDI_DOMINATORS, to)); + set_immediate_dominator (CDI_DOMINATORS, orig_dest, + recompute_dominator (CDI_DOMINATORS, orig_dest)); + } return recompute_toporder_p; } @@ -6156,6 +6156,10 @@ sel_remove_loop_preheader (void) if (BB_END (prev_bb) == bb_note (prev_bb)) free_data_sets (prev_bb); } + + set_immediate_dominator (CDI_DOMINATORS, next_bb, + recompute_dominator (CDI_DOMINATORS, + next_bb)); } } VEC_free (basic_block, heap, preheader_blocks); diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h index 8a67003df455..e5e905b8201b 100644 --- a/gcc/sel-sched-ir.h +++ b/gcc/sel-sched-ir.h @@ -1579,11 +1579,9 @@ extern bool in_same_ebb_p (insn_t, insn_t); extern bool tidy_control_flow (basic_block, bool); extern void free_bb_note_pool (void); -extern void sel_remove_empty_bb (basic_block, bool, bool); extern void purge_empty_blocks (void); extern basic_block sel_split_edge (edge); extern basic_block sel_create_recovery_block (insn_t); -extern void sel_merge_blocks (basic_block, basic_block); extern bool sel_redirect_edge_and_branch (edge, basic_block); extern void sel_redirect_edge_and_branch_force (edge, basic_block); extern void sel_init_pipelining (void); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e8fe3a5110fe..f0c4342233f8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2011-06-20 Andrey Belevantsev + + Backport from mainline + 2010-12-07 Andrey Belevantsev + + PR target/43603 + * gcc.target/ia64/pr43603.c: New. + * gcc/testsuite/g++.dg/opt/pr46640.C: New. + 2011-06-17 Hans-Peter Nilsson Backport from mainline diff --git a/gcc/testsuite/g++.dg/opt/pr46640.C b/gcc/testsuite/g++.dg/opt/pr46640.C new file mode 100644 index 000000000000..0892c9ac861c --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr46640.C @@ -0,0 +1,44 @@ +// { dg-do compile { target x86_64-*-* } } +// { dg-options "-fschedule-insns2 -fsel-sched-pipelining -fselective-scheduling2 -fno-exceptions -O" } + +struct QBasicAtomicInt +{ + int i, j; + bool deref () + { + asm volatile ("":"=m" (i), "=qm" (j)); + } +}; + +struct Data +{ + QBasicAtomicInt ref; + void *data; +}; + +struct QByteArray +{ + Data * d; + ~QByteArray () + { + d->ref.deref (); + } +}; + +int indexOf (unsigned); +int stat (void *, int *); +QByteArray encodeName (); + +bool makeDir (unsigned len) +{ + unsigned i = 0; + while (len) + { + int st; + int pos = indexOf (i); + QByteArray baseEncoded = encodeName (); + if (stat (baseEncoded.d->data, &st) && stat (baseEncoded.d, &st)) + return false; + i = pos; + } +} diff --git a/gcc/testsuite/gcc.target/ia64/pr43603.c b/gcc/testsuite/gcc.target/ia64/pr43603.c new file mode 100644 index 000000000000..ad3a5b114bc9 --- /dev/null +++ b/gcc/testsuite/gcc.target/ia64/pr43603.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +int +foo( long * np, int * dp, int qn) +{ + int i; + int n0; + int d0; + int a; + int b; + int c; + int d; + + a = 1; + b = 0; + c = 1; + d = 1; + + d0 = dp[0]; + + for (i = qn; i >= 0; i--) { + if (bar((c == 0)) && (np[1] == d0)) { + car(np - 3, dp, 3); + } else { + __asm__ ("xma.hu %0 = %2, %3, f0\n\txma.l %1 = %2, %3, f0" : "=&f" ((a)), +"=f" (b) : "f" ((c)), "f" ((d))); + n0 = np[0]; + if (n0 < d0) + c = 1; + else + c = 0; + + } + *--np = a; + } + + return 0; +}