diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 0c3c6e7cac4..5a4c5253b49 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -3636,26 +3636,19 @@ cgraph_node::get_fun () const
 static bool
 gimple_check_call_args (gimple *stmt, tree fndecl, bool args_count_match)
 {
-  tree parms, p;
-  unsigned int i, nargs;
-
   /* Calls to internal functions always match their signature.  */
   if (gimple_call_internal_p (stmt))
     return true;
 
-  nargs = gimple_call_num_args (stmt);
+  unsigned int nargs = gimple_call_num_args (stmt);
 
-  /* Get argument types for verification.  */
-  if (fndecl)
-    parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-  else
-    parms = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
-
-  /* Verify if the type of the argument matches that of the function
-     declaration.  If we cannot verify this or there is a mismatch,
-     return false.  */
+  /* If we have access to the declarations of formal parameters, match against
+     those.  */
   if (fndecl && DECL_ARGUMENTS (fndecl))
     {
+      unsigned int i;
+      tree p;
+
       for (i = 0, p = DECL_ARGUMENTS (fndecl);
 	   i < nargs;
 	   i++, p = DECL_CHAIN (p))
@@ -3676,17 +3669,75 @@ gimple_check_call_args (gimple *stmt, tree fndecl, bool args_count_match)
 	}
       if (args_count_match && p)
 	return false;
+
+      return true;
     }
-  else if (parms)
+
+  /* If we don't have decls of formal parameters, see if we have both the type
+     of the callee arguments in the fntype of the call statement and compare
+     those.  We rely on the fact that whatever promotions happened to
+     declarations for exactly the same sequence of types of parameters also
+     happened on the callee side.  */
+  if (fndecl
+      && TYPE_ARG_TYPES (TREE_TYPE (fndecl))
+      && TYPE_ARG_TYPES (gimple_call_fntype (stmt)))
     {
-      for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
+      unsigned int arg_idx = 0;
+      for (tree f = TYPE_ARG_TYPES (TREE_TYPE (fndecl)),
+	     s = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
+	   f || s;
+	   f = TREE_CHAIN (f), s = TREE_CHAIN (s), arg_idx++)
 	{
+	  if (!f
+	      || !s
+	      || TREE_VALUE (f) == error_mark_node
+	      || TREE_VALUE (s) == error_mark_node)
+	    return false;
+	  if (TREE_CODE (TREE_VALUE (f)) == VOID_TYPE)
+	    {
+	      if (TREE_CODE (TREE_VALUE (s)) != VOID_TYPE
+		  || arg_idx != nargs)
+		return false;
+	      else
+		break;
+	    }
+
 	  tree arg;
+
+	  if (arg_idx >= nargs
+	      || (arg = gimple_call_arg (stmt, arg_idx)) == error_mark_node)
+	    return false;
+
+	  if (TREE_CODE (TREE_VALUE (s)) == VOID_TYPE
+	      || (!types_compatible_p (TREE_VALUE (f), TREE_VALUE (s))
+		  && !fold_convertible_p (TREE_VALUE (f), arg)))
+	    return false;
+	}
+
+      if (args_count_match && arg_idx != nargs)
+	return false;
+
+      return true;
+    }
+
+  /* If we only have the fntype extracted from the call statement, check it
+     against the type of declarations while being pessimistic about
+     promotions.  */
+  tree p;
+
+  if (fndecl)
+    p = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+  else
+    p = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
+  if (p)
+    {
+      for (unsigned i = 0; i < nargs; i++, p = TREE_CHAIN (p))
+	{
 	  /* If this is a varargs function defer inlining decision
 	     to callee.  */
 	  if (!p)
 	    break;
-	  arg = gimple_call_arg (stmt, i);
+	  tree arg = gimple_call_arg (stmt, i);
 	  if (TREE_VALUE (p) == error_mark_node
 	      || arg == error_mark_node
 	      || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
diff --git a/gcc/testsuite/g++.dg/lto/pr70929_0.C b/gcc/testsuite/g++.dg/lto/pr70929_0.C
new file mode 100644
index 00000000000..c96fb1c743a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr70929_0.C
@@ -0,0 +1,18 @@
+// { dg-lto-do run }
+// { dg-lto-options { "-O3 -flto" } }
+
+struct s
+{
+  int a;
+  s() {a=1;}
+  ~s() {}
+};
+int t(struct s s);
+int main()
+{
+  s s;
+  int v=t(s);
+  if (!__builtin_constant_p (v))
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr70929_1.C b/gcc/testsuite/g++.dg/lto/pr70929_1.C
new file mode 100644
index 00000000000..b33aa8f35f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr70929_1.C
@@ -0,0 +1,10 @@
+struct s
+{
+  int a;
+  s() {a=1;}
+  ~s() {}
+};
+int t(struct s s)
+{
+  return s.a;
+}
