summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-sccvn.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-sccvn.c')
-rw-r--r--gcc/tree-ssa-sccvn.c159
1 files changed, 106 insertions, 53 deletions
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 0b20a4ebc72..86777c784f0 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1947,9 +1947,7 @@ process_scc (VEC (tree, heap) *scc)
changed |= visit_use (var);
}
- if (dump_file && (dump_flags & TDF_STATS))
- fprintf (dump_file, "Processing SCC required %d iterations\n",
- iterations);
+ statistics_histogram_event (cfun, "SCC iterations", iterations);
/* Finally, visit the SCC once using the valid table. */
current_info = valid_info;
@@ -1958,6 +1956,53 @@ process_scc (VEC (tree, heap) *scc)
}
}
+DEF_VEC_O(ssa_op_iter);
+DEF_VEC_ALLOC_O(ssa_op_iter,heap);
+
+/* Pop the components of the found SCC for NAME off the SCC stack
+ and process them. Returns true if all went well, false if
+ we run into resource limits. */
+
+static bool
+extract_and_process_scc_for_name (tree name)
+{
+ VEC (tree, heap) *scc = NULL;
+ tree x;
+
+ /* Found an SCC, pop the components off the SCC stack and
+ process them. */
+ do
+ {
+ x = VEC_pop (tree, sccstack);
+
+ VN_INFO (x)->on_sccstack = false;
+ VEC_safe_push (tree, heap, scc, x);
+ } while (x != name);
+
+ /* Bail out of SCCVN in case a SCC turns out to be incredibly large. */
+ if (VEC_length (tree, scc)
+ > (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE))
+ {
+ if (dump_file)
+ fprintf (dump_file, "WARNING: Giving up with SCCVN due to "
+ "SCC size %u exceeding %u\n", VEC_length (tree, scc),
+ (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE));
+ return false;
+ }
+
+ if (VEC_length (tree, scc) > 1)
+ sort_scc (scc);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ print_scc (dump_file, scc);
+
+ process_scc (scc);
+
+ VEC_free (tree, heap, scc);
+
+ return true;
+}
+
/* Depth first search on NAME to discover and process SCC's in the SSA
graph.
Execution of this algorithm relies on the fact that the SCC's are
@@ -1968,10 +2013,13 @@ process_scc (VEC (tree, heap) *scc)
static bool
DFS (tree name)
{
+ VEC(ssa_op_iter, heap) *itervec = NULL;
+ VEC(tree, heap) *namevec = NULL;
+ use_operand_p usep = NULL;
+ tree defstmt, use;
ssa_op_iter iter;
- use_operand_p usep;
- tree defstmt;
+start_over:
/* SCC info */
VN_INFO (name)->dfsnum = next_dfs_num++;
VN_INFO (name)->visited = true;
@@ -1984,20 +2032,63 @@ DFS (tree name)
/* Recursively DFS on our operands, looking for SCC's. */
if (!IS_EMPTY_STMT (defstmt))
{
- FOR_EACH_PHI_OR_STMT_USE (usep, SSA_NAME_DEF_STMT (name), iter,
- SSA_OP_ALL_USES)
+ /* Push a new iterator. */
+ if (TREE_CODE (defstmt) == PHI_NODE)
+ usep = op_iter_init_phiuse (&iter, defstmt, SSA_OP_ALL_USES);
+ else
+ usep = op_iter_init_use (&iter, defstmt, SSA_OP_ALL_USES);
+ }
+ else
+ iter.done = true;
+
+ while (1)
+ {
+ /* If we are done processing uses of a name, go up the stack
+ of iterators and process SCCs as we found them. */
+ if (op_iter_done (&iter))
{
- tree use = USE_FROM_PTR (usep);
+ /* See if we found an SCC. */
+ if (VN_INFO (name)->low == VN_INFO (name)->dfsnum)
+ if (!extract_and_process_scc_for_name (name))
+ {
+ VEC_free (tree, heap, namevec);
+ VEC_free (ssa_op_iter, heap, itervec);
+ return false;
+ }
- /* Since we handle phi nodes, we will sometimes get
- invariants in the use expression. */
- if (TREE_CODE (use) != SSA_NAME)
- continue;
+ /* Check if we are done. */
+ if (VEC_empty (tree, namevec))
+ {
+ VEC_free (tree, heap, namevec);
+ VEC_free (ssa_op_iter, heap, itervec);
+ return true;
+ }
+
+ /* Restore the last use walker and continue walking there. */
+ use = name;
+ name = VEC_pop (tree, namevec);
+ memcpy (&iter, VEC_last (ssa_op_iter, itervec),
+ sizeof (ssa_op_iter));
+ VEC_pop (ssa_op_iter, itervec);
+ goto continue_walking;
+ }
+ use = USE_FROM_PTR (usep);
+
+ /* Since we handle phi nodes, we will sometimes get
+ invariants in the use expression. */
+ if (TREE_CODE (use) == SSA_NAME)
+ {
if (! (VN_INFO (use)->visited))
{
- if (!DFS (use))
- return false;
+ /* Recurse by pushing the current use walking state on
+ the stack and starting over. */
+ VEC_safe_push(ssa_op_iter, heap, itervec, &iter);
+ VEC_safe_push(tree, heap, namevec, name);
+ name = use;
+ goto start_over;
+
+continue_walking:
VN_INFO (name)->low = MIN (VN_INFO (name)->low,
VN_INFO (use)->low);
}
@@ -2008,47 +2099,9 @@ DFS (tree name)
VN_INFO (name)->low);
}
}
- }
-
- /* See if we found an SCC. */
- if (VN_INFO (name)->low == VN_INFO (name)->dfsnum)
- {
- VEC (tree, heap) *scc = NULL;
- tree x;
-
- /* Found an SCC, pop the components off the SCC stack and
- process them. */
- do
- {
- x = VEC_pop (tree, sccstack);
-
- VN_INFO (x)->on_sccstack = false;
- VEC_safe_push (tree, heap, scc, x);
- } while (x != name);
-
- /* Bail out of SCCVN in case a SCC turns out to be incredibly large. */
- if (VEC_length (tree, scc)
- > (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE))
- {
- if (dump_file)
- fprintf (dump_file, "WARNING: Giving up with SCCVN due to "
- "SCC size %u exceeding %u\n", VEC_length (tree, scc),
- (unsigned)PARAM_VALUE (PARAM_SCCVN_MAX_SCC_SIZE));
- return false;
- }
- if (VEC_length (tree, scc) > 1)
- sort_scc (scc);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- print_scc (dump_file, scc);
-
- process_scc (scc);
-
- VEC_free (tree, heap, scc);
+ usep = op_iter_next_use (&iter);
}
-
- return true;
}
/* Allocate a value number table. */