This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] Support variable-sized aggregates
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 6 Jul 2009 20:27:34 -0400
- Subject: [lto] Support variable-sized aggregates
This patch adds support for variable sized aggregates in the
streamer. It stops pass_ipa_free_lang_data from removing
non-constant bounds from types and add support for comparing
variable-sized aggregates in gimple_compare_types.
This fixes 6 failures in execute.exp.
Diego.
* tree.c (free_lang_data_in_type): Do not reset
TYPE_SIZE, TYPE_SIZE_UNIT, TYPE_MIN_VALUE and
TYPE_MAX_VALUE.
* gimple.c (gimple_compare_types): Do not assume that
TYPE_MIN_VALUE and TYPE_MAX_VALUE are constants.
(iterative_hash_gimple_type): Do not assume that
TYPE_SIZE and TYPE_SIZE_UNIT are constants.
lto/ChangeLog
* lto.c (lto_fixup_type): Fixup TYPE_SIZE and
TYPE_SIZE_UNIT.
testsuite/ChangeLog.lto
* gcc.dg/lto/20090706-1_0.c: New test.
* gcc.dg/lto/20090706-2_0.c: New test.
Index: tree.c
===================================================================
--- tree.c (revision 149291)
+++ tree.c (working copy)
@@ -4044,20 +4044,6 @@ free_lang_data_in_type (tree type)
TREE_LANG_FLAG_5 (type) = 0;
TREE_LANG_FLAG_6 (type) = 0;
- if (TREE_CODE (type) == ARRAY_TYPE
- || TREE_CODE (type) == RECORD_TYPE)
- {
- tree unit_size = TYPE_SIZE_UNIT (type);
- tree size = TYPE_SIZE (type);
-
- if ((unit_size && TREE_CODE (unit_size) != INTEGER_CST)
- || (size && TREE_CODE (size) != INTEGER_CST))
- {
- TYPE_SIZE_UNIT (type) = NULL_TREE;
- TYPE_SIZE (type) = NULL_TREE;
- }
- }
-
if (TREE_CODE (type) == FUNCTION_TYPE)
{
/* Remove the const and volatile qualifiers from arguments. The
@@ -4126,23 +4112,6 @@ free_lang_data_in_type (tree type)
TYPE_BINFO (type) = NULL_TREE;
}
- if (TREE_CODE (type) == INTEGER_TYPE)
- {
- tree old_max = TYPE_MAX_VALUE (type);
- tree old_min = TYPE_MIN_VALUE (type);
-
- if ((old_max && TREE_CODE (old_max) != INTEGER_CST)
- || (old_min && TREE_CODE (old_min) != INTEGER_CST))
- set_min_and_max_values_for_integral_type (type,
- TYPE_PRECISION (type),
- TYPE_UNSIGNED (type));
-
- if (old_max && TREE_CODE (old_max) == INTEGER_CST)
- TYPE_MAX_VALUE (type) = old_max;
- if (old_min && TREE_CODE (old_min) == INTEGER_CST)
- TYPE_MIN_VALUE (type) = old_min;
- }
-
/* Overloads TYPE_BINFO for non-record, non-union types. */
if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE)
TYPE_LANG_SLOT_1 (type) = NULL_TREE;
Index: testsuite/gcc.dg/lto/20090706-1_0.c
===================================================================
--- testsuite/gcc.dg/lto/20090706-1_0.c (revision 0)
+++ testsuite/gcc.dg/lto/20090706-1_0.c (revision 0)
@@ -0,0 +1,42 @@
+#include <stdarg.h>
+
+extern void abort (void);
+
+void foo (int size, ...)
+{
+ struct
+ {
+ struct
+ {
+ char x[size];
+ } e;
+ unsigned r;
+ } d;
+ va_list ap;
+ char c;
+ int i;
+
+ va_start (ap, size);
+ d = va_arg (ap, typeof (d));
+ c = d.e.x[3];
+ if (c != '3')
+ abort ();
+ if (d.r != 2602)
+ abort ();
+ va_end (ap);
+}
+
+int main (void)
+{
+ int z = 5, i;
+ struct { struct { char a[z]; } y; unsigned r; } x;
+
+ x.y.a[0] = '0';
+ x.y.a[1] = '1';
+ x.y.a[2] = '2';
+ x.y.a[3] = '3';
+ x.y.a[4] = '4';
+ x.r = 2602;
+ foo (z, x);
+ return 0;
+}
Index: testsuite/gcc.dg/lto/20090706-2_0.c
===================================================================
--- testsuite/gcc.dg/lto/20090706-2_0.c (revision 0)
+++ testsuite/gcc.dg/lto/20090706-2_0.c (revision 0)
@@ -0,0 +1,16 @@
+extern void abort (void);
+
+int foo (int size)
+{
+ int a[size];
+ a[size - 10] = 42;
+ return a[size - 10] + size;
+}
+
+main()
+{
+ int x = foo (20);
+ if (x != 62)
+ abort ();
+ return 0;
+}
Index: lto/lto.c
===================================================================
--- lto/lto.c (revision 149291)
+++ lto/lto.c (working copy)
@@ -1204,8 +1204,8 @@ lto_fixup_type (tree t, void *data)
{
lto_fixup_common (t, data);
LTO_FIXUP_SUBTREE (TYPE_CACHED_VALUES (t));
- gcc_assert (no_fixup_p (TYPE_SIZE (t)));
- gcc_assert (no_fixup_p (TYPE_SIZE_UNIT (t)));
+ LTO_FIXUP_SUBTREE (TYPE_SIZE (t));
+ LTO_FIXUP_SUBTREE (TYPE_SIZE_UNIT (t));
LTO_FIXUP_SUBTREE (TYPE_ATTRIBUTES (t));
LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_POINTER_TO (t));
LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_REFERENCE_TO (t));
Index: gimple.c
===================================================================
--- gimple.c (revision 149291)
+++ gimple.c (working copy)
@@ -3278,16 +3278,28 @@ gimple_compare_types (tree t1, tree t2,
represented in GIMPLE and have each front end lower to that. */
if (TREE_CODE (t1) != ENUMERAL_TYPE)
{
+ tree min1 = TYPE_MIN_VALUE (t1);
+ tree max1 = TYPE_MAX_VALUE (t1);
+ tree min2 = TYPE_MIN_VALUE (t2);
+ tree max2 = TYPE_MAX_VALUE (t2);
+ bool min_equal_p = false;
+ bool max_equal_p = false;
+
/* If either type has a minimum value, the other type must
have the same. */
- if ((TYPE_MIN_VALUE (t1) || TYPE_MIN_VALUE (t2))
- && !tree_int_cst_equal (TYPE_MIN_VALUE (t1), TYPE_MIN_VALUE (t2)))
- goto different_types;
+ if (min1 == NULL_TREE && min2 == NULL_TREE)
+ min_equal_p = true;
+ else if (min1 && min2 && operand_equal_p (min1, min2, 0))
+ min_equal_p = true;
/* Likewise, if either type has a maximum value, the other
type must have the same. */
- if ((TYPE_MAX_VALUE (t1) || TYPE_MAX_VALUE (t2))
- && !tree_int_cst_equal (TYPE_MAX_VALUE (t1), TYPE_MAX_VALUE (t2)))
+ if (max1 == NULL_TREE && max2 == NULL_TREE)
+ max_equal_p = true;
+ else if (max1 && max2 && operand_equal_p (max1, max2, 0))
+ max_equal_p = true;
+
+ if (!min_equal_p || !max_equal_p)
goto different_types;
}
@@ -3331,49 +3343,34 @@ gimple_compare_types (tree t1, tree t2,
tree min2 = TYPE_MIN_VALUE (i2);
tree max1 = TYPE_MAX_VALUE (i1);
tree max2 = TYPE_MAX_VALUE (i2);
+ bool min_equal_p = false;
+ bool max_equal_p = false;
- /* If the array types both have unspecified bounds, then
- MAX{1,2} will be NULL_TREE. */
- if (min1 && min2 && !max1 && !max2)
- {
- if (integer_zerop (min1) && integer_zerop (min2))
- goto same_types;
- else
- goto different_types;
- }
+ /* For variable-sized arrays, use the same notion as in the C
+ front end. If either domain is variable, consider the types
+ compatible. */
+ if (min1 == NULL_TREE && min2 == NULL_TREE)
+ min_equal_p = true;
+ else if (min1 && TREE_CODE (min1) != INTEGER_CST)
+ min_equal_p = true;
+ else if (min2 && TREE_CODE (min2) != INTEGER_CST)
+ min_equal_p = true;
+ else if (min1 && min2 && operand_equal_p (min1, min2, 0))
+ min_equal_p = true;
+
+ if (max1 == NULL_TREE && max2 == NULL_TREE)
+ max_equal_p = true;
+ else if (max1 && TREE_CODE (max1) != INTEGER_CST)
+ max_equal_p = true;
+ else if (max2 && TREE_CODE (max2) != INTEGER_CST)
+ max_equal_p = true;
+ else if (max1 && max2 && operand_equal_p (max1, max2, 0))
+ max_equal_p = true;
- /* Otherwise, we need the bounds to be fully specified. */
- if (!min1 || !min2 || !max1 || !max2)
- goto different_types;
- else if (TREE_CODE (min1) != INTEGER_CST
- || TREE_CODE (min2) != INTEGER_CST
- || TREE_CODE (max1) != INTEGER_CST
- || TREE_CODE (max2) != INTEGER_CST)
- goto different_types;
- else if (tree_int_cst_equal (min1, min2))
- {
- if (tree_int_cst_equal (max1, max2))
- goto same_types;
- else
- goto different_types;
- }
+ if (min_equal_p && max_equal_p)
+ goto same_types;
else
- {
- tree nelts1 = array_type_nelts (t1);
- tree nelts2 = array_type_nelts (t2);
-
- if (!nelts1 || !nelts2)
- goto different_types;
-
- if (TREE_CODE (nelts1) != INTEGER_CST
- || TREE_CODE (nelts2) != INTEGER_CST)
- goto different_types;
-
- if (tree_int_cst_equal (nelts1, nelts2))
- goto same_types;
- else
- goto different_types;
- }
+ goto different_types;
}
}
@@ -3553,10 +3550,8 @@ iterative_hash_gimple_type (const_tree t
checked. */
v = iterative_hash_hashval_t (TREE_CODE (type), val);
v = iterative_hash_hashval_t (TYPE_QUALS (type), v);
- if (TYPE_SIZE (type))
- v = iterative_hash_host_wide_int (int_cst_value (TYPE_SIZE (type)), v);
- if (TYPE_SIZE_UNIT (type))
- v = iterative_hash_hashval_t (int_cst_value (TYPE_SIZE_UNIT (type)), v);
+ v = iterative_hash_expr (TYPE_SIZE (type), v);
+ v = iterative_hash_expr (TYPE_SIZE_UNIT (type), v);
v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
/* Incorporate common features of numerical types. */