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
This commit is contained in:
Richard Guenther 2006-01-14 14:30:33 +00:00 committed by Richard Biener
parent 7f17528ab5
commit a916f21d3c
19 changed files with 316 additions and 15 deletions

View File

@ -1,3 +1,26 @@
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

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -1,3 +1,18 @@
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.

View File

@ -0,0 +1,20 @@
/* { 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" } } */

View File

@ -0,0 +1,19 @@
/* { 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" } } */

View File

@ -0,0 +1,18 @@
/* { 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" } } */

View File

@ -0,0 +1,21 @@
/* { 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" } } */

View File

@ -0,0 +1,23 @@
/* { 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" } } */

View File

@ -0,0 +1,19 @@
/* { 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" } } */

View File

@ -0,0 +1,17 @@
/* { 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;
}

View File

@ -0,0 +1,15 @@
/* { 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;
}

View File

@ -0,0 +1,15 @@
/* { 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;
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
tree exp = TREE_OPERAND (t, 0);
get_constraint_for (TREE_OPERAND (t, 0), results);
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)
{