This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, gcc5 backport] Fix PR ipa/65908


Hi.

At the end of last week, Richi asked me to back port aforementioned PR.
The patch contains two parts: first one is the patch that was applied to trunk
and the second one is a hunk that implements param_used_p (coming from r222374).

Patch can bootstrap and survives regression tests on x86_64-linux-gnu.

Ready for 5 branch?
Thanks,
Martin
>From df7a30adc412324dfd181a39d4ac6b550428e49f Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Fri, 20 Nov 2015 16:30:42 +0100
Subject: [PATCH] PR ipa/65908

Backport from mainline

gcc/ChangeLog:

	PR ipa/65908
	* ipa-icf.c (sem_item::target_supports_symbol_aliases): Remove
	construction of arg_types.
	(sem_function::sem_function): Likewise.
	(sem_function::~sem_function): Remove destruction of arg_types.
	(sem_function::compatible_parm_types_p): New function.
	(sem_function::equals_wpa): Reorg matching of return values
	and parameter types.
	(sem_function::equals_private): Reorg mathcing of argument types.
	(sem_function::parse_tree_args): Remove.
	(sem_function::param_used_p): New function.
	* ipa-icf.h (init_wpa): Do not call it.
	(parse_tree_args): Remove.
	(compatible_parm_types_p): Declare.
	(result_type): Remove.
	(arg_types): Remove.
	(param_used_p): Declare.

gcc/testsuite/ChangeLog:

	PR ipa/65908
	* g++.dg/ipa/pr65908.C: New testcase.
---
 gcc/ipa-icf.c                      | 138 ++++++++++++++++++++++---------------
 gcc/ipa-icf.h                      |  17 ++---
 gcc/testsuite/g++.dg/ipa/pr65908.C |  27 ++++++++
 3 files changed, 117 insertions(+), 65 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr65908.C

diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index b902373..3f29011 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -273,7 +273,6 @@ sem_item::target_supports_symbol_aliases_p (void)
 sem_function::sem_function (bitmap_obstack *stack): sem_item (FUNC, stack),
   m_checker (NULL), m_compared_func (NULL)
 {
-  arg_types.create (0);
   bb_sizes.create (0);
   bb_sorted.create (0);
 }
@@ -285,7 +284,6 @@ sem_function::sem_function (cgraph_node *node, hashval_t hash,
   sem_item (FUNC, node, hash, stack),
   m_checker (NULL), m_compared_func (NULL)
 {
-  arg_types.create (0);
   bb_sizes.create (0);
   bb_sorted.create (0);
 }
@@ -295,7 +293,6 @@ sem_function::~sem_function ()
   for (unsigned i = 0; i < bb_sorted.length (); i++)
     delete (bb_sorted[i]);
 
-  arg_types.release ();
   bb_sizes.release ();
   bb_sorted.release ();
 }
@@ -417,6 +414,47 @@ bool sem_function::compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2)
   return true;
 }
 
+/* Perform additional check needed to match types function parameters that are
+   used.  Unlike for normal decls it matters if type is TYPE_RESTRICT and we
+   make an assumption that REFERENCE_TYPE parameters are always non-NULL.  */
+
+bool
+sem_function::compatible_parm_types_p (tree parm1, tree parm2)
+{
+  /* Be sure that parameters are TBAA compatible.  */
+  if (!func_checker::compatible_types_p (parm1, parm2))
+    return return_false_with_msg ("parameter type is not compatible");
+
+  if (POINTER_TYPE_P (parm1)
+      && (TYPE_RESTRICT (parm1) != TYPE_RESTRICT (parm2)))
+    return return_false_with_msg ("argument restrict flag mismatch");
+
+  /* nonnull_arg_p implies non-zero range to REFERENCE types.  */
+  if (POINTER_TYPE_P (parm1)
+      && TREE_CODE (parm1) != TREE_CODE (parm2)
+      && opt_for_fn (decl, flag_delete_null_pointer_checks))
+    return return_false_with_msg ("pointer wrt reference mismatch");
+
+  return true;
+}
+
+/* Return true if parameter I may be used.  */
+
+bool
+sem_function::param_used_p (unsigned int i)
+{
+  if (ipa_node_params_sum == NULL)
+    return false;
+
+  struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ());
+
+  if (parms_info->descriptors.is_empty ()
+      || parms_info->descriptors.length () <= i)
+     return true;
+
+  return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
+}
+
 /* Fast equality function based on knowledge known in WPA.  */
 
 bool
