re PR tree-optimization/47679 (Strange uninitialized warning after SRA)

PR tree-optimization/47679
	* Makefile.in (OBJS); Add tree-ssa-scopedtables.o.
	* tree-ssa-scopedtables.c: New file.
	* tree-ssa-scopedtables.h: New file.
	* tree-ssa-dom.c: Include tree-ssa-scopedtables.h.
	(const_and_copies): Change name/type.
	(record_const_or_copy): Move into tree-ssa-scopedtables.c
	(record_const_or_copy_1): Similarly.
	(restore_vars_to_original_value): Similarly.
	(pass_dominator::execute): Create and destroy const_and_copies table.
	(thread_across_edge): Update passing of const_and_copies.
	(record_temporary_equivalence): Use method calls rather than
	manipulating const_and_copies directly.
	(record_equality, cprop_into_successor_phis): Similarly.
	(dom_opt_dom_walker::before_dom_children): Similarly.
	(dom_opt_dom_walker::after_dom_children): Similarly.
	(eliminate_redundant_computations): Similarly.
	* tree-ssa-threadedge.c (remove_temporary_equivalences): Delete.
	(record_temporary_equivalence): Likewise.
	(invalidate_equivalences): Likewise.
	(record_temporary_equivalences_from_phis): Update due to type
	change of const_and_copies.  Use method calls rather than
	manipulating the stack directly.
	(record_temporary_equivalences_from_stmts_at_dest): Likewise.
	(thread_through_normal_block, thread_across_edge): Likewise.
	(thread_across_edge): Likewise.
	* tree-ssa-threadedge.h (thread_across_edge): Update prototype.
	* tree-vrp.c: Include tree-ssa-scopedtables.h.  Change type
	of equiv_stack.
	(identify_jump_threads): Update due to type change of equiv_stack.
	(finalize_jump_threads): Delete the equiv_stack when complete.

From-SVN: r222195
This commit is contained in:
Jeff Law 2015-04-17 13:24:17 -06:00 committed by Jeff Law
parent 90e00f872d
commit f6c72af46f
9 changed files with 270 additions and 210 deletions

View File

@ -1,3 +1,37 @@
2015-04-17 Jeff Law <law@redhat.com>
PR tree-optimization/47679
* Makefile.in (OBJS); Add tree-ssa-scopedtables.o.
* tree-ssa-scopedtables.c: New file.
* tree-ssa-scopedtables.h: New file.
* tree-ssa-dom.c: Include tree-ssa-scopedtables.h.
(const_and_copies): Change name/type.
(record_const_or_copy): Move into tree-ssa-scopedtables.c
(record_const_or_copy_1): Similarly.
(restore_vars_to_original_value): Similarly.
(pass_dominator::execute): Create and destroy const_and_copies table.
(thread_across_edge): Update passing of const_and_copies.
(record_temporary_equivalence): Use method calls rather than
manipulating const_and_copies directly.
(record_equality, cprop_into_successor_phis): Similarly.
(dom_opt_dom_walker::before_dom_children): Similarly.
(dom_opt_dom_walker::after_dom_children): Similarly.
(eliminate_redundant_computations): Similarly.
* tree-ssa-threadedge.c (remove_temporary_equivalences): Delete.
(record_temporary_equivalence): Likewise.
(invalidate_equivalences): Likewise.
(record_temporary_equivalences_from_phis): Update due to type
change of const_and_copies. Use method calls rather than
manipulating the stack directly.
(record_temporary_equivalences_from_stmts_at_dest): Likewise.
(thread_through_normal_block, thread_across_edge): Likewise.
(thread_across_edge): Likewise.
* tree-ssa-threadedge.h (thread_across_edge): Update prototype.
* tree-vrp.c: Include tree-ssa-scopedtables.h. Change type
of equiv_stack.
(identify_jump_threads): Update due to type change of equiv_stack.
(finalize_jump_threads): Delete the equiv_stack when complete.
2015-04-17 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): Remove.

View File

@ -1452,6 +1452,7 @@ OBJS = \
tree-ssa-propagate.o \
tree-ssa-reassoc.o \
tree-ssa-sccvn.o \
tree-ssa-scopedtables.o \
tree-ssa-sink.o \
tree-ssa-strlen.o \
tree-ssa-structalias.o \

View File

