diff mbox

IPA ICF: make hash values finer

Message ID 551174A3.2070400@suse.cz
State New
Headers show

Commit Message

Martin Liška March 24, 2015, 2:28 p.m. UTC
Hello.

Following patch should be final speed-up patch for IPA ICF. It just basically enhances hash values of a symbol,
computed in a TU. Having finer hash values, we do not spend so much time in WPA phase. It shows, we can reduce
utilization from 14% -> 9% (_w/o_ WPA streaming out). Time report and ICF dump are added as attachment.

Second, very small, part of the patch replaces add_ptr with add_int (for ultimate_alias_target).

Can boostrap on ppc64le-linux-pc and no regression seen on x86_64-linux-pc.
I've been running LTO builds for chrome, firefox and inkscape.

Ready for trunk?
Thanks,
Martin
1   false returned: '' (compare_phi_node:1426)
      4   false returned: '' (compare_operand:490)
      4   false returned: 'different dependence info' (compare_memory_operand:351)
      5   false returned: 'alignment mismatch' (equals_wpa:1530)
     11   false returned: 'TREE_CODE mismatch' (equals:1625)
     19   false returned: 'switch label_exprs are different' (compare_gimple_switch:950)
     42   false returned: 'INTEGER_CST precision mismatch' (equals:1708)
     49   false returned: 'ASM strings are different' (compare_gimple_asm:1027)
     57   false returned: 'case high values are different' (compare_gimple_switch:941)
     57   false returned: 'operator new flags are different' (equals_wpa:422)
    163   false returned: '' (compare_operand:493)
    195   false returned: '' (compare_phi_node:1449)
    196   false returned: 'PHI node comparison returns false' (equals_private:774)
    282   false returned: 'different operand volatility' (compare_memory_operand:312)
    283   false returned: 'ao alias sets are different' (compare_memory_operand:316)
    399   false returned: 'variables types are different' (equals:1596)
    448   false returned: 'Unknown TREE code reached' (compare_operand:572)
    477   false returned: 'Declaration mismatch' (equals:1704)
    478   false returned: 'case low values are different' (compare_gimple_switch:935)
    624   false returned: '' (compare_operand:472)
    689   false returned: 'different number of arguments' (equals_wpa:407)
    915   false returned: 'memory operands are different' (compare_gimple_call:805)
   1469   false returned: 'DECL_DISREGARD_INLINE_LIMITS are different' (equals_wpa:416)
   3298   false returned: '' (compare_operand:437)
   4918   false returned: 'Target flags are different' (equals_wpa:467)
   6036   false returned: 'different access alignment' (compare_memory_operand:334)
   7209   false returned: 'one type is not polymorphic' (compatible_polymorphic_types_p:258)
  10177   false returned: '' (equals_private:719)
  10979   false returned: 'OBJ_TYPE_REF OTR type mismatch' (compare_operand:523)
  11271   false returned: '' (equals_private:694)
  11282   false returned: 'DELC_CXX_CONSTRUCTOR mismatch' (equals_wpa:433)
  11624   false returned: 'alias sets are different' (compatible_types_p:278)
  11662   false returned: '' (compare_gimple_call:767)
  16327   false returned: 'virtual or final flag mismatch' (equals_wpa:1571)
  21104   false returned: 'METHOD_TYPE and FUNCTION_TYPE mismatch' (equals_wpa:523)
  26301   false returned: 'result types are different' (equals_wpa:487)
  32513   false returned: 'different references' (compare_cgraph_references:374)
  60327   false returned: 'DELC_CXX_DESTRUCTOR mismatch' (equals_wpa:436)
  73746   false returned: 'decl_or_type flags are different' (equals_wpa:439)
  91856   false returned: 'references to virtual tables can not be merged' (compare_cgraph_references:360)
 195276   false returned: 'argument type is different' (equals_wpa:498)
 209619   false returned: 'call function types are not compatible' (compare_gimple_call:789)
 223350   false returned: 'different tree types' (compatible_types_p:269)
 427168   false returned: 'ctor polymorphic type mismatch' (equals_wpa:452)
 507495   false returned: 'types are not compatible' (compatible_types_p:275)
 567596   false returned: 'memory operands are different' (compare_gimple_assign:844)
 628846   false returned: 'optimization flags are different' (equals_wpa:481)
 815465   false returned: '' (equals_private:737)
