aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2009-11-30 18:59:57 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2009-11-30 18:59:57 +0100
commit9fda11a2ecf9047b64bbe2e92343f1e263ce1509 (patch)
treeab1827bc63ebf292fe7e7a3a659302538d0eb39f
parentca659f6ed947ad43caf21917dca2aced344dc35b (diff)
downloadgcc-9fda11a2ecf9047b64bbe2e92343f1e263ce1509.zip
gcc-9fda11a2ecf9047b64bbe2e92343f1e263ce1509.tar.gz
gcc-9fda11a2ecf9047b64bbe2e92343f1e263ce1509.tar.bz2
re PR middle-end/42196 (ICE when SRAing partial assigments to complex number)
2009-11-30 Martin Jambor <mjambor@suse.cz> PR middle-end/42196 * tree-sra.c (struct access): New field grp_different_types. (dump_access): Dump grp_different_types. (compare_access_positions): Prefer scalars and vectors over other scalar types. (sort_and_splice_var_accesses): Set grp_different_types if appropriate. (sra_modify_expr): Use the original also when dealing with a complex or vector group accessed as multiple types. * testsuite/gcc.c-torture/compile/pr42196-1.c: New test. * testsuite/gcc.c-torture/compile/pr42196-2.c: New test. * testsuite/gcc.c-torture/compile/pr42196-3.c: New test. From-SVN: r154834
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr42196-1.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr42196-2.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr42196-3.c27
-rw-r--r--gcc/tree-sra.c39
6 files changed, 134 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 96cacc0..d5fb075 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2009-11-30 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/42196
+ * tree-sra.c (struct access): New field grp_different_types.
+ (dump_access): Dump grp_different_types.
+ (compare_access_positions): Prefer scalars and vectors over other
+ scalar types.
+ (sort_and_splice_var_accesses): Set grp_different_types if appropriate.
+ (sra_modify_expr): Use the original also when dealing with a complex
+ or vector group accessed as multiple types.
+
2009-11-30 Richard Henderson <rth@redhat.com>
* config/i386/i386.c (avx_vperm2f128_parallel): New.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4320d65..4cef144 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2009-11-30 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/42196
+ * gcc.c-torture/compile/pr42196-1.c: New test.
+ * gcc.c-torture/compile/pr42196-2.c: New test.
+ * gcc.c-torture/compile/pr42196-3.c: New test.
+
2009-11-30 Ira Rosen <irar@il.ibm.com>
* gfortran.dg/vect/vect-7.f90: New test.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr42196-1.c b/gcc/testsuite/gcc.c-torture/compile/pr42196-1.c
new file mode 100644
index 0000000..96936c5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr42196-1.c
@@ -0,0 +1,28 @@
+union U
+{
+ double d;
+ __complex__ int c;
+};
+
+double gd;
+extern double bar (union U);
+
+double foo (int b, double d, int c1, int c2)
+{
+ union U u;
+ double r;
+
+ if (b)
+ {
+ u.d = d;
+ r = u.d;
+ }
+ else
+ {
+ __real__ u.c = c1;
+ __imag__ u.c = c2;
+ r = bar (u);
+ }
+
+ return r;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr42196-2.c b/gcc/testsuite/gcc.c-torture/compile/pr42196-2.c
new file mode 100644
index 0000000..40ae077
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr42196-2.c
@@ -0,0 +1,28 @@
+union U
+{
+ __complex__ int ci;
+ __complex__ float cf;
+};
+
+float gd;
+extern float bar (union U);
+
+float foo (int b, double f1, double f2, int c1, int c2)
+{
+ union U u;
+ double r;
+
+ if (b)
+ {
+ __real__ u.cf = f1;
+ __imag__ u.cf = f2;
+ }
+ else
+ {
+ __real__ u.ci = c1;
+ __imag__ u.ci = c2;
+ }
+
+ r = bar (u);
+ return r;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr42196-3.c b/gcc/testsuite/gcc.c-torture/compile/pr42196-3.c
new file mode 100644
index 0000000..ccc0d7a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr42196-3.c
@@ -0,0 +1,27 @@
+union U
+{
+ __complex__ int ci;
+ __complex__ float cf;
+};
+
+float gd;
+extern float bar (float, float);
+
+float foo (int b, union U u)
+{
+ float f1, f2, r;
+
+ if (b)
+ {
+ f1 = __real__ u.cf;
+ f1 = __imag__ u.cf;
+ }
+ else
+ {
+ f1 = __real__ u.ci;
+ f1 = __imag__ u.ci;
+ }
+
+ r = bar (f1, f2);
+ return r;
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 34c0d3d..2c75838 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -199,6 +199,10 @@ struct access
BIT_FIELD_REF? */
unsigned grp_partial_lhs : 1;
+ /* Does this group contain accesses to different types? (I.e. through a union
+ or a similar mechanism). */
+ unsigned grp_different_types : 1;
+
/* Set when a scalar replacement should be created for this variable. We do
the decision and creation at different places because create_tmp_var
cannot be called from within FOR_EACH_REFERENCED_VAR. */
@@ -339,12 +343,14 @@ dump_access (FILE *f, struct access *access, bool grp)
fprintf (f, ", grp_write = %d, grp_read = %d, grp_hint = %d, "
"grp_covered = %d, grp_unscalarizable_region = %d, "
"grp_unscalarized_data = %d, grp_partial_lhs = %d, "
- "grp_to_be_replaced = %d\n grp_maybe_modified = %d, "
+ "grp_different_types = %d, grp_to_be_replaced = %d, "
+ "grp_maybe_modified = %d, "
"grp_not_necessarilly_dereferenced = %d\n",
access->grp_write, access->grp_read, access->grp_hint,
access->grp_covered, access->grp_unscalarizable_region,
access->grp_unscalarized_data, access->grp_partial_lhs,
- access->grp_to_be_replaced, access->grp_maybe_modified,
+ access->grp_different_types, access->grp_to_be_replaced,
+ access->grp_maybe_modified,
access->grp_not_necessarilly_dereferenced);
else
fprintf (f, ", write = %d, grp_partial_lhs = %d\n", access->write,
@@ -1112,14 +1118,25 @@ compare_access_positions (const void *a, const void *b)
{
/* Put any non-aggregate type before any aggregate type. */
if (!is_gimple_reg_type (f1->type)
- && is_gimple_reg_type (f2->type))
+ && is_gimple_reg_type (f2->type))
return 1;
else if (is_gimple_reg_type (f1->type)
&& !is_gimple_reg_type (f2->type))
return -1;
+ /* Put any complex or vector type before any other scalar type. */
+ else if (TREE_CODE (f1->type) != COMPLEX_TYPE
+ && TREE_CODE (f1->type) != VECTOR_TYPE
+ && (TREE_CODE (f2->type) == COMPLEX_TYPE
+ || TREE_CODE (f2->type) == VECTOR_TYPE))
+ return 1;
+ else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
+ || TREE_CODE (f1->type) == VECTOR_TYPE)
+ && TREE_CODE (f2->type) != COMPLEX_TYPE
+ && TREE_CODE (f2->type) != VECTOR_TYPE)
+ return -1;
/* Put the integral type with the bigger precision first. */
else if (INTEGRAL_TYPE_P (f1->type)
- && INTEGRAL_TYPE_P (f2->type))
+ && INTEGRAL_TYPE_P (f2->type))
return TYPE_PRECISION (f1->type) > TYPE_PRECISION (f2->type) ? -1 : 1;
/* Put any integral type with non-full precision last. */
else if (INTEGRAL_TYPE_P (f1->type)
@@ -1417,6 +1434,7 @@ sort_and_splice_var_accesses (tree var)
bool grp_read = !access->write;
bool multiple_reads = false;
bool grp_partial_lhs = access->grp_partial_lhs;
+ bool grp_different_types = false;
bool first_scalar = is_gimple_reg_type (access->type);
bool unscalarizable_region = access->grp_unscalarizable_region;
@@ -1448,6 +1466,7 @@ sort_and_splice_var_accesses (tree var)
grp_read = true;
}
grp_partial_lhs |= ac2->grp_partial_lhs;
+ grp_different_types |= !types_compatible_p (access->type, ac2->type);
unscalarizable_region |= ac2->grp_unscalarizable_region;
relink_to_new_repr (access, ac2);
@@ -1466,6 +1485,7 @@ sort_and_splice_var_accesses (tree var)
access->grp_read = grp_read;
access->grp_hint = multiple_reads;
access->grp_partial_lhs = grp_partial_lhs;
+ access->grp_different_types = grp_different_types;
access->grp_unscalarizable_region = unscalarizable_region;
if (access->first_link)
add_access_to_work_queue (access);
@@ -2112,8 +2132,15 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
access expression to extract the scalar component afterwards.
This happens if scalarizing a function return value or parameter
like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
- gcc.c-torture/compile/20011217-1.c. */
- if (!is_gimple_reg_type (type))
+ gcc.c-torture/compile/20011217-1.c.
+
+ We also want to use this when accessing a complex or vector which can
+ be accessed as a different type too, potentially creating a need for
+ type conversion (see PR42196). */
+ if (!is_gimple_reg_type (type)
+ || (access->grp_different_types
+ && (TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)))
{
tree ref = access->base;
bool ok;