diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e10fb251c16..36ddef64afd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2020-04-06  Martin Jambor  <mjambor@suse.cz>
+
+	PR tree-optimization/94482
+	* tree-sra.c (create_access_replacement): Dump new replacement with
+	TDF_UID.
+	(sra_modify_expr): Fix handling of cases when the original EXPR writes
+	to only part of the replacement.
+
 2020-04-05 Zachary Spytz  <zspytz@gmail.com>
 
 	* extend.texi: Add free to list of ISO C90 functions that
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 88bab5d3d19..8b85e55afe8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-06  Martin Jambor  <mjambor@suse.cz>
+
+	PR tree-optimization/94482
+	* gcc.dg/torture/pr94482.c: New test.
+	* gcc.dg/tree-ssa/pr94482-2.c: Likewise.
+
 2020-04-05  Iain Sandoe  <iain@sandoe.co.uk>
 
 	* g++.dg/coroutines/torture/co-await-14-template-traits.C: Rename...
diff --git a/gcc/testsuite/gcc.dg/torture/pr94482.c b/gcc/testsuite/gcc.dg/torture/pr94482.c
new file mode 100644
index 00000000000..5bb19e745c2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr94482.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+
+typedef unsigned V __attribute__ ((__vector_size__ (16)));
+union U
+{
+  V j;
+  unsigned long long i __attribute__ ((__vector_size__ (16)));
+};
+
+static inline __attribute__((always_inline)) V
+foo (unsigned long long a)
+{
+  union U z = { .j = (V) {} };
+  for (unsigned long i = 0; i < 1; i++)
+    z.i[i] = a;
+  return z.j;
+}
+
+static inline __attribute__((always_inline)) V
+bar (V a, unsigned long long i, int q)
+{
+  union U z = { .j = a };
+  z.i[q] = i;
+  return z.j;
+}
+
+int
+main ()
+{
+  union U z = { .j = bar (foo (1729), 2, 1) };
+  if (z.i[0] != 1729)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c
new file mode 100644
index 00000000000..fcac9d5e439
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94482-2.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+typedef unsigned long V __attribute__ ((__vector_size__ (8)));
+typedef _Complex int Ci;
+typedef _Complex float Cf;
+
+union U
+{
+  Ci ci;
+  Cf cf;
+};
+
+volatile Ci vgi;
+
+Cf foo (Cf c)
+{
+  __real c = 0x1ffp10;
+  return c;
+}
+
+Ci ioo (Ci c)
+{
+  __real c = 50;
+  return c;
+}
+
+
+int main (int argc, char *argv[])
+{
+  union U u;
+
+  __real u.ci = 500;
+  __imag u.ci = 1000;
+  vgi = u.ci;
+
+  u.ci = ioo (u.ci);
+  __imag u.ci = 100;
+
+  if (__real u.ci != 50 || __imag u.ci != 100)
+    __builtin_abort();
+
+  u.cf = foo (u.cf);
+  __imag u.cf = 0x1p3;
+
+  if (__real u.cf != 0x1ffp10 || __imag u.cf != 0x1p3)
+    __builtin_abort();
+
+  return 0;
+}
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index b2056b58750..494ab609149 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2257,7 +2257,7 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
 	  print_generic_expr (dump_file, access->base);
 	  fprintf (dump_file, " offset: %u, size: %u: ",
 		   (unsigned) access->offset, (unsigned) access->size);
-	  print_generic_expr (dump_file, repl);
+	  print_generic_expr (dump_file, repl, TDF_UID);
 	  fprintf (dump_file, "\n");
 	}
     }
@@ -3698,6 +3698,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
   location_t loc;
   struct access *access;
   tree type, bfr, orig_expr;
+  bool partial_cplx_access = false;
 
   if (TREE_CODE (*expr) == BIT_FIELD_REF)
     {
@@ -3708,7 +3709,10 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
     bfr = NULL_TREE;
 
   if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
-    expr = &TREE_OPERAND (*expr, 0);
+    {
+      expr = &TREE_OPERAND (*expr, 0);
+      partial_cplx_access = true;
+    }
   access = get_access_for_expr (*expr);
   if (!access)
     return false;
@@ -3736,13 +3740,18 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
          be accessed as a different type too, potentially creating a need for
          type conversion (see PR42196) and when scalarized unions are involved
          in assembler statements (see PR42398).  */
-      if (!useless_type_conversion_p (type, access->type))
+      if (!bfr && !useless_type_conversion_p (type, access->type))
 	{
 	  tree ref;
 
 	  ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
 
-	  if (write)
+	  if (partial_cplx_access)
+	    /* VIEW_CONVERT_EXPRs in partial complex access are fine even in
+	       the case of a write because in such case the replacement cannot
+	       be a gimple register.  */
+	    *expr = build1 (VIEW_CONVERT_EXPR, type, repl);
+	  else if (write)
 	    {
 	      gassign *stmt;
 
