--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop1-details -fdump-tree-esra-details -fexceptions" } */
+
+/* PR tree-optimization/122247 */
+
+struct s1
+{
+ int t[1024];
+};
+
+struct s1 f(void);
+
+void g(int a, int b, int );
+void p(struct s1);
+void h(struct s1 outer)
+{
+ struct s1 inner = outer;
+ p(inner);
+ g(outer.t[0], outer.t[1], outer.t[2]);
+}
+/* Forwprop should be able to copy prop the copy of `inner = outer` to the call of p.
+ Also remove this copy. */
+
+/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "Removing dead store stmt inner = outer" 1 "forwprop1" } } */
+
+/* The extra copy that was done by inlining is removed so SRA should not decide to cause
+ inner nor outer to be scalarized even for the 3 elements accessed afterwards. */
+/* { dg-final { scan-tree-dump-times "Disqualifying inner" 1 "esra" } } */
+/* { dg-final { scan-tree-dump-times "Disqualifying outer" 1 "esra" } } */
+
if (gimple_clobber_p (use_stmt, kind)
&& lhs == gimple_assign_lhs (use_stmt))
continue;
+ /* If the use is a phi and it is single use then check if that single use
+ is a clobber of the same kind and lhs is the same. */
+ if (gphi *use_phi = dyn_cast<gphi*>(use_stmt))
+ {
+ use_operand_p ou;
+ gimple *ostmt;
+ if (single_imm_use (gimple_phi_result (use_phi), &ou, &ostmt)
+ && gimple_clobber_p (ostmt, kind)
+ && lhs == gimple_assign_lhs (ostmt))
+ continue;
+ /* A phi node will never be dominating the clobber. */
+ return;
+ }
/* The use needs to be dominating the clobber. */
if ((ubb != bb && !dominated_by_p (CDI_DOMINATORS, bb, ubb))
|| ref_maybe_used_by_stmt_p (use_stmt, &read, false))