/* SSA operands management for trees.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
/* Number of functions with initialized ssa_operands. */
static int n_initialized = 0;
-/* Stack of statements to change. Every call to
- push_stmt_changes pushes the stmt onto the stack. Calls to
- pop_stmt_changes pop a stmt off of the stack and compute the set
- of changes for the popped statement. */
-static VEC(gimple_p,heap) *scb_stack;
-
/* Return the DECL_UID of the base variable of T. */
static inline unsigned
gcc_assert (cfun->gimple_df->vop == NULL_TREE);
- global_var = build_decl (VAR_DECL, get_identifier (".MEM"),
+ global_var = build_decl (BUILTINS_LOCATION, VAR_DECL,
+ get_identifier (".MEM"),
void_type_node);
DECL_ARTIFICIAL (global_var) = 1;
TREE_READONLY (global_var) = 0;
build_vuse = NULL_TREE;
build_vdef = NULL_TREE;
bitmap_obstack_initialize (&operands_bitmap_obstack);
- scb_stack = VEC_alloc (gimple_p, heap, 20);
}
gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL);
VEC_free (tree, heap, build_uses);
build_vdef = NULL_TREE;
build_vuse = NULL_TREE;
-
- /* The change buffer stack had better be empty. */
- gcc_assert (VEC_length (gimple_p, scb_stack) == 0);
- VEC_free (gimple_p, heap, scb_stack);
- scb_stack = NULL;
}
gimple_ssa_operands (cfun)->free_defs = NULL;
if (flags & opf_no_vops)
return;
+ gcc_assert (!is_gimple_debug (stmt));
+
if (flags & opf_def)
append_vdef (gimple_vop (cfun));
else
add_virtual_operand (stmt, flags);
}
-/* Add the base address of REF to SET. */
+/* Mark the base address of REF as having its address taken.
+ REF may be a single variable whose address has been taken or any
+ other valid GIMPLE memory reference (structure reference, array,
+ etc). */
static void
-add_to_addressable_set (tree ref, bitmap *set)
+mark_address_taken (tree ref)
{
tree var;
be referenced using pointer arithmetic. See PR 21407 and the
ensuing mailing list discussion. */
var = get_base_address (ref);
- if (var && SSA_VAR_P (var))
- {
- if (*set == NULL)
- *set = BITMAP_ALLOC (&operands_bitmap_obstack);
-
- bitmap_set_bit (*set, DECL_UID (var));
- TREE_ADDRESSABLE (var) = 1;
- }
-}
-
-/* Add the base address of REF to the set of addresses taken by STMT.
- REF may be a single variable whose address has been taken or any
- other valid GIMPLE memory reference (structure reference, array,
- etc). If the base address of REF is a decl that has sub-variables,
- also add all of its sub-variables. */
-
-static void
-gimple_add_to_addresses_taken (gimple stmt, tree ref)
-{
- gcc_assert (gimple_has_ops (stmt));
- add_to_addressable_set (ref, gimple_addresses_taken_ptr (stmt));
+ if (var && DECL_P (var))
+ TREE_ADDRESSABLE (var) = 1;
}
/* If requested, add a USE operand for the base pointer. */
if (recurse_on_base)
- get_expr_operands (stmt, pptr, opf_use);
+ get_expr_operands (stmt, pptr,
+ opf_use | (flags & opf_no_vops));
}
get_tmr_operands (gimple stmt, tree expr, int flags)
{
/* First record the real operands. */
- get_expr_operands (stmt, &TMR_BASE (expr), opf_use);
- get_expr_operands (stmt, &TMR_INDEX (expr), opf_use);
+ get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops));
+ get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops));
if (TMR_SYMBOL (expr))
- gimple_add_to_addresses_taken (stmt, TMR_SYMBOL (expr));
+ mark_address_taken (TMR_SYMBOL (expr));
add_virtual_operand (stmt, flags);
}
{
tree t = get_base_address (TREE_VALUE (link));
if (t && DECL_P (t))
- gimple_add_to_addresses_taken (stmt, t);
+ mark_address_taken (t);
}
get_expr_operands (stmt, &TREE_VALUE (link), opf_def);
{
tree t = get_base_address (TREE_VALUE (link));
if (t && DECL_P (t))
- gimple_add_to_addresses_taken (stmt, t);
+ mark_address_taken (t);
}
get_expr_operands (stmt, &TREE_VALUE (link), 0);
enum tree_code code;
enum tree_code_class codeclass;
tree expr = *expr_p;
+ int uflags = opf_use;
if (expr == NULL)
return;
+ if (is_gimple_debug (stmt))
+ uflags |= (flags & opf_no_vops);
+
code = TREE_CODE (expr);
codeclass = TREE_CODE_CLASS (code);
reference to it, but the fact that the statement takes its
address will be of interest to some passes (e.g. alias
resolution). */
- gimple_add_to_addresses_taken (stmt, TREE_OPERAND (expr, 0));
+ if (!is_gimple_debug (stmt))
+ mark_address_taken (TREE_OPERAND (expr, 0));
/* If the address is invariant, there may be no interesting
variable references inside. */
case REALPART_EXPR:
case IMAGPART_EXPR:
{
- tree ref;
- HOST_WIDE_INT offset, size, maxsize;
-
if (TREE_THIS_VOLATILE (expr))
gimple_set_has_volatile_ops (stmt, true);
- ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
- if (TREE_CODE (ref) == INDIRECT_REF)
- {
- get_indirect_ref_operands (stmt, ref, flags, false);
- flags |= opf_no_vops;
- }
-
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
if (code == COMPONENT_REF)
{
if (TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1)))
gimple_set_has_volatile_ops (stmt, true);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
}
else if (code == ARRAY_REF || code == ARRAY_RANGE_REF)
{
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags);
}
return;
case WITH_SIZE_EXPR:
/* WITH_SIZE_EXPR is a pass-through reference to its first argument,
and an rvalue reference to its second argument. */
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
return;
case COND_EXPR:
case VEC_COND_EXPR:
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_use);
- get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_use);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags);
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
return;
case CONSTRUCTOR:
for (idx = 0;
VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (expr), idx, ce);
idx++)
- get_expr_operands (stmt, &ce->value, opf_use);
+ get_expr_operands (stmt, &ce->value, uflags);
return;
}
return;
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- gcc_unreachable ();
-
case FUNCTION_DECL:
case LABEL_DECL:
case CONST_DECL:
case CASE_LABEL_EXPR:
- case FILTER_EXPR:
- case EXC_PTR_EXPR:
/* Expressions that make no memory references. */
return;
if (code == GIMPLE_ASM)
get_asm_expr_operands (stmt);
+ else if (is_gimple_debug (stmt))
+ {
+ if (gimple_debug_bind_p (stmt)
+ && gimple_debug_bind_has_value_p (stmt))
+ get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt),
+ opf_use | opf_no_vops);
+ }
else
{
size_t i, start = 0;
static void
build_ssa_operands (gimple stmt)
{
- /* Initially assume that the statement has no volatile operands and
- makes no memory references. */
+ /* Initially assume that the statement has no volatile operands. */
gimple_set_has_volatile_ops (stmt, false);
- /* Just clear the bitmap so we don't end up reallocating it over and over. */
- if (gimple_addresses_taken (stmt))
- bitmap_clear (gimple_addresses_taken (stmt));
-
start_ssa_stmt_operands ();
parse_ssa_operands (stmt);
finalize_ssa_stmt_operands (stmt);
gimple_set_use_ops (stmt, NULL);
}
- if (gimple_has_ops (stmt))
- gimple_set_addresses_taken (stmt, NULL);
-
if (gimple_has_mem_ops (stmt))
{
gimple_set_vuse (stmt, NULL_TREE);
}
-/* Push *STMT_P on the SCB_STACK. This function is deprecated, do not
- introduce new uses of it. */
-
-void
-push_stmt_changes (gimple *stmt_p)
-{
- gimple stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- VEC_safe_push (gimple_p, heap, scb_stack, stmt_p);
-}
-
-/* Pop the top stmt from SCB_STACK and act on the differences between
- what was recorded by push_stmt_changes and the current state of
- the statement. This function is deprecated, do not introduce
- new uses of it. */
-
-void
-pop_stmt_changes (gimple *stmt_p)
-{
- gimple *stmt2_p, stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- stmt2_p = VEC_pop (gimple_p, scb_stack);
- gcc_assert (stmt_p == stmt2_p);
-
- /* Force an operand re-scan on the statement and mark any newly
- exposed variables. This also will mark the virtual operand
- for renaming if necessary. */
- update_stmt (stmt);
-}
-
-/* Discard the topmost stmt from SCB_STACK. This is useful
- when the caller realized that it did not actually modified the
- statement. It avoids the expensive operand re-scan.
- This function is deprecated, do not introduce new uses of it. */
-
-void
-discard_stmt_changes (gimple *stmt_p)
-{
- gimple *stmt2_p, stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- stmt2_p = VEC_pop (gimple_p, scb_stack);
- gcc_assert (stmt_p == stmt2_p);
-}
-
/* Unlink STMTs virtual definition from the IL by propagating its use. */
void