various attributes for each variable used by alias analysis and the
optimizer. */
-static void
+static unsigned int
find_referenced_vars (void)
{
htab_t vars_found;
}
htab_delete (vars_found);
+ return 0;
}
struct tree_opt_pass pass_referenced_vars =
gcc_assert (DECL_P (t));
gcc_assert (!t->common.ann || t->common.ann->common.type == VAR_ANN);
- ann = ggc_alloc (sizeof (*ann));
+ ann = GGC_NEW (struct var_ann_d);
memset ((void *) ann, 0, sizeof (*ann));
ann->common.type = VAR_ANN;
return ann;
}
+/* Create a new annotation for a FUNCTION_DECL node T. */
+
+function_ann_t
+create_function_ann (tree t)
+{
+ function_ann_t ann;
+
+ gcc_assert (t);
+ gcc_assert (TREE_CODE (t) == FUNCTION_DECL);
+ gcc_assert (!t->common.ann || t->common.ann->common.type == FUNCTION_ANN);
+
+ ann = ggc_alloc (sizeof (*ann));
+ memset ((void *) ann, 0, sizeof (*ann));
+
+ ann->common.type = FUNCTION_ANN;
+
+ t->common.ann = (tree_ann_t) ann;
+
+ return ann;
+}
/* Create a new annotation for a statement node T. */
gcc_assert (is_gimple_stmt (t));
gcc_assert (!t->common.ann || t->common.ann->common.type == STMT_ANN);
- ann = ggc_alloc (sizeof (*ann));
+ ann = GGC_NEW (struct stmt_ann_d);
memset ((void *) ann, 0, sizeof (*ann));
ann->common.type = STMT_ANN;
gcc_assert (t);
gcc_assert (!t->common.ann || t->common.ann->common.type == TREE_ANN_COMMON);
- ann = ggc_alloc (sizeof (*ann));
+ ann = GGC_NEW (union tree_ann_d);
memset ((void *) ann, 0, sizeof (*ann));
ann->common.type = TREE_ANN_COMMON;
make_rename_temp (tree type, const char *prefix)
{
tree t = create_tmp_var (type, prefix);
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
+
if (referenced_vars)
{
add_referenced_tmp_var (t);
fprintf (file, ", ");
print_generic_expr (file, TREE_TYPE (var), dump_flags);
- if (ann && ann->type_mem_tag)
+ if (ann && ann->symbol_mem_tag)
{
- fprintf (file, ", type memory tag: ");
- print_generic_expr (file, ann->type_mem_tag, dump_flags);
+ fprintf (file, ", symbol memory tag: ");
+ print_generic_expr (file, ann->symbol_mem_tag, dump_flags);
}
- if (ann && ann->is_alias_tag)
- fprintf (file, ", is an alias tag");
+ if (ann && ann->is_aliased)
+ fprintf (file, ", is aliased");
if (TREE_ADDRESSABLE (var))
fprintf (file, ", is addressable");
fprintf (file, ", is volatile");
if (is_call_clobbered (var))
- fprintf (file, ", call clobbered");
+ {
+ fprintf (file, ", call clobbered");
+ if (dump_flags & TDF_DETAILS)
+ {
+ var_ann_t va = var_ann (var);
+ unsigned int escape_mask = va->escape_mask;
+
+ fprintf (file, " (");
+ if (escape_mask & ESCAPE_STORED_IN_GLOBAL)
+ fprintf (file, ", stored in global");
+ if (escape_mask & ESCAPE_TO_ASM)
+ fprintf (file, ", goes through ASM");
+ if (escape_mask & ESCAPE_TO_CALL)
+ fprintf (file, ", passed to call");
+ if (escape_mask & ESCAPE_BAD_CAST)
+ fprintf (file, ", bad cast");
+ if (escape_mask & ESCAPE_TO_RETURN)
+ fprintf (file, ", returned from func");
+ if (escape_mask & ESCAPE_TO_PURE_CONST)
+ fprintf (file, ", passed to pure/const");
+ if (escape_mask & ESCAPE_IS_GLOBAL)
+ fprintf (file, ", is global var");
+ if (escape_mask & ESCAPE_IS_PARM)
+ fprintf (file, ", is incoming pointer");
+ if (escape_mask & ESCAPE_UNKNOWN)
+ fprintf (file, ", unknown escape");
+ fprintf (file, " )");
+ }
+ }
if (default_def (var))
{
/* Lookup UID in the referenced_vars hashtable and return the associated
- variable or NULL if it is not there. */
-
-tree
-referenced_var_lookup_if_exists (unsigned int uid)
-{
- struct int_tree_map *h, in;
- in.uid = uid;
- h = htab_find_with_hash (referenced_vars, &in, uid);
- if (h)
- return h->to;
- return NULL_TREE;
-}
-
-/* Lookup UID in the referenced_vars hashtable and return the associated
variable. */
tree
{
struct int_tree_map *h, in;
in.uid = uid;
- h = htab_find_with_hash (referenced_vars, &in, uid);
+ h = (struct int_tree_map *) htab_find_with_hash (referenced_vars, &in, uid);
gcc_assert (h || uid == 0);
if (h)
return h->to;
struct int_tree_map *h;
void **loc;
- h = ggc_alloc (sizeof (struct int_tree_map));
+ h = GGC_NEW (struct int_tree_map);
h->uid = uid;
h->to = to;
loc = htab_find_slot_with_hash (referenced_vars, h, uid, INSERT);
struct int_tree_map *h, in;
gcc_assert (SSA_VAR_P (var));
in.uid = DECL_UID (var);
- h = htab_find_with_hash (default_defs, &in, DECL_UID (var));
+ h = (struct int_tree_map *) htab_find_with_hash (default_defs, &in,
+ DECL_UID (var));
if (h)
return h->to;
return NULL_TREE;
/* Default definition might be changed by tail call optimization. */
if (!*loc)
{
- h = ggc_alloc (sizeof (struct int_tree_map));
+ h = GGC_NEW (struct int_tree_map);
h->uid = DECL_UID (var);
h->to = def;
*(struct int_tree_map **) loc = h;
}
else
{
- h = *loc;
+ h = (struct int_tree_map *) *loc;
h->to = def;
}
}
*slot = (void *) var;
referenced_var_insert (DECL_UID (var), var);
-
- /* Global variables are always call-clobbered. */
- if (is_global_var (var))
- mark_call_clobbered (var);
-
+
/* Tag's don't have DECL_INITIAL. */
if (MTAG_P (var))
return;
-
+
/* Scan DECL_INITIAL for pointer variables as they may contain
address arithmetic referencing the address of other
variables. */
if (TREE_CODE (stmt) == PHI_NODE)
return;
+ get_stmt_ann (stmt);
vars_in_vops_to_rename = BITMAP_ALLOC (NULL);
/* Before re-scanning the statement for operands, mark the existing
HOST_WIDE_INT maxsize = -1;
tree size_tree = NULL_TREE;
tree bit_offset = bitsize_zero_node;
+ bool seen_variable_array_ref = false;
gcc_assert (!SSA_VAR_P (exp));
fold_convert (bitsizetype, index),
bitsize_unit_node);
bit_offset = size_binop (PLUS_EXPR, bit_offset, index);
+
+ /* An array ref with a constant index up in the structure
+ hierarchy will constrain the size of any variable array ref
+ lower in the access hierarchy. */
+ seen_variable_array_ref = false;
}
else
{
}
else
maxsize = -1;
+
+ /* Remember that we have seen an array ref with a variable
+ index. */
+ seen_variable_array_ref = true;
}
}
break;
}
done:
+ /* We need to deal with variable arrays ending structures such as
+ struct { int length; int a[1]; } x; x.a[d]
+ struct { struct { int a; int b; } a[1]; } x; x.a[d].a
+ struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
+ where we do not know maxsize for variable index accesses to
+ the array. The simplest way to conservatively deal with this
+ is to punt in the case that offset + maxsize reaches the
+ base type boundary. */
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ && TREE_INT_CST_LOW (bit_offset) + maxsize
+ == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))
+ maxsize = -1;
+
/* ??? Due to negative offsets in ARRAY_REF we can end up with
negative bit_offset here. We might want to store a zero offset
in this case. */