Commit a916f21d by Richard Guenther Committed by Richard Biener

re PR tree-optimization/22548 (Aliasing can not tell array members apart)

2006-01-14  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/22548
	PR tree-optimization/22555
	PR tree-optimization/22501
	* Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
	* params.def (salias-max-array-elements): New parameter.
	* params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
	* doc/invoke.texi (salias-max-array-elements): Document.
	* tree-flow-inline.h (var_can_have_subvars): We also handle
	arrays now.
	* tree-ssa-alias.c (find_used_portions): Handle ARRAY_REF like
	COMPONENT_REF.
	* tree-ssa-structalias.c (params.h): Include.
	(push_fields_onto_fieldstack): Handle ARRAY_TYPE.
	(find_func_aliases): Handle multiple constraints from ARRAY_REF.
	(get_constraint_for): For ADDR_EXPR operating on something
	containing an ARRAY_REF, add all subvars to the solution.
	(handle_ptr_arith): Handle ARRAY_TYPE like RECORD_TYPE types.
	* tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
	for creating MUST_DEFs.
	(get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.

	* gcc.dg/tree-ssa/alias-4.c: New testcase.
	* gcc.dg/tree-ssa/alias-5.c: Likewise.
	* gcc.dg/tree-ssa/alias-6.c: Likewise.
	* gcc.dg/tree-ssa/alias-7.c: Likewise.
	* gcc.dg/tree-ssa/alias-8.c: Likewise.
	* gcc.dg/tree-ssa/alias-9.c: Likewise.
	* gcc.dg/tree-ssa/alias-10.c: Likewise.
	* gcc.dg/tree-ssa/alias-11.c: Likewise.
	* gcc.dg/tree-ssa/alias-12.c: Likewise.

From-SVN: r109703
parent 7f17528a
2006-01-14 Richard Guenther <rguenther@suse.de>
PR tree-optimization/22548
PR tree-optimization/22555
PR tree-optimization/22501
* Makefile.in (tree-ssa-structalias.o): Depend on $(PARAMS_H).
* params.def (salias-max-array-elements): New parameter.
* params.h (SALIAS_MAX_ARRAY_ELEMENTS): Define.
* doc/invoke.texi (salias-max-array-elements): Document.
* tree-flow-inline.h (var_can_have_subvars): We also handle
arrays now.
* tree-ssa-alias.c (find_used_portions): Handle ARRAY_REF like
COMPONENT_REF.
* tree-ssa-structalias.c (params.h): Include.
(push_fields_onto_fieldstack): Handle ARRAY_TYPE.
(find_func_aliases): Handle multiple constraints from ARRAY_REF.
(get_constraint_for): For ADDR_EXPR operating on something
containing an ARRAY_REF, add all subvars to the solution.
(handle_ptr_arith): Handle ARRAY_TYPE like RECORD_TYPE types.
* tree-ssa-operands.c (parse_ssa_operands): Handle ARRAY_REF
for creating MUST_DEFs.
(get_expr_operands): Treat ARRAY_REF like COMPONENT_REF wrt subvars.
2006-01-14 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
......
......@@ -1792,7 +1792,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
tree-ssa-structalias.o: tree-ssa-structalias.c tree-ssa-structalias.h \
$(SYSTEM_H) $(CONFIG_H) $(GGC_H) $(TREE_H) $(TREE_FLOW_H) \
$(TM_H) coretypes.h cgraph.h tree-pass.h $(TIMEVAR_H) \
gt-tree-ssa-structalias.h
gt-tree-ssa-structalias.h $(PARAMS_H)
tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) output.h $(DIAGNOSTIC_H) \
toplev.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
......
......@@ -5744,6 +5744,10 @@ The maximum number of fields in a variable without direct
structure accesses for which structure aliasing will consider trying
to track each field. The default is 5
@item salias-max-array-elements
The maximum number of elements an array can have and its elements
still be tracked individually by structure aliasing. The default is 4
@item sra-max-structure-size
The maximum structure size, in bytes, at which the scalar replacement
of aggregates (SRA) optimization will perform block copies. The
......
......@@ -47,7 +47,14 @@ DEFPARAM (PARAM_SALIAS_MAX_IMPLICIT_FIELDS,
"salias-max-implicit-fields",
"The maximum number of fields in a structure variable without direct structure accesses that GCC will attempt to track separately",
5, 0, 0)
/* The maximum number of array elements structure aliasing will decompose
an array for. The default is 4. */
DEFPARAM (PARAM_SALIAS_MAX_ARRAY_ELEMENTS,
"salias-max-array-elements",
"The maximum number of elements in an array for wich we track its elements separately",
4, 0, 0)
/* The maximum structure size at which the scalar replacement of
aggregates (SRA) pass will perform block copies. The default
value, 0, implies that GCC will select the most appropriate size
......
......@@ -91,6 +91,8 @@ typedef enum compiler_param
/* Macros for the various parameters. */
#define SALIAS_MAX_IMPLICIT_FIELDS \
PARAM_VALUE (PARAM_SALIAS_MAX_IMPLICIT_FIELDS)
#define SALIAS_MAX_ARRAY_ELEMENTS \
PARAM_VALUE (PARAM_SALIAS_MAX_ARRAY_ELEMENTS)
#define SRA_MAX_STRUCTURE_SIZE \
PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
#define SRA_MAX_STRUCTURE_COUNT \
......
2006-01-14 Richard Guenther <rguenther@suse.de>
PR tree-optimization/22548
PR tree-optimization/22555
PR tree-optimization/22501
* gcc.dg/tree-ssa/alias-4.c: New testcase.
* gcc.dg/tree-ssa/alias-5.c: Likewise.
* gcc.dg/tree-ssa/alias-6.c: Likewise.
* gcc.dg/tree-ssa/alias-7.c: Likewise.
* gcc.dg/tree-ssa/alias-8.c: Likewise.
* gcc.dg/tree-ssa/alias-9.c: Likewise.
* gcc.dg/tree-ssa/alias-10.c: Likewise.
* gcc.dg/tree-ssa/alias-11.c: Likewise.
* gcc.dg/tree-ssa/alias-12.c: Likewise.
2005-01-14 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/pr19210-1.c: Update outcome. Add new test loop.
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct {
int i;
int x[2];
int j;
} a;
int foo(int i)
{
a.i = 1;
a.j = 2;
a.x[i] = 0;
return a.i + a.j;
}
/* { dg-final { scan-tree-dump "return 3;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct param { int *a; };
void foo(struct param *p);
int bar(void)
{
int a[32];
struct param p;
a[0] = 1;
a[1] = 1;
p.a = &a[0];
foo(&p);
return a[0] + *p.a;
}
/* { dg-final { scan-tree-dump "return \\*p\\.a \\\+ a.0.;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-alias1-vops" } */
struct {
int i;
int x[128];
int j;
} a;
int foo(int i)
{
a.x[i] = 0;
return a.x[i];
}
/* { dg-final { scan-tree-dump "V_MAY_DEF" "alias1" } } */
/* { dg-final { cleanup-tree-dump "alias1" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct {
int i;
struct {
int x[2];
} b;
} a;
int foo(void)
{
a.i = 1;
a.b.x[0] = 0;
a.b.x[1] = 1;
return a.i + a.b.x[0];
}
/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct {
int i;
struct {
struct {
int i;
} x[2];
} b;
} a;
int foo(void)
{
a.i = 1;
a.b.x[0].i = 0;
a.b.x[1].i = 1;
return a.i + a.b.x[0].i;
}
/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
struct param { int *a; };
void foo(struct param *p);
int bar(void)
{
int a[2];
struct param p;
a[0] = 1;
a[1] = 1;
p.a = &a[0];
foo(&p);
return a[0] + *p.a;
}
/* { dg-final { scan-tree-dump "return \\*p\\.a \\\+ a.0.;" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* { dg-do run } */
/* { dg-options "-O2" } */
void abort(void);
int main()
{
int a[2];
int *p = a;
int i;
a[0] = 1;
a[1] = 2;
for (i=0; i<2; ++i)
if (p[i] != i+1)
abort();
return 0;
}
/* { dg-do run } */
/* { dg-options "-O2" } */
void abort(void);
int main()
{
int a[2];
int i = 1;
a[0] = 1;
a[1] = 2;
if (*(a + i) != 2)
abort();
return 0;
}
/* { dg-do run } */
/* { dg-options "-O2" } */
void abort(void);
int main()
{
int a[32];
int i = 1;
a[0] = 1;
a[1] = 2;
if (*(a + i) != 2)
abort();
return 0;
}
......@@ -1489,8 +1489,7 @@ get_subvar_at (tree var, unsigned HOST_WIDE_INT offset)
}
/* 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. Also complex
Normally, this is any aggregate type. Also complex
types which are not gimple registers can have subvars. */
static inline bool
......@@ -1500,9 +1499,8 @@ var_can_have_subvars (tree v)
if (!DECL_P (v) || MTAG_P (v))
return false;
/* Aggregates besides arrays can have subvars. */
if (AGGREGATE_TYPE_P (TREE_TYPE (v))
&& TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
/* Aggregates can have subvars. */
if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
return true;
/* Complex types variables which are not also a gimple register can
......
......@@ -2698,6 +2698,7 @@ find_used_portions (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
case REALPART_EXPR:
case IMAGPART_EXPR:
case COMPONENT_REF:
case ARRAY_REF:
{
HOST_WIDE_INT bitsize;
HOST_WIDE_INT bitmaxsize;
......
......@@ -732,8 +732,7 @@ parse_ssa_operands (tree stmt)
if (TREE_CODE (lhs) == VIEW_CONVERT_EXPR)
lhs = TREE_OPERAND (lhs, 0);
if (TREE_CODE (lhs) != ARRAY_REF
&& TREE_CODE (lhs) != ARRAY_RANGE_REF
if (TREE_CODE (lhs) != ARRAY_RANGE_REF
&& TREE_CODE (lhs) != BIT_FIELD_REF)
lhs_flags |= opf_kill_def;
......@@ -1101,7 +1100,6 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
get_tmr_operands (stmt, expr, flags);
return;
case ARRAY_REF:
case ARRAY_RANGE_REF:
/* Treat array references as references to the virtual variable
representing the array. The virtual variable for an ARRAY_REF
......@@ -1115,6 +1113,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
return;
case ARRAY_REF:
case COMPONENT_REF:
case REALPART_EXPR:
case IMAGPART_EXPR:
......@@ -1162,6 +1161,12 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
s_ann->has_volatile_ops = true;
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
}
else if (code == ARRAY_REF)
{
get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
get_expr_operands (stmt, &TREE_OPERAND (expr, 3), opf_none);
}
return;
}
case WITH_SIZE_EXPR:
......@@ -1192,8 +1197,7 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == WITH_SIZE_EXPR)
op = TREE_OPERAND (expr, 0);
if (TREE_CODE (op) == ARRAY_REF
|| TREE_CODE (op) == ARRAY_RANGE_REF
if (TREE_CODE (op) == ARRAY_RANGE_REF
|| TREE_CODE (op) == REALPART_EXPR
|| TREE_CODE (op) == IMAGPART_EXPR)
subflags = opf_is_def;
......
......@@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "timevar.h"
#include "alloc-pool.h"
#include "splay-tree.h"
#include "params.h"
#include "tree-ssa-structalias.h"
#include "cgraph.h"
......@@ -2493,8 +2494,30 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
{
struct constraint_expr *c;
unsigned int i;
get_constraint_for (TREE_OPERAND (t, 0), results);
tree exp = TREE_OPERAND (t, 0);
get_constraint_for (exp, results);
/* Make sure we capture constraints to all elements
of an array. */
if ((handled_component_p (exp)
&& ref_contains_array_ref (exp))
|| TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
{
struct constraint_expr *origrhs;
varinfo_t origvar;
struct constraint_expr tmp;
gcc_assert (VEC_length (ce_s, *results) == 1);
origrhs = VEC_last (ce_s, *results);
tmp = *origrhs;
VEC_pop (ce_s, *results);
origvar = get_varinfo (origrhs->var);
for (; origvar; origvar = origvar->next)
{
tmp.var = origvar->id;
VEC_safe_push (ce_s, heap, *results, &tmp);
}
}
for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
{
if (c->type == DEREF)
......@@ -3151,7 +3174,6 @@ handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
get_constraint_for (op0, &temp);
if (POINTER_TYPE_P (TREE_TYPE (op0))
&& TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == RECORD_TYPE
&& TREE_CODE (op1) == INTEGER_CST)
{
rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
......@@ -3378,7 +3400,8 @@ find_func_aliases (tree origt)
get_constraint_for (rhsop, &rhsc);
if (TREE_CODE (strippedrhs) == ADDR_EXPR
&& AGGREGATE_TYPE_P (TREE_TYPE (rhstype)))
&& AGGREGATE_TYPE_P (TREE_TYPE (rhstype))
&& VEC_length (ce_s, rhsc) == 1)
{
struct constraint_expr *origrhs;
varinfo_t origvar;
......@@ -3568,6 +3591,63 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
return 2;
}
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree sz = TYPE_SIZE (type);
tree elsz = TYPE_SIZE (TREE_TYPE (type));
HOST_WIDE_INT nr;
int i;
if (! sz
|| ! host_integerp (sz, 1)
|| TREE_INT_CST_LOW (sz) == 0
|| ! elsz
|| ! host_integerp (elsz, 1)
|| TREE_INT_CST_LOW (elsz) == 0)
return 0;
nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
return 0;
for (i = 0; i < nr; ++i)
{
bool push = false;
int pushed = 0;
if (has_union
&& (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
|| TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
*has_union = true;
if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
push = true;
else if (!(pushed = push_fields_onto_fieldstack
(TREE_TYPE (type), fieldstack,
offset + i * TREE_INT_CST_LOW (elsz), has_union)))
/* Empty structures may have actual size, like in C++. So
see if we didn't push any subfields and the size is
nonzero, push the field onto the stack */
push = true;
if (push)
{
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
pair->type = TREE_TYPE (type);
pair->size = elsz;
pair->decl = NULL_TREE;
pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
count++;
}
else
count += pushed;
}
return count;
}
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
......
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