diff options
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 4 | ||||
-rw-r--r-- | gcc/params.def | 9 | ||||
-rw-r--r-- | gcc/params.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-10.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-11.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-12.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-4.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-5.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-6.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-7.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-8.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/alias-9.c | 15 | ||||
-rw-r--r-- | gcc/tree-flow-inline.h | 8 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-operands.c | 14 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 88 |
19 files changed, 317 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 24227042462..b9dc3c2fab0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index aa3c301a536..45152ae1f7e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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 \ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b428f2d8324..032f3ad048d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/params.def b/gcc/params.def index 7690383e12b..33fa4441cde 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -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 diff --git a/gcc/params.h b/gcc/params.h index 6c9f7d6cca3..f64193982b4 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -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 \ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ffe0dc991b1..318cc53fae2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c new file mode 100644 index 00000000000..03956100a2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c new file mode 100644 index 00000000000..cccc512cbe1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c new file mode 100644 index 00000000000..dbd33016032 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c new file mode 100644 index 00000000000..e0394327d91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c new file mode 100644 index 00000000000..f1faae52c9c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c new file mode 100644 index 00000000000..460dd11cd48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c new file mode 100644 index 00000000000..7ef604be293 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c @@ -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; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c new file mode 100644 index 00000000000..7c825f96579 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c @@ -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; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c new file mode 100644 index 00000000000..0a20e054366 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c @@ -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; +} + diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index 3f8e89d1361..7e36ccc0e2a 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -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 diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 667630343d2..353e7bd4448 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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; diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 6787dc2dc39..87a1fc6eb1d 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -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; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index e7b47fc31b2..90bd037e313 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -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) { |