15707328   false returned: 'inline attributes are different' (equals_wpa:419)
18891178   false returned: 'THIS pointer ODR type mismatch' (equals_wpa:527)
19311137   false returned: 'types are not same for ODR' (compatible_polymorphic_types_p:260)

Execution times (seconds)
 phase setup             :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall    1978 kB ( 0%) ggc
 phase opt and generate  :  96.43 (45%) usr   2.13 (46%) sys  98.52 (45%) wall 2497753 kB (12%) ggc
 phase stream in         : 120.12 (55%) usr   2.54 (54%) sys 122.61 (55%) wall18700766 kB (88%) ggc
 callgraph optimization  :   0.81 ( 0%) usr   0.00 ( 0%) sys   0.82 ( 0%) wall      14 kB ( 0%) ggc
 ipa dead code removal   :   6.85 ( 3%) usr   0.04 ( 1%) sys   6.76 ( 3%) wall       0 kB ( 0%) ggc
 ipa virtual call target :   4.04 ( 2%) usr   0.07 ( 1%) sys   4.08 ( 2%) wall       0 kB ( 0%) ggc
 ipa devirtualization    :   0.30 ( 0%) usr   0.00 ( 0%) sys   0.33 ( 0%) wall   34666 kB ( 0%) ggc
 ipa cp                  :   5.70 ( 3%) usr   0.38 ( 8%) sys   6.08 ( 3%) wall  919225 kB ( 4%) ggc
 ipa inlining heuristics :  27.05 (12%) usr   0.40 ( 9%) sys  27.61 (12%) wall  811784 kB ( 4%) ggc
 ipa comdats             :   0.62 ( 0%) usr   0.00 ( 0%) sys   0.62 ( 0%) wall       0 kB ( 0%) ggc
 ipa lto gimple in       :   5.74 ( 3%) usr   0.95 (20%) sys   6.67 ( 3%) wall 1161422 kB ( 5%) ggc
 ipa lto decl in         : 103.66 (48%) usr   1.63 (35%) sys 105.25 (48%) wall16830013 kB (79%) ggc
 ipa lto constructors in :   0.49 ( 0%) usr   0.05 ( 1%) sys   0.52 ( 0%) wall   27315 kB ( 0%) ggc
 ipa lto cgraph I/O      :   2.20 ( 1%) usr   0.29 ( 6%) sys   2.48 ( 1%) wall  954517 kB ( 5%) ggc
 ipa lto decl merge      :   4.13 ( 2%) usr   0.00 ( 0%) sys   4.13 ( 2%) wall   16383 kB ( 0%) ggc
 ipa lto cgraph merge    :   5.65 ( 3%) usr   0.01 ( 0%) sys   5.63 ( 3%) wall   21738 kB ( 0%) ggc
 whopr wpa               :   1.99 ( 1%) usr   0.00 ( 0%) sys   2.01 ( 1%) wall       2 kB ( 0%) ggc
 whopr partitioning      :   5.23 ( 2%) usr   0.01 ( 0%) sys   5.22 ( 2%) wall    8936 kB ( 0%) ggc
 ipa reference           :   3.57 ( 2%) usr   0.01 ( 0%) sys   3.57 ( 2%) wall       0 kB ( 0%) ggc
 ipa profile             :   0.50 ( 0%) usr   0.03 ( 1%) sys   0.53 ( 0%) wall       0 kB ( 0%) ggc
 ipa pure const          :   4.43 ( 2%) usr   0.07 ( 1%) sys   4.49 ( 2%) wall       0 kB ( 0%) ggc
 ipa icf                 :  30.49 (14%) usr   0.27 ( 6%) sys  30.82 (14%) wall   31893 kB ( 0%) ggc
 tree SSA rewrite        :   0.24 ( 0%) usr   0.08 ( 2%) sys   0.38 ( 0%) wall   47000 kB ( 0%) ggc
 tree SSA other          :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.01 ( 0%) wall       0 kB ( 0%) ggc
 tree SSA incremental    :   0.58 ( 0%) usr   0.11 ( 2%) sys   0.52 ( 0%) wall   30453 kB ( 0%) ggc
 tree operand scan       :   0.46 ( 0%) usr   0.09 ( 2%) sys   0.57 ( 0%) wall  302599 kB ( 1%) ggc
 dominance frontiers     :   0.01 ( 0%) usr   0.00 ( 0%) sys   0.03 ( 0%) wall       0 kB ( 0%) ggc
 dominance computation   :   0.34 ( 0%) usr   0.06 ( 1%) sys   0.35 ( 0%) wall       0 kB ( 0%) ggc
 varconst                :   0.03 ( 0%) usr   0.04 ( 1%) sys   0.09 ( 0%) wall       0 kB ( 0%) ggc
 loop init               :   0.02 ( 0%) usr   0.00 ( 0%) sys   0.02 ( 0%) wall     546 kB ( 0%) ggc
 loop fini               :   0.12 ( 0%) usr   0.00 ( 0%) sys   0.15 ( 0%) wall       0 kB ( 0%) ggc
 unaccounted todo        :   1.23 ( 1%) usr   0.00 ( 0%) sys   1.23 ( 1%) wall       0 kB ( 0%) ggc
 TOTAL                 : 216.55             4.67           221.13           21200498 kB
