Use func_checker::hash_operand for hashing of GIMPLE operands.
authorMartin Liska <mliska@suse.cz>
Thu, 14 Nov 2019 08:35:25 +0000 (09:35 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 14 Nov 2019 08:35:25 +0000 (08:35 +0000)
2019-11-14  Martin Liska  <mliska@suse.cz>

* ipa-icf-gimple.h (func_checker::func_checker): Add
default constructor.
* ipa-icf.c (sem_function::init): Make operand_equal_p
and hash_operand public.
(sem_item::add_expr): Remove.
(sem_item::add_type): Remove.
(sem_function::hash_stmt): Use m_checker for hashing
of GIMPLE statements.
(sem_function::parse): Init with checker.
(sem_variable::parse): Pass NULL as checker.
(sem_item_optimizer::parse_funcs_and_vars):
Pass checker to ::parse function.
(sem_item_optimizer::parse_nonsingleton_classes): Likewise.
(sem_variable::parse): New function.
(sem_variable::get_hash): Only return computed hash value.
(sem_variable::init): Initialize hash of a variable.
* ipa-icf.h: Remove add_expr, add_type and add func_checker
to couple of functions as a new argument.

From-SVN: r278207

gcc/ChangeLog
gcc/ipa-icf-gimple.h
gcc/ipa-icf.c
gcc/ipa-icf.h

index e6a3cb2393b2b1a509832be84199f1135197dca4..e60da6e03227b399a308042b05c16d5b5620baea 100644 (file)
@@ -1,3 +1,24 @@
+2019-11-14  Martin Liska  <mliska@suse.cz>
+
+       * ipa-icf-gimple.h (func_checker::func_checker): Add
+       default constructor.
+       * ipa-icf.c (sem_function::init): Make operand_equal_p
+       and hash_operand public.
+       (sem_item::add_expr): Remove.
+       (sem_item::add_type): Remove.
+       (sem_function::hash_stmt): Use m_checker for hashing
+       of GIMPLE statements.
+       (sem_function::parse): Init with checker.
+       (sem_variable::parse): Pass NULL as checker.
+       (sem_item_optimizer::parse_funcs_and_vars):
+       Pass checker to ::parse function.
+       (sem_item_optimizer::parse_nonsingleton_classes): Likewise.
+       (sem_variable::parse): New function.
+       (sem_variable::get_hash): Only return computed hash value.
+       (sem_variable::init): Initialize hash of a variable.
+       * ipa-icf.h: Remove add_expr, add_type and add func_checker
+       to couple of functions as a new argument.
+
 2019-11-14  Martin Liska  <mliska@suse.cz>
 
        * ipa-icf-gimple.c (func_checker::compare_gimple_call): Update
index 8213e4f2f4628c730ee32e9bfc072a6bad5bbaaa..b59d05fd605b1f887b69a1738dc761a9874a2247 100644 (file)
@@ -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);
index 53e387403c8e1bed5cd2c044fbb53ca8cf3ed582..8297eec93883a2bb1553f2641649a11cb0e824d5 100644 (file)
@@ -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;
       }
 
index 0b99a6120168930a967c158c0dce289fcb19c6ca..906002214d5d2b8dbbcf3e3781cfc06a0fac5888 100644 (file)
@@ -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.  */