2015-04-17 21:24:17 +02:00
|
|
|
/* 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 "tm.h"
|
|
|
|
#include "alias.h"
|
|
|
|
#include "tree.h"
|
|
|
|
#include "tree-pretty-print.h"
|
|
|
|
#include "tree-pass.h"
|
|
|
|
#include "tree-ssa-scopedtables.h"
|
|
|
|
#include "tree-ssa-threadedge.h"
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2015-09-11 23:32:38 +02:00
|
|
|
while (m_stack.length () > 0)
|
2015-04-17 21:24:17 +02:00
|
|
|
{
|
|
|
|
tree prev_value, dest;
|
|
|
|
|
2015-09-11 23:32:38 +02:00
|
|
|
dest = m_stack.pop ();
|
2015-04-17 21:24:17 +02:00
|
|
|
|
|
|
|
/* 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");
|
|
|
|
}
|
|
|
|
|
2015-09-11 23:32:38 +02:00
|
|
|
prev_value = m_stack.pop ();
|
2015-04-17 21:24:17 +02:00
|
|
|
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);
|
2015-09-11 23:32:38 +02:00
|
|
|
m_stack.reserve (2);
|
|
|
|
m_stack.quick_push (prev_x);
|
|
|
|
m_stack.quick_push (x);
|
2015-04-17 21:24:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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. */
|
2015-09-11 23:32:38 +02:00
|
|
|
for (int i = m_stack.length() - 1; i >= 0; i--)
|
2015-04-17 21:24:17 +02:00
|
|
|
{
|
|
|
|
/* Ignore the stop unwinding markers. */
|
2015-09-11 23:32:38 +02:00
|
|
|
if ((m_stack)[i] == NULL)
|
2015-04-17 21:24:17 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* We want to check the current value of stack[i] to see if
|
|
|
|
it matches LHS. If so, then invalidate. */
|
2015-09-11 23:32:38 +02:00
|
|
|
if (SSA_NAME_VALUE ((m_stack)[i]) == lhs)
|
|
|
|
record_const_or_copy ((m_stack)[i], NULL_TREE);
|
2015-04-17 21:24:17 +02:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|