@@ -427,9 +465,6 @@ sem_function::equals_wpa (sem_item *item,
 
   m_compared_func = static_cast<sem_function *> (item);
 
-  if (arg_types.length () != m_compared_func->arg_types.length ())
-    return return_false_with_msg ("different number of arguments");
-
   /* Compare special function DECL attributes.  */
   if (DECL_FUNCTION_PERSONALITY (decl)
       != DECL_FUNCTION_PERSONALITY (item->decl))
@@ -506,26 +541,40 @@ sem_function::equals_wpa (sem_item *item,
     }
 
   /* Result type checking.  */
-  if (!func_checker::compatible_types_p (result_type,
-					 m_compared_func->result_type))
+  if (!func_checker::compatible_types_p
+	 (TREE_TYPE (TREE_TYPE (decl)),
+	  TREE_TYPE (TREE_TYPE (m_compared_func->decl))))
     return return_false_with_msg ("result types are different");
 
   /* Checking types of arguments.  */
-  for (unsigned i = 0; i < arg_types.length (); i++)
+  tree list1 = TYPE_ARG_TYPES (TREE_TYPE (decl)),
+       list2 = TYPE_ARG_TYPES (TREE_TYPE (m_compared_func->decl));
+  for (unsigned i = 0; list1 && list2;
+       list1 = TREE_CHAIN (list1), list2 = TREE_CHAIN (list2), i++)
     {
+      tree parm1 = TREE_VALUE (list1);
+      tree parm2 = TREE_VALUE (list2);
+
       /* This guard is here for function pointer with attributes (pr59927.c).  */
-      if (!arg_types[i] || !m_compared_func->arg_types[i])
+      if (!parm1 || !parm2)
 	return return_false_with_msg ("NULL argument type");
 
-      if (!func_checker::compatible_types_p (arg_types[i],
-					     m_compared_func->arg_types[i]))
-	return return_false_with_msg ("argument type is different");
-      if (POINTER_TYPE_P (arg_types[i])
-	  && (TYPE_RESTRICT (arg_types[i])
-	      != TYPE_RESTRICT (m_compared_func->arg_types[i])))
-	return return_false_with_msg ("argument restrict flag mismatch");
+      /* Verify that types are compatible to ensure that both functions
+	 have same calling conventions.  */
+      if (!types_compatible_p (parm1, parm2))
+	return return_false_with_msg ("parameter types are not compatible");
+
+      if (!param_used_p (i))
+	continue;
+
+      /* Perform additional checks for used parameters.  */
+      if (!compatible_parm_types_p (parm1, parm2))
+	return false;
     }
 
+  if (list1 || list2)
+    return return_false_with_msg ("Mismatched number of parameters");
+
   if (node->num_references () != item->node->num_references ())
     return return_false_with_msg ("different number of references");
 
@@ -740,11 +789,23 @@ sem_function::equals_private (sem_item *item,
   if (decl1 != decl2)
     return return_false();
 
-  for (arg1 = DECL_ARGUMENTS (decl),
-       arg2 = DECL_ARGUMENTS (m_compared_func->decl);
-       arg1; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2))
-    if (!m_checker->compare_decl (arg1, arg2))
-      return return_false ();
+  arg1 = DECL_ARGUMENTS (decl);
+  arg2 = DECL_ARGUMENTS (m_compared_func->decl);
+  for (unsigned i = 0;
+       arg1 && arg2; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2), i++)
+    {
+      if (!types_compatible_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
+	return return_false_with_msg ("argument types are not compatible");
+      if (!param_used_p (i))
+	continue;
+      /* Perform additional checks for used parameters.  */
+      if (!compatible_parm_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
+	return false;
+      if (!m_checker->compare_decl (arg1, arg2))
+	return return_false ();
+    }
+  if (arg1 || arg2)
+    return return_false_with_msg ("Mismatched number of arguments");
 
   /* Fill-up label dictionary.  */
   for (unsigned i = 0; i < bb_sorted.length (); ++i)
@@ -1222,8 +1283,6 @@ sem_function::init (void)
 
     bb_sorted.safe_push (semantic_bb);
   }
-
-  parse_tree_args ();
 }
 
 /* Accumulate to HSTATE a hash of expression EXP.
@@ -1476,37 +1535,6 @@ sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
   return f;
 }
 
-/* Parses function arguments and result type.  */
-
-void
-sem_function::parse_tree_args (void)
-{
-  tree result;
-
-  if (arg_types.exists ())
-    arg_types.release ();
-
-  arg_types.create (4);
-  tree fnargs = DECL_ARGUMENTS (decl);
-
-  for (tree parm = fnargs; parm; parm = DECL_CHAIN (parm))
-    arg_types.safe_push (DECL_ARG_TYPE (parm));
-
-  /* Function result type.  */
-  result = DECL_RESULT (decl);
-  result_type = result ? TREE_TYPE (result) : NULL;
-
-  /* During WPA, we can get arguments by following method.  */
-  if (!fnargs)
-    {
-      tree type = TYPE_ARG_TYPES (TREE_TYPE (decl));
-      for (tree parm = type; parm; parm = TREE_CHAIN (parm))
-	arg_types.safe_push (TYPE_CANONICAL (TREE_VALUE (parm)));
-
-      result_type = TREE_TYPE (TREE_TYPE (decl));
-    }
-}
-
 /* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
    return true if phi nodes are semantically equivalent in these blocks .  */
 
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index 7eb9f27..98a3d4a 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -276,7 +276,6 @@ public:
 
   inline virtual void init_wpa (void)
   {
-    parse_tree_args ();
   }
 
   virtual void init (void);
