aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr42237.c32
-rw-r--r--gcc/tree-sra.c18
4 files changed, 57 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 939b7bc..3b15962 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-01 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/42237
+ * tree-sra.c (sra_ipa_modify_assign): Split gimple_reg_type assignments
+ in between references into two.
+
2009-12-01 Richard Guenther <rguenther@suse.de>
* tree-inline.c (copy_tree_body_r): Do not set TREE_BLOCK
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bfc58ea..c691529 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-12-01 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/42237
+ * gcc.c-torture/compile/pr42237.c: New test.
+
2009-12-01 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/42057
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr42237.c b/gcc/testsuite/gcc.c-torture/compile/pr42237.c
new file mode 100644
index 0000000..58db866
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr42237.c
@@ -0,0 +1,32 @@
+struct A
+{
+ int p;
+};
+
+struct B
+{
+ struct A n;
+ struct A m;
+ int x;
+ int y;
+ int z;
+};
+
+extern int g1, g2;
+
+static void __attribute__((noinline)) foo (struct B *b)
+{
+ int t;
+
+ t = b->n.p;
+ g1 = t;
+ b->n.p = t+1;
+ g2 = b->m.p;
+
+ b->m = b->n;
+}
+
+void bar (struct B *b)
+{
+ foo (b);
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 2c75838..a6a1a90 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -3707,12 +3707,22 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, void *data)
any |= sra_ipa_modify_expr (lhs_p, gsi, true, data);
if (any)
{
+ tree new_rhs = NULL_TREE;
+
if (!useless_type_conversion_p (TREE_TYPE (*lhs_p), TREE_TYPE (*rhs_p)))
+ new_rhs = fold_build1_loc (gimple_location (stmt), VIEW_CONVERT_EXPR,
+ TREE_TYPE (*lhs_p), *rhs_p);
+ else if (REFERENCE_CLASS_P (*rhs_p)
+ && is_gimple_reg_type (TREE_TYPE (*lhs_p))
+ && !is_gimple_reg (*lhs_p))
+ /* This can happen when an assignment in between two single field
+ structures is turned into an assignment in between two pointers to
+ scalars (PR 42237). */
+ new_rhs = *rhs_p;
+
+ if (new_rhs)
{
- location_t loc = gimple_location (stmt);
- tree vce = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
- TREE_TYPE (*lhs_p), *rhs_p);
- tree tmp = force_gimple_operand_gsi (gsi, vce, true, NULL_TREE,
+ tree tmp = force_gimple_operand_gsi (gsi, new_rhs, true, NULL_TREE,
true, GSI_SAME_STMT);
gimple_assign_set_rhs_from_tree (gsi, tmp);