@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-threadupdate.h"
#include "langhooks.h"
#include "params.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
#include "tree-ssa-dom.h"
#include "inchash.h"
@ -235,11 +236,8 @@ expr_elt_hasher::remove (value_type &element)
in this table. */
static hash_table<expr_elt_hasher> *avail_exprs;
/* Stack of dest,src pairs that need to be restored during finalization.
A NULL entry is used to mark the end of pairs which need to be
restored during finalization of this block. */
static vec<tree> const_and_copies_stack;
/* Unwindable const/copy equivalences. */
static const_and_copies *const_and_copies;
/* Track whether or not we have changed the control flow graph. */
static bool cfg_altered;
@ -268,14 +266,12 @@ static hashval_t avail_expr_hash (const void *);
static void htab_statistics (FILE *,
const hash_table<expr_elt_hasher> &);
static void record_cond (cond_equivalence *);
static void record_const_or_copy (tree, tree);
static void record_equality (tree, tree);
static void record_equivalences_from_phis (basic_block);
static void record_equivalences_from_incoming_edge (basic_block);
static void eliminate_redundant_computations (gimple_stmt_iterator *);
static void record_equivalences_from_stmt (gimple, int);
static void remove_local_expressions_from_table (void);
static void restore_vars_to_original_value (void);
static edge single_incoming_edge_ignoring_loop_edges (basic_block);
@ -1196,7 +1192,7 @@ pass_dominator::execute (function *fun)
/* Create our hash tables. */
avail_exprs = new hash_table<expr_elt_hasher> (1024);
avail_exprs_stack.create (20);
const_and_copies_stack.create (20);
const_and_copies = new class const_and_copies (dump_file, dump_flags);
need_eh_cleanup = BITMAP_ALLOC (NULL);
need_noreturn_fixup.create (0);
@ -1319,7 +1315,7 @@ pass_dominator::execute (function *fun)
BITMAP_FREE (need_eh_cleanup);
need_noreturn_fixup.release ();
avail_exprs_stack.release ();
const_and_copies_stack.release ();
delete const_and_copies;
/* Free the value-handle array. */
threadedge_finalize_values ();
@ -1420,36 +1416,6 @@ remove_local_expressions_from_table (void)
}
}
/* Use the source/dest pairs in CONST_AND_COPIES_STACK to restore
CONST_AND_COPIES to its original state, stopping when we hit a
NULL marker. */
static void
restore_vars_to_original_value (void)
{
while (const_and_copies_stack.length () > 0)
{
tree prev_value, dest;
dest = const_and_copies_stack.pop ();
if (dest == NULL)
break;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "<<<< COPY ");
print_generic_expr (dump_file, dest, 0);
fprintf (dump_file, " = ");
print_generic_expr (dump_file, SSA_NAME_VALUE (dest), 0);
fprintf (dump_file, "\n");
}
prev_value = const_and_copies_stack.pop ();
set_ssa_name_value (dest, prev_value);
}
}
/* A trivial wrapper so that we can present the generic jump
threading code with a simple API for simplifying statements. */
static tree
@ -1479,7 +1445,7 @@ record_temporary_equivalences (edge e)
/* If we have a simple NAME = VALUE equivalence, record it. */
if (lhs && TREE_CODE (lhs) == SSA_NAME)
record_const_or_copy (lhs, rhs);
const_and_copies->record_const_or_copy (lhs, rhs);
/* If we have 0 = COND or 1 = COND equivalences, record them
into our expression hash tables. */
@ -1505,7 +1471,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
current state. */
avail_exprs_stack.safe_push
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
const_and_copies_stack.safe_push (NULL_TREE);
const_and_copies->push_marker ();
/* Traversing E may result in equivalences we can utilize. */
record_temporary_equivalences (e);
@ -1513,7 +1479,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
/* With all the edge equivalences in the tables, go ahead and attempt
to thread through E->dest. */
::thread_across_edge (m_dummy_cond, e, false,
&const_and_copies_stack,
const_and_copies,
simplify_stmt_for_jump_threading);
/* And restore the various tables to their state before
@ -1752,48 +1718,6 @@ record_cond (cond_equivalence *p)
free_expr_hash_elt (element);
}
/* A helper function for record_const_or_copy and record_equality.
Do the work of recording the value and undo info. */
static void
record_const_or_copy_1 (tree x, tree y, tree prev_x)
{
set_ssa_name_value (x, y);
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "0>>> COPY ");
print_generic_expr (dump_file, x, 0);
fprintf (dump_file, " = ");
print_generic_expr (dump_file, y, 0);
fprintf (dump_file, "\n");
}
const_and_copies_stack.reserve (2);
const_and_copies_stack.quick_push (prev_x);
const_and_copies_stack.quick_push (x);
}
/* Record that X is equal to Y in const_and_copies. Record undo
information in the block-local vector. */
static void
record_const_or_copy (tree x, tree y)
{
tree prev_x = SSA_NAME_VALUE (x);
gcc_assert (TREE_CODE (x) == SSA_NAME);
if (TREE_CODE (y) == SSA_NAME)
{
tree tmp = SSA_NAME_VALUE (y);
if (tmp)
y = tmp;
}
record_const_or_copy_1 (x, y, prev_x);
}
/* Return the loop depth of the basic block of the defining statement of X.
This number should not be treated as absolutely correct because the loop
information may not be completely up-to-date when dom runs. However, it
@ -1863,7 +1787,7 @@ record_equality (tree x, tree y)
|| REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (y))))
return;
record_const_or_copy_1 (x, y, prev_x);
const_and_copies->record_const_or_copy (x, y, prev_x);
}
/* Returns true when STMT is a simple iv increment. It detects the
@ -1940,7 +1864,7 @@ cprop_into_successor_phis (basic_block bb)
/* Push the unwind marker so we can reset the const and copies
table back to its original state after processing this edge. */
const_and_copies_stack.safe_push (NULL_TREE);
const_and_copies->push_marker ();
/* Extract and record any simple NAME = VALUE equivalences.
@ -1953,7 +1877,7 @@ cprop_into_successor_phis (basic_block bb)
tree rhs = edge_info->rhs;
if (lhs && TREE_CODE (lhs) == SSA_NAME)
record_const_or_copy (lhs, rhs);
const_and_copies->record_const_or_copy (lhs, rhs);
}
indx = e->dest_idx;
@ -1982,7 +1906,7 @@ cprop_into_successor_phis (basic_block bb)
propagate_value (orig_p, new_val);
}
restore_vars_to_original_value ();
const_and_copies->pop_to_marker ();
}
}
@ -1998,7 +1922,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
far to unwind when we finalize this block. */
avail_exprs_stack.safe_push
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
const_and_copies_stack.safe_push (NULL_TREE);
const_and_copies->push_marker ();
record_equivalences_from_incoming_edge (bb);
@ -2064,7 +1988,7 @@ dom_opt_dom_walker::after_dom_children (basic_block bb)
/* These remove expressions local to BB from the tables. */
remove_local_expressions_from_table ();
restore_vars_to_original_value ();
const_and_copies->pop_to_marker ();
}
/* Search for redundant computations in STMT. If any are found, then
@ -2128,7 +2052,7 @@ eliminate_redundant_computations (gimple_stmt_iterator* gsi)
This should be sufficient to kill the redundant phi. */
{
if (def && cached_lhs)
record_const_or_copy (def, cached_lhs);
const_and_copies->record_const_or_copy (def, cached_lhs);
return;
}
else