1   false returned: '' (compare_phi_node:1534)
      2   false returned: 'operator new flags are different' (equals_wpa:442)
      4   false returned: '' (compare_operand:490)
      4   false returned: 'different dependence info' (compare_memory_operand:351)
      5   false returned: 'alignment mismatch' (equals_wpa:1638)
     11   false returned: 'TREE_CODE mismatch' (equals:1733)
     18   false returned: 'switch label_exprs are different' (compare_gimple_switch:950)
     42   false returned: 'INTEGER_CST precision mismatch' (equals:1816)
     49   false returned: 'ASM strings are different' (compare_gimple_asm:1027)
     57   false returned: 'case high values are different' (compare_gimple_switch:941)
     76   false returned: 'one type is not polymorphic' (compatible_polymorphic_types_p:258)
    124   false returned: '' (compare_operand:493)
    145   false returned: 'ao alias sets are different' (compare_memory_operand:316)
    179   false returned: 'different operand volatility' (compare_memory_operand:312)
    195   false returned: '' (compare_phi_node:1557)
    196   false returned: 'PHI node comparison returns false' (equals_private:794)
    382   false returned: 'DECL_CXX_DESTRUCTOR mismatch' (equals_wpa:456)
    399   false returned: 'variables types are different' (equals:1704)
    447   false returned: 'Unknown TREE code reached' (compare_operand:572)
    477   false returned: 'Declaration mismatch' (equals:1812)
    478   false returned: 'case low values are different' (compare_gimple_switch:935)
    558   false returned: '' (compare_operand:472)
    694   false returned: 'different number of arguments' (equals_wpa:427)
    836   false returned: 'ctor polymorphic type mismatch' (equals_wpa:472)
    915   false returned: 'memory operands are different' (compare_gimple_call:805)
   1462   false returned: 'DECL_DISREGARD_INLINE_LIMITS are different' (equals_wpa:436)
   2012   false returned: 'METHOD_TYPE and FUNCTION_TYPE mismatch' (equals_wpa:543)
   2132   false returned: 'DECL_CXX_CONSTRUCTOR mismatch' (equals_wpa:453)
   2937   false returned: 'different access alignment' (compare_memory_operand:334)
   3291   false returned: '' (compare_operand:437)
   4446   false returned: 'decl_or_type flags are different' (equals_wpa:459)
   4498   false returned: 'result types are different' (equals_wpa:507)
   6176   false returned: 'alias sets are different' (compatible_types_p:278)
  10175   false returned: '' (equals_private:739)
  10975   false returned: 'OBJ_TYPE_REF OTR type mismatch' (compare_operand:523)
  11271   false returned: '' (equals_private:714)
  11472   false returned: '' (compare_gimple_call:767)
  16327   false returned: 'virtual or final flag mismatch' (equals_wpa:1679)
  30871   false returned: 'optimization flags are different' (equals_wpa:501)
  32210   false returned: 'different references' (compare_cgraph_references:394)
  61843   false returned: 'THIS pointer ODR type mismatch' (equals_wpa:547)
  62603   false returned: 'types are not same for ODR' (compatible_polymorphic_types_p:260)
  65471   false returned: 'argument type is different' (equals_wpa:518)
  72113   false returned: 'different tree types' (compatible_types_p:269)
  82299   false returned: 'references to virtual tables can not be merged' (compare_cgraph_references:380)
 149847   false returned: 'inline attributes are different' (equals_wpa:439)
 209606   false returned: 'call function types are not compatible' (compare_gimple_call:789)
 489018   false returned: 'types are not compatible' (compatible_types_p:275)
 540847   false returned: 'memory operands are different' (compare_gimple_assign:844)
 765620   false returned: '' (equals_private:757)

