Commit c75ab022 by Daniel Berlin Committed by Daniel Berlin

In gcc/ada/ 2005-03-12 Daniel Berlin <dberlin@dberlin.org>

In gcc/ada/
2005-03-12  Daniel Berlin <dberlin@dberlin.org>

	* misc.c (gnat_post_options): Turn off structural
	aliasing for now.
In gcc/
2005-03-12  Daniel Berlin  <dberlin@dberlin.org>

	* tree-flow-inline.h (ref_contains_array_ref): New function.
	(lookup_subvars_for_var): Ditto.
	(get_subvars_for_var): Ditto.
	(var_can_have_subvars): Ditto.

	* tree-flow.h (mem_tag_kind): Add STRUCT_FIELD.
	(struct subvar): New type.

	* tree-dfa.c (okay_component_ref_for_subvars): New function.

	* tree-optimize.c (init_tree_optimization_passes): Call
	pass_create_structure_vars.

	* tree-ssa-alias.c: Include vec.h.
	(init_alias_info): Don't auto-clear call clobbered on struct-field
	tags.
	(compute_flow_insensitive_aliasing): Handle subvars.
	(group_aliases): Handle STRUCT_FIELD aliases.
	(setup_pointers_and_addressables): Ditto.
	Don't mark variables non-addressable if they still have
	addressable subvars.
	Also mark subvars addressable when the real variable is marked
	addressable.
	(add_pointed_to_var): Try to prune the pointed-to set by only
	pointing to subvars when possible.
	Otherwise, make sure we set addresses_needed and pt_vars to
	properly include subvars.
	(bitpos_of_field): New function.
	(push_fields_onto_fieldstack): Ditto.
	(get_or_create_used_part_for): Ditto.
	(create_overlap_variables_for): Ditto.
	(find_used_portions): Ditto.
	(create_structure_vars): Ditto.
	(pass_create_structure_vars): New structure.

	* tree-ssa-operands.c (finalize_ssa_v_must_defs): Remove assert.
	(get_expr_operands): Handle subvars.  Also try to turn
	COMPONENT_REF accesses into must-defs now that we can accurately
	portray it.
	(note_addressable): Try to only mark as addressable those subvars
	we know a COMPONENT_REF touches.
	(overlap_subvar): New function.

	* tree-vect-analyze.c (vect_object_analysis): Add new parameter.
	Handle subvar storing.
	(vect_address_analysis): Update caller of vect_object_analysis.

	* tree-vect-transform.c (vect_create_data_ref_ptr): Copy subvars.

	* tree-vectorizer.h (struct _stmt_vec_info): Add subvars member.
	(STMT_VINFO_SUBVARS): New macro.

	* common.opts: add flag_tree_salias.

	* opts.c (decode_options): flag_tree_salias defaults to on.

	* doc/invoke.texi: Document fdump-tree-svars and -ftree-salias.

	* doc/tree-ssa.texi: Document structural alias analysis.