View File

@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "tree-inline.h"
#include "flags.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
/* Duplicates headers of loops if they are small enough, so that the statements

152
gcc/tree-ssa-scopedtables.c Normal file
View File

@ -0,0 +1,152 @@
/* Header file for SSA dominator optimizations.
Copyright (C) 2013-2015 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "hash-table.h"
#include "tm.h"
#include "hash-set.h"
#include "machmode.h"
#include "vec.h"
#include "double-int.h"
#include "input.h"
#include "alias.h"
#include "symtab.h"
#include "wide-int.h"
#include "inchash.h"
#include "real.h"
#include "tree.h"
#include "tree-pretty-print.h"
#include "tree-pass.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
const_and_copies::const_and_copies (FILE *file, int flags)
{
stack.create (20);
dump_file = file;
dump_flags = flags;
}
/* Pop entries off the stack until we hit the NULL marker.
For each entry popped, use the SRC/DEST pair to restore
SRC to its prior value. */
void
const_and_copies::pop_to_marker (void)
{
while (stack.length () > 0)
{
tree prev_value, dest;
dest = stack.pop ();
/* A NULL value indicates we should stop unwinding, otherwise
pop off the next entry as they're recorded in pairs. */
if (dest == NULL)
break;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "<<<< COPY ");
print_generic_expr (dump_file, dest, 0);
fprintf (dump_file, " = ");
print_generic_expr (dump_file, SSA_NAME_VALUE (dest), 0);
fprintf (dump_file, "\n");
}
prev_value = stack.pop ();
set_ssa_name_value (dest, prev_value);
}
}
/* Record that X has the value Y. */
void
const_and_copies::record_const_or_copy (tree x, tree y)
{
record_const_or_copy (x, y, SSA_NAME_VALUE (x));
}
/* Record that X has the value Y and that X's previous value is PREV_X. */
void
const_and_copies::record_const_or_copy (tree x, tree y, tree prev_x)
{
/* Y may be NULL if we are invalidating entries in the table. */
if (y && TREE_CODE (y) == SSA_NAME)
{
tree tmp = SSA_NAME_VALUE (y);
y = tmp ? tmp : y;
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "0>>> COPY ");
print_generic_expr (dump_file, x, 0);
fprintf (dump_file, " = ");
print_generic_expr (dump_file, y, 0);
fprintf (dump_file, "\n");
}
set_ssa_name_value (x, y);
stack.reserve (2);
stack.quick_push (prev_x);
stack.quick_push (x);
}
/* A new value has been assigned to LHS. If necessary, invalidate any
equivalences that are no longer valid. This includes invaliding
LHS and any objects that are currently equivalent to LHS.
Finding the objects that are currently marked as equivalent to LHS
is a bit tricky. We could walk the ssa names and see if any have
SSA_NAME_VALUE that is the same as LHS. That's expensive.
However, it's far more efficient to look at the unwinding stack as
that will have all context sensitive equivalences which are the only
ones that we really have to worry about here. */
void
const_and_copies::invalidate (tree lhs)
{
/* The stack is an unwinding stack. If the current element is NULL
then it's a "stop unwinding" marker. Else the current marker is
the SSA_NAME with an equivalence and the prior entry in the stack
is what the current element is equivalent to. */
for (int i = stack.length() - 1; i >= 0; i--)
{
/* Ignore the stop unwinding markers. */
if ((stack)[i] == NULL)
continue;
/* We want to check the current value of stack[i] to see if
it matches LHS. If so, then invalidate. */
if (SSA_NAME_VALUE ((stack)[i]) == lhs)
record_const_or_copy ((stack)[i], NULL_TREE);
/* Remember, we're dealing with two elements in this case. */
i--;
}
/* And invalidate any known value for LHS itself. */
if (SSA_NAME_VALUE (lhs))
record_const_or_copy (lhs, NULL_TREE);
}