Equal symbols: 84571

Execution times (seconds)
 phase setup             :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall    1978 kB ( 0%) ggc
 phase opt and generate  :  70.09 (43%) usr   1.54 (41%) sys  71.60 (43%) wall 2463719 kB (12%) ggc
 phase stream in         :  94.04 (57%) usr   2.26 (59%) sys  96.53 (57%) wall18700766 kB (88%) ggc
 callgraph optimization  :   0.73 ( 0%) usr   0.00 ( 0%) sys   0.73 ( 0%) wall      14 kB ( 0%) ggc
 ipa dead code removal   :   6.07 ( 4%) usr   0.02 ( 1%) sys   5.85 ( 3%) wall       0 kB ( 0%) ggc
 ipa virtual call target :   3.05 ( 2%) usr   0.05 ( 1%) sys   3.44 ( 2%) wall       0 kB ( 0%) ggc
 ipa devirtualization    :   0.25 ( 0%) usr   0.00 ( 0%) sys   0.24 ( 0%) wall   34666 kB ( 0%) ggc
 ipa cp                  :   4.86 ( 3%) usr   0.25 ( 7%) sys   5.08 ( 3%) wall  919225 kB ( 4%) ggc
 ipa inlining heuristics :  22.24 (14%) usr   0.25 ( 7%) sys  22.44 (13%) wall  811770 kB ( 4%) ggc
 ipa comdats             :   0.55 ( 0%) usr   0.00 ( 0%) sys   0.56 ( 0%) wall       0 kB ( 0%) ggc
 ipa lto gimple in       :   4.27 ( 3%) usr   0.70 (18%) sys   5.01 ( 3%) wall 1136096 kB ( 5%) ggc
 ipa lto decl in         :  80.30 (49%) usr   1.44 (38%) sys  81.97 (49%) wall16830013 kB (80%) ggc
 ipa lto constructors in :   0.35 ( 0%) usr   0.06 ( 2%) sys   0.38 ( 0%) wall   27315 kB ( 0%) ggc
 ipa lto cgraph I/O      :   1.51 ( 1%) usr   0.27 ( 7%) sys   1.78 ( 1%) wall  954517 kB ( 5%) ggc
 ipa lto decl merge      :   3.56 ( 2%) usr   0.00 ( 0%) sys   3.56 ( 2%) wall   16383 kB ( 0%) ggc
 ipa lto cgraph merge    :   4.89 ( 3%) usr   0.00 ( 0%) sys   4.89 ( 3%) wall   21738 kB ( 0%) ggc
 whopr wpa               :   1.83 ( 1%) usr   0.00 ( 0%) sys   1.87 ( 1%) wall       2 kB ( 0%) ggc
 whopr partitioning      :   4.87 ( 3%) usr   0.01 ( 0%) sys   4.87 ( 3%) wall    8936 kB ( 0%) ggc
 ipa reference           :   2.77 ( 2%) usr   0.01 ( 0%) sys   2.78 ( 2%) wall       0 kB ( 0%) ggc
 ipa profile             :   0.49 ( 0%) usr   0.03 ( 1%) sys   0.54 ( 0%) wall       0 kB ( 0%) ggc
 ipa pure const          :   3.23 ( 2%) usr   0.05 ( 1%) sys   3.28 ( 2%) wall       0 kB ( 0%) ggc
 ipa icf                 :  15.59 ( 9%) usr   0.29 ( 8%) sys  15.71 ( 9%) wall   31897 kB ( 0%) ggc
 tree SSA rewrite        :   0.30 ( 0%) usr   0.06 ( 2%) sys   0.26 ( 0%) wall   45801 kB ( 0%) ggc
 tree SSA incremental    :   0.37 ( 0%) usr   0.07 ( 2%) sys   0.54 ( 0%) wall   29452 kB ( 0%) ggc
 tree operand scan       :   0.31 ( 0%) usr   0.09 ( 2%) sys   0.51 ( 0%) wall  296103 kB ( 1%) ggc
 dominance frontiers     :   0.01 ( 0%) usr   0.00 ( 0%) sys   0.02 ( 0%) wall       0 kB ( 0%) ggc
 dominance computation   :   0.30 ( 0%) usr   0.04 ( 1%) sys   0.31 ( 0%) wall       0 kB ( 0%) ggc
 varconst                :   0.04 ( 0%) usr   0.01 ( 0%) sys   0.07 ( 0%) wall       0 kB ( 0%) ggc
 loop init               :   0.01 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall     546 kB ( 0%) ggc
 loop fini               :   0.12 ( 0%) usr   0.00 ( 0%) sys   0.14 ( 0%) wall       0 kB ( 0%) ggc
 unaccounted todo        :   1.20 ( 1%) usr   0.00 ( 0%) sys   1.15 ( 1%) wall       0 kB ( 0%) ggc
 TOTAL                 : 164.13             3.80           168.13           21166465 kB

