diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h
index 8213e4f2f46..b59d05fd605 100644
--- a/gcc/ipa-icf-gimple.h
+++ b/gcc/ipa-icf-gimple.h
@@ -121,6 +121,16 @@ public:
 class func_checker : operand_compare
 {
 public:
+  /* Default constructor.  */
+  func_checker ():
+    m_source_func_decl (NULL_TREE), m_target_func_decl (NULL_TREE),
+    m_ignored_source_nodes (NULL), m_ignored_target_nodes (NULL),
+    m_ignore_labels (false)
+  {
+    m_source_ssa_names.create (0);
+    m_target_ssa_names.create (0);
+  }
+
   /* Initialize internal structures for a given SOURCE_FUNC_DECL and
      TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
      an option COMPARE_POLYMORPHIC is true. For special cases, one can
@@ -254,6 +264,7 @@ private:
   /* Flag if ignore labels in comparison.  */
   bool m_ignore_labels;
 
+public:
   /* Return true if two operands are equal.  The flags fields can be used
      to specify OEP flags described above.  */
   virtual bool operand_equal_p (const_tree, const_tree, unsigned int flags);
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 53e387403c8..8297eec9388 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -1335,8 +1335,9 @@ sem_function::merge (sem_item *alias_item)
 /* Semantic item initialization function.  */
 
 void
-sem_function::init (void)
+sem_function::init (ipa_icf_gimple::func_checker *checker)
 {
+  m_checker = checker;
   if (in_lto_p)
     get_node ()->get_untransformed_body ();
 
@@ -1411,161 +1412,6 @@ sem_function::init (void)
     }
 }
 
-/* Accumulate to HSTATE a hash of expression EXP.
-   Identical to inchash::add_expr, but guaranteed to be stable across LTO
-   and DECL equality classes.  */
-
-void
-sem_item::add_expr (const_tree exp, inchash::hash &hstate)
-{
-  if (exp == NULL_TREE)
-    {
-      hstate.merge_hash (0);
-      return;
-    }
-
-  /* Handled component can be matched in a cureful way proving equivalence
-     even if they syntactically differ.  Just skip them.  */
-  STRIP_NOPS (exp);
-  while (handled_component_p (exp))
-    exp = TREE_OPERAND (exp, 0);
-
-  enum tree_code code = TREE_CODE (exp);
-  hstate.add_int (code);
-
-  switch (code)
-    {
-    /* Use inchash::add_expr for everything that is LTO stable.  */
-    case VOID_CST:
-    case INTEGER_CST:
-    case REAL_CST:
-    case FIXED_CST:
-    case STRING_CST:
-    case COMPLEX_CST:
-    case VECTOR_CST:
-      inchash::add_expr (exp, hstate);
-      break;
-    case CONSTRUCTOR:
-      {
-	unsigned HOST_WIDE_INT idx;
-	tree value;
-
-	hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
-
-	FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
-	  if (value)
-	    add_expr (value, hstate);
-	break;
-      }
-    case ADDR_EXPR:
-    case FDESC_EXPR:
-      add_expr (get_base_address (TREE_OPERAND (exp, 0)), hstate);
-      break;
-    case SSA_NAME:
-    case VAR_DECL:
-    case CONST_DECL:
-    case PARM_DECL:
-      hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
-      break;
-    case MEM_REF:
-    case POINTER_PLUS_EXPR:
-    case MINUS_EXPR:
-    case RANGE_EXPR:
-      add_expr (TREE_OPERAND (exp, 0), hstate);
-      add_expr (TREE_OPERAND (exp, 1), hstate);
-      break;
-    case PLUS_EXPR:
-      {
-	inchash::hash one, two;
-	add_expr (TREE_OPERAND (exp, 0), one);
-	add_expr (TREE_OPERAND (exp, 1), two);
-	hstate.add_commutative (one, two);
-      }
-      break;
-    CASE_CONVERT:
-      hstate.add_hwi (int_size_in_bytes (TREE_TYPE (exp)));
-      return add_expr (TREE_OPERAND (exp, 0), hstate);
-    default:
-      break;
-    }
-}
-
-/* Accumulate to HSTATE a hash of type t.
-   TYpes that may end up being compatible after LTO type merging needs to have
-   the same hash.  */
-
-void
-sem_item::add_type (const_tree type, inchash::hash &hstate)
-{
-  if (type == NULL_TREE)
-    {
-      hstate.merge_hash (0);
-      return;
-    }
-
-  type = TYPE_MAIN_VARIANT (type);
-
-  hstate.add_int (TYPE_MODE (type));
-
-  if (TREE_CODE (type) == COMPLEX_TYPE)
-    {
-      hstate.add_int (COMPLEX_TYPE);
-      sem_item::add_type (TREE_TYPE (type), hstate);
-    }
-  else if (INTEGRAL_TYPE_P (type))
-    {
-      hstate.add_int (INTEGER_TYPE);
-      hstate.add_flag (TYPE_UNSIGNED (type));
-      hstate.add_int (TYPE_PRECISION (type));
-    }
-  else if (VECTOR_TYPE_P (type))
-    {
-      hstate.add_int (VECTOR_TYPE);
-      hstate.add_int (TYPE_PRECISION (type));
-      sem_item::add_type (TREE_TYPE (type), hstate);
-    }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      hstate.add_int (ARRAY_TYPE);
-      /* Do not hash size, so complete and incomplete types can match.  */
-      sem_item::add_type (TREE_TYPE (type), hstate);
-    }
-  else if (RECORD_OR_UNION_TYPE_P (type))
-    {
-      /* Incomplete types must be skipped here.  */
-      if (!COMPLETE_TYPE_P (type))
-	{
-	  hstate.add_int (RECORD_TYPE);
-	  return;
-	}
-
-      hashval_t *val = m_type_hash_cache.get (type);
-
-      if (!val)
-	{
-	  inchash::hash hstate2;
-	  unsigned nf;
-	  tree f;
-	  hashval_t hash;
-
-	  hstate2.add_int (RECORD_TYPE);
-	  for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
-	    if (TREE_CODE (f) == FIELD_DECL)
-	      {
-		add_type (TREE_TYPE (f), hstate2);
-		nf++;
-	      }
-
-	  hstate2.add_int (nf);
-	  hash = hstate2.end ();
-	  hstate.add_hwi (hash);
-	  m_type_hash_cache.put (type, hash);
-	}
-      else
-        hstate.add_hwi (*val);
-    }
-}
-
 /* Improve accumulated hash for HSTATE based on a gimple statement STMT.  */
 
 void
@@ -1578,27 +1424,19 @@ sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
   switch (code)
     {
     case GIMPLE_SWITCH:
-      add_expr (gimple_switch_index (as_a <gswitch *> (stmt)), hstate);
+      m_checker->hash_operand (gimple_switch_index (as_a <gswitch *> (stmt)),
+			     hstate, 0);
       break;
     case GIMPLE_ASSIGN:
       hstate.add_int (gimple_assign_rhs_code (stmt));
       if (commutative_tree_code (gimple_assign_rhs_code (stmt))
 	  || commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
 	{
-	  inchash::hash one, two;
-
-	  add_expr (gimple_assign_rhs1 (stmt), one);
-	  add_type (TREE_TYPE (gimple_assign_rhs1 (stmt)), one);
-	  add_expr (gimple_assign_rhs2 (stmt), two);
-	  hstate.add_commutative (one, two);
+	  m_checker->hash_operand (gimple_assign_rhs1 (stmt), hstate, 0);
+	  m_checker->hash_operand (gimple_assign_rhs2 (stmt), hstate, 0);
 	  if (commutative_ternary_tree_code (gimple_assign_rhs_code (stmt)))
-	    {
-	      add_expr (gimple_assign_rhs3 (stmt), hstate);
-	      add_type (TREE_TYPE (gimple_assign_rhs3 (stmt)), hstate);
-	    }
-	  add_expr (gimple_assign_lhs (stmt), hstate);
-	  add_type (TREE_TYPE (gimple_assign_lhs (stmt)), two);
-	  break;
+	    m_checker->hash_operand (gimple_assign_rhs3 (stmt), hstate, 0);
+	  m_checker->hash_operand (gimple_assign_lhs (stmt), hstate, 0);
 	}
       /* fall through */
     case GIMPLE_CALL:
@@ -1608,11 +1446,7 @@ sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
     case GIMPLE_RETURN:
       /* All these statements are equivalent if their operands are.  */
       for (unsigned i = 0; i < gimple_num_ops (stmt); ++i)
-	{
-	  add_expr (gimple_op (stmt, i), hstate);
-	  if (gimple_op (stmt, i))
-	    add_type (TREE_TYPE (gimple_op (stmt, i)), hstate);
-	}
+	m_checker->hash_operand (gimple_op (stmt, i), hstate, 0);
       /* Consider nocf_check attribute in hash as it affects code
  	 generation.  */
       if (code == GIMPLE_CALL
@@ -1648,7 +1482,8 @@ sem_function::compare_polymorphic_p (void)
    semantic function item.  */
 
 sem_function *
-sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
+sem_function::parse (cgraph_node *node, bitmap_obstack *stack,
+		     func_checker *checker)
 {
   tree fndecl = node->decl;
   function *func = DECL_STRUCT_FUNCTION (fndecl);
@@ -1669,8 +1504,7 @@ sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
     return NULL;
 
   sem_function *f = new sem_function (node, stack);
-
-  f->init ();
+  f->init (checker);
 
   return f;
 }
@@ -2038,40 +1872,45 @@ sem_variable::equals (tree t1, tree t2)
 /* Parser function that visits a varpool NODE.  */
 
 sem_variable *
-sem_variable::parse (varpool_node *node, bitmap_obstack *stack)
+sem_variable::parse (varpool_node *node, bitmap_obstack *stack,
+		     func_checker *checker)
 {
   if (TREE_THIS_VOLATILE (node->decl) || DECL_HARD_REGISTER (node->decl)
       || node->alias)
     return NULL;
 
   sem_variable *v = new sem_variable (node, stack);
-
-  v->init ();
+  v->init (checker);
 
   return v;
 }
 
-/* References independent hash function.  */
+/* Semantic variable initialization function.  */
 
-hashval_t
-sem_variable::get_hash (void)
+void
+sem_variable::init (ipa_icf_gimple::func_checker *checker)
 {
-  if (m_hash_set)
-    return m_hash;
+  decl = get_node ()->decl;
 
   /* All WPA streamed in symbols should have their hashes computed at compile
      time.  At this point, the constructor may not be in memory at all.
      DECL_INITIAL (decl) would be error_mark_node in that case.  */
-  gcc_assert (!node->lto_file_data);
-  tree ctor = DECL_INITIAL (decl);
-  inchash::hash hstate;
+  if (!m_hash_set)
+    {
+      gcc_assert (!node->lto_file_data);
+      inchash::hash hstate;
+      hstate.add_int (456346417);
+      checker->hash_operand (DECL_INITIAL (decl), hstate, 0);
+      set_hash (hstate.end ());
+    }
+}
 
-  hstate.add_int (456346417);
-  if (DECL_SIZE (decl) && tree_fits_shwi_p (DECL_SIZE (decl)))
-    hstate.add_hwi (tree_to_shwi (DECL_SIZE (decl)));
-  add_expr (ctor, hstate);
-  set_hash (hstate.end ());
+/* References independent hash function.  */
 
+hashval_t
+sem_variable::get_hash (void)
+{
+  gcc_checking_assert (m_hash_set);
   return m_hash;
 }
 
@@ -2590,10 +2429,13 @@ sem_item_optimizer::parse_funcs_and_vars (void)
 {
   cgraph_node *cnode;
 
+  /* Create dummy func_checker for hashing purpose.  */
+  func_checker checker;
+
   if (flag_ipa_icf_functions)
     FOR_EACH_DEFINED_FUNCTION (cnode)
     {
-      sem_function *f = sem_function::parse (cnode, &m_bmstack);
+      sem_function *f = sem_function::parse (cnode, &m_bmstack, &checker);
       if (f)
 	{
 	  m_items.safe_push (f);
@@ -2606,7 +2448,7 @@ sem_item_optimizer::parse_funcs_and_vars (void)
   if (flag_ipa_icf_variables)
     FOR_EACH_DEFINED_VARIABLE (vnode)
     {
-      sem_variable *v = sem_variable::parse (vnode, &m_bmstack);
+      sem_variable *v = sem_variable::parse (vnode, &m_bmstack, &checker);
 
       if (v)
 	{
@@ -2750,10 +2592,13 @@ sem_item_optimizer::parse_nonsingleton_classes (void)
 {
   unsigned int counter = 0;
 
+  /* Create dummy func_checker for hashing purpose.  */
+  func_checker checker;
+
   for (unsigned i = 0; i < m_items.length (); i++)
     if (m_items[i]->cls->members.length () > 1)
       {
-	m_items[i]->init ();
+	m_items[i]->init (&checker);
 	++counter;
       }
 
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index 0b99a612016..906002214d5 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -191,7 +191,7 @@ public:
   DEBUG_FUNCTION void dump (void);
 
   /* Semantic item initialization function.  */
-  virtual void init (void) = 0;
+  virtual void init (ipa_icf_gimple::func_checker *) = 0;
 
   /* Add reference to a semantic TARGET.  */
   void add_reference (ref_map *map, sem_item *target);
@@ -269,11 +269,6 @@ public:
 protected:
   /* Cached, once calculated hash for the item.  */
 
-  /* Accumulate to HSTATE a hash of expression EXP.  */
-  static void add_expr (const_tree exp, inchash::hash &hstate);
-  /* Accumulate to HSTATE a hash of type T.  */
-  static void add_type (const_tree t, inchash::hash &hstate);
-
   /* Compare properties of symbol that does not affect semantics of symbol
      itself but affects semantics of its references.
      If ADDRESS is true, do extra checking needed for IPA_REF_ADDR.  */
@@ -322,7 +317,7 @@ public:
 
   ~sem_function ();
 
-  virtual void init (void);
+  virtual void init (ipa_icf_gimple::func_checker *);
   virtual bool equals_wpa (sem_item *item,
 			   hash_map <symtab_node *, sem_item *> &ignored_nodes);
   virtual hashval_t get_hash (void);
@@ -351,7 +346,8 @@ public:
 
   /* For a given call graph NODE, the function constructs new
      semantic function item.  */
-  static sem_function *parse (cgraph_node *node, bitmap_obstack *stack);
+  static sem_function *parse (cgraph_node *node, bitmap_obstack *stack,
+			      ipa_icf_gimple::func_checker *checker);
 
   /* Perform additional checks needed to match types of used function
      paramters.  */
@@ -423,10 +419,7 @@ public:
   sem_variable (varpool_node *_node, bitmap_obstack *stack);
 
   /* Semantic variable initialization function.  */
-  inline virtual void init (void)
-  {
-    decl = get_node ()->decl;
-  }
+  virtual void init (ipa_icf_gimple::func_checker *);
 
   virtual hashval_t get_hash (void);
   virtual bool merge (sem_item *alias_item);
@@ -445,7 +438,8 @@ public:
   }
 
   /* Parser function that visits a varpool NODE.  */
-  static sem_variable *parse (varpool_node *node, bitmap_obstack *stack);
+  static sem_variable *parse (varpool_node *node, bitmap_obstack *stack,
+			      ipa_icf_gimple::func_checker *checker);
 
 private:
   /* Compares trees T1 and T2 for semantic equality.  */
