aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/gimplify.c12
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr71104-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr71104-2.c12
5 files changed, 48 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index db920bd..e42e288 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2016-07-13 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/71104
+ * gimplify.c (gimplify_modify_expr): Gimplify the RHS before
+ gimplifying the LHS. Make sure to gimplify a returning twice
+ call LHS without using SSA names.
+
2016-07-12 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
* tree-data-ref.c (find_data_references_in_stmt): Remove
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2ea1e57..fb27dd0 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -4810,7 +4810,19 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
return ret;
/* Then gimplify the LHS. */
+ /* If we gimplified the RHS to a CALL_EXPR and that call may return
+ twice we have to make sure to gimplify into non-SSA as otherwise
+ the abnormal edge added later will make those defs not dominate
+ their uses.
+ ??? Technically this applies only to the registers used in the
+ resulting non-register *TO_P. */
+ bool saved_into_ssa = gimplify_ctxp->into_ssa;
+ if (saved_into_ssa
+ && TREE_CODE (*from_p) == CALL_EXPR
+ && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
+ gimplify_ctxp->into_ssa = false;
ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
+ gimplify_ctxp->into_ssa = saved_into_ssa;
if (ret == GS_ERROR)
return ret;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index cb2c9e0..d4e0fca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2016-07-13 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/71104
+ * gcc.dg/pr71104-1.c: New testcase.
+ * gcc.dg/pr71104-2.c: Likewise.
+
2016-07-12 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/71805
diff --git a/gcc/testsuite/gcc.dg/pr71104-1.c b/gcc/testsuite/gcc.dg/pr71104-1.c
new file mode 100644
index 0000000..20c055a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr71104-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+void foo(void);
+int vfork(void);
+int *p;
+
+void bar(void)
+{
+ foo();
+ *p = vfork();
+}
diff --git a/gcc/testsuite/gcc.dg/pr71104-2.c b/gcc/testsuite/gcc.dg/pr71104-2.c
new file mode 100644
index 0000000..03c52a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr71104-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+struct Foo { char c[1024]; };
+void foo(void);
+struct Foo baz(void) __attribute__((returns_twice));
+struct Foo *p;
+
+void bar(void)
+{
+ foo();
+ *p = baz();
+}