diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index c1973aa36c4c2085bf8f3a27824d9b57f2ba8d54..12ac0e7865a7f1f427c2e0eb75a41bcc9e56f783 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -5600,4 +5600,36 @@ ipa_modref_cc_finalize ()
   escape_summaries = NULL;
 }
 
+/* Return true if call is known to perform no memory reads.  */
+
+bool
+ipa_modref_callee_reads_no_memory_p (gcall *call)
+{
+  if (gimple_call_flags (call) & ECF_CONST)
+    return true;
+  attr_fnspec fnspec = gimple_call_fnspec (call);
+  if (fnspec.known_p ()
+      && !fnspec.global_memory_read_p ())
+    {
+      bool found = false;
+      for (unsigned int i = 0; i < gimple_call_num_args (call) && !found; i++)
+	if (!POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, i))))
+	  ;
+      else if (!fnspec.arg_specified_p (i)
+	       || fnspec.arg_maybe_read_p (i))
+	  found = true;
+      if (!found)
+	return true;
+    }
+
+  /* For interposed calls we can not be sure that the other, semantically
+     equivalent body, will not perform some redundant load from memory
+     that may become undefined if we optimize out some stores.  */
+  bool interposed;
+  modref_summary *sum = get_modref_function_summary (call, &interposed);
+  if (sum && !interposed && !sum->global_memory_read && !sum->loads)
+    return true;
+  return false;
+}
+
 #include "gt-ipa-modref.h"
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index 1bbe9bffee05fc3275c96700275e0f5ae7ffc495..a0eb63a0afab3b6c0cbb5124dcbb08b4c41e4f44 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -75,6 +75,7 @@ modref_summary *get_modref_function_summary (cgraph_node *func);
 modref_summary *get_modref_function_summary (gcall *call, bool *interposed);
 void ipa_modref_cc_finalize ();
 void ipa_merge_modref_summary_after_inlining (cgraph_edge *e);
+bool ipa_modref_callee_reads_no_memory_p (gcall *call);
 
 /* All flags that are implied by the ECF_CONST functions.  */
 static const int implicit_const_eaf_flags
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr109442.C b/gcc/testsuite/g++.dg/tree-ssa/pr109442.C
new file mode 100644
index 0000000000000000000000000000000000000000..ec40c470c8ddf050af185fd69c4ae2b452921668
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr109442.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O1 -fdump-tree-optimized" }
+#include <vector>
+#define T int
+T vat1(std::vector<T> v1) {
+    auto v = v1;
+    return 10;
+}
+// This should compile to empty function; check that no size of
+// vector is determined and there is no allocation
+// { dg-final { scan-tree-dump-not "_M_start" "optimized" } }
+// { dg-final { scan-tree-dump-not "delete" "optimized" } }
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index 643a1efd870702c62065dd78f2c6d71fdc24d188..70e3843cabfd651d15dbf0a0c81b9872456f753e 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -69,6 +69,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "gimple-fold.h"
 #include "tree-ssa.h"
+#include "ipa-modref-tree.h"
+#include "ipa-modref.h"
 
 static struct stmt_stats
 {
@@ -998,24 +1000,6 @@ propagate_necessity (bool aggressive)
 	      tree callee = gimple_call_fndecl (call);
 	      unsigned i;
 
-	      /* Calls to functions that are merely acting as barriers
-		 or that only store to memory do not make any previous
-		 stores necessary.  */
-	      if (callee != NULL_TREE
-		  && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL
-		  && (DECL_FUNCTION_CODE (callee) == BUILT_IN_MEMSET
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_MEMSET_CHK
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_MALLOC
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ALIGNED_ALLOC
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_FREE
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_VA_END
-		      || ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee))
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
-		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
-		continue;
-
 	      if (callee != NULL_TREE
 		  && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)
 		      || DECL_IS_OPERATOR_DELETE_P (callee))
@@ -1025,9 +1009,9 @@ propagate_necessity (bool aggressive)
 	      if (is_removable_cxa_atexit_call (call))
 		continue;
 
+	      bool all_refs = false;
 	      /* Calls implicitly load from memory, their arguments
 	         in addition may explicitly perform memory loads.  */
-	      mark_all_reaching_defs_necessary (call);
 	      for (i = 0; i < gimple_call_num_args (call); ++i)
 		{
 		  tree arg = gimple_call_arg (call, i);
@@ -1038,7 +1022,13 @@ propagate_necessity (bool aggressive)
 		    arg = TREE_OPERAND (arg, 0);
 		  if (!ref_may_be_aliased (arg))
 		    mark_aliased_reaching_defs_necessary (call, arg);
+		  else
+		    all_refs = true;
 		}
+
+	      if (!all_refs && ipa_modref_callee_reads_no_memory_p (call))
+		continue;
+	      mark_all_reaching_defs_necessary (call);
 	    }
 	  else if (gimple_assign_single_p (stmt))
 	    {