Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-ssa-threadedge.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/tree-ssa-threadedge.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/tree-ssa-threadedge.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* SSA Jump Threading - Copyright (C) 2005-2017 Free Software Foundation, Inc. + Copyright (C) 2005-2018 Free Software Foundation, Inc. Contributed by Jeff Law <law@redhat.com> This file is part of GCC. @@ -37,6 +37,9 @@ #include "tree-ssa-dom.h" #include "gimple-fold.h" #include "cfganal.h" +#include "alloc-pool.h" +#include "vr-values.h" +#include "gimple-ssa-evrp-analyze.h" /* To avoid code explosion due to jump threading, we limit the number of statements we are going to copy. This variable @@ -114,17 +117,16 @@ } /* Record temporary equivalences created by PHIs at the target of the - edge E. Record unwind information for the equivalences onto STACK. + edge E. Record unwind information for the equivalences into + CONST_AND_COPIES and EVRP_RANGE_DATA. If a PHI which prevents threading is encountered, then return FALSE - indicating we should not thread this edge, else return TRUE. - - If SRC_MAP/DST_MAP exist, then mark the source and destination SSA_NAMEs - of any equivalences recorded. We use this to make invalidation after - traversing back edges less painful. */ + indicating we should not thread this edge, else return TRUE. */ static bool -record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_copies) +record_temporary_equivalences_from_phis (edge e, + const_and_copies *const_and_copies, + evrp_range_analyzer *evrp_range_analyzer) { gphi_iterator gsi; @@ -152,6 +154,40 @@ stmt_count++; const_and_copies->record_const_or_copy (dst, src); + + /* Also update the value range associated with DST, using + the range from SRC. + + Note that even if SRC is a constant we need to set a suitable + output range so that VR_UNDEFINED ranges do not leak through. */ + if (evrp_range_analyzer) + { + /* Get an empty new VR we can pass to update_value_range and save + away in the VR stack. */ + vr_values *vr_values = evrp_range_analyzer->get_vr_values (); + value_range *new_vr = vr_values->allocate_value_range (); + *new_vr = value_range (); + + /* There are three cases to consider: + + First if SRC is an SSA_NAME, then we can copy the value + range from SRC into NEW_VR. + + Second if SRC is an INTEGER_CST, then we can just wet + NEW_VR to a singleton range. + + Otherwise set NEW_VR to varying. This may be overly + conservative. */ + if (TREE_CODE (src) == SSA_NAME) + new_vr->deep_copy (vr_values->get_value_range (src)); + else if (TREE_CODE (src) == INTEGER_CST) + set_value_range_to_value (new_vr, src, NULL); + else + set_value_range_to_varying (new_vr); + + /* This is a temporary range for DST, so push it. */ + evrp_range_analyzer->push_value_range (dst, new_vr); + } } return true; } @@ -191,6 +227,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, const_and_copies *const_and_copies, avail_exprs_stack *avail_exprs_stack, + evrp_range_analyzer *evrp_range_analyzer, pfn_simplify simplify) { gimple *stmt = NULL; @@ -233,7 +270,27 @@ expansion, then do not thread through this block. */ stmt_count++; if (stmt_count > max_stmt_count) - return NULL; + { + /* If any of the stmts in the PATH's dests are going to be + killed due to threading, grow the max count + accordingly. */ + if (max_stmt_count + == PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS)) + { + max_stmt_count += estimate_threading_killed_stmts (e->dest); + if (dump_file) + fprintf (dump_file, "threading bb %i up to %i stmts\n", + e->dest->index, max_stmt_count); + } + /* If we're still past the limit, we're done. */ + if (stmt_count > max_stmt_count) + return NULL; + } + + /* These are temporary ranges, do nto reflect them back into + the global range data. */ + if (evrp_range_analyzer) + evrp_range_analyzer->record_ranges_from_stmt (stmt, true); /* If this is not a statement that sets an SSA_NAME to a new value, then do not try to simplify this statement as it will @@ -692,7 +749,7 @@ void propagate_threaded_block_debug_into (basic_block dest, basic_block src) { - if (!MAY_HAVE_DEBUG_STMTS) + if (!MAY_HAVE_DEBUG_BIND_STMTS) return; if (!single_pred_p (dest)) @@ -712,6 +769,8 @@ gimple *stmt = gsi_stmt (si); if (!is_gimple_debug (stmt)) break; + if (gimple_debug_nonbind_marker_p (stmt)) + continue; i++; } @@ -739,6 +798,8 @@ var = gimple_debug_bind_get_var (stmt); else if (gimple_debug_source_bind_p (stmt)) var = gimple_debug_source_bind_get_var (stmt); + else if (gimple_debug_nonbind_marker_p (stmt)) + continue; else gcc_unreachable (); @@ -766,17 +827,23 @@ var = gimple_debug_bind_get_var (stmt); else if (gimple_debug_source_bind_p (stmt)) var = gimple_debug_source_bind_get_var (stmt); + else if (gimple_debug_nonbind_marker_p (stmt)) + continue; else gcc_unreachable (); - /* Discard debug bind overlaps. ??? Unlike stmts from src, + /* Discard debug bind overlaps. Unlike stmts from src, copied into a new block that will precede BB, debug bind stmts in bypassed BBs may actually be discarded if - they're overwritten by subsequent debug bind stmts, which - might be a problem once we introduce stmt frontier notes - or somesuch. Adding `&& bb == src' to the condition - below will preserve all potentially relevant debug - notes. */ + they're overwritten by subsequent debug bind stmts. We + want to copy binds for all modified variables, so that we + retain a bind to the shared def if there is one, or to a + newly introduced PHI node if there is one. Our bind will + end up reset if the value is dead, but that implies the + variable couldn't have survived, so it's fine. We are + not actually running the code that performed the binds at + this point, we're just adding binds so that they survive + the new confluence, so markers should not be copied. */ if (vars && vars->add (var)) continue; else if (!vars) @@ -787,8 +854,7 @@ break; if (i >= 0) continue; - - if (fewvars.length () < (unsigned) alloc_count) + else if (fewvars.length () < (unsigned) alloc_count) fewvars.quick_push (var); else { @@ -911,11 +977,12 @@ || TREE_CODE (cond) == CASE_LABEL_EXPR)) { if (TREE_CODE (cond) == CASE_LABEL_EXPR) - taken_edge = find_edge (bb, label_to_block (CASE_LABEL (cond))); + taken_edge = find_edge (bb, label_to_block (cfun, CASE_LABEL (cond))); else taken_edge = find_taken_edge (bb, cond); - if ((taken_edge->flags & EDGE_DFS_BACK) != 0) + if (!taken_edge + || (taken_edge->flags & EDGE_DFS_BACK) != 0) return false; if (bitmap_bit_p (visited, taken_edge->dest->index)) @@ -972,6 +1039,7 @@ gcond *dummy_cond, const_and_copies *const_and_copies, avail_exprs_stack *avail_exprs_stack, + evrp_range_analyzer *evrp_range_analyzer, pfn_simplify simplify, vec<jump_thread_edge *> *path, bitmap visited) @@ -983,7 +1051,8 @@ Note that if we found a PHI that made the block non-threadable, then we need to bubble that up to our caller in the same manner we do when we prematurely stop processing statements below. */ - if (!record_temporary_equivalences_from_phis (e, const_and_copies)) + if (!record_temporary_equivalences_from_phis (e, const_and_copies, + evrp_range_analyzer)) return -1; /* Now walk each statement recording any context sensitive @@ -991,6 +1060,7 @@ gimple *stmt = record_temporary_equivalences_from_stmts_at_dest (e, const_and_copies, avail_exprs_stack, + evrp_range_analyzer, simplify); /* There's two reasons STMT might be null, and distinguishing @@ -1040,7 +1110,7 @@ edge taken_edge; if (TREE_CODE (cond) == CASE_LABEL_EXPR) taken_edge = find_edge (e->dest, - label_to_block (CASE_LABEL (cond))); + label_to_block (cfun, CASE_LABEL (cond))); else taken_edge = find_taken_edge (e->dest, cond); @@ -1105,12 +1175,15 @@ edge e, class const_and_copies *const_and_copies, class avail_exprs_stack *avail_exprs_stack, + class evrp_range_analyzer *evrp_range_analyzer, pfn_simplify simplify) { bitmap visited = BITMAP_ALLOC (NULL); const_and_copies->push_marker (); avail_exprs_stack->push_marker (); + if (evrp_range_analyzer) + evrp_range_analyzer->push_marker (); stmt_count = 0; @@ -1124,6 +1197,7 @@ threaded = thread_through_normal_block (e, dummy_cond, const_and_copies, avail_exprs_stack, + evrp_range_analyzer, simplify, path, visited); else @@ -1135,6 +1209,8 @@ e->dest); const_and_copies->pop_to_marker (); avail_exprs_stack->pop_to_marker (); + if (evrp_range_analyzer) + evrp_range_analyzer->pop_to_marker (); BITMAP_FREE (visited); register_jump_thread (path); return; @@ -1160,6 +1236,8 @@ BITMAP_FREE (visited); const_and_copies->pop_to_marker (); avail_exprs_stack->pop_to_marker (); + if (evrp_range_analyzer) + evrp_range_analyzer->pop_to_marker (); return; } } @@ -1187,6 +1265,8 @@ { const_and_copies->pop_to_marker (); avail_exprs_stack->pop_to_marker (); + if (evrp_range_analyzer) + evrp_range_analyzer->pop_to_marker (); BITMAP_FREE (visited); return; } @@ -1202,6 +1282,8 @@ for each of E->dest's successors. */ const_and_copies->push_marker (); avail_exprs_stack->push_marker (); + if (evrp_range_analyzer) + evrp_range_analyzer->push_marker (); /* Avoid threading to any block we have already visited. */ bitmap_clear (visited); @@ -1229,6 +1311,7 @@ found = thread_through_normal_block (path->last ()->e, dummy_cond, const_and_copies, avail_exprs_stack, + evrp_range_analyzer, simplify, path, visited) > 0; @@ -1244,12 +1327,16 @@ delete_jump_thread_path (path); /* And unwind the equivalence table. */ + if (evrp_range_analyzer) + evrp_range_analyzer->pop_to_marker (); avail_exprs_stack->pop_to_marker (); const_and_copies->pop_to_marker (); } BITMAP_FREE (visited); } + if (evrp_range_analyzer) + evrp_range_analyzer->pop_to_marker (); const_and_copies->pop_to_marker (); avail_exprs_stack->pop_to_marker (); } @@ -1271,6 +1358,7 @@ thread_outgoing_edges (basic_block bb, gcond *dummy_cond, class const_and_copies *const_and_copies, class avail_exprs_stack *avail_exprs_stack, + class evrp_range_analyzer *evrp_range_analyzer, tree (*simplify) (gimple *, gimple *, class avail_exprs_stack *, basic_block)) @@ -1288,7 +1376,7 @@ { thread_across_edge (dummy_cond, single_succ_edge (bb), const_and_copies, avail_exprs_stack, - simplify); + evrp_range_analyzer, simplify); } else if ((last = last_stmt (bb)) && gimple_code (last) == GIMPLE_COND @@ -1304,11 +1392,13 @@ more than one predecessor and more than one successor. */ if (potentially_threadable_block (true_edge->dest)) thread_across_edge (dummy_cond, true_edge, - const_and_copies, avail_exprs_stack, simplify); + const_and_copies, avail_exprs_stack, + evrp_range_analyzer, simplify); /* Similarly for the ELSE arm. */ if (potentially_threadable_block (false_edge->dest)) thread_across_edge (dummy_cond, false_edge, - const_and_copies, avail_exprs_stack, simplify); + const_and_copies, avail_exprs_stack, + evrp_range_analyzer, simplify); } }