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:
parent
90e00f872d
commit
f6c72af46f
|
@ -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>
|
2015-04-17 Uros Bizjak <ubizjak@gmail.com>
|
||||||
|
|
||||||
* config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): Remove.
|
* config/i386/i386.h (LEGITIMIZE_RELOAD_ADDRESS): Remove.
|
||||||
|
|
|
@ -1452,6 +1452,7 @@ OBJS = \
|
||||||
tree-ssa-propagate.o \
|
tree-ssa-propagate.o \
|
||||||
tree-ssa-reassoc.o \
|
tree-ssa-reassoc.o \
|
||||||
tree-ssa-sccvn.o \
|
tree-ssa-sccvn.o \
|
||||||
|
tree-ssa-scopedtables.o \
|
||||||
tree-ssa-sink.o \
|
tree-ssa-sink.o \
|
||||||
tree-ssa-strlen.o \
|
tree-ssa-strlen.o \
|
||||||
tree-ssa-structalias.o \
|
tree-ssa-structalias.o \
|
||||||
|
|
|
@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "tree-ssa-threadupdate.h"
|
#include "tree-ssa-threadupdate.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "tree-ssa-scopedtables.h"
|
||||||
#include "tree-ssa-threadedge.h"
|
#include "tree-ssa-threadedge.h"
|
||||||
#include "tree-ssa-dom.h"
|
#include "tree-ssa-dom.h"
|
||||||
#include "inchash.h"
|
#include "inchash.h"
|
||||||
|
@ -235,11 +236,8 @@ expr_elt_hasher::remove (value_type &element)
|
||||||
in this table. */
|
in this table. */
|
||||||
static hash_table<expr_elt_hasher> *avail_exprs;
|
static hash_table<expr_elt_hasher> *avail_exprs;
|
||||||
|
|
||||||
/* Stack of dest,src pairs that need to be restored during finalization.
|
/* Unwindable const/copy equivalences. */
|
||||||
|
static const_and_copies *const_and_copies;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Track whether or not we have changed the control flow graph. */
|
/* Track whether or not we have changed the control flow graph. */
|
||||||
static bool cfg_altered;
|
static bool cfg_altered;
|
||||||
|
@ -268,14 +266,12 @@ static hashval_t avail_expr_hash (const void *);
|
||||||
static void htab_statistics (FILE *,
|
static void htab_statistics (FILE *,
|
||||||
const hash_table<expr_elt_hasher> &);
|
const hash_table<expr_elt_hasher> &);
|
||||||
static void record_cond (cond_equivalence *);
|
static void record_cond (cond_equivalence *);
|
||||||
static void record_const_or_copy (tree, tree);
|
|
||||||
static void record_equality (tree, tree);
|
static void record_equality (tree, tree);
|
||||||
static void record_equivalences_from_phis (basic_block);
|
static void record_equivalences_from_phis (basic_block);
|
||||||
static void record_equivalences_from_incoming_edge (basic_block);
|
static void record_equivalences_from_incoming_edge (basic_block);
|
||||||
static void eliminate_redundant_computations (gimple_stmt_iterator *);
|
static void eliminate_redundant_computations (gimple_stmt_iterator *);
|
||||||
static void record_equivalences_from_stmt (gimple, int);
|
static void record_equivalences_from_stmt (gimple, int);
|
||||||
static void remove_local_expressions_from_table (void);
|
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);
|
static edge single_incoming_edge_ignoring_loop_edges (basic_block);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1196,7 +1192,7 @@ pass_dominator::execute (function *fun)
|
||||||
/* Create our hash tables. */
|
/* Create our hash tables. */
|
||||||
avail_exprs = new hash_table<expr_elt_hasher> (1024);
|
avail_exprs = new hash_table<expr_elt_hasher> (1024);
|
||||||
avail_exprs_stack.create (20);
|
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_eh_cleanup = BITMAP_ALLOC (NULL);
|
||||||
need_noreturn_fixup.create (0);
|
need_noreturn_fixup.create (0);
|
||||||
|
|
||||||
|
@ -1319,7 +1315,7 @@ pass_dominator::execute (function *fun)
|
||||||
BITMAP_FREE (need_eh_cleanup);
|
BITMAP_FREE (need_eh_cleanup);
|
||||||
need_noreturn_fixup.release ();
|
need_noreturn_fixup.release ();
|
||||||
avail_exprs_stack.release ();
|
avail_exprs_stack.release ();
|
||||||
const_and_copies_stack.release ();
|
delete const_and_copies;
|
||||||
|
|
||||||
/* Free the value-handle array. */
|
/* Free the value-handle array. */
|
||||||
threadedge_finalize_values ();
|
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
|
/* A trivial wrapper so that we can present the generic jump
|
||||||
threading code with a simple API for simplifying statements. */
|
threading code with a simple API for simplifying statements. */
|
||||||
static tree
|
static tree
|
||||||
|
@ -1479,7 +1445,7 @@ record_temporary_equivalences (edge e)
|
||||||
|
|
||||||
/* If we have a simple NAME = VALUE equivalence, record it. */
|
/* If we have a simple NAME = VALUE equivalence, record it. */
|
||||||
if (lhs && TREE_CODE (lhs) == SSA_NAME)
|
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
|
/* If we have 0 = COND or 1 = COND equivalences, record them
|
||||||
into our expression hash tables. */
|
into our expression hash tables. */
|
||||||
|
@ -1505,7 +1471,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
|
||||||
current state. */
|
current state. */
|
||||||
avail_exprs_stack.safe_push
|
avail_exprs_stack.safe_push
|
||||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
|
(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. */
|
/* Traversing E may result in equivalences we can utilize. */
|
||||||
record_temporary_equivalences (e);
|
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
|
/* With all the edge equivalences in the tables, go ahead and attempt
|
||||||
to thread through E->dest. */
|
to thread through E->dest. */
|
||||||
::thread_across_edge (m_dummy_cond, e, false,
|
::thread_across_edge (m_dummy_cond, e, false,
|
||||||
&const_and_copies_stack,
|
const_and_copies,
|
||||||
simplify_stmt_for_jump_threading);
|
simplify_stmt_for_jump_threading);
|
||||||
|
|
||||||
/* And restore the various tables to their state before
|
/* And restore the various tables to their state before
|
||||||
|
@ -1752,48 +1718,6 @@ record_cond (cond_equivalence *p)
|
||||||
free_expr_hash_elt (element);
|
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.
|
/* 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
|
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
|
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))))
|
|| REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (y))))
|
||||||
return;
|
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
|
/* 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
|
/* Push the unwind marker so we can reset the const and copies
|
||||||
table back to its original state after processing this edge. */
|
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.
|
/* Extract and record any simple NAME = VALUE equivalences.
|
||||||
|
|
||||||
|
@ -1953,7 +1877,7 @@ cprop_into_successor_phis (basic_block bb)
|
||||||
tree rhs = edge_info->rhs;
|
tree rhs = edge_info->rhs;
|
||||||
|
|
||||||
if (lhs && TREE_CODE (lhs) == SSA_NAME)
|
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;
|
indx = e->dest_idx;
|
||||||
|
@ -1982,7 +1906,7 @@ cprop_into_successor_phis (basic_block bb)
|
||||||
propagate_value (orig_p, new_val);
|
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. */
|
far to unwind when we finalize this block. */
|
||||||
avail_exprs_stack.safe_push
|
avail_exprs_stack.safe_push
|
||||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
|
(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);
|
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. */
|
/* These remove expressions local to BB from the tables. */
|
||||||
remove_local_expressions_from_table ();
|
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
|
/* 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. */
|
This should be sufficient to kill the redundant phi. */
|
||||||
{
|
{
|
||||||
if (def && cached_lhs)
|
if (def && cached_lhs)
|
||||||
record_const_or_copy (def, cached_lhs);
|
const_and_copies->record_const_or_copy (def, cached_lhs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "cfgloop.h"
|
#include "cfgloop.h"
|
||||||
#include "tree-inline.h"
|
#include "tree-inline.h"
|
||||||
#include "flags.h"
|
#include "flags.h"
|
||||||
|
#include "tree-ssa-scopedtables.h"
|
||||||
#include "tree-ssa-threadedge.h"
|
#include "tree-ssa-threadedge.h"
|
||||||
|
|
||||||
/* Duplicates headers of loops if they are small enough, so that the statements
|
/* Duplicates headers of loops if they are small enough, so that the statements
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
|
@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "tree-ssa-threadupdate.h"
|
#include "tree-ssa-threadupdate.h"
|
||||||
#include "langhooks.h"
|
#include "langhooks.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "tree-ssa-scopedtables.h"
|
||||||
#include "tree-ssa-threadedge.h"
|
#include "tree-ssa-threadedge.h"
|
||||||
#include "tree-ssa-loop.h"
|
#include "tree-ssa-loop.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
|
@ -163,57 +164,6 @@ lhs_of_dominating_assert (tree op, basic_block bb, gimple stmt)
|
||||||
return op;
|
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
|
/* 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 onto STACK.
|
||||||
|
|
||||||
|
@ -225,7 +175,7 @@ record_temporary_equivalence (tree x, tree y, vec<tree> *stack)
|
||||||
traversing back edges less painful. */
|
traversing back edges less painful. */
|
||||||
|
|
||||||
static bool
|
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;
|
gphi_iterator gsi;
|
||||||
|
|
||||||
|
@ -252,7 +202,7 @@ record_temporary_equivalences_from_phis (edge e, vec<tree> *stack)
|
||||||
if (!virtual_operand_p (dst))
|
if (!virtual_operand_p (dst))
|
||||||
stmt_count++;
|
stmt_count++;
|
||||||
|
|
||||||
record_temporary_equivalence (dst, src, stack);
|
const_and_copies->record_const_or_copy (dst, src);
|
||||||
}
|
}
|
||||||
return true;
|
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
|
/* Try to simplify each statement in E->dest, ultimately leading to
|
||||||
a simplification of the COND_EXPR at the end of E->dest.
|
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
|
static gimple
|
||||||
record_temporary_equivalences_from_stmts_at_dest (edge e,
|
record_temporary_equivalences_from_stmts_at_dest (edge e,
|
||||||
vec<tree> *stack,
|
const_and_copies *const_and_copies,
|
||||||
tree (*simplify) (gimple,
|
tree (*simplify) (gimple,
|
||||||
gimple),
|
gimple),
|
||||||
bool backedge_seen)
|
bool backedge_seen)
|
||||||
|
@ -425,7 +336,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
|
||||||
|
|
||||||
if (backedge_seen)
|
if (backedge_seen)
|
||||||
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
|
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
|
||||||
invalidate_equivalences (op, stack);
|
const_and_copies->invalidate (op);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -465,7 +376,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
|
||||||
if (backedge_seen)
|
if (backedge_seen)
|
||||||
{
|
{
|
||||||
tree lhs = gimple_get_lhs (stmt);
|
tree lhs = gimple_get_lhs (stmt);
|
||||||
invalidate_equivalences (lhs, stack);
|
const_and_copies->invalidate (lhs);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -541,9 +452,9 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
|
||||||
if (cached_lhs
|
if (cached_lhs
|
||||||
&& (TREE_CODE (cached_lhs) == SSA_NAME
|
&& (TREE_CODE (cached_lhs) == SSA_NAME
|
||||||
|| is_gimple_min_invariant (cached_lhs)))
|
|| 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)
|
else if (backedge_seen)
|
||||||
invalidate_equivalences (gimple_get_lhs (stmt), stack);
|
const_and_copies->invalidate (gimple_get_lhs (stmt));
|
||||||
}
|
}
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
@ -1264,7 +1175,7 @@ static int
|
||||||
thread_through_normal_block (edge e,
|
thread_through_normal_block (edge e,
|
||||||
gcond *dummy_cond,
|
gcond *dummy_cond,
|
||||||
bool handle_dominating_asserts,
|
bool handle_dominating_asserts,
|
||||||
vec<tree> *stack,
|
const_and_copies *const_and_copies,
|
||||||
tree (*simplify) (gimple, gimple),
|
tree (*simplify) (gimple, gimple),
|
||||||
vec<jump_thread_edge *> *path,
|
vec<jump_thread_edge *> *path,
|
||||||
bitmap visited,
|
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
|
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
|
we need to bubble that up to our caller in the same manner we do
|
||||||
when we prematurely stop processing statements below. */
|
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;
|
return -1;
|
||||||
|
|
||||||
/* Now walk each statement recording any context sensitive
|
/* Now walk each statement recording any context sensitive
|
||||||
temporary equivalences we can detect. */
|
temporary equivalences we can detect. */
|
||||||
gimple stmt
|
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);
|
*backedge_seen_p);
|
||||||
|
|
||||||
/* There's two reasons STMT might be null, and distinguishing
|
/* There's two reasons STMT might be null, and distinguishing
|
||||||
|
@ -1434,7 +1345,7 @@ void
|
||||||
thread_across_edge (gcond *dummy_cond,
|
thread_across_edge (gcond *dummy_cond,
|
||||||
edge e,
|
edge e,
|
||||||
bool handle_dominating_asserts,
|
bool handle_dominating_asserts,
|
||||||
vec<tree> *stack,
|
const_and_copies *const_and_copies,
|
||||||
tree (*simplify) (gimple, gimple))
|
tree (*simplify) (gimple, gimple))
|
||||||
{
|
{
|
||||||
bitmap visited = BITMAP_ALLOC (NULL);
|
bitmap visited = BITMAP_ALLOC (NULL);
|
||||||
|
@ -1452,13 +1363,13 @@ thread_across_edge (gcond *dummy_cond,
|
||||||
|
|
||||||
int threaded = thread_through_normal_block (e, dummy_cond,
|
int threaded = thread_through_normal_block (e, dummy_cond,
|
||||||
handle_dominating_asserts,
|
handle_dominating_asserts,
|
||||||
stack, simplify, path,
|
const_and_copies, simplify, path,
|
||||||
visited, &backedge_seen);
|
visited, &backedge_seen);
|
||||||
if (threaded > 0)
|
if (threaded > 0)
|
||||||
{
|
{
|
||||||
propagate_threaded_block_debug_into (path->last ()->e->dest,
|
propagate_threaded_block_debug_into (path->last ()->e->dest,
|
||||||
e->dest);
|
e->dest);
|
||||||
remove_temporary_equivalences (stack);
|
const_and_copies->pop_to_marker ();
|
||||||
BITMAP_FREE (visited);
|
BITMAP_FREE (visited);
|
||||||
register_jump_thread (path);
|
register_jump_thread (path);
|
||||||
return;
|
return;
|
||||||
|
@ -1482,7 +1393,7 @@ thread_across_edge (gcond *dummy_cond,
|
||||||
if (threaded < 0)
|
if (threaded < 0)
|
||||||
{
|
{
|
||||||
BITMAP_FREE (visited);
|
BITMAP_FREE (visited);
|
||||||
remove_temporary_equivalences (stack);
|
const_and_copies->pop_to_marker ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1508,7 +1419,7 @@ thread_across_edge (gcond *dummy_cond,
|
||||||
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
|
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
|
||||||
if (taken_edge->flags & EDGE_ABNORMAL)
|
if (taken_edge->flags & EDGE_ABNORMAL)
|
||||||
{
|
{
|
||||||
remove_temporary_equivalences (stack);
|
const_and_copies->pop_to_marker ();
|
||||||
BITMAP_FREE (visited);
|
BITMAP_FREE (visited);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1518,7 +1429,7 @@ thread_across_edge (gcond *dummy_cond,
|
||||||
{
|
{
|
||||||
/* Push a fresh marker so we can unwind the equivalences created
|
/* Push a fresh marker so we can unwind the equivalences created
|
||||||
for each of E->dest's successors. */
|
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. */
|
/* Avoid threading to any block we have already visited. */
|
||||||
bitmap_clear (visited);
|
bitmap_clear (visited);
|
||||||
|
@ -1553,7 +1464,7 @@ thread_across_edge (gcond *dummy_cond,
|
||||||
if (!found)
|
if (!found)
|
||||||
found = thread_through_normal_block (path->last ()->e, dummy_cond,
|
found = thread_through_normal_block (path->last ()->e, dummy_cond,
|
||||||
handle_dominating_asserts,
|
handle_dominating_asserts,
|
||||||
stack, simplify, path, visited,
|
const_and_copies, simplify, path, visited,
|
||||||
&backedge_seen) > 0;
|
&backedge_seen) > 0;
|
||||||
|
|
||||||
/* If we were able to thread through a successor of E->dest, then
|
/* 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. */
|
/* And unwind the equivalence table. */
|
||||||
remove_temporary_equivalences (stack);
|
const_and_copies->pop_to_marker ();
|
||||||
}
|
}
|
||||||
BITMAP_FREE (visited);
|
BITMAP_FREE (visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_temporary_equivalences (stack);
|
const_and_copies->pop_to_marker ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ extern void threadedge_finalize_values (void);
|
||||||
extern bool potentially_threadable_block (basic_block);
|
extern bool potentially_threadable_block (basic_block);
|
||||||
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
|
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
|
||||||
extern void thread_across_edge (gcond *, edge, bool,
|
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 */
|
#endif /* GCC_TREE_SSA_THREADEDGE_H */
|
||||||
|
|
|
@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "insn-codes.h"
|
#include "insn-codes.h"
|
||||||
#include "optabs.h"
|
#include "optabs.h"
|
||||||
|
#include "tree-ssa-scopedtables.h"
|
||||||
#include "tree-ssa-threadedge.h"
|
#include "tree-ssa-threadedge.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -10054,12 +10055,8 @@ vrp_fold_stmt (gimple_stmt_iterator *si)
|
||||||
return simplify_stmt_using_ranges (si);
|
return simplify_stmt_using_ranges (si);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stack of dest,src equivalency pairs that need to be restored after
|
/* Unwindable const/copy equivalences. */
|
||||||
each attempt to thread a block's incoming edge to an outgoing edge.
|
const_and_copies *equiv_stack;
|
||||||
|
|
||||||
A NULL entry is used to mark the end of pairs which need to be
|
|
||||||
restored. */
|
|
||||||
static vec<tree> equiv_stack;
|
|
||||||
|
|
||||||
/* A trivial wrapper so that we can present the generic jump threading
|
/* A trivial wrapper so that we can present the generic jump threading
|
||||||
code with a simple API for simplifying statements. STMT is the
|
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
|
/* Allocate our unwinder stack to unwind any temporary equivalences
|
||||||
that might be recorded. */
|
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
|
/* To avoid lots of silly node creation, we create a single
|
||||||
conditional and just modify it in-place when attempting to
|
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))
|
if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
thread_across_edge (dummy, e, true, &equiv_stack,
|
thread_across_edge (dummy, e, true, equiv_stack,
|
||||||
simplify_stmt_for_jump_threading);
|
simplify_stmt_for_jump_threading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10219,7 +10216,7 @@ static void
|
||||||
finalize_jump_threads (void)
|
finalize_jump_threads (void)
|
||||||
{
|
{
|
||||||
thread_through_all_blocks (false);
|
thread_through_all_blocks (false);
|
||||||
equiv_stack.release ();
|
delete equiv_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue