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]

Support thunks in ICF


Hi,
this patch adds necessary code to match thunks (that is rather easy to do).
Firefox currently duoes not build for me with mainline (for syntax errors)
so I did not test how much effect the patch has in practice.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

	* ipa-icf.c (sem_function::equals_wpa): Compare thunk info.
	(sem_function::equals): IGNORED_NODES parameter is now unused;
	update call of equals_private.
	(sem_function::equals_private): Do not call equals_wpa; skip
	gimple body matching if there is no body.
	(sem_function::init): Add logic to hash tthunk info.
	(sem_function::parse): Also parse thunks.
	* ipa-icf.h (equals_private): Update declaration.
Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 222374)
+++ ipa-icf.c	(working copy)
@@ -601,12 +601,32 @@ sem_function::equals_wpa (sem_item *item
 			  hash_map <symtab_node *, sem_item *> &ignored_nodes)
 {
   gcc_assert (item->type == FUNC);
+  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+  cgraph_node *cnode2 = dyn_cast <cgraph_node *> (item->node);
 
   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");
 
+  if (cnode->thunk.thunk_p != cnode2->thunk.thunk_p)
+    return return_false_with_msg ("thunk_p mismatch");
+
+  if (cnode->thunk.thunk_p)
+    {
+      if (cnode->thunk.fixed_offset != cnode2->thunk.fixed_offset)
+        return return_false_with_msg ("thunk fixed_offset mismatch");
+      if (cnode->thunk.virtual_value != cnode2->thunk.virtual_value)
+        return return_false_with_msg ("thunk virtual_value mismatch");
+      if (cnode->thunk.this_adjusting != cnode2->thunk.this_adjusting)
+        return return_false_with_msg ("thunk this_adjusting mismatch");
+      if (cnode->thunk.virtual_offset_p != cnode2->thunk.virtual_offset_p)
+        return return_false_with_msg ("thunk virtual_offset_p mismatch");
+      if (cnode->thunk.add_pointer_bounds_args
+	  != cnode2->thunk.add_pointer_bounds_args)
+        return return_false_with_msg ("thunk add_pointer_bounds_args mismatch");
+    }
+
   /* Compare special function DECL attributes.  */
   if (DECL_FUNCTION_PERSONALITY (decl)
       != DECL_FUNCTION_PERSONALITY (item->decl))
@@ -862,10 +882,10 @@ sem_item::update_hash_by_local_refs (has
 
 bool
 sem_function::equals (sem_item *item,
-		      hash_map <symtab_node *, sem_item *> &ignored_nodes)
+		      hash_map <symtab_node *, sem_item *> &)
 {
   gcc_assert (item->type == FUNC);
-  bool eq = equals_private (item, ignored_nodes);
+  bool eq = equals_private (item);
 
   if (m_checker != NULL)
     {
@@ -890,8 +910,7 @@ sem_function::equals (sem_item *item,
 /* Processes function equality comparison.  */
 
 bool
-sem_function::equals_private (sem_item *item,
-			      hash_map <symtab_node *, sem_item *> &ignored_nodes)
+sem_function::equals_private (sem_item *item)
 {
   if (item->type != FUNC)
     return false;
@@ -911,9 +930,6 @@ sem_function::equals_private (sem_item *
       || cfg_checksum != m_compared_func->cfg_checksum)
     return return_false ();
 
-  if (!equals_wpa (item, ignored_nodes))
-    return false;
-
   m_checker = new func_checker (decl, m_compared_func->decl,
 				compare_polymorphic_p (),
 				false,
@@ -925,6 +941,9 @@ sem_function::equals_private (sem_item *
     if (!m_checker->compare_decl (arg1, arg2))
       return return_false ();
 
+  if (!dyn_cast <cgraph_node *> (node)->has_gimple_body_p ())
+    return true;
+
   /* Fill-up label dictionary.  */
   for (unsigned i = 0; i < bb_sorted.length (); ++i)
     {
@@ -1380,44 +1399,59 @@ sem_function::init (void)
   arg_count = count_formal_params (fndecl);
 
   edge_count = n_edges_for_fn (func);
-  cfg_checksum = coverage_compute_cfg_checksum (func);
-
-  inchash::hash hstate;
+  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+  if (!cnode->thunk.thunk_p)
+    {
+      cfg_checksum = coverage_compute_cfg_checksum (func);
 
-  basic_block bb;
-  FOR_EACH_BB_FN (bb, func)
-  {
-    unsigned nondbg_stmt_count = 0;
-
-    edge e;
-    for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e);
-	 ei_next (&ei))
-      cfg_checksum = iterative_hash_host_wide_int (e->flags,
-		     cfg_checksum);
+      inchash::hash hstate;
 
-    for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
-	 gsi_next (&gsi))
+      basic_block bb;
+      FOR_EACH_BB_FN (bb, func)
       {
-	gimple stmt = gsi_stmt (gsi);
+	unsigned nondbg_stmt_count = 0;
+
+	edge e;
+	for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e);
+	     ei_next (&ei))
+	  cfg_checksum = iterative_hash_host_wide_int (e->flags,
+			 cfg_checksum);
 
-	if (gimple_code (stmt) != GIMPLE_DEBUG
-	    && gimple_code (stmt) != GIMPLE_PREDICT)
+	for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+	     gsi_next (&gsi))
 	  {
-	    hash_stmt (stmt, hstate);
-	    nondbg_stmt_count++;
+	    gimple stmt = gsi_stmt (gsi);
+
+	    if (gimple_code (stmt) != GIMPLE_DEBUG
+		&& gimple_code (stmt) != GIMPLE_PREDICT)
+	      {
+		hash_stmt (stmt, hstate);
+		nondbg_stmt_count++;
+	      }
 	  }
-      }
 
-    gcode_hash = hstate.end ();
-    bb_sizes.safe_push (nondbg_stmt_count);
+	gcode_hash = hstate.end ();
+	bb_sizes.safe_push (nondbg_stmt_count);
 
-    /* Inserting basic block to hash table.  */
-    sem_bb *semantic_bb = new sem_bb (bb, nondbg_stmt_count,
-				      EDGE_COUNT (bb->preds)
-				      + EDGE_COUNT (bb->succs));
+	/* Inserting basic block to hash table.  */
+	sem_bb *semantic_bb = new sem_bb (bb, nondbg_stmt_count,
+					  EDGE_COUNT (bb->preds)
+					  + EDGE_COUNT (bb->succs));
 
-    bb_sorted.safe_push (semantic_bb);
-  }
+	bb_sorted.safe_push (semantic_bb);
+      }
+    }
+  else
+    {
+      cfg_checksum = 0;
+      inchash::hash hstate;
+      hstate.add_wide_int (cnode->thunk.fixed_offset);
+      hstate.add_wide_int (cnode->thunk.virtual_value);
+      hstate.add_flag (cnode->thunk.this_adjusting);
+      hstate.add_flag (cnode->thunk.virtual_offset_p);
+      hstate.add_flag (cnode->thunk.add_pointer_bounds_args);
+      gcode_hash = hstate.end ();
+    }
 
   parse_tree_args ();
 }
@@ -1657,9 +1691,7 @@ sem_function::parse (cgraph_node *node,
   tree fndecl = node->decl;
   function *func = DECL_STRUCT_FUNCTION (fndecl);
 
-  /* TODO: add support for thunks.  */
-
-  if (!func || !node->has_gimple_body_p ())
+  if (!func || (!node->has_gimple_body_p () && !node->thunk.thunk_p))
     return NULL;
 
   if (lookup_attribute_by_prefix ("omp ", DECL_ATTRIBUTES (node->decl)) != NULL)
Index: ipa-icf.h
===================================================================
--- ipa-icf.h	(revision 222374)
+++ ipa-icf.h	(working copy)
@@ -380,8 +380,7 @@ private:
   bool compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2);
 
   /* Processes function equality comparison.  */
-  bool equals_private (sem_item *item,
-		       hash_map <symtab_node *, sem_item *> &ignored_nodes);
+  bool equals_private (sem_item *item);
 
   /* Returns true if tree T can be compared as a handled component.  */
   static bool icf_handled_component_p (tree t);


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