Comments

Jan Hubicka March 24, 2015, 5:32 p.m. UTC | #1
> >From 1943aa293c1ff7622cf9090a834d7bd9dfaaf086 Mon Sep 17 00:00:00 2001
> From: mliska <mliska@suse.cz>
> Date: Mon, 23 Mar 2015 15:36:11 +0100
> Subject: [PATCH] IPA ICF: enhance hash value calculated in TU
> 
> gcc/ChangeLog:
> 
> 2015-03-23  Jan Hubicka  <hubicka@ucw.cz>
> 	    Martin Liska  <mliska@suse.cz>
> 
> 	* ipa-icf-gimple.h (return_with_result): Add missing colon to dump.
> 	* ipa-icf.c (sem_function::get_hash): Hash new declaration properties.
> 	(sem_item::add_type): New function.
> 	(sem_function::hash_stmt): Add TREE_TYPE of gimple_op.
> 	(sem_function::compare_polymorphic_p): Do not consider indirect calls.
> 	(sem_item_optimizer::update_hash_by_addr_refs): Add ODR type to hash.
> 	(sem_function::equals_wpa): Fix typo.
> 	* ipa-icf.h (sem_item::add_type): New function.
> 	(symbol_compare_hashmap_traits): Replace hashing of pointer with symbol
> 	order.

OK,
thanks!
Honza
diff mbox

Patch

From 1943aa293c1ff7622cf9090a834d7bd9dfaaf086 Mon Sep 17 00:00:00 2001
From: mliska <mliska@suse.cz>
Date: Mon, 23 Mar 2015 15:36:11 +0100
Subject: [PATCH] IPA ICF: enhance hash value calculated in TU

gcc/ChangeLog:

2015-03-23  Jan Hubicka  <hubicka@ucw.cz>
	    Martin Liska  <mliska@suse.cz>

	* ipa-icf-gimple.h (return_with_result): Add missing colon to dump.
	* ipa-icf.c (sem_function::get_hash): Hash new declaration properties.
	(sem_item::add_type): New function.
	(sem_function::hash_stmt): Add TREE_TYPE of gimple_op.
	(sem_function::compare_polymorphic_p): Do not consider indirect calls.
	(sem_item_optimizer::update_hash_by_addr_refs): Add ODR type to hash.
	(sem_function::equals_wpa): Fix typo.
	* ipa-icf.h (sem_item::add_type): New function.
	(symbol_compare_hashmap_traits): Replace hashing of pointer with symbol
	order.
---
 gcc/ipa-icf-gimple.h |   2 +-
 gcc/ipa-icf.c        | 160 ++++++++++++++++++++++++++++++++++++++++++++++-----
 gcc/ipa-icf.h        |  10 +++-
 3 files changed, 154 insertions(+), 18 deletions(-)

diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h
index 53a1bfe..6a9cbed 100644
--- a/gcc/ipa-icf-gimple.h
+++ b/gcc/ipa-icf-gimple.h
@@ -75,7 +75,7 @@  static inline bool
 return_with_result (bool result, const char *func, unsigned int line)
 {
   if (!result && dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "  false returned (%s:%u)\n", func, line);
+    fprintf (dump_file, "  false returned: (%s:%u)\n", func, line);
 
   return result;
 }
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 48a7d3d..ad868e1 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -128,6 +128,11 @@  using namespace ipa_icf_gimple;
 
 namespace ipa_icf {
 
+/* Initialization and computation of symtab node hash, there data
+   are propagated later on.  */
+
+static sem_item_optimizer *optimizer = NULL;
+
 /* Constructor.  */
 
 symbol_compare_collection::symbol_compare_collection (symtab_node *node)
@@ -328,6 +333,21 @@  sem_function::get_hash (void)
       for (unsigned i = 0; i < bb_sizes.length (); i++)
 	hstate.add_int (bb_sizes[i]);
 
+
+      /* Add common features of declaration itself.  */
+      if (DECL_FUNCTION_SPECIFIC_TARGET (decl))
+        hstate.add_wide_int
+	 (cl_target_option_hash
+	   (TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (decl))));
+      if (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
+	 (cl_optimization_hash
+	   (TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
+      hstate.add_flag (DECL_DISREGARD_INLINE_LIMITS (decl));
+      hstate.add_flag (DECL_DECLARED_INLINE_P (decl));
+      hstate.add_flag (DECL_IS_OPERATOR_NEW (decl));
+      hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
+      hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));
+
       hash = hstate.end ();
     }
 
@@ -430,10 +450,10 @@  sem_function::equals_wpa (sem_item *item,
     return return_false_with_msg ("no stack limit attributes are different");
 
   if (DECL_CXX_CONSTRUCTOR_P (decl) != DECL_CXX_CONSTRUCTOR_P (item->decl))
-    return return_false_with_msg ("DELC_CXX_CONSTRUCTOR mismatch");
+    return return_false_with_msg ("DECL_CXX_CONSTRUCTOR mismatch");
 
   if (DECL_CXX_DESTRUCTOR_P (decl) != DECL_CXX_DESTRUCTOR_P (item->decl))
-    return return_false_with_msg ("DELC_CXX_DESTRUCTOR mismatch");
+    return return_false_with_msg ("DECL_CXX_DESTRUCTOR mismatch");
 
   if (flags_from_decl_or_type (decl) != flags_from_decl_or_type (item->decl))
     return return_false_with_msg ("decl_or_type flags are different");
@@ -1283,6 +1303,80 @@  sem_item::add_expr (const_tree exp, inchash::hash &hstate)
     }
 }
 
+/* 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);
+  if (TYPE_CANONICAL (type))
+    type = TYPE_CANONICAL (type);
+
+  if (!AGGREGATE_TYPE_P (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))
+    {
+      hashval_t *val = optimizer->m_type_hash_cache.get (type);
+
+      if (!val)
+	{
+	  inchash::hash hstate2;
+	  unsigned nf;
+	  tree f;
+	  hashval_t hash;
+
+	  hstate2.add_int (RECORD_TYPE);
+	  gcc_assert (COMPLETE_TYPE_P (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_wide_int (hash);
+	  optimizer->m_type_hash_cache.put (type, hash);
+	}
+      else
+        hstate.add_wide_int (*val);
+    }
+}
+
 /* Improve accumulated hash for HSTATE based on a gimple statement STMT.  */
 
 void
@@ -1294,16 +1388,27 @@  sem_function::hash_stmt (gimple stmt, inchash::hash &hstate)
 
   switch (code)
     {
+    case GIMPLE_SWITCH:
+      add_expr (gimple_switch_index (as_a <gswitch *> (stmt)), hstate);
+      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);
+	  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;
 	}
       /* ... fall through ... */
@@ -1314,7 +1419,11 @@  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);
+	{
+	  add_expr (gimple_op (stmt, i), hstate);
+	  if (gimple_op (stmt, i))
+	    add_type (TREE_TYPE (gimple_op (stmt, i)), hstate);
+	}
     default:
       break;
     }
@@ -1328,14 +1437,13 @@  sem_function::compare_polymorphic_p (void)
 {
   struct cgraph_edge *e;
 
-  if (!opt_for_fn (decl, flag_devirtualize))
+  if (!opt_for_fn (get_node ()->decl, flag_devirtualize))
     return false;
-  if (get_node ()->indirect_calls != NULL
-      || m_compared_func->get_node ()->indirect_calls != NULL)
+  if (get_node ()->indirect_calls != NULL)
     return true;
   /* TODO: We can do simple propagation determining what calls may lead to
      a polymorphic call.  */
-  for (e = m_compared_func->get_node ()->callees; e; e = e->next_callee)
+  for (e = get_node ()->callees; e; e = e->next_callee)
     if (e->callee->definition
 	&& opt_for_fn (e->callee->decl, flag_devirtualize))
       return true;
@@ -2386,9 +2494,38 @@  sem_item_optimizer::add_item_to_class (congruence_class *cls, sem_item *item)
 void
 sem_item_optimizer::update_hash_by_addr_refs ()
 {
-  /* First, append to hash sensitive references.  */
+  /* First, append to hash sensitive references and class type if it need to
+     be matched for ODR.  */
   for (unsigned i = 0; i < m_items.length (); i++)
-    m_items[i]->update_hash_by_addr_refs (m_symtab_node_map);
+    {
+      m_items[i]->update_hash_by_addr_refs (m_symtab_node_map);
+      if (m_items[i]->type == FUNC)
+	{
+	  if (TREE_CODE (TREE_TYPE (m_items[i]->decl)) == METHOD_TYPE
+	      && contains_polymorphic_type_p
+		   (method_class_type (TREE_TYPE (m_items[i]->decl)))
+	      && (DECL_CXX_CONSTRUCTOR_P (m_items[i]->decl)
+		  || ((!flag_ipa_cp
+		       || ipa_is_param_used (
+			    IPA_NODE_REF
+			      (dyn_cast <cgraph_node *>(m_items[i]->node)), 0))
+		      && static_cast<sem_function *> (m_items[i])
+			   ->compare_polymorphic_p ())))
+	     {
+	        tree class_type
+		  = method_class_type (TREE_TYPE (m_items[i]->decl));
+		inchash::hash hstate (m_items[i]->hash);
+
+		if (TYPE_NAME (class_type)
+		     && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (class_type)))
+		  hstate.add_wide_int
+		    (IDENTIFIER_HASH_VALUE
+		       (DECL_ASSEMBLER_NAME (TYPE_NAME (class_type))));
+
+		m_items[i]->hash = hstate.end ();
+	     }
+	}
+    }
 
   /* Once all symbols have enhanced hash value, we can append
      hash values of symbols that are seen by IPA ICF and are
@@ -3123,11 +3260,6 @@  congruence_class::is_class_used (void)
   return false;
 }
 
-/* Initialization and computation of symtab node hash, there data
-   are propagated later on.  */
-
-static sem_item_optimizer *optimizer = NULL;
-
 /* Generate pass summary for IPA ICF pass.  */
 
 static void
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index cd21cac..7eb9f27 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -96,12 +96,12 @@  struct symbol_compare_hashmap_traits: default_hashmap_traits
     hstate.add_int (v->m_references.length ());
 
     for (unsigned i = 0; i < v->m_references.length (); i++)
-      hstate.add_ptr (v->m_references[i]->ultimate_alias_target ());
+      hstate.add_int (v->m_references[i]->ultimate_alias_target ()->order);
 
     hstate.add_int (v->m_interposables.length ());
 
     for (unsigned i = 0; i < v->m_interposables.length (); i++)
-      hstate.add_ptr (v->m_interposables[i]->ultimate_alias_target ());
+      hstate.add_int (v->m_interposables[i]->ultimate_alias_target ()->order);
 
     return hstate.end ();
   }
@@ -243,8 +243,10 @@  public:
 protected:
   /* Cached, once calculated hash for the item.  */
 
-  /* Accumulate to HSTATE a hash of constructor expression EXP.  */
+  /* 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);
 
   /* For a given symbol table nodes N1 and N2, we check that FUNCTION_DECLs
      point to a same function. Comparison can be skipped if IGNORED_NODES
@@ -505,6 +507,8 @@  public:
   congruence_class_group *get_group_by_hash (hashval_t hash,
       sem_item_type type);
 
+  /* Because types can be arbitrarily large, avoid quadratic bottleneck.  */
+  hash_map<const_tree, hashval_t> m_type_hash_cache;
 private:
 
   /* For each semantic item, append hash values of references.  */
-- 
2.1.4