View File

@ -0,0 +1,40 @@
/* Header file for SSA dominator optimizations.
Copyright (C) 2013-2015 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_TREE_SSA_SCOPED_TABLES_H
#define GCC_TREE_SSA_SCOPED_TABLES_H
class const_and_copies
{
public:
const_and_copies (FILE *, int);
~const_and_copies (void) { stack.release (); }
void push_marker (void) { stack.safe_push (NULL_TREE); }
void pop_to_marker (void);
void record_const_or_copy (tree, tree);
void record_const_or_copy (tree, tree, tree);
void invalidate (tree);
private:
vec<tree> stack;
FILE *dump_file;
int dump_flags;
};
#endif /* GCC_TREE_SSA_SCOPED_TABLES_H */

View File

@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-threadupdate.h"
#include "langhooks.h"
#include "params.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
#include "tree-ssa-loop.h"
#include "builtins.h"
@ -163,57 +164,6 @@ lhs_of_dominating_assert (tree op, basic_block bb, gimple stmt)
return op;
}
/* We record temporary equivalences created by PHI nodes or
statements within the target block. Doing so allows us to
identify more jump threading opportunities, even in blocks
with side effects.
We keep track of those temporary equivalences in a stack
structure so that we can unwind them when we're done processing
a particular edge. This routine handles unwinding the data
structures. */
static void
remove_temporary_equivalences (vec<tree> *stack)
{
while (stack->length () > 0)
{
tree prev_value, dest;
dest = stack->pop ();
/* A NULL value indicates we should stop unwinding, otherwise
pop off the next entry as they're recorded in pairs. */
if (dest == NULL)
break;
prev_value = stack->pop ();
set_ssa_name_value (dest, prev_value);
}
}
/* Record a temporary equivalence, saving enough information so that
we can restore the state of recorded equivalences when we're
done processing the current edge. */
static void
record_temporary_equivalence (tree x, tree y, vec<tree> *stack)
{
tree prev_x = SSA_NAME_VALUE (x);
/* Y may be NULL if we are invalidating entries in the table. */
if (y && TREE_CODE (y) == SSA_NAME)
{
tree tmp = SSA_NAME_VALUE (y);
y = tmp ? tmp : y;
}
set_ssa_name_value (x, y);
stack->reserve (2);
stack->quick_push (prev_x);
stack->quick_push (x);
}
/* Record temporary equivalences created by PHIs at the target of the
edge E. Record unwind information for the equivalences onto STACK.
@ -225,7 +175,7 @@ record_temporary_equivalence (tree x, tree y, vec<tree> *stack)
traversing back edges less painful. */
static bool
record_temporary_equivalences_from_phis (edge e, vec<tree> *stack)
record_temporary_equivalences_from_phis (edge e, const_and_copies *const_and_copies)
{
gphi_iterator gsi;
@ -252,7 +202,7 @@ record_temporary_equivalences_from_phis (edge e, vec<tree> *stack)
if (!virtual_operand_p (dst))
stmt_count++;
record_temporary_equivalence (dst, src, stack);
const_and_copies->record_const_or_copy (dst, src);
}
return true;
}
@ -307,45 +257,6 @@ fold_assignment_stmt (gimple stmt)
}
}
/* A new value has been assigned to LHS. If necessary, invalidate any
equivalences that are no longer valid. This includes invaliding
LHS and any objects that are currently equivalent to LHS.
Finding the objects that are currently marked as equivalent to LHS
is a bit tricky. We could walk the ssa names and see if any have
SSA_NAME_VALUE that is the same as LHS. That's expensive.
However, it's far more efficient to look at the unwinding stack as
that will have all context sensitive equivalences which are the only
ones that we really have to worry about here. */
static void
invalidate_equivalences (tree lhs, vec<tree> *stack)
{
/* The stack is an unwinding stack. If the current element is NULL
then it's a "stop unwinding" marker. Else the current marker is
the SSA_NAME with an equivalence and the prior entry in the stack
is what the current element is equivalent to. */
for (int i = stack->length() - 1; i >= 0; i--)
{
/* Ignore the stop unwinding markers. */
if ((*stack)[i] == NULL)
continue;
/* We want to check the current value of stack[i] to see if
it matches LHS. If so, then invalidate. */
if (SSA_NAME_VALUE ((*stack)[i]) == lhs)
record_temporary_equivalence ((*stack)[i], NULL_TREE, stack);
/* Remember, we're dealing with two elements in this case. */
i--;
}
/* And invalidate any known value for LHS itself. */
if (SSA_NAME_VALUE (lhs))
record_temporary_equivalence (lhs, NULL_TREE, stack);
}
/* Try to simplify each statement in E->dest, ultimately leading to
a simplification of the COND_EXPR at the end of E->dest.
@ -365,7 +276,7 @@ invalidate_equivalences (tree lhs, vec<tree> *stack)
static gimple
record_temporary_equivalences_from_stmts_at_dest (edge e,
vec<tree> *stack,
const_and_copies *const_and_copies,
tree (*simplify) (gimple,
gimple),
bool backedge_seen)
@ -425,7 +336,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
if (backedge_seen)
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
invalidate_equivalences (op, stack);
const_and_copies->invalidate (op);
continue;
}
@ -465,7 +376,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
if (backedge_seen)
{
tree lhs = gimple_get_lhs (stmt);
invalidate_equivalences (lhs, stack);
const_and_copies->invalidate (lhs);
}
continue;
}
@ -541,9 +452,9 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
if (cached_lhs
&& (TREE_CODE (cached_lhs) == SSA_NAME
|| is_gimple_min_invariant (cached_lhs)))
record_temporary_equivalence (gimple_get_lhs (stmt), cached_lhs, stack);
const_and_copies->record_const_or_copy (gimple_get_lhs (stmt), cached_lhs);
else if (backedge_seen)
invalidate_equivalences (gimple_get_lhs (stmt), stack);
const_and_copies->invalidate (gimple_get_lhs (stmt));
}
return stmt;
}
@ -1264,7 +1175,7 @@ static int
thread_through_normal_block (edge e,
gcond *dummy_cond,
bool handle_dominating_asserts,
vec<tree> *stack,
const_and_copies *const_and_copies,
tree (*simplify) (gimple, gimple),
vec<jump_thread_edge *> *path,
bitmap visited,
@ -1281,13 +1192,13 @@ thread_through_normal_block (edge e,
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, stack))
if (!record_temporary_equivalences_from_phis (e, const_and_copies))
return -1;
/* Now walk each statement recording any context sensitive
temporary equivalences we can detect. */
gimple stmt
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
= record_temporary_equivalences_from_stmts_at_dest (e, const_and_copies, simplify,
*backedge_seen_p);
/* There's two reasons STMT might be null, and distinguishing
@ -1434,7 +1345,7 @@ void
thread_across_edge (gcond *dummy_cond,
edge e,
bool handle_dominating_asserts,
vec<tree> *stack,
const_and_copies *const_and_copies,
tree (*simplify) (gimple, gimple))
{
bitmap visited = BITMAP_ALLOC (NULL);
@ -1452,13 +1363,13 @@ thread_across_edge (gcond *dummy_cond,
int threaded = thread_through_normal_block (e, dummy_cond,
handle_dominating_asserts,
stack, simplify, path,
const_and_copies, simplify, path,
visited, &backedge_seen);
if (threaded > 0)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
e->dest);
remove_temporary_equivalences (stack);
const_and_copies->pop_to_marker ();
BITMAP_FREE (visited);
register_jump_thread (path);
return;
@ -1482,7 +1393,7 @@ thread_across_edge (gcond *dummy_cond,
if (threaded < 0)
{
BITMAP_FREE (visited);
remove_temporary_equivalences (stack);
const_and_copies->pop_to_marker ();
return;
}
}
@ -1508,7 +1419,7 @@ thread_across_edge (gcond *dummy_cond,
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
if (taken_edge->flags & EDGE_ABNORMAL)
{
remove_temporary_equivalences (stack);
const_and_copies->pop_to_marker ();
BITMAP_FREE (visited);
return;
}
@ -1518,7 +1429,7 @@ thread_across_edge (gcond *dummy_cond,
{
/* Push a fresh marker so we can unwind the equivalences created
for each of E->dest's successors. */
stack->safe_push (NULL_TREE);
const_and_copies->push_marker ();
/* Avoid threading to any block we have already visited. */
bitmap_clear (visited);
@ -1553,7 +1464,7 @@ thread_across_edge (gcond *dummy_cond,
if (!found)
found = thread_through_normal_block (path->last ()->e, dummy_cond,
handle_dominating_asserts,
stack, simplify, path, visited,
const_and_copies, simplify, path, visited,
&backedge_seen) > 0;
/* If we were able to thread through a successor of E->dest, then
@ -1570,10 +1481,10 @@ thread_across_edge (gcond *dummy_cond,
}
/* And unwind the equivalence table. */
remove_temporary_equivalences (stack);
const_and_copies->pop_to_marker ();
}
BITMAP_FREE (visited);
}
remove_temporary_equivalences (stack);
const_and_copies->pop_to_marker ();
}

