diff options
Diffstat (limited to 'gcc/tree-ssa-threadedge.c')
-rw-r--r-- | gcc/tree-ssa-threadedge.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 9e10e44..4f83991 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "params.h" #include "tree-ssa-threadedge.h" +#include "tree-ssa-loop.h" #include "builtins.h" #include "cfg.h" #include "cfganal.h" @@ -1006,7 +1007,8 @@ static int max_threaded_paths; static void fsm_find_control_statement_thread_paths (tree expr, hash_set<gimple> *visited_phis, - vec<basic_block, va_gc> *&path) + vec<basic_block, va_gc> *&path, + bool seen_loop_phi) { tree var = SSA_NAME_VAR (expr); gimple def_stmt = SSA_NAME_DEF_STMT (expr); @@ -1030,6 +1032,14 @@ fsm_find_control_statement_thread_paths (tree expr, int next_path_length = 0; basic_block last_bb_in_path = path->last (); + if (loop_containing_stmt (phi)->header == gimple_bb (phi)) + { + /* Do not walk through more than one loop PHI node. */ + if (seen_loop_phi) + return; + seen_loop_phi = true; + } + /* Following the chain of SSA_NAME definitions, we jumped from a definition in LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */ @@ -1090,7 +1100,9 @@ fsm_find_control_statement_thread_paths (tree expr, { vec_safe_push (path, bbi); /* Recursively follow SSA_NAMEs looking for a constant definition. */ - fsm_find_control_statement_thread_paths (arg, visited_phis, path); + fsm_find_control_statement_thread_paths (arg, visited_phis, path, + seen_loop_phi); + path->pop (); continue; } @@ -1357,7 +1369,8 @@ thread_through_normal_block (edge e, hash_set<gimple> *visited_phis = new hash_set<gimple>; max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS); - fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path); + fsm_find_control_statement_thread_paths (cond, visited_phis, bb_path, + false); delete visited_phis; vec_free (bb_path); |