From b720e91919619f0b4886b0c21c704916ce133fbb Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Sun, 18 Sep 2016 20:44:53 +0200 Subject: [PATCH] passes.def (pass_early_thread_jumps): Schedule after forwprop. * passes.def (pass_early_thread_jumps): Schedule after forwprop. * tree-pass.h (make_pass_early_thread_jumps): Declare. * tree-ssa-threadbackward.c (fsm_find_thread_path, fsm_find_thread_path, profitable_jump_thread_path, fsm_find_control_statement_thread_paths, find_jump_threads_backwards): Add speed_p parameter. (pass_data_early_thread_jumps): New pass. (make_pass_early_thread_jumps): New function. * g++.dg/predict-loop-exit-1.C: Disable early jump threading. * g++.dg/predict-loop-exit-2.C: Disable early jump threading. * g++.dg/predict-loop-exit-3.C: Disable early jump threading. * gcc.dg/tree-ssa/pr69196-1.c: Disable early jump threading. * gcc.dg/tree-ssa/vrp01.c: Disable early jump threading. * gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Disable early jump threading. * gcc.dg/tree-ssa/pr68198.c: Scan ethread dump. * gcc.dg/tree-ssa/ssa-thread-13.c: Scan ethread dump. * gcc.dg/tree-ssa/vrp56.c: Scan ethread dump. * gcc.dg/tree-ssa/vrp92.c: Scan ethread dump. * gcc.dg/uninit-15.c: Swap xfailed and non-xfailed alternative. From-SVN: r240221 --- gcc/ChangeLog | 11 ++ gcc/passes.def | 1 + gcc/testsuite/ChangeLog | 14 +++ gcc/testsuite/g++.dg/predict-loop-exit-1.C | 2 +- gcc/testsuite/g++.dg/predict-loop-exit-2.C | 2 +- gcc/testsuite/g++.dg/predict-loop-exit-3.C | 2 +- gcc/testsuite/gcc.dg/tree-ssa/pr68198.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c | 2 +- .../gcc.dg/tree-ssa/ssa-dom-thread-2b.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/vrp01.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/vrp56.c | 4 +- gcc/testsuite/gcc.dg/tree-ssa/vrp92.c | 2 +- gcc/testsuite/gcc.dg/uninit-15.c | 10 +- gcc/tree-pass.h | 1 + gcc/tree-ssa-threadbackward.c | 100 +++++++++++++++--- 16 files changed, 128 insertions(+), 35 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b8a9dab5042..8eecbfe5118 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-09-17 Jan Hubicka + + * passes.def (pass_early_thread_jumps): Schedule after forwprop. + * tree-pass.h (make_pass_early_thread_jumps): Declare. + * tree-ssa-threadbackward.c (fsm_find_thread_path, + fsm_find_thread_path, profitable_jump_thread_path, + fsm_find_control_statement_thread_paths, + find_jump_threads_backwards): Add speed_p parameter. + (pass_data_early_thread_jumps): New pass. + (make_pass_early_thread_jumps): New function. + 2016-09-17 Andreas Schwab * config/ia64/ia64.h (ASM_OUTPUT_DWARF_OFFSET): Add cast. diff --git a/gcc/passes.def b/gcc/passes.def index 533157d621c..e98a719fc2b 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see /* After CCP we rewrite no longer addressed locals into SSA form if possible. */ NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_early_thread_jumps); NEXT_PASS (pass_sra_early); /* pass_build_ealias is a dummy pass that ensures that we execute TODO_rebuild_alias at this point. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5793f83ea24..956977c5439 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2016-09-17 Jan Hubicka + + * g++.dg/predict-loop-exit-1.C: Disable early jump threading. + * g++.dg/predict-loop-exit-2.C: Disable early jump threading. + * g++.dg/predict-loop-exit-3.C: Disable early jump threading. + * gcc.dg/tree-ssa/pr69196-1.c: Disable early jump threading. + * gcc.dg/tree-ssa/vrp01.c: Disable early jump threading. + * gcc.dg/tree-ssa/ssa-dom-thread-2b.c: Disable early jump threading. + * gcc.dg/tree-ssa/pr68198.c: Scan ethread dump. + * gcc.dg/tree-ssa/ssa-thread-13.c: Scan ethread dump. + * gcc.dg/tree-ssa/vrp56.c: Scan ethread dump. + * gcc.dg/tree-ssa/vrp92.c: Scan ethread dump. + * gcc.dg/uninit-15.c: Swap xfailed and non-xfailed alternative. + 2016-09-18 Kirill Yukhin * gcc.target/i386/pr68633.c: Fix expected result. diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-1.C b/gcc/testsuite/g++.dg/predict-loop-exit-1.C index 88262eb9d00..47bdf5182c1 100644 --- a/gcc/testsuite/g++.dg/predict-loop-exit-1.C +++ b/gcc/testsuite/g++.dg/predict-loop-exit-1.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ +/* { dg-options "-O2 -fdump-tree-profile_estimate -fdisable-tree-ethread" } */ int g; int foo(); diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-2.C b/gcc/testsuite/g++.dg/predict-loop-exit-2.C index 15e9866d897..15b63eeb0fa 100644 --- a/gcc/testsuite/g++.dg/predict-loop-exit-2.C +++ b/gcc/testsuite/g++.dg/predict-loop-exit-2.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ +/* { dg-options "-O2 -fdump-tree-profile_estimate -fdisable-tree-ethread" } */ int g; int foo(); diff --git a/gcc/testsuite/g++.dg/predict-loop-exit-3.C b/gcc/testsuite/g++.dg/predict-loop-exit-3.C index 61af84b6f56..8d417422b60 100644 --- a/gcc/testsuite/g++.dg/predict-loop-exit-3.C +++ b/gcc/testsuite/g++.dg/predict-loop-exit-3.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-profile_estimate" } */ +/* { dg-options "-O2 -fdump-tree-profile_estimate -fdisable-tree-ethread" } */ int g; int foo(); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c index d678dc8c2cd..79e65aa01f4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr68198.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-details" } */ +/* { dg-options "-O2 -fdump-tree-thread1-details -fdisable-tree-ethread" } */ extern void abort (void); @@ -40,4 +40,4 @@ c_finish_omp_clauses (tree clauses) /* There are 3 FSM jump threading opportunities, two of which will get filtered out. */ /* { dg-final { scan-tree-dump-times "Registering FSM" 1 "thread1"} } */ -/* { dg-final { scan-tree-dump-times "FSM Thread through multiway branch without threading a multiway branch" 2 "thread1"} } */ +/* { dg-final { scan-tree-dump-times "FSM Thread through multiway branch without threading a multiway branch" 2 "ethread"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c index 5842e28b94b..5f92447854b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr69196-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target sparc*-*-* x86_64-*-* } } */ -/* { dg-options "-O2 -fdump-tree-thread1-details" } */ +/* { dg-options "-O2 -fdump-tree-thread1-details -fdisable-tree-ethread" } */ /* { dg-final { scan-tree-dump "FSM did not thread around loop and would copy too many statements" "thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c index eb66136e47f..e1c33e86cd7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2b.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-dom2-stats" } */ +/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-dom2-stats -fdisable-tree-ethread" } */ void foo(); void bla(); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c index f5f338ba357..061f2235533 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-13.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-details" } */ -/* { dg-final { scan-tree-dump "FSM" "thread1" } } */ +/* { dg-options "-O2 -fdump-tree-ethread-details" } */ +/* { dg-final { scan-tree-dump "FSM" "ethread" } } */ typedef struct rtx_def *rtx; typedef const struct rtx_def *const_rtx; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c index c6d10c2dbcf..f25f2761d47 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1" } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdisable-tree-ethread" } */ int foo (int *p, int i) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c index 3a64b017c18..c2870c45907 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp56.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-stats" } */ +/* { dg-options "-O2 -fdump-tree-ethread-stats" } */ typedef struct basic_block_def *basic_block; struct basic_block_def; struct edge_def; @@ -38,5 +38,5 @@ cleanup_empty_eh (basic_block bb) foo (); } } -/* { dg-final { scan-tree-dump "Jumps threaded: 1" "thread1"} } */ +/* { dg-final { scan-tree-dump "Jumps threaded: 1" "ethread"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c index b096e9b3602..5d5375073e6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details -fdisable-tree-ethread" } */ void bar (void); int foo (int i, int j) diff --git a/gcc/testsuite/gcc.dg/uninit-15.c b/gcc/testsuite/gcc.dg/uninit-15.c index 20bea95acd8..6154f4b638a 100644 --- a/gcc/testsuite/gcc.dg/uninit-15.c +++ b/gcc/testsuite/gcc.dg/uninit-15.c @@ -1,16 +1,16 @@ /* PR tree-optimization/17506 We issue an uninitialized variable warning at a wrong location at line 11, which is very confusing. Make sure we print out a note to - make it less confusing. (xfailed alternative) + make it less confusing. (not xfailed alternative) But it is of course ok if we warn in bar about uninitialized use - of j. (not xfailed alternative) */ + of j. (xfailed alternative) */ /* { dg-do compile } */ /* { dg-options "-O1 -Wuninitialized" } */ inline int foo (int i) { - if (i) /* { dg-warning "used uninitialized in this function" "" { xfail *-*-* } } */ + if (i) /* { dg-warning "used uninitialized in this function" } */ return 1; return 0; } @@ -20,7 +20,7 @@ void baz (void); void bar (void) { - int j; /* { dg-message "note: 'j' was declared here" "" { xfail *-*-* } } */ - for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" } */ + int j; /* { dg-message "note: 'j' was declared here" } */ + for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */ baz (); } diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index c0059de89ff..cc87b184d67 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -399,6 +399,7 @@ extern gimple_opt_pass *make_pass_cd_dce (gcc::context *ctxt); extern gimple_opt_pass *make_pass_call_cdce (gcc::context *ctxt); extern gimple_opt_pass *make_pass_merge_phi (gcc::context *ctxt); extern gimple_opt_pass *make_pass_thread_jumps (gcc::context *ctxt); +extern gimple_opt_pass *make_pass_early_thread_jumps (gcc::context *ctxt); extern gimple_opt_pass *make_pass_split_crit_edges (gcc::context *ctxt); extern gimple_opt_pass *make_pass_laddress (gcc::context *ctxt); extern gimple_opt_pass *make_pass_pre (gcc::context *ctxt); diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c index 506078f2358..6b522adcefb 100644 --- a/gcc/tree-ssa-threadbackward.c +++ b/gcc/tree-ssa-threadbackward.c @@ -61,12 +61,14 @@ get_gimple_control_stmt (basic_block bb) /* Return true if the CFG contains at least one path from START_BB to END_BB. When a path is found, record in PATH the blocks from END_BB to START_BB. VISITED_BBS is used to make sure we don't fall into an infinite loop. Bound - the recursion to basic blocks belonging to LOOP. */ + the recursion to basic blocks belonging to LOOP. + SPEED_P indicate that we could increase code size to improve the code path */ static bool fsm_find_thread_path (basic_block start_bb, basic_block end_bb, vec *&path, - hash_set *visited_bbs, loop_p loop) + hash_set *visited_bbs, loop_p loop, + bool speed_p) { if (loop != start_bb->loop_father) return false; @@ -82,7 +84,8 @@ fsm_find_thread_path (basic_block start_bb, basic_block end_bb, edge e; edge_iterator ei; FOR_EACH_EDGE (e, ei, start_bb->succs) - if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop)) + if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop, + speed_p)) { vec_safe_push (path, start_bb); return true; @@ -101,11 +104,13 @@ fsm_find_thread_path (basic_block start_bb, basic_block end_bb, value on PATH. ARG is the value of that SSA_NAME. BBI will be appended to PATH when we have a profitable jump threading - path. Callers are responsible for removing BBI from PATH in that case. */ + path. Callers are responsible for removing BBI from PATH in that case. + + SPEED_P indicate that we could increase code size to improve the code path */ static edge profitable_jump_thread_path (vec *&path, - basic_block bbi, tree name, tree arg) + basic_block bbi, tree name, tree arg, bool speed_p) { /* Note BBI is not in the path yet, hence the +1 in the test below to make sure BBI is accounted for in the path length test. */ @@ -307,7 +312,7 @@ profitable_jump_thread_path (vec *&path, return NULL; } - if (optimize_edge_for_speed_p (taken_edge)) + if (speed_p && optimize_edge_for_speed_p (taken_edge)) { if (n_insns >= PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATH_INSNS)) { @@ -422,13 +427,15 @@ convert_and_register_jump_thread_path (vec *path, /* We trace the value of the SSA_NAME NAME back through any phi nodes looking for places where it gets a constant value and save the path. Stop after - having recorded MAX_PATHS jump threading paths. */ + having recorded MAX_PATHS jump threading paths. + + SPEED_P indicate that we could increase code size to improve the code path */ static void fsm_find_control_statement_thread_paths (tree name, hash_set *visited_bbs, vec *&path, - bool seen_loop_phi) + bool seen_loop_phi, bool speed_p) { /* If NAME appears in an abnormal PHI, then don't try to trace its value back through PHI nodes. */ @@ -496,7 +503,7 @@ fsm_find_control_statement_thread_paths (tree name, hash_set *visited_bbs = new hash_set; if (fsm_find_thread_path (var_bb, e->src, next_path, visited_bbs, - e->src->loop_father)) + e->src->loop_father, speed_p)) ++e_count; delete visited_bbs; @@ -562,7 +569,7 @@ fsm_find_control_statement_thread_paths (tree name, /* Recursively follow SSA_NAMEs looking for a constant definition. */ fsm_find_control_statement_thread_paths (arg, visited_bbs, path, - seen_loop_phi); + seen_loop_phi, speed_p); path->pop (); continue; @@ -573,7 +580,8 @@ fsm_find_control_statement_thread_paths (tree name, /* If this is a profitable jump thread path, then convert it into the canonical form and register it. */ - edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg); + edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg, + speed_p); if (taken_edge) { if (bb_loop_depth (taken_edge->src) @@ -589,7 +597,7 @@ fsm_find_control_statement_thread_paths (tree name, if (TREE_CODE (arg) == SSA_NAME) fsm_find_control_statement_thread_paths (arg, visited_bbs, - path, seen_loop_phi); + path, seen_loop_phi, speed_p); else { @@ -599,7 +607,7 @@ fsm_find_control_statement_thread_paths (tree name, path->pop (); edge taken_edge = profitable_jump_thread_path (path, var_bb, - name, arg); + name, arg, speed_p); if (taken_edge) { if (bb_loop_depth (taken_edge->src) @@ -623,10 +631,11 @@ fsm_find_control_statement_thread_paths (tree name, is a constant. Record such paths for jump threading. It is assumed that BB ends with a control statement and that by - finding a path where NAME is a constant, we can thread the path. */ + finding a path where NAME is a constant, we can thread the path. + SPEED_P indicate that we could increase code size to improve the code path */ void -find_jump_threads_backwards (basic_block bb) +find_jump_threads_backwards (basic_block bb, bool speed_p) { gimple *stmt = get_gimple_control_stmt (bb); if (!stmt) @@ -656,7 +665,8 @@ find_jump_threads_backwards (basic_block bb) hash_set *visited_bbs = new hash_set; max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS); - fsm_find_control_statement_thread_paths (name, visited_bbs, bb_path, false); + fsm_find_control_statement_thread_paths (name, visited_bbs, bb_path, false, + speed_p); delete visited_bbs; vec_free (bb_path); @@ -706,7 +716,7 @@ pass_thread_jumps::execute (function *fun) FOR_EACH_BB_FN (bb, fun) { if (EDGE_COUNT (bb->succs) > 1) - find_jump_threads_backwards (bb); + find_jump_threads_backwards (bb, true); } bool changed = thread_through_all_blocks (true); @@ -721,3 +731,59 @@ make_pass_thread_jumps (gcc::context *ctxt) { return new pass_thread_jumps (ctxt); } + +namespace { + +const pass_data pass_data_early_thread_jumps = +{ + GIMPLE_PASS, + "ethread", + OPTGROUP_NONE, + TV_TREE_SSA_THREAD_JUMPS, + ( PROP_cfg | PROP_ssa ), + 0, + 0, + 0, + ( TODO_cleanup_cfg | TODO_update_ssa ), +}; + +class pass_early_thread_jumps : public gimple_opt_pass +{ +public: + pass_early_thread_jumps (gcc::context *ctxt) + : gimple_opt_pass (pass_data_early_thread_jumps, ctxt) + {} + + opt_pass * clone (void) { return new pass_early_thread_jumps (m_ctxt); } + virtual bool gate (function *); + virtual unsigned int execute (function *); +}; + +bool +pass_early_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED) +{ + return true; +} + + +unsigned int +pass_early_thread_jumps::execute (function *fun) +{ + /* Try to thread each block with more than one successor. */ + basic_block bb; + FOR_EACH_BB_FN (bb, fun) + { + if (EDGE_COUNT (bb->succs) > 1) + find_jump_threads_backwards (bb, false); + } + thread_through_all_blocks (true); + return 0; +} + +} + +gimple_opt_pass * +make_pass_early_thread_jumps (gcc::context *ctxt) +{ + return new pass_early_thread_jumps (ctxt); +} -- 2.30.2