diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c8272188caa1e19f6fda2bb06fb574569cf4f983..e18d220975f00e30dd424fe03b9019e60e1eb664 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2012-03-16  Richard Guenther  <rguenther@suse.de>
+	Kai Tietz  <ktietz@redhat.com>
+
+	PR middle-end/48814
+	* gimplify.c (gimplify_self_mod_expr): Evaluate postfix
+	side-effects completely in the pre-queue and use a temporary
+	for the result.
+
 2012-03-16  Richard Guenther  <rguenther@suse.de>
 
 	* stor-layout.c (finish_bitfield_representative): Fall back
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 07eb8fd81df08b76a007c5725568fc4a42367f4d..3c412944e334aaee80fe82f6652f94355c2ffb1f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2265,17 +2265,18 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       arith_code = POINTER_PLUS_EXPR;
     }
 
-  t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
-
   if (postfix)
     {
-      gimplify_assign (lvalue, t1, orig_post_p);
+      tree t2 = get_initialized_tmp_var (lhs, pre_p, NULL);
+      t1 = build2 (arith_code, TREE_TYPE (*expr_p), t2, rhs);
+      gimplify_assign (lvalue, t1, pre_p);
       gimplify_seq_add_seq (orig_post_p, post);
-      *expr_p = lhs;
+      *expr_p = t2;
       return GS_ALL_DONE;
     }
   else
     {
+      t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
       *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
       return GS_OK;
     }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eddbface0f9845dffe864294b58ed67a20558ebd..ba1e455391a43f1994d4226b4a1eb4025e443bac 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2012-03-16  Richard Guenther  <rguenther@suse.de>
+	Kai Tietz  <ktietz@redhat.com>
+
+	PR middle-end/48814
+	* gcc.c-torture/execute/pr48814-1.c: New test.
+	* gcc.c-torture/execute/pr48814-2.c: New test.
+	* gcc.dg/tree-ssa/assign-1.c: New test.
+	* gcc.dg/tree-ssa/assign-2.c: New test.
+	* gcc.dg/tree-ssa/assign-3.c: New test.
+
 2012-03-16  Richard Guenther  <rguenther@suse.de>
 
 	* gnat.dg/specs/pack7.ads: New testcase.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr48814-1.c b/gcc/testsuite/gcc.c-torture/execute/pr48814-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..452aaab30f9593d1116d3d94d7c9b0f46fc76468
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr48814-1.c
@@ -0,0 +1,18 @@
+extern void abort (void);
+
+int arr[] = {1,2,3,4};
+int count = 0;
+
+int __attribute__((noinline))
+incr (void)
+{
+  return ++count;
+}
+
+int main()
+{
+  arr[count++] = incr ();
+  if (count != 2 || arr[count] != 3)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr48814-2.c b/gcc/testsuite/gcc.c-torture/execute/pr48814-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9eea3289ab1a594fb254642f08239acf480eff5b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr48814-2.c
@@ -0,0 +1,18 @@
+extern void abort (void);
+
+int arr[] = {1,2,3,4};
+int count = 0;
+
+int
+incr (void)
+{
+  return ++count;
+}
+
+int main()
+{
+  arr[count++] = incr ();
+  if (count != 2 || arr[count] != 3)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assign-1.c b/gcc/testsuite/gcc.dg/tree-ssa/assign-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..f95f03ff42865ba9de027ff629fd1f834e22a872
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/assign-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+volatile int count;
+void bar(int);
+void foo()
+{
+ bar(count++);
+}
+
+/* { dg-final { scan-tree-dump-times "count =" 1 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assign-2.c b/gcc/testsuite/gcc.dg/tree-ssa/assign-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..47c38225b67ba7b398e936edf9c2d805f431e037
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/assign-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+volatile int count;
+int arr[4];
+void foo()
+{
+ arr[count++] = 0;
+}
+
+/* { dg-final { scan-tree-dump-times "count =" 1 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/assign-3.c b/gcc/testsuite/gcc.dg/tree-ssa/assign-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5426d781e593f31e98b9b14741b66566bad7a60
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/assign-3.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-gimple" } */
+
+extern void abort (void);
+struct S { int i; };
+struct S arr[32];
+volatile int count = 0;
+
+struct S __attribute__((noinline))
+incr ()
+{
+  ++count;
+}
+
+int main()
+{
+  arr[count++] = incr ();
+  if (count != 2)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times " = count;" 3 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */