From 9fda11a2ecf9047b64bbe2e92343f1e263ce1509 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Mon, 30 Nov 2009 18:59:57 +0100 Subject: [PATCH] re PR middle-end/42196 (ICE when SRAing partial assigments to complex number) 2009-11-30 Martin Jambor 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 --- gcc/ChangeLog | 11 ++++++ gcc/testsuite/ChangeLog | 7 ++++ .../gcc.c-torture/compile/pr42196-1.c | 28 +++++++++++++ .../gcc.c-torture/compile/pr42196-2.c | 28 +++++++++++++ .../gcc.c-torture/compile/pr42196-3.c | 27 +++++++++++++ gcc/tree-sra.c | 39 ++++++++++++++++--- 6 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr42196-1.c create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr42196-2.c create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr42196-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96cacc0e0f78..d5fb07532b00 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2009-11-30 Martin Jambor + + 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 * config/i386/i386.c (avx_vperm2f128_parallel): New. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4320d65045b4..4cef144e9c67 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2009-11-30 Martin Jambor + + 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 * 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 000000000000..96936c5e5889 --- /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 000000000000..40ae077f6b97 --- /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 000000000000..ccc0d7a195cf --- /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 34c0d3de8930..2c75838835a0 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;