summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-14 14:30:33 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-14 14:30:33 +0000
commit03c253f34520658a02d13362e24ea6217d379179 (patch)
tree97912e34de2d72cef706a4b2d7ff6e7a163b3439
parent0f81d1b1db2329f88deb03f1ca4c1bf6476d23d8 (diff)
downloadppe42-gcc-03c253f34520658a02d13362e24ea6217d379179.tar.gz
ppe42-gcc-03c253f34520658a02d13362e24ea6217d379179.zip
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109703 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/doc/invoke.texi4
-rw-r--r--gcc/params.def9
-rw-r--r--gcc/params.h2
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-10.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-11.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-12.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-4.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-5.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-6.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-7.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-8.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-9.c15
-rw-r--r--gcc/tree-flow-inline.h8
-rw-r--r--gcc/tree-ssa-alias.c1
-rw-r--r--gcc/tree-ssa-operands.c14
-rw-r--r--gcc/tree-ssa-structalias.c88
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)
{
OpenPOWER on IntegriCloud