2009-12-01 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Dec 2009 17:39:44 +0000 (17:39 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 1 Dec 2009 17:39:44 +0000 (17:39 +0000)
PR tree-optimization/42237
* tree-sra.c (sra_ipa_modify_assign): Split gimple_reg_type assignments
in between references into two.

* testsuite/gcc.c-torture/compile/pr42237.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154874 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr42237.c [new file with mode: 0644]
gcc/tree-sra.c

index 939b7bc..3b15962 100644 (file)
@@ -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
index bfc58ea..c691529 100644 (file)
@@ -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 (file)
index 0000000..58db866
--- /dev/null
@@ -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);
+}
index 2c75838..a6a1a90 100644 (file)
@@ -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);