diff mbox

Support thunks in ICF

Message ID 20150423235647.GF79833@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka April 23, 2015, 11:56 p.m. UTC
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.
diff mbox

Patch

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);