From-SVN: r96362
parent 23845f02
2005-03-12 Daniel Berlin <dberlin@dberlin.org>
* tree-flow-inline.h (ref_contains_array_ref): New function.
(lookup_subvars_for_var): Ditto.
(get_subvars_for_var): Ditto.
(var_can_have_subvars): Ditto.
* tree-flow.h (mem_tag_kind): Add STRUCT_FIELD.
(struct subvar): New type.
* tree-dfa.c (okay_component_ref_for_subvars): New function.
* tree-optimize.c (init_tree_optimization_passes): Call
pass_create_structure_vars.
* tree-ssa-alias.c: Include vec.h.
(init_alias_info): Don't auto-clear call clobbered on struct-field
tags.
(compute_flow_insensitive_aliasing): Handle subvars.
(group_aliases): Handle STRUCT_FIELD aliases.
(setup_pointers_and_addressables): Ditto.
Don't mark variables non-addressable if they still have
addressable subvars.
Also mark subvars addressable when the real variable is marked
addressable.
(add_pointed_to_var): Try to prune the pointed-to set by only
pointing to subvars when possible.
Otherwise, make sure we set addresses_needed and pt_vars to
properly include subvars.
(bitpos_of_field): New function.
(push_fields_onto_fieldstack): Ditto.
(get_or_create_used_part_for): Ditto.
(create_overlap_variables_for): Ditto.
(find_used_portions): Ditto.
(create_structure_vars): Ditto.
(pass_create_structure_vars): New structure.
* tree-ssa-operands.c (finalize_ssa_v_must_defs): Remove assert.
(get_expr_operands): Handle subvars. Also try to turn
COMPONENT_REF accesses into must-defs now that we can accurately
portray it.
(note_addressable): Try to only mark as addressable those subvars
we know a COMPONENT_REF touches.
(overlap_subvar): New function.
* tree-vect-analyze.c (vect_object_analysis): Add new parameter.
Handle subvar storing.
(vect_address_analysis): Update caller of vect_object_analysis.
* tree-vect-transform.c (vect_create_data_ref_ptr): Copy subvars.
* tree-vectorizer.h (struct _stmt_vec_info): Add subvars member.
(STMT_VINFO_SUBVARS): New macro.
* common.opts: add flag_tree_salias.
* opts.c (decode_options): flag_tree_salias defaults to on.
* doc/invoke.texi: Document fdump-tree-svars and -ftree-salias.
* doc/tree-ssa.texi: Document structural alias analysis.
2005-03-12 Steven Bosscher <stevenb@suse.de>
* tree-cfg.c (make_goto_expr_edges): Don't use error_mark_node.
......
2005-03-12 Daniel Berlin <dberlin@dberlin.org>
* misc.c (gnat_post_options): Turn off structural
aliasing for now.
2005-03-08 Laurent Guerby <laurent@guerby.net>
* system-linux-sparc.ads: Fix typo in previous commit.
......
......@@ -352,6 +352,8 @@ gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
flag_no_inline = 1;
if (flag_inline_functions)
flag_inline_trees = 2;
flag_tree_salias = 0;
return false;
}
......
......@@ -872,6 +872,10 @@ ftree-pre
Common Report Var(flag_tree_pre)
Enable SSA-PRE optimization on trees
ftree-salias
Common Report Var(flag_tree_salias)
Perform structural alias analysis
ftree-sink
Common Report Var(flag_tree_sink)
Enable SSA code sinking on trees
......
......@@ -266,6 +266,7 @@ Objective-C and Objective-C++ Dialects}.
-fdump-tree-nrv -fdump-tree-vect @gol
-fdump-tree-sink @gol
-fdump-tree-sra@r{[}-@var{n}@r{]} @gol
-fdump-tree-salias @gol
-fdump-tree-fre@r{[}-@var{n}@r{]} @gol
-ftree-vectorizer-verbose=@var{n} @gol
-feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
......@@ -322,6 +323,7 @@ Objective-C and Objective-C++ Dialects}.
-ftree-loop-linear -ftree-loop-im -ftree-loop-ivcanon -fivopts @gol
-ftree-dominator-opts -ftree-dse -ftree-copyrename -ftree-sink @gol
-ftree-ch -ftree-sra -ftree-ter -ftree-lrs -ftree-fre -ftree-vectorize @gol
-ftree-salias @gol
--param @var{name}=@var{value}
-O -O0 -O1 -O2 -O3 -Os}
......@@ -3819,6 +3821,11 @@ appending @file{.ch} to the source file name.
Dump SSA related information to a file. The file name is made by appending
@file{.ssa} to the source file name.
@item salias
@opindex fdump-tree-salias
Dump structure aliasing variable information to a file. This file name
is made by appending @file{.salias} to the source file name.
@item alias
@opindex fdump-tree-alias
Dump aliasing information for each function. The file name is made by
......@@ -4695,6 +4702,10 @@ that are computed on all paths leading to the redundant computation.
This analysis faster than PRE, though it exposes fewer redundancies.
This flag is enabled by default at @option{-O} and higher.
@item -ftree-salias
Perform structural alias analysis on trees. This flag
is enabled by default at @option{-O} and higher.
@item -ftree-sink
Perform forward store motion on trees. This flag is
enabled by default at @option{-O} and higher.
......
......@@ -1208,9 +1208,46 @@ hooks to execute custom code at various points during traversal:
@cindex flow-sensitive alias analysis
@cindex flow-insensitive alias analysis
Alias analysis proceeds in 3 main phases:
Alias analysis proceeds in 4 main phases:
@enumerate
@item Structural alias analysis.
This phase walks the types for structure variables, and determines which
of the fields can overlap using offset and size of each field. For each
field, a ``subvariable'' called a ``Structure field tag'' (SFT)@ is
created, which represents that field as a separate variable. All
accesses that could possibly overlap with a given field will have
virtual operands for the SFT of that field.
@smallexample
struct foo
@{
int a;
int b;
@}
struct foo temp;
int bar (void)
@{
int tmp1, tmp2, tmp3;
SFT.0_2 = V_MUST_DEF <SFT.0_1>
temp.a = 5;
SFT.1_4 = V_MUST_DEF <SFT.1_3>
temp.b = 6;
VUSE <SFT.1_4>
tmp1_5 = temp.b;
VUSE <SFT.0_2>
tmp2_6 = temp.a;
tmp3_7 = tmp1_5 + tmp2_6;
return tmp3_7;
@}
@end smallexample
If you copy the type tag for a variable for some reason, you probably
also want to copy the subvariables for that variable.
@item Points-to and escape analysis.
This phase walks the use-def chains in the SSA web looking for
......
......@@ -502,6 +502,7 @@ decode_options (unsigned int argc, const char **argv)
flag_tree_copyrename = 1;
flag_tree_fre = 1;
flag_tree_sink = 1;
flag_tree_salias = 1;
if (!optimize_size)
{
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-lim-details" } */
int x; int y;
struct { int x; int y; } global;
int foo() {
int i;
for ( i=0; i<10; i++)
y += x*x;
for ( i=0; i<10; i++)
global.y += global.x*global.x;
}
/* { dg-final { scan-tree-dump-times "Executing store motion of global.y" 1 "lim" } } */
/* XXX: We should also check for the load motion of global.x, but there is no easy way to do this. */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized -fno-tree-sra" } */
/* Even without SRA being enabled, we should be able to eliminate every structure store and load here. */
extern void foo (const int);
int main(void)
{
struct a
{
int e;
int f;
int g;
} a;
struct a b;
int x, c;
a.e = 50;
a.f = 9;
a.g = a.e * a.f;
foo (a.f);
foo (a.g);
x = a.f;
c = a.e;
foo (x);
foo (c);
a.e = 5;
a.f = 40;
a.g = 90;
foo (a.e);
foo (a.f);
foo (a.g);
c = a.f;
foo (c);
b.e = 9;
a.e = b.e + 1 * c;
a.f = 30;
foo (a.e);
foo (a.f);
x = a.e * a.f;
foo (x);
}
/* { dg-final { scan-tree-dump-times "a.e" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "a.f" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "a.g" 0 "optimized" } } */
/* { dg-final { scan-tree-dump-times "b.e" 0 "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct foo
{
int a;
int b;
} temp;
/* We should be able to optimize this to return 11. */
int main(void)
{
temp.a = 5;
temp.b = 6;
return temp.a + temp.b;
}
/* { dg-final { scan-tree-dump-times "return 11" 1 "optimized" } } */
......@@ -1053,3 +1053,46 @@ mark_call_clobbered_vars_to_rename (void)
bitmap_set_bit (vars_to_rename, var_ann (var)->uid);
}
}
/* If REF is a COMPONENT_REF for a structure that can have sub-variables, and
we know where REF is accessing, return the variable in REF that has the
sub-variables. If the return value is not NULL, POFFSET will be the
offset, in bits, of REF inside the return value, and PSIZE will be the
size, in bits, of REF inside the return value. */
tree
okay_component_ref_for_subvars (tree ref, HOST_WIDE_INT *poffset,
HOST_WIDE_INT *psize)
{
tree result = NULL;
HOST_WIDE_INT bitsize;
HOST_WIDE_INT bitpos;
tree offset;
enum machine_mode mode;
int unsignedp;
int volatilep;
gcc_assert (!SSA_VAR_P (ref));
*poffset = 0;
*psize = (unsigned int) -1;
if (ref_contains_array_ref (ref))
return result;
ref = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, false);
if (TREE_CODE (ref) == INDIRECT_REF)
return result;
else if (offset == NULL && bitsize != -1 && SSA_VAR_P (ref))
{
*poffset = bitpos;
*psize = bitsize;
if (get_subvars_for_var (ref) != NULL)
return ref;
}
else if (SSA_VAR_P (ref))
{
if (get_subvars_for_var (ref) != NULL)
return ref;
}
return NULL_TREE;
}
......@@ -878,4 +878,60 @@ op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill,
op_iter_init (ptr, stmt, SSA_OP_VMUSTDEFKILL);
op_iter_next_mustdef (kill, def, ptr);
}
/* Return true if REF, a COMPONENT_REF, has an ARRAY_REF somewhere in it. */
static inline bool
ref_contains_array_ref (tree ref)
{
while (handled_component_p (ref))
{
if (TREE_CODE (ref) == ARRAY_REF)
return true;
ref = TREE_OPERAND (ref, 0);
}
return false;
}
/* Given a variable VAR, lookup and return a pointer to the list of
subvariables for it. */
static inline subvar_t *
lookup_subvars_for_var (tree var)
{
var_ann_t ann = var_ann (var);
gcc_assert (ann);
return &ann->subvars;
}
/* Given a variable VAR, return a linked list of subvariables for VAR, or
NULL, if there are no subvariables. */
static inline subvar_t
get_subvars_for_var (tree var)
{
subvar_t subvars;
gcc_assert (SSA_VAR_P (var));
if (TREE_CODE (var) == SSA_NAME)
subvars = *(lookup_subvars_for_var (SSA_NAME_VAR (var)));
else
subvars = *(lookup_subvars_for_var (var));
return subvars;
}
/* Return true if V is a tree that we can have subvars for.
Normally, this is any aggregate type, however, due to implementation
limitations ATM, we exclude array types as well. */
static inline bool
var_can_have_subvars (tree v)
{
return (AGGREGATE_TYPE_P (TREE_TYPE (v)) &&
TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE);
}
#endif /* _TREE_FLOW_INLINE_H */
......@@ -138,7 +138,26 @@ enum mem_tag_kind {
TYPE_TAG,
/* This variable is a name memory tag (NMT). */
NAME_TAG
NAME_TAG,
/* This variable represents a structure field. */
STRUCT_FIELD
};
struct subvar;
typedef struct subvar *subvar_t;
/* This structure represents a fake sub-variable for a structure field. */
struct subvar GTY(())
{
/* Fake variable name */
tree var;
/* Offset inside structure. */
HOST_WIDE_INT offset;
/* Size of field. */
HOST_WIDE_INT size;
/* Next subvar for this structure. */
subvar_t next;
};
struct var_ann_d GTY(())
......@@ -211,6 +230,8 @@ struct var_ann_d GTY(())
live at the same time and this can happen for each call to the
dominator optimizer. */
tree current_def;
subvar_t subvars;
};
......@@ -556,6 +577,9 @@ extern tree make_rename_temp (tree, const char *);
extern void record_vars (tree);
extern bool block_may_fallthru (tree block);
typedef tree tree_on_heap;
DEF_VEC_MALLOC_P (tree_on_heap);
/* In tree-ssa-alias.c */
extern void dump_may_aliases_for (FILE *, tree);
extern void debug_may_aliases_for (tree);
......@@ -567,13 +591,15 @@ extern void dump_points_to_info_for (FILE *, tree);
extern void debug_points_to_info_for (tree);
extern bool may_be_aliased (tree);
extern struct ptr_info_def *get_ptr_info (tree);
static inline subvar_t get_subvars_for_var (tree);
static inline bool ref_contains_array_ref (tree);
extern tree okay_component_ref_for_subvars (tree, HOST_WIDE_INT *,
HOST_WIDE_INT *);
static inline bool var_can_have_subvars (tree);
/* Call-back function for walk_use_def_chains(). At each reaching
definition, a function with this prototype is called. */
typedef bool (*walk_use_def_chains_fn) (tree, tree, void *);
typedef tree tree_on_heap;
DEF_VEC_MALLOC_P (tree_on_heap);
/* In tree-ssa.c */
extern void init_tree_ssa (void);
......
......@@ -348,6 +348,7 @@ init_tree_optimization_passes (void)
p = &pass_all_optimizations.sub;
NEXT_PASS (pass_referenced_vars);
NEXT_PASS (pass_create_structure_vars);
NEXT_PASS (pass_build_ssa);
NEXT_PASS (pass_may_alias);
NEXT_PASS (pass_rename_ssa_copies);
......
......@@ -167,5 +167,6 @@ extern struct tree_opt_pass pass_rest_of_compilation;
extern struct tree_opt_pass pass_sink_code;
extern struct tree_opt_pass pass_fre;
extern struct tree_opt_pass pass_linear_transform;
extern struct tree_opt_pass pass_create_structure_vars;
#endif /* GCC_TREE_PASS_H */
......@@ -683,8 +683,12 @@ finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p,
if (num == 0)
return NULL;
/* There should only be a single V_MUST_DEF per assignment. */
gcc_assert (TREE_CODE (stmt) != MODIFY_EXPR || num <= 1);
/* In the presence of subvars, there may be more than one V_MUST_DEF per
statement (one for each subvar). It is a bit expensive to verify that
all must-defs in a statement belong to subvars if there is more than one
MUST-def, so we don't do it. Suffice to say, if you reach here without
having subvars, and have num >1, you have hit a bug. */
old_ops = *old_ops_p;
......@@ -907,7 +911,6 @@ build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
lhs = TREE_OPERAND (lhs, 0);
if (TREE_CODE (lhs) != ARRAY_REF && TREE_CODE (lhs) != ARRAY_RANGE_REF
&& TREE_CODE (lhs) != COMPONENT_REF
&& TREE_CODE (lhs) != BIT_FIELD_REF
&& TREE_CODE (lhs) != REALPART_EXPR
&& TREE_CODE (lhs) != IMAGPART_EXPR)
......@@ -1021,6 +1024,49 @@ get_stmt_operands (tree stmt)
}
/* Return true if OFFSET and SIZE define a range that overlaps with some
portion of the range of SV, a subvar. If there was an exact overlap,
*EXACT will be set to true upon return. */
static bool
overlap_subvar (HOST_WIDE_INT offset, HOST_WIDE_INT size,
subvar_t sv, bool *exact)
{
/* There are three possible cases of overlap.
1. We can have an exact overlap, like so:
|offset, offset + size |
|sv->offset, sv->offset + sv->size |
2. We can have offset starting after sv->offset, like so:
|offset, offset + size |
|sv->offset, sv->offset + sv->size |
3. We can have offset starting before sv->offset, like so:
|offset, offset + size |
|sv->offset, sv->offset + sv->size|
*/
if (exact)
*exact = false;
if (offset == sv->offset && size == sv->size)
{
if (exact)
*exact = true;
return true;
}
else if (offset >= sv->offset && offset < (sv->offset + sv->size))
{
return true;
}
else if (offset < sv->offset && (offset + size > sv->offset))
{
return true;
}
return false;
}
/* Recursively scan the expression pointed by EXPR_P in statement referred to
by INFO. FLAGS is one of the OPF_* constants modifying how to interpret the
operands found. */
......@@ -1068,11 +1114,25 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case PARM_DECL:
case RESULT_DECL:
case CONST_DECL:
/* If we found a variable, add it to DEFS or USES depending
on the operand flags. */
add_stmt_operand (expr_p, s_ann, flags);
return;
{
subvar_t svars;
/* Add the subvars for a variable if it has subvars, to DEFS or USES.
Otherwise, add the variable itself.
Whether it goes to USES or DEFS depends on the operand flags. */
if (var_can_have_subvars (expr)
&& (svars = get_subvars_for_var (expr)))
{
subvar_t sv;
for (sv = svars; sv; sv = sv->next)
add_stmt_operand (&sv->var, s_ann, flags);
}
else
{
add_stmt_operand (expr_p, s_ann, flags);
}
return;
}
case MISALIGNED_INDIRECT_REF:
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
/* fall through */
......@@ -1104,30 +1164,39 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
/* Similarly to arrays, references to compound variables (complex
types and structures/unions) are globbed.
FIXME: This means that
a.x = 6;
a.y = 7;
foo (a.x, a.y);
will not be constant propagated because the two partial
definitions to 'a' will kill each other. Note that SRA may be
able to fix this problem if 'a' can be scalarized. */
/* If the LHS of the compound reference is not a regular variable,
recurse to keep looking for more operands in the subexpression. */
if (SSA_VAR_P (TREE_OPERAND (expr, 0)))
add_stmt_operand (expr_p, s_ann, flags);
else
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
if (code == COMPONENT_REF)
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
return;
{
tree ref;
HOST_WIDE_INT offset, size;
/* This component ref becomes an access to all of the subvariables
it can touch, if we can determine that, but *NOT* the real one.
If we can't determine which fields we could touch, the recursion
will eventually get to a variable and add *all* of its subvars, or
whatever is the minimum correct subset. */
ref = okay_component_ref_for_subvars (expr, &offset, &size);
if (ref)
{
subvar_t svars = get_subvars_for_var (ref);
subvar_t sv;
for (sv = svars; sv; sv = sv->next)
{
bool exact;
if (overlap_subvar (offset, size, sv, &exact))
{
if (exact)
flags &= ~opf_kill_def;
add_stmt_operand (&sv->var, s_ann, flags);
}
}
}
else
get_expr_operands (stmt, &TREE_OPERAND (expr, 0),
flags & ~opf_kill_def);
if (code == COMPONENT_REF)
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
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. */
......@@ -1158,7 +1227,6 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == ARRAY_REF
|| TREE_CODE (op) == ARRAY_RANGE_REF
|| TREE_CODE (op) == COMPONENT_REF
|| TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
......@@ -1554,9 +1622,10 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
{
if (flags & opf_kill_def)
{
/* Only regular variables may get a V_MUST_DEF
operand. */
gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG);
/* Only regular variables or struct fields may get a
V_MUST_DEF operand. */
gcc_assert (v_ann->mem_tag_kind == NOT_A_TAG
|| v_ann->mem_tag_kind == STRUCT_FIELD);
/* V_MUST_DEF for non-aliased, non-GIMPLE register
variable definitions. */
append_v_must_def (var);
......@@ -1615,26 +1684,60 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
}
}
/* Record that VAR had its address taken in the statement with annotations
S_ANN. */
static void
note_addressable (tree var, stmt_ann_t s_ann)
{
tree ref;
subvar_t svars;
HOST_WIDE_INT offset;
HOST_WIDE_INT size;
if (!s_ann)
return;
/* If this is a COMPONENT_REF, and we know exactly what it touches, we only
take the address of the subvariables it will touch.
Otherwise, we take the address of all the subvariables, plus the real
ones. */
if (var && TREE_CODE (var) == COMPONENT_REF
&& (ref = okay_component_ref_for_subvars (var, &offset, &size)))
{
subvar_t sv;
svars = get_subvars_for_var (ref);
if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
for (sv = svars; sv; sv = sv->next)
{
if (overlap_subvar (offset, size, sv, NULL))
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
}
return;
}
var = get_base_address (var);
if (var && SSA_VAR_P (var))
{
if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var)))
{
subvar_t sv;
for (sv = svars; sv; sv = sv->next)
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
}
}
}
/* Add clobbering definitions for .GLOBAL_VAR or for each of the call
clobbered variables in the function. */
......
......@@ -70,7 +70,7 @@ static bool vect_base_addr_differ_p (struct data_reference *,
struct data_reference *drb, bool *);
static tree vect_object_analysis (tree, tree, bool, tree,
struct data_reference **, tree *, tree *,
tree *, bool *, tree *);
tree *, bool *, tree *, subvar_t *);
static tree vect_address_analysis (tree, tree, bool, tree,
struct data_reference *, tree *, tree *,
tree *, bool *);
......@@ -1377,6 +1377,7 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1;
tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
tree dummy;
subvar_t dummy2;
switch (TREE_CODE (expr))
{
......@@ -1426,9 +1427,10 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
return base_addr0 ? base_addr0 : base_addr1;
case ADDR_EXPR:
base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt, is_read,
vectype, &dr, offset, misalign, step,
base_aligned, &dummy);
base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt,
is_read, vectype, &dr, offset,
misalign, step, base_aligned,
&dummy, &dummy2);
return base_address;
case SSA_NAME:
......@@ -1507,6 +1509,7 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
STEP - evolution of the DR_REF in the loop
BASE_ALIGNED - indicates if BASE is aligned
MEMTAG - memory tag for aliasing purposes
SUBVAR - Sub-variables of the variable
If something unexpected is encountered (an unsupported form of data-ref),
then NULL_TREE is returned. */
......@@ -1515,7 +1518,8 @@ static tree
vect_object_analysis (tree memref, tree stmt, bool is_read,
tree vectype, struct data_reference **dr,
tree *offset, tree *misalign, tree *step,
bool *base_aligned, tree *memtag)
bool *base_aligned, tree *memtag,
subvar_t *subvars)
{
tree base = NULL_TREE, base_address = NULL_TREE;
tree object_offset = ssize_int (0), object_misalign = ssize_int (0);
......@@ -1611,6 +1615,8 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
us to object. */
DR_BASE_NAME ((*dr)) = memref;
if (SSA_VAR_P (memref) && var_can_have_subvars (memref))
*subvars = get_subvars_for_var (memref);
base_address = build_fold_addr_expr (memref);
*memtag = memref;
}
......@@ -1698,6 +1704,9 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
/* MEMREF cannot be analyzed. */
return NULL_TREE;
if (SSA_VAR_P (*memtag) && var_can_have_subvars (*memtag))
*subvars = get_subvars_for_var (*memtag);
/* Part 2: Combine the results of object and address analysis to calculate
INITIAL_OFFSET, STEP and misalignment info. */
*offset = size_binop (PLUS_EXPR, object_offset, address_offset);
......@@ -1780,6 +1789,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
tree scalar_type, vectype;
tree base, offset, misalign, step, tag;
bool base_aligned;
subvar_t subvars;
/* Assumption: there exists a data-ref in stmt, if and only if
it has vuses/vdefs. */
......@@ -1843,7 +1853,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
dr = NULL;
base = vect_object_analysis (memref, stmt, is_read, vectype, &dr,
&offset, &misalign, &step,
&base_aligned, &tag);
&base_aligned, &tag, &subvars);
if (!base)
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
......@@ -1860,6 +1870,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
STMT_VINFO_VECT_MISALIGNMENT (stmt_info) = misalign;
STMT_VINFO_VECT_BASE_ALIGNED_P (stmt_info) = base_aligned;
STMT_VINFO_MEMTAG (stmt_info) = tag;
STMT_VINFO_SUBVARS (stmt_info) = subvars;
STMT_VINFO_VECTYPE (stmt_info) = vectype;
VARRAY_PUSH_GENERIC_PTR (*datarefs, dr);
STMT_VINFO_DATA_REF (stmt_info) = dr;
......
......@@ -353,12 +353,14 @@ vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
tag = STMT_VINFO_MEMTAG (stmt_info);
gcc_assert (tag);
get_var_ann (vect_ptr)->type_mem_tag = tag;
get_var_ann (vect_ptr)->subvars = STMT_VINFO_SUBVARS (stmt_info);
/* Mark for renaming all aliased variables
(i.e, the may-aliases of the type-mem-tag). */
nvuses = NUM_VUSES (vuses);
nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
for (i = 0; i < nvuses; i++)
{
tree use = VUSE_OP (vuses, i);
......
......@@ -172,6 +172,7 @@ typedef struct _stmt_vec_info {
/* Aliasing information. */
tree memtag;
subvar_t subvars;
/** The following fields are used to store the information about
data-reference. {base_address + initial_offset} is the first location
......@@ -213,6 +214,7 @@ typedef struct _stmt_vec_info {
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
#define STMT_VINFO_MEMTAG(S) (S)->memtag
#define STMT_VINFO_SUBVARS(S) (S)->subvars
#define STMT_VINFO_VECT_DR_BASE_ADDRESS(S)(S)->base_address
#define STMT_VINFO_VECT_INIT_OFFSET(S) (S)->initial_offset
#define STMT_VINFO_VECT_STEP(S) (S)->step
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment