/* Operand is a "non-specific" kill for call-clobbers and such. This
is used to distinguish "reset the world" events from explicit
- MODIFY_EXPRs. */
+ GIMPLE_MODIFY_STMTs. */
#define opf_non_specific (1 << 3)
/* Array for building all the def operands. */
/* Array for building all the V_MUST_DEF operands. */
static VEC(tree,heap) *build_v_must_defs;
-/* These arrays are the cached operand vectors for call clobbered calls. */
-static bool ops_active = false;
-
-static GTY (()) struct ssa_operand_memory_d *operand_memory = NULL;
-static unsigned operand_memory_index;
-
static void get_expr_operands (tree, tree *, int);
-static def_optype_p free_defs = NULL;
-static use_optype_p free_uses = NULL;
-static vuse_optype_p free_vuses = NULL;
-static maydef_optype_p free_maydefs = NULL;
-static mustdef_optype_p free_mustdefs = NULL;
+/* Number of functions with initialized ssa_operands. */
+static int n_initialized = 0;
/* Allocates operand OP of given TYPE from the appropriate free list,
or of the new value if the list is empty. */
#define ALLOC_OPTYPE(OP, TYPE) \
do \
{ \
- TYPE##_optype_p ret = free_##TYPE##s; \
+ TYPE##_optype_p ret \
+ = gimple_ssa_operands (cfun)->free_##TYPE##s; \
if (ret) \
- free_##TYPE##s = ret->next; \
+ gimple_ssa_operands (cfun)->free_##TYPE##s \
+ = ret->next; \
else \
ret = ssa_operand_alloc (sizeof (*ret)); \
(OP) = ret; \
bool
ssa_operands_active (void)
{
- return ops_active;
+ return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active;
}
void
init_ssa_operands (void)
{
- build_defs = VEC_alloc (tree, heap, 5);
- build_uses = VEC_alloc (tree, heap, 10);
- build_vuses = VEC_alloc (tree, heap, 25);
- build_v_may_defs = VEC_alloc (tree, heap, 25);
- build_v_must_defs = VEC_alloc (tree, heap, 25);
-
- gcc_assert (operand_memory == NULL);
- operand_memory_index = SSA_OPERAND_MEMORY_SIZE;
- ops_active = true;
+ if (!n_initialized++)
+ {
+ build_defs = VEC_alloc (tree, heap, 5);
+ build_uses = VEC_alloc (tree, heap, 10);
+ build_vuses = VEC_alloc (tree, heap, 25);
+ build_v_may_defs = VEC_alloc (tree, heap, 25);
+ build_v_must_defs = VEC_alloc (tree, heap, 25);
+ }
+
+ gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL);
+ gimple_ssa_operands (cfun)->operand_memory_index = SSA_OPERAND_MEMORY_SIZE;
+ gimple_ssa_operands (cfun)->ops_active = true;
memset (&clobber_stats, 0, sizeof (clobber_stats));
}
fini_ssa_operands (void)
{
struct ssa_operand_memory_d *ptr;
- VEC_free (tree, heap, build_defs);
- VEC_free (tree, heap, build_uses);
- VEC_free (tree, heap, build_v_must_defs);
- VEC_free (tree, heap, build_v_may_defs);
- VEC_free (tree, heap, build_vuses);
- free_defs = NULL;
- free_uses = NULL;
- free_vuses = NULL;
- free_maydefs = NULL;
- free_mustdefs = NULL;
- while ((ptr = operand_memory) != NULL)
+ if (!--n_initialized)
+ {
+ VEC_free (tree, heap, build_defs);
+ VEC_free (tree, heap, build_uses);
+ VEC_free (tree, heap, build_v_must_defs);
+ VEC_free (tree, heap, build_v_may_defs);
+ VEC_free (tree, heap, build_vuses);
+ }
+ gimple_ssa_operands (cfun)->free_defs = NULL;
+ gimple_ssa_operands (cfun)->free_uses = NULL;
+ gimple_ssa_operands (cfun)->free_vuses = NULL;
+ gimple_ssa_operands (cfun)->free_maydefs = NULL;
+ gimple_ssa_operands (cfun)->free_mustdefs = NULL;
+ while ((ptr = gimple_ssa_operands (cfun)->operand_memory) != NULL)
{
- operand_memory = operand_memory->next;
+ gimple_ssa_operands (cfun)->operand_memory
+ = gimple_ssa_operands (cfun)->operand_memory->next;
ggc_free (ptr);
}
- ops_active = false;
+ gimple_ssa_operands (cfun)->ops_active = false;
if (dump_file && (dump_flags & TDF_STATS))
{
ssa_operand_alloc (unsigned size)
{
char *ptr;
- if (operand_memory_index + size >= SSA_OPERAND_MEMORY_SIZE)
+ if (gimple_ssa_operands (cfun)->operand_memory_index + size
+ >= SSA_OPERAND_MEMORY_SIZE)
{
struct ssa_operand_memory_d *ptr;
ptr = GGC_NEW (struct ssa_operand_memory_d);
- ptr->next = operand_memory;
- operand_memory = ptr;
- operand_memory_index = 0;
+ ptr->next = gimple_ssa_operands (cfun)->operand_memory;
+ gimple_ssa_operands (cfun)->operand_memory = ptr;
+ gimple_ssa_operands (cfun)->operand_memory_index = 0;
}
- ptr = &(operand_memory->mem[operand_memory_index]);
- operand_memory_index += size;
+ ptr = &(gimple_ssa_operands (cfun)->operand_memory
+ ->mem[gimple_ssa_operands (cfun)->operand_memory_index]);
+ gimple_ssa_operands (cfun)->operand_memory_index += size;
return ptr;
}
do \
{ \
TYPE##_optype_p next = (OP)->next; \
- (OP)->next = free_##TYPE##s; \
- free_##TYPE##s = (OP); \
+ (OP)->next \
+ = gimple_ssa_operands (cfun)->free_##TYPE##s; \
+ gimple_ssa_operands (cfun)->free_##TYPE##s = (OP);\
(OP) = next; \
} while (0)
/* If there is anything in the old list, free it. */
if (old_ops)
{
- old_ops->next = free_defs;
- free_defs = old_ops;
+ old_ops->next = gimple_ssa_operands (cfun)->free_defs;
+ gimple_ssa_operands (cfun)->free_defs = old_ops;
}
/* Now set the stmt's operands. */
unsigned int num = VEC_length (tree, build_defs);
/* There should only be a single real definition per assignment. */
- gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
+ gcc_assert ((stmt && TREE_CODE (stmt) != GIMPLE_MODIFY_STMT) || num <= 1);
/* If there is an old list, often the new list is identical, or close, so
find the elements at the beginning that are the same as the vector. */
{
for (ptr = old_ops; ptr; ptr = ptr->next)
delink_imm_use (USE_OP_PTR (ptr));
- old_ops->next = free_uses;
- free_uses = old_ops;
+ old_ops->next = gimple_ssa_operands (cfun)->free_uses;
+ gimple_ssa_operands (cfun)->free_uses = old_ops;
}
/* Now create nodes for all the new nodes. */
{
for (ptr = old_ops; ptr; ptr = ptr->next)
delink_imm_use (MAYDEF_OP_PTR (ptr));
- old_ops->next = free_maydefs;
- free_maydefs = old_ops;
+ old_ops->next = gimple_ssa_operands (cfun)->free_maydefs;
+ gimple_ssa_operands (cfun)->free_maydefs = old_ops;
}
/* Now set the stmt's operands. */
{
for (ptr = old_ops; ptr; ptr = ptr->next)
delink_imm_use (VUSE_OP_PTR (ptr));
- old_ops->next = free_vuses;
- free_vuses = old_ops;
+ old_ops->next = gimple_ssa_operands (cfun)->free_vuses;
+ gimple_ssa_operands (cfun)->free_vuses = old_ops;
}
/* Now set the stmt's operands. */
{
for (ptr = old_ops; ptr; ptr = ptr->next)
delink_imm_use (MUSTDEF_KILL_PTR (ptr));
- old_ops->next = free_mustdefs;
- free_mustdefs = old_ops;
+ old_ops->next = gimple_ssa_operands (cfun)->free_mustdefs;
+ gimple_ssa_operands (cfun)->free_mustdefs = old_ops;
}
/* Now set the stmt's operands. */
/* If ALIAS is .GLOBAL_VAR then the memory reference REF must be
using a call-clobbered memory tag. By definition, call-clobbered
memory tags can always touch .GLOBAL_VAR. */
- if (alias == global_var)
- return true;
-
- /* We cannot prune nonlocal aliases because they are not type
- specific. */
- if (alias == nonlocal_all)
+ if (alias == gimple_global_var (cfun))
return true;
/* If ALIAS is an SFT, it can't be touched if the offset
&& flag_strict_aliasing
&& TREE_CODE (ref) != INDIRECT_REF
&& !MTAG_P (alias)
- && !var_ann (alias)->is_heapvar
&& (TREE_CODE (base) != INDIRECT_REF
|| TREE_CODE (TREE_TYPE (base)) != UNION_TYPE)
&& !AGGREGATE_TYPE_P (TREE_TYPE (alias))
&& TREE_CODE (TREE_TYPE (alias)) != COMPLEX_TYPE
+ && !var_ann (alias)->is_heapvar
/* When the struct has may_alias attached to it, we need not to
return true. */
&& get_alias_set (base))
check that this only happens on non-specific stores.
Note that if this is a specific store, i.e. associated with a
- modify_expr, then we can't suppress the V_MAY_DEF, lest we run
+ gimple_modify_stmt, then we can't suppress the V_MAY_DEF, lest we run
into validation problems.
This can happen when programs cast away const, leaving us with a
if (v_ann->is_aliased
|| none_added
|| (TREE_CODE (var) == SYMBOL_MEMORY_TAG
- && for_clobber
- && SMT_USED_ALONE (var)))
+ && for_clobber))
{
- /* Every bare SMT def we add should have SMT_USED_ALONE
- set on it, or else we will get the wrong answer on
- clobbers. */
- if (none_added
- && !updating_used_alone && aliases_computed_p
- && TREE_CODE (var) == SYMBOL_MEMORY_TAG)
- gcc_assert (SMT_USED_ALONE (var));
-
append_v_may_def (var);
}
}
/* If we created .GLOBAL_VAR earlier, just use it. See compute_may_aliases
for the heuristic used to decide whether to create .GLOBAL_VAR or not. */
- if (global_var)
+ if (gimple_global_var (cfun))
{
- add_stmt_operand (&global_var, s_ann, opf_is_def);
+ tree var = gimple_global_var (cfun);
+ add_stmt_operand (&var, s_ann, opf_is_def);
return;
}
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
not_written_b = callee ? ipa_reference_get_not_written_global (callee) : NULL;
/* Add a V_MAY_DEF operand for every call clobbered variable. */
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
+ EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
{
tree var = referenced_var_lookup (u);
unsigned int escape_mask = var_ann (var)->escape_mask;
/* if the function is not pure, it may reference memory. Add
a VUSE for .GLOBAL_VAR if it has been created. See add_referenced_var
for the heuristic used to decide whether to create .GLOBAL_VAR. */
- if (global_var)
+ if (gimple_global_var (cfun))
{
- add_stmt_operand (&global_var, s_ann, opf_none);
+ tree var = gimple_global_var (cfun);
+ add_stmt_operand (&var, s_ann, opf_none);
return;
}
not_read_b = callee ? ipa_reference_get_not_read_global (callee) : NULL;
/* Add a VUSE for each call-clobbered variable. */
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
+ EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, u, bi)
{
tree var = referenced_var (u);
tree real_var = var;
computed. By not bothering with virtual operands for CALL_EXPRs
we avoid adding superfluous virtual operands, which can be a
significant compile time sink (See PR 15855). */
- if (aliases_computed_p
- && !bitmap_empty_p (call_clobbered_vars)
+ if (gimple_aliases_computed_p (cfun)
+ && !bitmap_empty_p (gimple_call_clobbered_vars (cfun))
&& !(call_flags & ECF_NOVOPS))
{
/* A 'pure' or a 'const' function never call-clobbers anything.
/* Clobber all call-clobbered variables (or .GLOBAL_VAR if we
decided to group them). */
- if (global_var)
- add_stmt_operand (&global_var, s_ann, opf_is_def);
+ if (gimple_global_var (cfun))
+ {
+ tree var = gimple_global_var (cfun);
+ add_stmt_operand (&var, s_ann, opf_is_def);
+ }
else
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (gimple_call_clobbered_vars (cfun), 0, i, bi)
{
tree var = referenced_var (i);
add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
}
/* Now clobber all addressables. */
- EXECUTE_IF_SET_IN_BITMAP (addressable_vars, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (gimple_addressable_vars (cfun), 0, i, bi)
{
tree var = referenced_var (i);
/* Scan operands for the assignment expression EXPR in statement STMT. */
static void
-get_modify_expr_operands (tree stmt, tree expr)
+get_modify_stmt_operands (tree stmt, tree expr)
{
/* First get operands from the RHS. */
- get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
+ get_expr_operands (stmt, &GIMPLE_STMT_OPERAND (expr, 1), opf_none);
/* For the LHS, use a regular definition (OPF_IS_DEF) for GIMPLE
registers. If the LHS is a store to memory, we will either need
The determination of whether to use a preserving or a killing
definition is done while scanning the LHS of the assignment. By
default, assume that we will emit a V_MUST_DEF. */
- get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def|opf_kill_def);
+ get_expr_operands (stmt, &GIMPLE_STMT_OPERAND (expr, 0),
+ opf_is_def|opf_kill_def);
}
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
return;
- case MODIFY_EXPR:
- get_modify_expr_operands (stmt, expr);
+ case GIMPLE_MODIFY_STMT:
+ get_modify_stmt_operands (stmt, expr);
return;
case CONSTRUCTOR:
code = TREE_CODE (stmt);
switch (code)
{
- case MODIFY_EXPR:
- get_modify_expr_operands (stmt, stmt);
+ case GIMPLE_MODIFY_STMT:
+ get_modify_stmt_operands (stmt, stmt);
break;
case COND_EXPR:
{
dump_immediate_uses_for (stderr, var);
}
-
-#include "gt-tree-ssa-operands.h"