diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index e55fe2776f2..a73a5d9ec1d 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -5748,6 +5748,44 @@ ipcp_modif_dom_walker::before_dom_children (basic_block bb)
   return NULL;
 }
 
+/* If IPA-CP discovered a constant in parameter PARM at OFFSET of a given SIZE
+   - whether passed by reference or not is given by BY_REF - return that
+   constant.  Otherwise return NULL_TREE.  */
+
+tree
+ipcp_get_aggregate_const (tree parm, bool by_ref,
+			  HOST_WIDE_INT offset, HOST_WIDE_INT size)
+{
+  cgraph_node *cnode = cgraph_node::get (current_function_decl);
+
+  ipa_agg_replacement_value *aggval = ipa_get_agg_replacements_for_node (cnode);
+  if (!aggval)
+    return NULL_TREE;
+
+  int index = 0;
+  for (tree p = DECL_ARGUMENTS (current_function_decl);
+       p != parm; p = DECL_CHAIN (p))
+    {
+      index++;
+      if (!p)
+	return NULL_TREE;
+    }
+
+  ipa_agg_replacement_value *v;
+  for (v = aggval; v; v = v->next)
+    if (v->index == index
+	&& v->offset == offset)
+      break;
+  if (!v
+      || v->by_ref != by_ref
+      || maybe_ne (tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (v->value))),
+		   size))
+    return NULL_TREE;
+
+  return v->value;
+}
+
+
 /* Return true if we have recorded VALUE and MASK about PARM.
    Set VALUE and MASk accordingly.  */
 
@@ -6055,11 +6093,6 @@ ipcp_transform_function (struct cgraph_node *node)
     free_ipa_bb_info (bi);
   fbi.bb_infos.release ();
 
-  ipcp_transformation *s = ipcp_transformation_sum->get (node);
-  s->agg_values = NULL;
-  s->bits = NULL;
-  s->m_vr = NULL;
-
   vec_free (descriptors);
   if (cfg_changed)
     delete_unreachable_blocks_update_callgraph (node, false);
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 553adfc9f35..aa6fcb522ac 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -1181,6 +1181,8 @@ void ipa_dump_param (FILE *, class ipa_node_params *info, int i);
 void ipa_release_body_info (struct ipa_func_body_info *);
 tree ipa_get_callee_param_type (struct cgraph_edge *e, int i);
 bool ipcp_get_parm_bits (tree, tree *, widest_int *);
+tree ipcp_get_aggregate_const (tree parm, bool by_ref,
+			       HOST_WIDE_INT offset, HOST_WIDE_INT size);
 bool unadjusted_ptr_and_unit_offset (tree op, tree *ret,
 				     poly_int64 *offset_ret);
 
diff --git a/gcc/testsuite/gcc.dg/ipa/pr92497-1.c b/gcc/testsuite/gcc.dg/ipa/pr92497-1.c
new file mode 100644
index 00000000000..eb8f2e75fd0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr92497-1.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-early-inlining"  } */
+
+struct a {int a;};
+static int //__attribute__ ((noinline))
+foo (struct a a)
+{
+  if (!__builtin_constant_p (a.a))
+    __builtin_abort ();
+  return a.a;
+}
+
+static int __attribute__ ((noinline))
+bar (struct a a)
+{
+  return foo(a);
+}
+
+volatile int r;
+
+int main()
+{
+  struct a a={1};
+  r = bar (a);
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/pr92497-2.c b/gcc/testsuite/gcc.dg/ipa/pr92497-2.c
new file mode 100644
index 00000000000..56e611df8f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr92497-2.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-early-inlining -fno-ipa-sra"  } */
+
+struct a {int a;};
+static int //__attribute__ ((noinline))
+foo (struct a *a)
+{
+  if (!__builtin_constant_p (a->a))
+    __builtin_abort ();
+  return a->a;
+}
+
+static int __attribute__ ((noinline))
+bar (struct a *a)
+{
+  return foo(a);
+}
+
+volatile int r;
+
+int main()
+{
+  struct a a={1};
+  r = bar (&a);
+  return 0;
+}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 66b4fc21f5b..da558055054 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -74,6 +74,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-modref-tree.h"
 #include "ipa-modref.h"
 #include "tree-ssa-sccvn.h"
+#include "alloc-pool.h"
+#include "symbol-summary.h"
+#include "ipa-prop.h"
 
 /* This algorithm is based on the SCC algorithm presented by Keith
    Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
@@ -2273,7 +2276,7 @@ vn_walk_cb_data::push_partial_def (pd_data pd,
    with the current VUSE and performs the expression lookup.  */
 
 static void *
-vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *data_)
+vn_reference_lookup_2 (ao_ref *op, tree vuse, void *data_)
 {
   vn_walk_cb_data *data = (vn_walk_cb_data *)data_;
   vn_reference_t vr = data->vr;
@@ -2307,6 +2310,36 @@ vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *data_)
       return *slot;
     }
 
+  if (SSA_NAME_IS_DEFAULT_DEF (vuse))
+    {
+      HOST_WIDE_INT offset, size;
+      tree v = NULL_TREE;
+      if (op->base && TREE_CODE (op->base) == PARM_DECL
+	  && op->offset.is_constant (&offset)
+	  && op->size.is_constant (&size))
+	v = ipcp_get_aggregate_const (op->base, false, offset, size);
+      else if (op->ref)
+	{
+	  HOST_WIDE_INT offset, size;
+	  bool reverse;
+	  tree base = get_ref_base_and_extent_hwi (op->ref, &offset,
+						   &size, &reverse);
+	  if (base && TREE_CODE (base) == PARM_DECL)
+	    v = ipcp_get_aggregate_const (base, false, offset, size);
+	  else if (base
+		   && TREE_CODE (base) == MEM_REF
+		   && integer_zerop (TREE_OPERAND (base, 1))
+		   && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
+		   && SSA_NAME_IS_DEFAULT_DEF (TREE_OPERAND (base, 0))
+		   && (TREE_CODE (SSA_NAME_VAR (TREE_OPERAND (base, 0)))
+		       == PARM_DECL))
+	    v = ipcp_get_aggregate_const (SSA_NAME_VAR (TREE_OPERAND (base, 0)),
+					  true, offset, size);
+	}
+      if (v)
+	return data->finish (vr->set, vr->base_set, v);
+    }
+
   return NULL;
 }
 