View File

@ -31,6 +31,6 @@ extern void threadedge_finalize_values (void);
extern bool potentially_threadable_block (basic_block);
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
extern void thread_across_edge (gcond *, edge, bool,
vec<tree> *, tree (*) (gimple, gimple));
const_and_copies *, tree (*) (gimple, gimple));
#endif /* GCC_TREE_SSA_THREADEDGE_H */

View File

@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "insn-codes.h"
#include "optabs.h"
#include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h"
@ -10054,12 +10055,8 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
return simplify_stmt_using_ranges (si);
}
/* Stack of dest,src equivalency pairs that need to be restored after
each attempt to thread a block's incoming edge to an outgoing edge.
A NULL entry is used to mark the end of pairs which need to be
restored. */
static vec<tree> equiv_stack;
/* Unwindable const/copy equivalences. */
const_and_copies *equiv_stack;
/* A trivial wrapper so that we can present the generic jump threading
code with a simple API for simplifying statements. STMT is the
@ -10140,7 +10137,7 @@ identify_jump_threads (void)
/* Allocate our unwinder stack to unwind any temporary equivalences
that might be recorded. */
equiv_stack.create (20);
equiv_stack = new const_and_copies (dump_file, dump_flags);
/* To avoid lots of silly node creation, we create a single
conditional and just modify it in-place when attempting to
@ -10198,7 +10195,7 @@ identify_jump_threads (void)
if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
continue;
thread_across_edge (dummy, e, true, &equiv_stack,
thread_across_edge (dummy, e, true, equiv_stack,
simplify_stmt_for_jump_threading);
}
}
@ -10219,7 +10216,7 @@ static void
finalize_jump_threads (void)
{
thread_through_all_blocks (false);
equiv_stack.release ();
delete equiv_stack;
}