@@ -294,9 +293,6 @@ public:
     dump_function_to_file (decl, file, TDF_DETAILS);
   }
 
-  /* Parses function arguments and result type.  */
-  void parse_tree_args (void);
-
   /* Returns cgraph_node.  */
   inline cgraph_node *get_node (void)
   {
@@ -313,15 +309,13 @@ public:
      semantic function item.  */
   static sem_function *parse (cgraph_node *node, bitmap_obstack *stack);
 
+  /* Perform additional checks needed to match types of used function
+     paramters.  */
+  bool compatible_parm_types_p (tree, tree);
+
   /* Exception handling region tree.  */
   eh_region region_tree;
 
-  /* Result type tree node.  */
-  tree result_type;
-
-  /* Array of argument tree types.  */
-  vec <tree> arg_types;
-
   /* Number of function arguments.  */
   unsigned int arg_count;
 
@@ -343,6 +337,9 @@ public:
   /* Array of structures for all basic blocks.  */
   vec <ipa_icf_gimple::sem_bb *> bb_sorted;
 
+  /* Return true if parameter I may be used.  */
+  bool param_used_p (unsigned int i);
+
 private:
   /* Calculates hash value based on a BASIC_BLOCK.  */
   hashval_t get_bb_hash (const ipa_icf_gimple::sem_bb *basic_block);
diff --git a/gcc/testsuite/g++.dg/ipa/pr65908.C b/gcc/testsuite/g++.dg/ipa/pr65908.C
new file mode 100644
index 0000000..38730bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr65908.C
@@ -0,0 +1,27 @@
+// PR ipa/65908
+// { dg-do compile }
+// { dg-options "-O2" }
+// { dg-additional-options "-fPIC" { target fpic } }
+
+class A
+{
+  A (A &);
+};
+class B
+{
+  const A &m_fn1 () const;
+};
+class C
+{
+  A m_fn2 () const;
+};
+A
+C::m_fn2 () const
+{
+  throw 0;
+}
+const A &
+B::m_fn1 () const
+{
+  throw 0;
+}
-- 
2.6.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]