diff options
author | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-12 12:53:53 +0000 |
---|---|---|
committer | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-12 12:53:53 +0000 |
commit | c6829ed5779df9545071cabf6f9b4c75e3e33e07 (patch) | |
tree | 8204bc7db38fa0de22d6be0af6e5095e7e8aaf5a /gcc | |
parent | 3ab7b731173156a56b52c191c9917c5b0fbb6e42 (diff) | |
download | gcc-c6829ed5779df9545071cabf6f9b4c75e3e33e07.tar.gz |
2013-11-12 Martin Jambor <mjambor@suse.cz>
PR rtl-optimization/10474
* ira.c (interesting_dest_for_shprep): New function.
(split_live_ranges_for_shrink_wrap): Likewise.
(find_moveable_pseudos): Move calculation of dominance info,
df_analysios and the final anlyses to...
(ira): ...here, call split_live_ranges_for_shrink_wrap.
testsuite/
* gcc.dg/pr10474.c: New testcase.
* gcc.dg/ira-shrinkwrap-prep-1.c: Likewise.
* gcc.dg/ira-shrinkwrap-prep-2.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204698 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/ira.c | 216 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr10474.c | 16 |
6 files changed, 304 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9fcafb66865..4a8b2e1fe97 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-11-12 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/10474 + * ira.c (interesting_dest_for_shprep): New function. + (split_live_ranges_for_shrink_wrap): Likewise. + (find_moveable_pseudos): Move calculation of dominance info, + df_analysios and the final anlyses to... + (ira): ...here, call split_live_ranges_for_shrink_wrap. + 2013-11-12 Bin Cheng <bin.cheng@arm.com> * tree-ssa-loop-ivopts.c (force_expr_to_var_cost): Refactor the code. diff --git a/gcc/ira.c b/gcc/ira.c index 10e71d97db3..2ef69cb5e6d 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -4515,9 +4515,6 @@ find_moveable_pseudos (void) pseudo_replaced_reg.release (); pseudo_replaced_reg.safe_grow_cleared (max_regs); - df_analyze (); - calculate_dominance_info (CDI_DOMINATORS); - i = 0; bitmap_initialize (&live, 0); bitmap_initialize (&used, 0); @@ -4830,14 +4827,196 @@ find_moveable_pseudos (void) free (bb_moveable_reg_sets); last_moveable_pseudo = max_reg_num (); +} - fix_reg_equiv_init (); - expand_reg_info (); - regstat_free_n_sets_and_refs (); - regstat_free_ri (); - regstat_init_n_sets_and_refs (); - regstat_compute_ri (); - free_dominance_info (CDI_DOMINATORS); + +/* If insn is interesting for parameter range-splitting shring-wrapping + preparation, i.e. it is a single set from a hard register to a pseudo, which + is live at CALL_DOM, return the destination. Otherwise return NULL. */ + +static rtx +interesting_dest_for_shprep (rtx insn, basic_block call_dom) +{ + rtx set = single_set (insn); + if (!set) + return NULL; + rtx src = SET_SRC (set); + rtx dest = SET_DEST (set); + if (!REG_P (src) || !HARD_REGISTER_P (src) + || !REG_P (dest) || HARD_REGISTER_P (dest) + || (call_dom && !bitmap_bit_p (df_get_live_in (call_dom), REGNO (dest)))) + return NULL; + return dest; +} + +/* Split live ranges of pseudos that are loaded from hard registers in the + first BB in a BB that dominates all non-sibling call if such a BB can be + found and is not in a loop. Return true if the function has made any + changes. */ + +static bool +split_live_ranges_for_shrink_wrap (void) +{ + basic_block bb, call_dom = NULL; + basic_block first = single_succ (ENTRY_BLOCK_PTR); + rtx insn, last_interesting_insn = NULL; + bitmap_head need_new, reachable; + vec<basic_block> queue; + + if (!flag_shrink_wrap) + return false; + + bitmap_initialize (&need_new, 0); + bitmap_initialize (&reachable, 0); + queue.create (n_basic_blocks); + + FOR_EACH_BB (bb) + FOR_BB_INSNS (bb, insn) + if (CALL_P (insn) && !SIBLING_CALL_P (insn)) + { + if (bb == first) + { + bitmap_clear (&need_new); + bitmap_clear (&reachable); + queue.release (); + return false; + } + + bitmap_set_bit (&need_new, bb->index); + bitmap_set_bit (&reachable, bb->index); + queue.quick_push (bb); + break; + } + + if (queue.is_empty ()) + { + bitmap_clear (&need_new); + bitmap_clear (&reachable); + queue.release (); + return false; + } + + while (!queue.is_empty ()) + { + edge e; + edge_iterator ei; + + bb = queue.pop (); + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->dest != EXIT_BLOCK_PTR + && bitmap_set_bit (&reachable, e->dest->index)) + queue.quick_push (e->dest); + } + queue.release (); + + FOR_BB_INSNS (first, insn) + { + rtx dest = interesting_dest_for_shprep (insn, NULL); + if (!dest) + continue; + + if (DF_REG_DEF_COUNT (REGNO (dest)) > 1) + { + bitmap_clear (&need_new); + bitmap_clear (&reachable); + return false; + } + + for (df_ref use = DF_REG_USE_CHAIN (REGNO(dest)); + use; + use = DF_REF_NEXT_REG (use)) + { + if (NONDEBUG_INSN_P (DF_REF_INSN (use)) + && GET_CODE (DF_REF_REG (use)) == SUBREG) + { + /* This is necessary to avoid hitting an assert at + postreload.c:2294 in libstc++ testcases on x86_64-linux. I'm + not really sure what the probblem actually is there. */ + bitmap_clear (&need_new); + bitmap_clear (&reachable); + return false; + } + + int ubbi = DF_REF_BB (use)->index; + if (bitmap_bit_p (&reachable, ubbi)) + bitmap_set_bit (&need_new, ubbi); + } + last_interesting_insn = insn; + } + + bitmap_clear (&reachable); + if (!last_interesting_insn) + { + bitmap_clear (&need_new); + return false; + } + + call_dom = nearest_common_dominator_for_set (CDI_DOMINATORS, &need_new); + bitmap_clear (&need_new); + if (call_dom == first) + return false; + + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + while (bb_loop_depth (call_dom) > 0) + call_dom = get_immediate_dominator (CDI_DOMINATORS, call_dom); + loop_optimizer_finalize (); + + if (call_dom == first) + return false; + + calculate_dominance_info (CDI_POST_DOMINATORS); + if (dominated_by_p (CDI_POST_DOMINATORS, first, call_dom)) + { + free_dominance_info (CDI_POST_DOMINATORS); + return false; + } + free_dominance_info (CDI_POST_DOMINATORS); + + if (dump_file) + fprintf (dump_file, "Will split live ranges of parameters at BB %i\n", + call_dom->index); + + bool ret = false; + FOR_BB_INSNS (first, insn) + { + rtx dest = interesting_dest_for_shprep (insn, call_dom); + if (!dest) + continue; + + rtx newreg = NULL_RTX; + df_ref use, next; + for (use = DF_REG_USE_CHAIN (REGNO(dest)); use; use = next) + { + rtx uin = DF_REF_INSN (use); + next = DF_REF_NEXT_REG (use); + + basic_block ubb = BLOCK_FOR_INSN (uin); + if (ubb == call_dom + || dominated_by_p (CDI_DOMINATORS, ubb, call_dom)) + { + if (!newreg) + newreg = ira_create_new_reg (dest); + validate_change (uin, DF_REF_LOC (use), newreg, true); + } + } + + if (newreg) + { + rtx new_move = gen_move_insn (newreg, dest); + emit_insn_after (new_move, bb_note (call_dom)); + if (dump_file) + { + fprintf (dump_file, "Split live-range of register "); + print_rtl_single (dump_file, dest); + } + ret = true; + } + + if (insn == last_interesting_insn) + break; + } + apply_change_group (); + return ret; } /* Perform the second half of the transformation started in @@ -5049,7 +5228,22 @@ ira (FILE *f) allocation because of -O0 usage or because the function is too big. */ if (ira_conflicts_p) - find_moveable_pseudos (); + { + df_analyze (); + calculate_dominance_info (CDI_DOMINATORS); + + find_moveable_pseudos (); + if (split_live_ranges_for_shrink_wrap ()) + df_analyze (); + + fix_reg_equiv_init (); + expand_reg_info (); + regstat_free_n_sets_and_refs (); + regstat_free_ri (); + regstat_init_n_sets_and_refs (); + regstat_compute_ri (); + free_dominance_info (CDI_DOMINATORS); + } max_regno_before_ira = max_reg_num (); ira_setup_eliminable_regset (true); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 07106bc31a7..e685e669908 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-11-12 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/10474 + * gcc.dg/pr10474.c: New testcase. + * gcc.dg/ira-shrinkwrap-prep-1.c: Likewise. + * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise. + 2013-11-12 Paolo Carlini <paolo.carlini@oracle.com> PR c++/57734 diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c new file mode 100644 index 00000000000..16095e30854 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c @@ -0,0 +1,31 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */ + +int __attribute__((noinline, noclone)) +foo (int a) +{ + return a + 5; +} + +static int g; + +int __attribute__((noinline, noclone)) +bar (int a) +{ + int r; + + if (a) + { + r = foo (a); + g = r + a; + } + else + r = a+1; + return r; +} + +/* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } */ +/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" } } */ +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */ +/* { dg-final { cleanup-rtl-dump "ira" } } */ +/* { dg-final { cleanup-rtl-dump "pro_and_epilogue" } } */ diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c new file mode 100644 index 00000000000..2b00c5b4997 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c @@ -0,0 +1,36 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */ + +int __attribute__((noinline, noclone)) +foo (int a) +{ + return a + 5; +} + +static int g; + +int __attribute__((noinline, noclone)) +bar (int a) +{ + int r; + + if (a) + { + r = a; + while (r < 500) + if (r % 2) + r = foo (r); + else + r = foo (r+1); + g = r + a; + } + else + r = g+1; + return r; +} + +/* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } */ +/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" } } */ +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */ +/* { dg-final { cleanup-rtl-dump "ira" } } */ +/* { dg-final { cleanup-rtl-dump "pro_and_epilogue" } } */ diff --git a/gcc/testsuite/gcc.dg/pr10474.c b/gcc/testsuite/gcc.dg/pr10474.c new file mode 100644 index 00000000000..4fcd75deed7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr10474.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O3 -fdump-rtl-pro_and_epilogue" } */ + +void f(int *i) +{ + if (!i) + return; + else + { + __builtin_printf("Hi"); + *i=0; + } +} + +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */ +/* { dg-final { cleanup-rtl-dump "pro_and_epilogue" } } */ |