/* Interprocedural Identical Code Folding pass
   Copyright (C) 2014-2017 Free Software Foundation, Inc.

   Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

/* Interprocedural Identical Code Folding for functions and
   read-only variables.

   The goal of this transformation is to discover functions and read-only
   variables which do have exactly the same semantics.

   In case of functions,
   we could either create a virtual clone or do a simple function wrapper
   that will call equivalent function. If the function is just locally visible,
   all function calls can be redirected. For read-only variables, we create
   aliases if possible.

   Optimization pass arranges as follows:
   1) All functions and read-only variables are visited and internal
      data structure, either sem_function or sem_variables is created.
   2) For every symbol from the previous step, VAR_DECL and FUNCTION_DECL are
      saved and matched to corresponding sem_items.
   3) These declaration are ignored for equality check and are solved
      by Value Numbering algorithm published by Alpert, Zadeck in 1992.
   4) We compute hash value for each symbol.
   5) Congruence classes are created based on hash value. If hash value are
      equal, equals function is called and symbols are deeply compared.
      We must prove that all SSA names, declarations and other items
      correspond.
   6) Value Numbering is executed for these classes. At the end of the process
      all symbol members in remaining classes can be merged.
   7) Merge operation creates alias in case of read-only variables. For
      callgraph node, we must decide if we can redirect local calls,
      create an alias or a thunk.

*/

#include "config.h"
#define INCLUDE_LIST
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "alloc-pool.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "coverage.h"
#include "gimple-pretty-print.h"
#include "data-streamer.h"
#include "fold-const.h"
#include "calls.h"
#include "varasm.h"
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "symbol-summary.h"
#include "ipa-prop.h"
#include "ipa-inline.h"
#include "except.h"
#include "attribs.h"
#include "print-tree.h"
#include "ipa-utils.h"
#include "ipa-icf-gimple.h"
#include "ipa-icf.h"
#include "stor-layout.h"
#include "dbgcnt.h"

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)
{
  m_references.create (0);
  m_interposables.create (0);

  ipa_ref *ref;

  if (is_a <varpool_node *> (node) && DECL_VIRTUAL_P (node->decl))
    return;

  for (unsigned i = 0; node->iterate_reference (i, ref); i++)
    {
      if (ref->address_matters_p ())
	m_references.safe_push (ref->referred);

      if (ref->referred->get_availability () <= AVAIL_INTERPOSABLE)
        {
	  if (ref->address_matters_p ())
	    m_references.safe_push (ref->referred);
	  else
	    m_interposables.safe_push (ref->referred);
	}
    }

  if (is_a <cgraph_node *> (node))
    {
      cgraph_node *cnode = dyn_cast <cgraph_node *> (node);

      for (cgraph_edge *e = cnode->callees; e; e = e->next_callee)
	if (e->callee->get_availability () <= AVAIL_INTERPOSABLE)
	  m_interposables.safe_push (e->callee);
    }
}

/* Constructor for key value pair, where _ITEM is key and _INDEX is a target.  */

sem_usage_pair::sem_usage_pair (sem_item *_item, unsigned int _index)
: item (_item), index (_index)
{
}

sem_item::sem_item (sem_item_type _type, bitmap_obstack *stack)
: type (_type), m_hash (-1), m_hash_set (false)
{
  setup (stack);
}

sem_item::sem_item (sem_item_type _type, symtab_node *_node,
		    bitmap_obstack *stack)
: type (_type), node (_node), m_hash (-1), m_hash_set (false)
{
  decl = node->decl;
  setup (stack);
}

/* Add reference to a semantic TARGET.  */

void
sem_item::add_reference (sem_item *target)
{
  refs.safe_push (target);
  unsigned index = refs.length ();
  target->usages.safe_push (new sem_usage_pair(this, index));
  bitmap_set_bit (target->usage_index_bitmap, index);
  refs_set.add (target->node);
}

/* Initialize internal data structures. Bitmap STACK is used for
   bitmap memory allocation process.  */

void
sem_item::setup (bitmap_obstack *stack)
{
  gcc_checking_assert (node);

  refs.create (0);
  tree_refs.create (0);
  usages.create (0);
  usage_index_bitmap = BITMAP_ALLOC (stack);
}

sem_item::~sem_item ()
{
  for (unsigned i = 0; i < usages.length (); i++)
    delete usages[i];

  refs.release ();
  tree_refs.release ();
  usages.release ();

  BITMAP_FREE (usage_index_bitmap);
}

/* Dump function for debugging purpose.  */

DEBUG_FUNCTION void
sem_item::dump (void)
{
  if (dump_file)
    {
      fprintf (dump_file, "[%s] %s (%u) (tree:%p)\n", type == FUNC ? "func" : "var",
	       node->name(), node->order, (void *) node->decl);
      fprintf (dump_file, "  hash: %u\n", get_hash ());
      fprintf (dump_file, "  references: ");

      for (unsigned i = 0; i < refs.length (); i++)
	fprintf (dump_file, "%s%s ", refs[i]->node->name (),
		 i < refs.length() - 1 ? "," : "");

      fprintf (dump_file, "\n");
    }
}

/* Return true if target supports alias symbols.  */

bool
sem_item::target_supports_symbol_aliases_p (void)
{
#if !defined (ASM_OUTPUT_DEF) || (!defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL))
  return false;
#else
  return true;
#endif
}

void sem_item::set_hash (hashval_t hash)
{
  m_hash = hash;
  m_hash_set = true;
}

/* Semantic function constructor that uses STACK as bitmap memory stack.  */

sem_function::sem_function (bitmap_obstack *stack)
: sem_item (FUNC, stack), m_checker (NULL), m_compared_func (NULL)
{
  bb_sizes.create (0);
  bb_sorted.create (0);
}

sem_function::sem_function (cgraph_node *node, bitmap_obstack *stack)
: sem_item (FUNC, node, stack), m_checker (NULL), m_compared_func (NULL)
{
  bb_sizes.create (0);
  bb_sorted.create (0);
}

sem_function::~sem_function ()
{
  for (unsigned i = 0; i < bb_sorted.length (); i++)
    delete (bb_sorted[i]);

  bb_sizes.release ();
  bb_sorted.release ();
}

/* Calculates hash value based on a BASIC_BLOCK.  */

hashval_t
sem_function::get_bb_hash (const sem_bb *basic_block)
{
  inchash::hash hstate;

  hstate.add_int (basic_block->nondbg_stmt_count);
  hstate.add_int (basic_block->edge_count);

  return hstate.end ();
}

/* References independent hash function.  */

hashval_t
sem_function::get_hash (void)
{
  if (!m_hash_set)
    {
      inchash::hash hstate;
      hstate.add_int (177454); /* Random number for function type.  */

      hstate.add_int (arg_count);
      hstate.add_int (cfg_checksum);
      hstate.add_int (gcode_hash);

      for (unsigned i = 0; i < bb_sorted.length (); i++)
	hstate.merge_hash (get_bb_hash (bb_sorted[i]));

      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))
	hstate.add_wide_int
	 (cl_optimization_hash
	   (TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))));
      hstate.add_flag (DECL_CXX_CONSTRUCTOR_P (decl));
      hstate.add_flag (DECL_CXX_DESTRUCTOR_P (decl));

      set_hash (hstate.end ());
    }

  return m_hash;
}

/* Return ture if A1 and A2 represent equivalent function attribute lists.
   Based on comp_type_attributes.  */

bool
sem_item::compare_attributes (const_tree a1, const_tree a2)
{
  const_tree a;
  if (a1 == a2)
    return true;
  for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
    {
      const struct attribute_spec *as;
      const_tree attr;

      as = lookup_attribute_spec (get_attribute_name (a));
      /* TODO: We can introduce as->affects_decl_identity
	 and as->affects_decl_reference_identity if attribute mismatch
	 gets a common reason to give up on merging.  It may not be worth
	 the effort.
	 For example returns_nonnull affects only references, while
	 optimize attribute can be ignored because it is already lowered
	 into flags representation and compared separately.  */
      if (!as)
        continue;

      attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
      if (!attr || !attribute_value_equal (a, attr))
        break;
    }
  if (!a)
    {
      for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
	{
	  const struct attribute_spec *as;

	  as = lookup_attribute_spec (get_attribute_name (a));
	  if (!as)
	    continue;

	  if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
	    break;
	  /* We don't need to compare trees again, as we did this
	     already in first loop.  */
	}
      if (!a)
        return true;
    }
  /* TODO: As in comp_type_attributes we may want to introduce target hook.  */
  return false;
}

/* Compare properties of symbols N1 and N2 that does not affect semantics of
   symbol itself but affects semantics of its references from USED_BY (which
   may be NULL if it is unknown).  If comparsion is false, symbols
   can still be merged but any symbols referring them can't.

   If ADDRESS is true, do extra checking needed for IPA_REF_ADDR.

   TODO: We can also split attributes to those that determine codegen of
   a function body/variable constructor itself and those that are used when
   referring to it.  */

bool
sem_item::compare_referenced_symbol_properties (symtab_node *used_by,
						symtab_node *n1,
						symtab_node *n2,
						bool address)
{
  if (is_a <cgraph_node *> (n1))
    {
      /* Inline properties matters: we do now want to merge uses of inline
	 function to uses of normal function because inline hint would be lost.
	 We however can merge inline function to noinline because the alias
	 will keep its DECL_DECLARED_INLINE flag.

	 Also ignore inline flag when optimizing for size or when function
	 is known to not be inlinable.

	 TODO: the optimize_size checks can also be assumed to be true if
	 unit has no !optimize_size functions. */

      if ((!used_by || address || !is_a <cgraph_node *> (used_by)
	   || !opt_for_fn (used_by->decl, optimize_size))
	  && !opt_for_fn (n1->decl, optimize_size)
	  && n1->get_availability () > AVAIL_INTERPOSABLE
	  && (!DECL_UNINLINABLE (n1->decl) || !DECL_UNINLINABLE (n2->decl)))
	{
	  if (DECL_DISREGARD_INLINE_LIMITS (n1->decl)
	      != DECL_DISREGARD_INLINE_LIMITS (n2->decl))
	    return return_false_with_msg
		     ("DECL_DISREGARD_INLINE_LIMITS are different");

	  if (DECL_DECLARED_INLINE_P (n1->decl)
	      != DECL_DECLARED_INLINE_P (n2->decl))
	    return return_false_with_msg ("inline attributes are different");
	}

      if (DECL_IS_OPERATOR_NEW (n1->decl)
	  != DECL_IS_OPERATOR_NEW (n2->decl))
	return return_false_with_msg ("operator new flags are different");
    }

  /* Merging two definitions with a reference to equivalent vtables, but
     belonging to a different type may result in ipa-polymorphic-call analysis
     giving a wrong answer about the dynamic type of instance.  */
  if (is_a <varpool_node *> (n1))
    {
      if ((DECL_VIRTUAL_P (n1->decl) || DECL_VIRTUAL_P (n2->decl))
	  && (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl)
	      || !types_must_be_same_for_odr (DECL_CONTEXT (n1->decl),
					      DECL_CONTEXT (n2->decl)))
	  && (!used_by || !is_a <cgraph_node *> (used_by) || address
	      || opt_for_fn (used_by->decl, flag_devirtualize)))
	return return_false_with_msg
		 ("references to virtual tables can not be merged");

      if (address && DECL_ALIGN (n1->decl) != DECL_ALIGN (n2->decl))
	return return_false_with_msg ("alignment mismatch");

      /* For functions we compare attributes in equals_wpa, because we do
	 not know what attributes may cause codegen differences, but for
	 variables just compare attributes for references - the codegen
	 for constructors is affected only by those attributes that we lower
	 to explicit representation (such as DECL_ALIGN or DECL_SECTION).  */
      if (!compare_attributes (DECL_ATTRIBUTES (n1->decl),
			       DECL_ATTRIBUTES (n2->decl)))
	return return_false_with_msg ("different var decl attributes");
      if (comp_type_attributes (TREE_TYPE (n1->decl),
				TREE_TYPE (n2->decl)) != 1)
	return return_false_with_msg ("different var type attributes");
    }

  /* When matching virtual tables, be sure to also match information
     relevant for polymorphic call analysis.  */
  if (used_by && is_a <varpool_node *> (used_by)
      && DECL_VIRTUAL_P (used_by->decl))
    {
      if (DECL_VIRTUAL_P (n1->decl) != DECL_VIRTUAL_P (n2->decl))
	return return_false_with_msg ("virtual flag mismatch");
      if (DECL_VIRTUAL_P (n1->decl) && is_a <cgraph_node *> (n1)
	  && (DECL_FINAL_P (n1->decl) != DECL_FINAL_P (n2->decl)))
	return return_false_with_msg ("final flag mismatch");
    }
  return true;
}

/* Hash properties that are compared by compare_referenced_symbol_properties. */

void
sem_item::hash_referenced_symbol_properties (symtab_node *ref,
					     inchash::hash &hstate,
					     bool address)
{
  if (is_a <cgraph_node *> (ref))
    {
      if ((type != FUNC || address || !opt_for_fn (decl, optimize_size))
	  && !opt_for_fn (ref->decl, optimize_size)
	  && !DECL_UNINLINABLE (ref->decl))
	{
	  hstate.add_flag (DECL_DISREGARD_INLINE_LIMITS (ref->decl));
	  hstate.add_flag (DECL_DECLARED_INLINE_P (ref->decl));
	}
      hstate.add_flag (DECL_IS_OPERATOR_NEW (ref->decl));
    }
  else if (is_a <varpool_node *> (ref))
    {
      hstate.add_flag (DECL_VIRTUAL_P (ref->decl));
      if (address)
	hstate.add_int (DECL_ALIGN (ref->decl));
    }
}


/* 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
   contains these nodes.  ADDRESS indicate if address is taken.  */

bool
sem_item::compare_symbol_references (
    hash_map <symtab_node *, sem_item *> &ignored_nodes,
    symtab_node *n1, symtab_node *n2, bool address)
{
  enum availability avail1, avail2;

  if (n1 == n2)
    return true;

  /* Never match variable and function.  */
  if (is_a <varpool_node *> (n1) != is_a <varpool_node *> (n2))
    return false;

  if (!compare_referenced_symbol_properties (node, n1, n2, address))
    return false;
  if (address && n1->equal_address_to (n2) == 1)
    return true;
  if (!address && n1->semantically_equivalent_p (n2))
    return true;

  n1 = n1->ultimate_alias_target (&avail1);
  n2 = n2->ultimate_alias_target (&avail2);

  if (avail1 > AVAIL_INTERPOSABLE && ignored_nodes.get (n1)
      && avail2 > AVAIL_INTERPOSABLE && ignored_nodes.get (n2))
    return true;

  return return_false_with_msg ("different references");
}

/* If cgraph edges E1 and E2 are indirect calls, verify that
   ECF flags are the same.  */

bool sem_function::compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2)
{
  if (e1->indirect_info && e2->indirect_info)
    {
      int e1_flags = e1->indirect_info->ecf_flags;
      int e2_flags = e2->indirect_info->ecf_flags;

      if (e1_flags != e2_flags)
	return return_false_with_msg ("ICF flags are different");
    }
  else if (e1->indirect_info || e2->indirect_info)
    return false;

  return true;
}

/* Return true if parameter I may be used.  */

bool
sem_function::param_used_p (unsigned int i)
{
  if (ipa_node_params_sum == NULL)
    return true;

  struct ipa_node_params *parms_info = IPA_NODE_REF (get_node ());

  if (vec_safe_length (parms_info->descriptors) <= i)
    return true;

  return ipa_is_param_used (IPA_NODE_REF (get_node ()), i);
}

/* Perform additional check needed to match types function parameters that are
   used.  Unlike for normal decls it matters if type is TYPE_RESTRICT and we
   make an assumption that REFERENCE_TYPE parameters are always non-NULL.  */

bool
sem_function::compatible_parm_types_p (tree parm1, tree parm2)
{
  /* Be sure that parameters are TBAA compatible.  */
  if (!func_checker::compatible_types_p (parm1, parm2))
    return return_false_with_msg ("parameter type is not compatible");

  if (POINTER_TYPE_P (parm1)
      && (TYPE_RESTRICT (parm1) != TYPE_RESTRICT (parm2)))
    return return_false_with_msg ("argument restrict flag mismatch");

  /* nonnull_arg_p implies non-zero range to REFERENCE types.  */
  if (POINTER_TYPE_P (parm1)
      && TREE_CODE (parm1) != TREE_CODE (parm2)
      && opt_for_fn (decl, flag_delete_null_pointer_checks))
    return return_false_with_msg ("pointer wrt reference mismatch");

  return true;
}

/* Fast equality function based on knowledge known in WPA.  */

bool
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 (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))
    return return_false_with_msg ("function personalities are different");

  if (DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl)
       != DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (item->decl))
    return return_false_with_msg ("intrument function entry exit "
				  "attributes are different");

  if (DECL_NO_LIMIT_STACK (decl) != DECL_NO_LIMIT_STACK (item->decl))
    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 ("DECL_CXX_CONSTRUCTOR mismatch");

  if (DECL_CXX_DESTRUCTOR_P (decl) != DECL_CXX_DESTRUCTOR_P (item->decl))
    return return_false_with_msg ("DECL_CXX_DESTRUCTOR mismatch");

  /* TODO: pure/const flags mostly matters only for references, except for
     the fact that codegen takes LOOPING flag as a hint that loops are
     finite.  We may arrange the code to always pick leader that has least
     specified flags and then this can go into comparing symbol properties.  */
  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");

  /* Do not match polymorphic constructors of different types.  They calls
     type memory location for ipa-polymorphic-call and we do not want
     it to get confused by wrong type.  */
  if (DECL_CXX_CONSTRUCTOR_P (decl)
      && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
    {
      if (TREE_CODE (TREE_TYPE (item->decl)) != METHOD_TYPE)
        return return_false_with_msg ("DECL_CXX_CONSTURCTOR type mismatch");
      else if (!func_checker::compatible_polymorphic_types_p
		 (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
		  TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
        return return_false_with_msg ("ctor polymorphic type mismatch");
    }

  /* Checking function TARGET and OPTIMIZATION flags.  */
  cl_target_option *tar1 = target_opts_for_fn (decl);
  cl_target_option *tar2 = target_opts_for_fn (item->decl);

  if (tar1 != tar2 && !cl_target_option_eq (tar1, tar2))
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "target flags difference");
	  cl_target_option_print_diff (dump_file, 2, tar1, tar2);
	}

      return return_false_with_msg ("Target flags are different");
    }

  cl_optimization *opt1 = opts_for_fn (decl);
  cl_optimization *opt2 = opts_for_fn (item->decl);

  if (opt1 != opt2 && memcmp (opt1, opt2, sizeof(cl_optimization)))
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "optimization flags difference");
	  cl_optimization_print_diff (dump_file, 2, opt1, opt2);
	}

      return return_false_with_msg ("optimization flags are different");
    }

  /* Result type checking.  */
  if (!func_checker::compatible_types_p
	 (TREE_TYPE (TREE_TYPE (decl)),
	  TREE_TYPE (TREE_TYPE (m_compared_func->decl))))
    return return_false_with_msg ("result types are different");

  /* Checking types of arguments.  */
  tree list1 = TYPE_ARG_TYPES (TREE_TYPE (decl)),
       list2 = TYPE_ARG_TYPES (TREE_TYPE (m_compared_func->decl));
  for (unsigned i = 0; list1 && list2;
       list1 = TREE_CHAIN (list1), list2 = TREE_CHAIN (list2), i++)
    {
      tree parm1 = TREE_VALUE (list1);
      tree parm2 = TREE_VALUE (list2);

      /* This guard is here for function pointer with attributes (pr59927.c).  */
      if (!parm1 || !parm2)
	return return_false_with_msg ("NULL argument type");

      /* Verify that types are compatible to ensure that both functions
	 have same calling conventions.  */
      if (!types_compatible_p (parm1, parm2))
	return return_false_with_msg ("parameter types are not compatible");

      if (!param_used_p (i))
	continue;

      /* Perform additional checks for used parameters.  */
      if (!compatible_parm_types_p (parm1, parm2))
	return false;
    }

  if (list1 || list2)
    return return_false_with_msg ("Mismatched number of parameters");

  if (node->num_references () != item->node->num_references ())
    return return_false_with_msg ("different number of references");

  /* Checking function attributes.
     This is quadratic in number of attributes  */
  if (comp_type_attributes (TREE_TYPE (decl),
			    TREE_TYPE (item->decl)) != 1)
    return return_false_with_msg ("different type attributes");
  if (!compare_attributes (DECL_ATTRIBUTES (decl),
			   DECL_ATTRIBUTES (item->decl)))
    return return_false_with_msg ("different decl attributes");

  /* The type of THIS pointer type memory location for
     ipa-polymorphic-call-analysis.  */
  if (opt_for_fn (decl, flag_devirtualize)
      && (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
          || TREE_CODE (TREE_TYPE (item->decl)) == METHOD_TYPE)
      && param_used_p (0)
      && compare_polymorphic_p ())
    {
      if (TREE_CODE (TREE_TYPE (decl)) != TREE_CODE (TREE_TYPE (item->decl)))
	return return_false_with_msg ("METHOD_TYPE and FUNCTION_TYPE mismatch");
      if (!func_checker::compatible_polymorphic_types_p
	   (TYPE_METHOD_BASETYPE (TREE_TYPE (decl)),
	    TYPE_METHOD_BASETYPE (TREE_TYPE (item->decl)), false))
	return return_false_with_msg ("THIS pointer ODR type mismatch");
    }

  ipa_ref *ref = NULL, *ref2 = NULL;
  for (unsigned i = 0; node->iterate_reference (i, ref); i++)
    {
      item->node->iterate_reference (i, ref2);

      if (ref->use != ref2->use)
	return return_false_with_msg ("reference use mismatch");

      if (!compare_symbol_references (ignored_nodes, ref->referred,
				      ref2->referred,
				      ref->address_matters_p ()))
	return false;
    }

  cgraph_edge *e1 = dyn_cast <cgraph_node *> (node)->callees;
  cgraph_edge *e2 = dyn_cast <cgraph_node *> (item->node)->callees;

  while (e1 && e2)
    {
      if (!compare_symbol_references (ignored_nodes, e1->callee,
				      e2->callee, false))
	return false;
      if (!compare_edge_flags (e1, e2))
	return false;

      e1 = e1->next_callee;
      e2 = e2->next_callee;
    }

  if (e1 || e2)
    return return_false_with_msg ("different number of calls");

  e1 = dyn_cast <cgraph_node *> (node)->indirect_calls;
  e2 = dyn_cast <cgraph_node *> (item->node)->indirect_calls;

  while (e1 && e2)
    {
      if (!compare_edge_flags (e1, e2))
	return false;

      e1 = e1->next_callee;
      e2 = e2->next_callee;
    }

  if (e1 || e2)
    return return_false_with_msg ("different number of indirect calls");

  return true;
}

/* Update hash by address sensitive references. We iterate over all
   sensitive references (address_matters_p) and we hash ultime alias
   target of these nodes, which can improve a semantic item hash.

   Also hash in referenced symbols properties.  This can be done at any time
   (as the properties should not change), but it is convenient to do it here
   while we walk the references anyway.  */

void
sem_item::update_hash_by_addr_refs (hash_map <symtab_node *,
				    sem_item *> &m_symtab_node_map)
{
  ipa_ref* ref;
  inchash::hash hstate (get_hash ());

  for (unsigned i = 0; node->iterate_reference (i, ref); i++)
    {
      hstate.add_int (ref->use);
      hash_referenced_symbol_properties (ref->referred, hstate,
					 ref->use == IPA_REF_ADDR);
      if (ref->address_matters_p () || !m_symtab_node_map.get (ref->referred))
	hstate.add_int (ref->referred->ultimate_alias_target ()->order);
    }

  if (is_a <cgraph_node *> (node))
    {
      for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callers; e;
	   e = e->next_caller)
	{
	  sem_item **result = m_symtab_node_map.get (e->callee);
	  hash_referenced_symbol_properties (e->callee, hstate, false);
	  if (!result)
	    hstate.add_int (e->callee->ultimate_alias_target ()->order);
	}
    }

  set_hash (hstate.end ());
}

/* Update hash by computed local hash values taken from different
   semantic items.
   TODO: stronger SCC based hashing would be desirable here.  */

void
sem_item::update_hash_by_local_refs (hash_map <symtab_node *,
				     sem_item *> &m_symtab_node_map)
{
  ipa_ref* ref;
  inchash::hash state (get_hash ());

  for (unsigned j = 0; node->iterate_reference (j, ref); j++)
    {
      sem_item **result = m_symtab_node_map.get (ref->referring);
      if (result)
	state.merge_hash ((*result)->get_hash ());
    }

  if (type == FUNC)
    {
      for (cgraph_edge *e = dyn_cast <cgraph_node *> (node)->callees; e;
	   e = e->next_callee)
	{
	  sem_item **result = m_symtab_node_map.get (e->caller);
	  if (result)
	    state.merge_hash ((*result)->get_hash ());
	}
    }

  global_hash = state.end ();
}

/* Returns true if the item equals to ITEM given as argument.  */

bool
sem_function::equals (sem_item *item,
		      hash_map <symtab_node *, sem_item *> &)
{
  gcc_assert (item->type == FUNC);
  bool eq = equals_private (item);

  if (m_checker != NULL)
    {
      delete m_checker;
      m_checker = NULL;
    }

  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file,
	     "Equals called for:%s:%s (%u:%u) (%s:%s) with result: %s\n\n",
	     xstrdup_for_dump (node->name()),
	     xstrdup_for_dump (item->node->name ()),
	     node->order,
	     item->node->order,
	     xstrdup_for_dump (node->asm_name ()),
	     xstrdup_for_dump (item->node->asm_name ()),
	     eq ? "true" : "false");

  return eq;
}

/* Processes function equality comparison.  */

bool
sem_function::equals_private (sem_item *item)
{
  if (item->type != FUNC)
    return false;

  basic_block bb1, bb2;
  edge e1, e2;
  edge_iterator ei1, ei2;
  bool result = true;
  tree arg1, arg2;

  m_compared_func = static_cast<sem_function *> (item);

  gcc_assert (decl != item->decl);

  if (bb_sorted.length () != m_compared_func->bb_sorted.length ()
      || edge_count != m_compared_func->edge_count
      || cfg_checksum != m_compared_func->cfg_checksum)
    return return_false ();

  m_checker = new func_checker (decl, m_compared_func->decl,
				compare_polymorphic_p (),
				false,
				&refs_set,
				&m_compared_func->refs_set);
  arg1 = DECL_ARGUMENTS (decl);
  arg2 = DECL_ARGUMENTS (m_compared_func->decl);
  for (unsigned i = 0;
       arg1 && arg2; arg1 = DECL_CHAIN (arg1), arg2 = DECL_CHAIN (arg2), i++)
    {
      if (!types_compatible_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
	return return_false_with_msg ("argument types are not compatible");
      if (!param_used_p (i))
	continue;
      /* Perform additional checks for used parameters.  */
      if (!compatible_parm_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
	return false;
      if (!m_checker->compare_decl (arg1, arg2))
        return return_false ();
    }
  if (arg1 || arg2)
    return return_false_with_msg ("Mismatched number of arguments");

  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)
    {
      m_checker->parse_labels (bb_sorted[i]);
      m_checker->parse_labels (m_compared_func->bb_sorted[i]);
    }

  /* Checking all basic blocks.  */
  for (unsigned i = 0; i < bb_sorted.length (); ++i)
    if(!m_checker->compare_bb (bb_sorted[i], m_compared_func->bb_sorted[i]))
      return return_false();

  dump_message ("All BBs are equal\n");

  auto_vec <int> bb_dict;

  /* Basic block edges check.  */
  for (unsigned i = 0; i < bb_sorted.length (); ++i)
    {
      bb1 = bb_sorted[i]->bb;
      bb2 = m_compared_func->bb_sorted[i]->bb;

      ei2 = ei_start (bb2->preds);

      for (ei1 = ei_start (bb1->preds); ei_cond (ei1, &e1); ei_next (&ei1))
	{
	  ei_cond (ei2, &e2);

	  if (e1->flags != e2->flags)
	    return return_false_with_msg ("flags comparison returns false");

	  if (!bb_dict_test (&bb_dict, e1->src->index, e2->src->index))
	    return return_false_with_msg ("edge comparison returns false");

	  if (!bb_dict_test (&bb_dict, e1->dest->index, e2->dest->index))
	    return return_false_with_msg ("BB comparison returns false");

	  if (!m_checker->compare_edge (e1, e2))
	    return return_false_with_msg ("edge comparison returns false");

	  ei_next (&ei2);
	}
    }

  /* Basic block PHI nodes comparison.  */
  for (unsigned i = 0; i < bb_sorted.length (); i++)
    if (!compare_phi_node (bb_sorted[i]->bb, m_compared_func->bb_sorted[i]->bb))
      return return_false_with_msg ("PHI node comparison returns false");

  return result;
}

/* Set LOCAL_P of NODE to true if DATA is non-NULL.
   Helper for call_for_symbol_thunks_and_aliases.  */

static bool
set_local (cgraph_node *node, void *data)
{
  node->local.local = data != NULL;
  return false;
}

/* TREE_ADDRESSABLE of NODE to true.
   Helper for call_for_symbol_thunks_and_aliases.  */

static bool
set_addressable (varpool_node *node, void *)
{
  TREE_ADDRESSABLE (node->decl) = 1;
  return false;
}

/* Clear DECL_RTL of NODE. 
   Helper for call_for_symbol_thunks_and_aliases.  */

static bool
clear_decl_rtl (symtab_node *node, void *)
{
  SET_DECL_RTL (node->decl, NULL);
  return false;
}

/* Redirect all callers of N and its aliases to TO.  Remove aliases if
   possible.  Return number of redirections made.  */

static int
redirect_all_callers (cgraph_node *n, cgraph_node *to)
{
  int nredirected = 0;
  ipa_ref *ref;
  cgraph_edge *e = n->callers;

  while (e)
    {
      /* Redirecting thunks to interposable symbols or symbols in other sections
	 may not be supported by target output code.  Play safe for now and
	 punt on redirection.  */
      if (!e->caller->thunk.thunk_p)
	{
	  struct cgraph_edge *nexte = e->next_caller;
          e->redirect_callee (to);
	  e = nexte;
          nredirected++;
	}
      else
	e = e->next_callee;
    }
  for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
    {
      bool removed = false;
      cgraph_node *n_alias = dyn_cast <cgraph_node *> (ref->referring);

      if ((DECL_COMDAT_GROUP (n->decl)
	   && (DECL_COMDAT_GROUP (n->decl)
	       == DECL_COMDAT_GROUP (n_alias->decl)))
	  || (n_alias->get_availability () > AVAIL_INTERPOSABLE
	      && n->get_availability () > AVAIL_INTERPOSABLE))
	{
	  nredirected += redirect_all_callers (n_alias, to);
	  if (n_alias->can_remove_if_no_direct_calls_p ()
	      && !n_alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
							NULL, true)
	      && !n_alias->has_aliases_p ())
	    n_alias->remove ();
	}
      if (!removed)
	i++;
    }
  return nredirected;
}

/* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
   be applied.  */

bool
sem_function::merge (sem_item *alias_item)
{
  gcc_assert (alias_item->type == FUNC);

  sem_function *alias_func = static_cast<sem_function *> (alias_item);

  cgraph_node *original = get_node ();
  cgraph_node *local_original = NULL;
  cgraph_node *alias = alias_func->get_node ();

  bool create_wrapper = false;
  bool create_alias = false;
  bool redirect_callers = false;
  bool remove = false;

  bool original_discardable = false;
  bool original_discarded = false;

  bool original_address_matters = original->address_matters_p ();
  bool alias_address_matters = alias->address_matters_p ();

  if (DECL_EXTERNAL (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; alias is external.\n\n");
      return false;
    }

  if (DECL_NO_INLINE_WARNING_P (original->decl)
      != DECL_NO_INLINE_WARNING_P (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; "
		 "DECL_NO_INLINE_WARNING mismatch.\n\n");
      return false;
    }

  /* Do not attempt to mix functions from different user sections;
     we do not know what user intends with those.  */
  if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
       || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
      && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; "
		 "original and alias are in different sections.\n\n");
      return false;
    }

  if (!original->in_same_comdat_group_p (alias)
      || original->comdat_local_p ())
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; alias nor wrapper cannot be created; "
		 "across comdat group boundary\n\n");

      return false;
    }

  /* See if original is in a section that can be discarded if the main
     symbol is not used.  */

  if (original->can_be_discarded_p ())
    original_discardable = true;
  /* Also consider case where we have resolution info and we know that
     original's definition is not going to be used.  In this case we can not
     create alias to original.  */
  if (node->resolution != LDPR_UNKNOWN
      && !decl_binds_to_current_def_p (node->decl))
    original_discardable = original_discarded = true;

  /* Creating a symtab alias is the optimal way to merge.
     It however can not be used in the following cases:

     1) if ORIGINAL and ALIAS may be possibly compared for address equality.
     2) if ORIGINAL is in a section that may be discarded by linker or if
	it is an external functions where we can not create an alias
	(ORIGINAL_DISCARDABLE)
     3) if target do not support symbol aliases.
     4) original and alias lie in different comdat groups.

     If we can not produce alias, we will turn ALIAS into WRAPPER of ORIGINAL
     and/or redirect all callers from ALIAS to ORIGINAL.  */
  if ((original_address_matters && alias_address_matters)
      || (original_discardable
	  && (!DECL_COMDAT_GROUP (alias->decl)
	      || (DECL_COMDAT_GROUP (alias->decl)
		  != DECL_COMDAT_GROUP (original->decl))))
      || original_discarded
      || !sem_item::target_supports_symbol_aliases_p ()
      || DECL_COMDAT_GROUP (alias->decl) != DECL_COMDAT_GROUP (original->decl))
    {
      /* First see if we can produce wrapper.  */

      /* Symbol properties that matter for references must be preserved.
	 TODO: We can produce wrapper, but we need to produce alias of ORIGINAL
	 with proper properties.  */
      if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
							   alias->address_taken))
        {
	  if (dump_file)
	    fprintf (dump_file,
		     "Wrapper cannot be created because referenced symbol "
		     "properties mismatch\n");
        }
      /* Do not turn function in one comdat group into wrapper to another
	 comdat group. Other compiler producing the body of the
	 another comdat group may make opossite decision and with unfortunate
	 linker choices this may close a loop.  */
      else if (DECL_COMDAT_GROUP (original->decl)
	       && DECL_COMDAT_GROUP (alias->decl)
	       && (DECL_COMDAT_GROUP (alias->decl)
		   != DECL_COMDAT_GROUP (original->decl)))
	{
	  if (dump_file)
	    fprintf (dump_file,
		     "Wrapper cannot be created because of COMDAT\n");
	}
      else if (DECL_STATIC_CHAIN (alias->decl)
	       || DECL_STATIC_CHAIN (original->decl))
        {
	  if (dump_file)
	    fprintf (dump_file,
		     "Cannot create wrapper of nested function.\n");
        }
      /* TODO: We can also deal with variadic functions never calling
	 VA_START.  */
      else if (stdarg_p (TREE_TYPE (alias->decl)))
	{
	  if (dump_file)
	    fprintf (dump_file,
		     "can not create wrapper of stdarg function.\n");
	}
      else if (inline_summaries
	       && inline_summaries->get (alias)->self_size <= 2)
	{
	  if (dump_file)
	    fprintf (dump_file, "Wrapper creation is not "
		     "profitable (function is too small).\n");
	}
      /* If user paid attention to mark function noinline, assume it is
	 somewhat special and do not try to turn it into a wrapper that can
	 not be undone by inliner.  */
      else if (lookup_attribute ("noinline", DECL_ATTRIBUTES (alias->decl)))
	{
	  if (dump_file)
	    fprintf (dump_file, "Wrappers are not created for noinline.\n");
	}
      else
        create_wrapper = true;

      /* We can redirect local calls in the case both alias and orignal
	 are not interposable.  */
      redirect_callers
	= alias->get_availability () > AVAIL_INTERPOSABLE
	  && original->get_availability () > AVAIL_INTERPOSABLE
	  && !alias->instrumented_version;
      /* TODO: We can redirect, but we need to produce alias of ORIGINAL
	 with proper properties.  */
      if (!sem_item::compare_referenced_symbol_properties (NULL, original, alias,
							   alias->address_taken))
	redirect_callers = false;

      if (!redirect_callers && !create_wrapper)
	{
	  if (dump_file)
	    fprintf (dump_file, "Not unifying; can not redirect callers nor "
		     "produce wrapper\n\n");
	  return false;
	}

      /* Work out the symbol the wrapper should call.
	 If ORIGINAL is interposable, we need to call a local alias.
	 Also produce local alias (if possible) as an optimization.

	 Local aliases can not be created inside comdat groups because that
	 prevents inlining.  */
      if (!original_discardable && !original->get_comdat_group ())
	{
	  local_original
	    = dyn_cast <cgraph_node *> (original->noninterposable_alias ());
	  if (!local_original
	      && original->get_availability () > AVAIL_INTERPOSABLE)
	    local_original = original;
	}
      /* If we can not use local alias, fallback to the original
	 when possible.  */
      else if (original->get_availability () > AVAIL_INTERPOSABLE)
	local_original = original;

      /* If original is COMDAT local, we can not really redirect calls outside
	 of its comdat group to it.  */
      if (original->comdat_local_p ())
        redirect_callers = false;
      if (!local_original)
	{
	  if (dump_file)
	    fprintf (dump_file, "Not unifying; "
		     "can not produce local alias.\n\n");
	  return false;
	}

      if (!redirect_callers && !create_wrapper)
	{
	  if (dump_file)
	    fprintf (dump_file, "Not unifying; "
		     "can not redirect callers nor produce a wrapper\n\n");
	  return false;
	}
      if (!create_wrapper
	  && !alias->call_for_symbol_and_aliases (cgraph_node::has_thunk_p,
						  NULL, true)
	  && !alias->can_remove_if_no_direct_calls_p ())
	{
	  if (dump_file)
	    fprintf (dump_file, "Not unifying; can not make wrapper and "
		     "function has other uses than direct calls\n\n");
	  return false;
	}
    }
  else
    create_alias = true;

  if (redirect_callers)
    {
      int nredirected = redirect_all_callers (alias, local_original);

      if (nredirected)
	{
	  alias->icf_merged = true;
	  local_original->icf_merged = true;

	  if (dump_file && nredirected)
	    fprintf (dump_file, "%i local calls have been "
		     "redirected.\n", nredirected);
	}

      /* If all callers was redirected, do not produce wrapper.  */
      if (alias->can_remove_if_no_direct_calls_p ()
	  && !DECL_VIRTUAL_P (alias->decl)
	  && !alias->has_aliases_p ())
	{
	  create_wrapper = false;
	  remove = true;
	}
      gcc_assert (!create_alias);
    }
  else if (create_alias)
    {
      alias->icf_merged = true;

      /* Remove the function's body.  */
      ipa_merge_profiles (original, alias);
      alias->release_body (true);
      alias->reset ();
      /* Notice global symbol possibly produced RTL.  */
      ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
							   NULL, true);

      /* Create the alias.  */
      cgraph_node::create_alias (alias_func->decl, decl);
      alias->resolve_alias (original);

      original->call_for_symbol_thunks_and_aliases
	 (set_local, (void *)(size_t) original->local_p (), true);

      if (dump_file)
	fprintf (dump_file, "Unified; Function alias has been created.\n\n");
    }
  if (create_wrapper)
    {
      gcc_assert (!create_alias);
      alias->icf_merged = true;
      local_original->icf_merged = true;

      ipa_merge_profiles (local_original, alias, true);
      alias->create_wrapper (local_original);

      if (dump_file)
	fprintf (dump_file, "Unified; Wrapper has been created.\n\n");
    }

  /* It's possible that redirection can hit thunks that block
     redirection opportunities.  */
  gcc_assert (alias->icf_merged || remove || redirect_callers);
  original->icf_merged = true;

  /* We use merged flag to track cases where COMDAT function is known to be
     compatible its callers.  If we merged in non-COMDAT, we need to give up
     on this optimization.  */
  if (original->merged_comdat && !alias->merged_comdat)
    {
      if (dump_file)
	fprintf (dump_file, "Dropping merged_comdat flag.\n\n");
      if (local_original)
        local_original->merged_comdat = false;
      original->merged_comdat = false;
    }

  if (remove)
    {
      ipa_merge_profiles (original, alias);
      alias->release_body ();
      alias->reset ();
      alias->body_removed = true;
      alias->icf_merged = true;
      if (dump_file)
	fprintf (dump_file, "Unified; Function body was removed.\n");
    }

  return true;
}

/* Semantic item initialization function.  */

void
sem_function::init (void)
{
  if (in_lto_p)
    get_node ()->get_untransformed_body ();

  tree fndecl = node->decl;
  function *func = DECL_STRUCT_FUNCTION (fndecl);

  gcc_assert (func);
  gcc_assert (SSANAMES (func));

  ssa_names_size = SSANAMES (func)->length ();
  node = node;

  decl = fndecl;
  region_tree = func->eh->region_tree;

  /* iterating all function arguments.  */
  arg_count = count_formal_params (fndecl);

  edge_count = n_edges_for_fn (func);
  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
  if (!cnode->thunk.thunk_p)
    {
      cfg_checksum = coverage_compute_cfg_checksum (func);

      inchash::hash hstate;

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

	for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
	     gsi_next (&gsi))
	  {
	    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);

	/* 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);
      }
    }
  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 ();
    }
}

/* 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_wide_int (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_wide_int (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_wide_int (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))
    {
      gcc_checking_assert (COMPLETE_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
sem_function::hash_stmt (gimple *stmt, inchash::hash &hstate)
{
  enum gimple_code code = gimple_code (stmt);

  hstate.add_int (code);

  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 */
    case GIMPLE_CALL:
    case GIMPLE_ASM:
    case GIMPLE_COND:
    case GIMPLE_GOTO:
    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);
	}
    default:
      break;
    }
}


/* Return true if polymorphic comparison must be processed.  */

bool
sem_function::compare_polymorphic_p (void)
{
  struct cgraph_edge *e;

  if (!opt_for_fn (get_node ()->decl, flag_devirtualize))
    return false;
  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 = get_node ()->callees; e; e = e->next_callee)
    if (e->callee->definition
	&& opt_for_fn (e->callee->decl, flag_devirtualize))
      return true;
  return false;
}

/* For a given call graph NODE, the function constructs new
   semantic function item.  */

sem_function *
sem_function::parse (cgraph_node *node, bitmap_obstack *stack)
{
  tree fndecl = node->decl;
  function *func = DECL_STRUCT_FUNCTION (fndecl);

  if (!func || (!node->has_gimple_body_p () && !node->thunk.thunk_p))
    return NULL;

  if (lookup_attribute_by_prefix ("omp ", DECL_ATTRIBUTES (node->decl)) != NULL)
    return NULL;

  if (lookup_attribute_by_prefix ("oacc ",
				  DECL_ATTRIBUTES (node->decl)) != NULL)
    return NULL;

  /* PR ipa/70306.  */
  if (DECL_STATIC_CONSTRUCTOR (node->decl)
      || DECL_STATIC_DESTRUCTOR (node->decl))
    return NULL;

  sem_function *f = new sem_function (node, stack);

  f->init ();

  return f;
}

/* For given basic blocks BB1 and BB2 (from functions FUNC1 and FUNC),
   return true if phi nodes are semantically equivalent in these blocks .  */

bool
sem_function::compare_phi_node (basic_block bb1, basic_block bb2)
{
  gphi_iterator si1, si2;
  gphi *phi1, *phi2;
  unsigned size1, size2, i;
  tree t1, t2;
  edge e1, e2;

  gcc_assert (bb1 != NULL);
  gcc_assert (bb2 != NULL);

  si2 = gsi_start_phis (bb2);
  for (si1 = gsi_start_phis (bb1); !gsi_end_p (si1);
       gsi_next (&si1))
    {
      gsi_next_nonvirtual_phi (&si1);
      gsi_next_nonvirtual_phi (&si2);

      if (gsi_end_p (si1) && gsi_end_p (si2))
	break;

      if (gsi_end_p (si1) || gsi_end_p (si2))
	return return_false();

      phi1 = si1.phi ();
      phi2 = si2.phi ();

      tree phi_result1 = gimple_phi_result (phi1);
      tree phi_result2 = gimple_phi_result (phi2);

      if (!m_checker->compare_operand (phi_result1, phi_result2))
	return return_false_with_msg ("PHI results are different");

      size1 = gimple_phi_num_args (phi1);
      size2 = gimple_phi_num_args (phi2);

      if (size1 != size2)
	return return_false ();

      for (i = 0; i < size1; ++i)
	{
	  t1 = gimple_phi_arg (phi1, i)->def;
	  t2 = gimple_phi_arg (phi2, i)->def;

	  if (!m_checker->compare_operand (t1, t2))
	    return return_false ();

	  e1 = gimple_phi_arg_edge (phi1, i);
	  e2 = gimple_phi_arg_edge (phi2, i);

	  if (!m_checker->compare_edge (e1, e2))
	    return return_false ();
	}

      gsi_next (&si2);
    }

  return true;
}

/* Returns true if tree T can be compared as a handled component.  */

bool
sem_function::icf_handled_component_p (tree t)
{
  tree_code tc = TREE_CODE (t);

  return (handled_component_p (t)
	  || tc == ADDR_EXPR || tc == MEM_REF || tc == OBJ_TYPE_REF);
}

/* Basic blocks dictionary BB_DICT returns true if SOURCE index BB
   corresponds to TARGET.  */

bool
sem_function::bb_dict_test (vec<int> *bb_dict, int source, int target)
{
  source++;
  target++;

  if (bb_dict->length () <= (unsigned)source)
    bb_dict->safe_grow_cleared (source + 1);

  if ((*bb_dict)[source] == 0)
    {
      (*bb_dict)[source] = target;
      return true;
    }
  else
    return (*bb_dict)[source] == target;
}

sem_variable::sem_variable (bitmap_obstack *stack): sem_item (VAR, stack)
{
}

sem_variable::sem_variable (varpool_node *node, bitmap_obstack *stack)
: sem_item (VAR, node, stack)
{
  gcc_checking_assert (node);
  gcc_checking_assert (get_node ());
}

/* Fast equality function based on knowledge known in WPA.  */

bool
sem_variable::equals_wpa (sem_item *item,
			  hash_map <symtab_node *, sem_item *> &ignored_nodes)
{
  gcc_assert (item->type == VAR);

  if (node->num_references () != item->node->num_references ())
    return return_false_with_msg ("different number of references");

  if (DECL_TLS_MODEL (decl) || DECL_TLS_MODEL (item->decl))
    return return_false_with_msg ("TLS model");

  /* DECL_ALIGN is safe to merge, because we will always chose the largest
     alignment out of all aliases.  */

  if (DECL_VIRTUAL_P (decl) != DECL_VIRTUAL_P (item->decl))
    return return_false_with_msg ("Virtual flag mismatch");

  if (DECL_SIZE (decl) != DECL_SIZE (item->decl)
      && ((!DECL_SIZE (decl) || !DECL_SIZE (item->decl))
	  || !operand_equal_p (DECL_SIZE (decl),
			       DECL_SIZE (item->decl), OEP_ONLY_CONST)))
    return return_false_with_msg ("size mismatch");

  /* Do not attempt to mix data from different user sections;
     we do not know what user intends with those.  */
  if (((DECL_SECTION_NAME (decl) && !node->implicit_section)
       || (DECL_SECTION_NAME (item->decl) && !item->node->implicit_section))
      && DECL_SECTION_NAME (decl) != DECL_SECTION_NAME (item->decl))
    return return_false_with_msg ("user section mismatch");

  if (DECL_IN_TEXT_SECTION (decl) != DECL_IN_TEXT_SECTION (item->decl))
    return return_false_with_msg ("text section");

  ipa_ref *ref = NULL, *ref2 = NULL;
  for (unsigned i = 0; node->iterate_reference (i, ref); i++)
    {
      item->node->iterate_reference (i, ref2);

      if (ref->use != ref2->use)
	return return_false_with_msg ("reference use mismatch");

      if (!compare_symbol_references (ignored_nodes,
				      ref->referred, ref2->referred,
				      ref->address_matters_p ()))
	return false;
    }

  return true;
}

/* Returns true if the item equals to ITEM given as argument.  */

bool
sem_variable::equals (sem_item *item,
		      hash_map <symtab_node *, sem_item *> &)
{
  gcc_assert (item->type == VAR);
  bool ret;

  if (DECL_INITIAL (decl) == error_mark_node && in_lto_p)
    dyn_cast <varpool_node *>(node)->get_constructor ();
  if (DECL_INITIAL (item->decl) == error_mark_node && in_lto_p)
    dyn_cast <varpool_node *>(item->node)->get_constructor ();

  /* As seen in PR ipa/65303 we have to compare variables types.  */
  if (!func_checker::compatible_types_p (TREE_TYPE (decl),
					 TREE_TYPE (item->decl)))
    return return_false_with_msg ("variables types are different");

  ret = sem_variable::equals (DECL_INITIAL (decl),
			      DECL_INITIAL (item->node->decl));
  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file,
	     "Equals called for vars:%s:%s (%u:%u) (%s:%s) with result: %s\n\n",
	     xstrdup_for_dump (node->name()),
	     xstrdup_for_dump (item->node->name ()),
	     node->order, item->node->order,
	     xstrdup_for_dump (node->asm_name ()),
	     xstrdup_for_dump (item->node->asm_name ()), ret ? "true" : "false");

  return ret;
}

/* Compares trees T1 and T2 for semantic equality.  */

bool
sem_variable::equals (tree t1, tree t2)
{
  if (!t1 || !t2)
    return return_with_debug (t1 == t2);
  if (t1 == t2)
    return true;
  tree_code tc1 = TREE_CODE (t1);
  tree_code tc2 = TREE_CODE (t2);

  if (tc1 != tc2)
    return return_false_with_msg ("TREE_CODE mismatch");

  switch (tc1)
    {
    case CONSTRUCTOR:
      {
	vec<constructor_elt, va_gc> *v1, *v2;
	unsigned HOST_WIDE_INT idx;

	enum tree_code typecode = TREE_CODE (TREE_TYPE (t1));
	if (typecode != TREE_CODE (TREE_TYPE (t2)))
	  return return_false_with_msg ("constructor type mismatch");

	if (typecode == ARRAY_TYPE)
	  {
	    HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
	    /* For arrays, check that the sizes all match.  */
	    if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
		|| size_1 == -1
		|| size_1 != int_size_in_bytes (TREE_TYPE (t2)))
	      return return_false_with_msg ("constructor array size mismatch");
	  }
	else if (!func_checker::compatible_types_p (TREE_TYPE (t1),
						    TREE_TYPE (t2)))
	  return return_false_with_msg ("constructor type incompatible");

	v1 = CONSTRUCTOR_ELTS (t1);
	v2 = CONSTRUCTOR_ELTS (t2);
	if (vec_safe_length (v1) != vec_safe_length (v2))
	  return return_false_with_msg ("constructor number of elts mismatch");

	for (idx = 0; idx < vec_safe_length (v1); ++idx)
	  {
	    constructor_elt *c1 = &(*v1)[idx];
	    constructor_elt *c2 = &(*v2)[idx];

	    /* Check that each value is the same...  */
	    if (!sem_variable::equals (c1->value, c2->value))
	      return false;
	    /* ... and that they apply to the same fields!  */
	    if (!sem_variable::equals (c1->index, c2->index))
	      return false;
	  }
	return true;
      }
    case MEM_REF:
      {
	tree x1 = TREE_OPERAND (t1, 0);
	tree x2 = TREE_OPERAND (t2, 0);
	tree y1 = TREE_OPERAND (t1, 1);
	tree y2 = TREE_OPERAND (t2, 1);

	if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2)))
	  return return_false ();

	/* Type of the offset on MEM_REF does not matter.  */
	return return_with_debug (sem_variable::equals (x1, x2)
			          && wi::to_offset  (y1)
				     == wi::to_offset  (y2));
      }
    case ADDR_EXPR:
    case FDESC_EXPR:
      {
	tree op1 = TREE_OPERAND (t1, 0);
	tree op2 = TREE_OPERAND (t2, 0);
	return sem_variable::equals (op1, op2);
      }
    /* References to other vars/decls are compared using ipa-ref.  */
    case FUNCTION_DECL:
    case VAR_DECL:
      if (decl_in_symtab_p (t1) && decl_in_symtab_p (t2))
	return true;
      return return_false_with_msg ("Declaration mismatch");
    case CONST_DECL:
      /* TODO: We can check CONST_DECL by its DECL_INITIAL, but for that we
	 need to process its VAR/FUNCTION references without relying on ipa-ref
	 compare.  */
    case FIELD_DECL:
    case LABEL_DECL:
      return return_false_with_msg ("Declaration mismatch");
    case INTEGER_CST:
      /* Integer constants are the same only if the same width of type.  */
      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
        return return_false_with_msg ("INTEGER_CST precision mismatch");
      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
        return return_false_with_msg ("INTEGER_CST mode mismatch");
      return return_with_debug (tree_int_cst_equal (t1, t2));
    case STRING_CST:
      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
        return return_false_with_msg ("STRING_CST mode mismatch");
      if (TREE_STRING_LENGTH (t1) != TREE_STRING_LENGTH (t2))
	return return_false_with_msg ("STRING_CST length mismatch");
      if (memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
		    TREE_STRING_LENGTH (t1)))
	return return_false_with_msg ("STRING_CST mismatch");
      return true;
    case FIXED_CST:
      /* Fixed constants are the same only if the same width of type.  */
      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
        return return_false_with_msg ("FIXED_CST precision mismatch");

      return return_with_debug (FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
							TREE_FIXED_CST (t2)));
    case COMPLEX_CST:
      return (sem_variable::equals (TREE_REALPART (t1), TREE_REALPART (t2))
	      && sem_variable::equals (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
    case REAL_CST:
      /* Real constants are the same only if the same width of type.  */
      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
        return return_false_with_msg ("REAL_CST precision mismatch");
      return return_with_debug (real_identical (&TREE_REAL_CST (t1),
						&TREE_REAL_CST (t2)));
    case VECTOR_CST:
      {
	unsigned i;

        if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))
          return return_false_with_msg ("VECTOR_CST nelts mismatch");

	for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
	  if (!sem_variable::equals (VECTOR_CST_ELT (t1, i),
				     VECTOR_CST_ELT (t2, i)))
	    return 0;

	return 1;
      }
    case ARRAY_REF:
    case ARRAY_RANGE_REF:
      {
	tree x1 = TREE_OPERAND (t1, 0);
	tree x2 = TREE_OPERAND (t2, 0);
	tree y1 = TREE_OPERAND (t1, 1);
	tree y2 = TREE_OPERAND (t2, 1);

	if (!sem_variable::equals (x1, x2) || !sem_variable::equals (y1, y2))
	  return false;
	if (!sem_variable::equals (array_ref_low_bound (t1),
				   array_ref_low_bound (t2)))
	  return false;
        if (!sem_variable::equals (array_ref_element_size (t1),
			           array_ref_element_size (t2)))
	  return false;
	return true;
      }
     
    case COMPONENT_REF:
    case POINTER_PLUS_EXPR:
    case PLUS_EXPR:
    case MINUS_EXPR:
    case RANGE_EXPR:
      {
	tree x1 = TREE_OPERAND (t1, 0);
	tree x2 = TREE_OPERAND (t2, 0);
	tree y1 = TREE_OPERAND (t1, 1);
	tree y2 = TREE_OPERAND (t2, 1);

	return sem_variable::equals (x1, x2) && sem_variable::equals (y1, y2);
      }

    CASE_CONVERT:
    case VIEW_CONVERT_EXPR:
      if (!func_checker::compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
	  return return_false ();
      return sem_variable::equals (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
    case ERROR_MARK:
      return return_false_with_msg ("ERROR_MARK");
    default:
      return return_false_with_msg ("Unknown TREE code reached");
    }
}

/* Parser function that visits a varpool NODE.  */

sem_variable *
sem_variable::parse (varpool_node *node, bitmap_obstack *stack)
{
  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 ();

  return v;
}

/* References independent hash function.  */

hashval_t
sem_variable::get_hash (void)
{
  if (m_hash_set)
    return m_hash;

  /* 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;

  hstate.add_int (456346417);
  if (DECL_SIZE (decl) && tree_fits_shwi_p (DECL_SIZE (decl)))
    hstate.add_wide_int (tree_to_shwi (DECL_SIZE (decl)));
  add_expr (ctor, hstate);
  set_hash (hstate.end ());

  return m_hash;
}

/* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
   be applied.  */

bool
sem_variable::merge (sem_item *alias_item)
{
  gcc_assert (alias_item->type == VAR);

  if (!sem_item::target_supports_symbol_aliases_p ())
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; "
		 "Symbol aliases are not supported by target\n\n");
      return false;
    }

  if (DECL_EXTERNAL (alias_item->decl))
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; alias is external.\n\n");
      return false;
    }

  sem_variable *alias_var = static_cast<sem_variable *> (alias_item);

  varpool_node *original = get_node ();
  varpool_node *alias = alias_var->get_node ();
  bool original_discardable = false;

  bool alias_address_matters = alias->address_matters_p ();

  /* See if original is in a section that can be discarded if the main
     symbol is not used.
     Also consider case where we have resolution info and we know that
     original's definition is not going to be used.  In this case we can not
     create alias to original.  */
  if (original->can_be_discarded_p ()
      || (node->resolution != LDPR_UNKNOWN
	  && !decl_binds_to_current_def_p (node->decl)))
    original_discardable = true;

  gcc_assert (!TREE_ASM_WRITTEN (alias->decl));

  /* Constant pool machinery is not quite ready for aliases.
     TODO: varasm code contains logic for merging DECL_IN_CONSTANT_POOL.
     For LTO merging does not happen that is an important missing feature.
     We can enable merging with LTO if the DECL_IN_CONSTANT_POOL
     flag is dropped and non-local symbol name is assigned.  */
  if (DECL_IN_CONSTANT_POOL (alias->decl)
      || DECL_IN_CONSTANT_POOL (original->decl))
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; constant pool variables.\n\n");
      return false;
    }

  /* Do not attempt to mix functions from different user sections;
     we do not know what user intends with those.  */
  if (((DECL_SECTION_NAME (original->decl) && !original->implicit_section)
       || (DECL_SECTION_NAME (alias->decl) && !alias->implicit_section))
      && DECL_SECTION_NAME (original->decl) != DECL_SECTION_NAME (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; "
		 "original and alias are in different sections.\n\n");
      return false;
    }

  /* We can not merge if address comparsion metters.  */
  if (alias_address_matters && flag_merge_constants < 2)
    {
      if (dump_file)
	fprintf (dump_file,
		 "Not unifying; address of original may be compared.\n\n");
      return false;
    }

  if (DECL_ALIGN (original->decl) < DECL_ALIGN (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; "
		 "original and alias have incompatible alignments\n\n");

      return false;
    }

  if (DECL_COMDAT_GROUP (original->decl) != DECL_COMDAT_GROUP (alias->decl))
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; alias cannot be created; "
		 "across comdat group boundary\n\n");

      return false;
    }

  if (original_discardable)
    {
      if (dump_file)
	fprintf (dump_file, "Not unifying; alias cannot be created; "
		 "target is discardable\n\n");

      return false;
    }
  else
    {
      gcc_assert (!original->alias);
      gcc_assert (!alias->alias);

      alias->analyzed = false;

      DECL_INITIAL (alias->decl) = NULL;
      ((symtab_node *)alias)->call_for_symbol_and_aliases (clear_decl_rtl,
							   NULL, true);
      alias->need_bounds_init = false;
      alias->remove_all_references ();
      if (TREE_ADDRESSABLE (alias->decl))
        original->call_for_symbol_and_aliases (set_addressable, NULL, true);

      varpool_node::create_alias (alias_var->decl, decl);
      alias->resolve_alias (original);

      if (dump_file)
	fprintf (dump_file, "Unified; Variable alias has been created.\n");

      return true;
    }
}

/* Dump symbol to FILE.  */

void
sem_variable::dump_to_file (FILE *file)
{
  gcc_assert (file);

  print_node (file, "", decl, 0);
  fprintf (file, "\n\n");
}

unsigned int sem_item_optimizer::class_id = 0;

sem_item_optimizer::sem_item_optimizer ()
: worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL),
  m_varpool_node_hooks (NULL), m_merged_variables ()
{
  m_items.create (0);
  bitmap_obstack_initialize (&m_bmstack);
}

sem_item_optimizer::~sem_item_optimizer ()
{
  for (unsigned int i = 0; i < m_items.length (); i++)
    delete m_items[i];


  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    {
      for (unsigned int i = 0; i < (*it)->classes.length (); i++)
	delete (*it)->classes[i];

      (*it)->classes.release ();
      free (*it);
    }

  m_items.release ();

  bitmap_obstack_release (&m_bmstack);
  m_merged_variables.release ();
}

/* Write IPA ICF summary for symbols.  */

void
sem_item_optimizer::write_summary (void)
{
  unsigned int count = 0;

  output_block *ob = create_output_block (LTO_section_ipa_icf);
  lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
  ob->symbol = NULL;

  /* Calculate number of symbols to be serialized.  */
  for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
       !lsei_end_p (lsei);
       lsei_next_in_partition (&lsei))
    {
      symtab_node *node = lsei_node (lsei);

      if (m_symtab_node_map.get (node))
	count++;
    }

  streamer_write_uhwi (ob, count);

  /* Process all of the symbols.  */
  for (lto_symtab_encoder_iterator lsei = lsei_start_in_partition (encoder);
       !lsei_end_p (lsei);
       lsei_next_in_partition (&lsei))
    {
      symtab_node *node = lsei_node (lsei);

      sem_item **item = m_symtab_node_map.get (node);

      if (item && *item)
	{
	  int node_ref = lto_symtab_encoder_encode (encoder, node);
	  streamer_write_uhwi_stream (ob->main_stream, node_ref);

	  streamer_write_uhwi (ob, (*item)->get_hash ());
	}
    }

  streamer_write_char_stream (ob->main_stream, 0);
  produce_asm (ob, NULL);
  destroy_output_block (ob);
}

/* Reads a section from LTO stream file FILE_DATA. Input block for DATA
   contains LEN bytes.  */

void
sem_item_optimizer::read_section (lto_file_decl_data *file_data,
				  const char *data, size_t len)
{
  const lto_function_header *header
    = (const lto_function_header *) data;
  const int cfg_offset = sizeof (lto_function_header);
  const int main_offset = cfg_offset + header->cfg_size;
  const int string_offset = main_offset + header->main_size;
  data_in *data_in;
  unsigned int i;
  unsigned int count;

  lto_input_block ib_main ((const char *) data + main_offset, 0,
			   header->main_size, file_data->mode_table);

  data_in
    = lto_data_in_create (file_data, (const char *) data + string_offset,
			  header->string_size, vNULL);

  count = streamer_read_uhwi (&ib_main);

  for (i = 0; i < count; i++)
    {
      unsigned int index;
      symtab_node *node;
      lto_symtab_encoder_t encoder;

      index = streamer_read_uhwi (&ib_main);
      encoder = file_data->symtab_node_encoder;
      node = lto_symtab_encoder_deref (encoder, index);

      hashval_t hash = streamer_read_uhwi (&ib_main);

      gcc_assert (node->definition);

      if (dump_file)
	fprintf (dump_file, "Symbol added:%s (tree: %p, uid:%u)\n",
		 node->asm_name (), (void *) node->decl, node->order);

      if (is_a<cgraph_node *> (node))
	{
	  cgraph_node *cnode = dyn_cast <cgraph_node *> (node);

	  sem_function *fn = new sem_function (cnode, &m_bmstack);
	  fn->set_hash (hash);
	  m_items.safe_push (fn);
	}
      else
	{
	  varpool_node *vnode = dyn_cast <varpool_node *> (node);

	  sem_variable *var = new sem_variable (vnode, &m_bmstack);
	  var->set_hash (hash);
	  m_items.safe_push (var);
	}
    }

  lto_free_section_data (file_data, LTO_section_ipa_icf, NULL, data,
			 len);
  lto_data_in_delete (data_in);
}

/* Read IPA ICF summary for symbols.  */

void
sem_item_optimizer::read_summary (void)
{
  lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
  lto_file_decl_data *file_data;
  unsigned int j = 0;

  while ((file_data = file_data_vec[j++]))
    {
      size_t len;
      const char *data = lto_get_section_data (file_data,
			 LTO_section_ipa_icf, NULL, &len);

      if (data)
	read_section (file_data, data, len);
    }
}

/* Register callgraph and varpool hooks.  */

void
sem_item_optimizer::register_hooks (void)
{
  if (!m_cgraph_node_hooks)
    m_cgraph_node_hooks = symtab->add_cgraph_removal_hook
			  (&sem_item_optimizer::cgraph_removal_hook, this);

  if (!m_varpool_node_hooks)
    m_varpool_node_hooks = symtab->add_varpool_removal_hook
			   (&sem_item_optimizer::varpool_removal_hook, this);
}

/* Unregister callgraph and varpool hooks.  */

void
sem_item_optimizer::unregister_hooks (void)
{
  if (m_cgraph_node_hooks)
    symtab->remove_cgraph_removal_hook (m_cgraph_node_hooks);

  if (m_varpool_node_hooks)
    symtab->remove_varpool_removal_hook (m_varpool_node_hooks);
}

/* Adds a CLS to hashtable associated by hash value.  */

void
sem_item_optimizer::add_class (congruence_class *cls)
{
  gcc_assert (cls->members.length ());

  congruence_class_group *group
    = get_group_by_hash (cls->members[0]->get_hash (),
			 cls->members[0]->type);
  group->classes.safe_push (cls);
}

/* Gets a congruence class group based on given HASH value and TYPE.  */

congruence_class_group *
sem_item_optimizer::get_group_by_hash (hashval_t hash, sem_item_type type)
{
  congruence_class_group *item = XNEW (congruence_class_group);
  item->hash = hash;
  item->type = type;

  congruence_class_group **slot = m_classes.find_slot (item, INSERT);

  if (*slot)
    free (item);
  else
    {
      item->classes.create (1);
      *slot = item;
    }

  return *slot;
}

/* Callgraph removal hook called for a NODE with a custom DATA.  */

void
sem_item_optimizer::cgraph_removal_hook (cgraph_node *node, void *data)
{
  sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
  optimizer->remove_symtab_node (node);
}

/* Varpool removal hook called for a NODE with a custom DATA.  */

void
sem_item_optimizer::varpool_removal_hook (varpool_node *node, void *data)
{
  sem_item_optimizer *optimizer = (sem_item_optimizer *) data;
  optimizer->remove_symtab_node (node);
}

/* Remove symtab NODE triggered by symtab removal hooks.  */

void
sem_item_optimizer::remove_symtab_node (symtab_node *node)
{
  gcc_assert (!m_classes.elements ());

  m_removed_items_set.add (node);
}

void
sem_item_optimizer::remove_item (sem_item *item)
{
  if (m_symtab_node_map.get (item->node))
    m_symtab_node_map.remove (item->node);
  delete item;
}

/* Removes all callgraph and varpool nodes that are marked by symtab
   as deleted.  */

void
sem_item_optimizer::filter_removed_items (void)
{
  auto_vec <sem_item *> filtered;

  for (unsigned int i = 0; i < m_items.length(); i++)
    {
      sem_item *item = m_items[i];

      if (m_removed_items_set.contains (item->node))
        {
	  remove_item (item);
	  continue;
        }

      if (item->type == FUNC)
        {
	  cgraph_node *cnode = static_cast <sem_function *>(item)->get_node ();

	  if (in_lto_p && (cnode->alias || cnode->body_removed))
	    remove_item (item);
	  else
	    filtered.safe_push (item);
        }
      else /* VAR.  */
        {
	  if (!flag_ipa_icf_variables)
	    remove_item (item);
	  else
	    {
	      /* Filter out non-readonly variables.  */
	      tree decl = item->decl;
	      if (TREE_READONLY (decl))
		filtered.safe_push (item);
	      else
		remove_item (item);
	    }
        }
    }

  /* Clean-up of released semantic items.  */

  m_items.release ();
  for (unsigned int i = 0; i < filtered.length(); i++)
    m_items.safe_push (filtered[i]);
}

/* Optimizer entry point which returns true in case it processes
   a merge operation. True is returned if there's a merge operation
   processed.  */

bool
sem_item_optimizer::execute (void)
{
  filter_removed_items ();
  unregister_hooks ();

  build_graph ();
  update_hash_by_addr_refs ();
  build_hash_based_classes ();

  if (dump_file)
    fprintf (dump_file, "Dump after hash based groups\n");
  dump_cong_classes ();

  for (unsigned int i = 0; i < m_items.length(); i++)
    m_items[i]->init_wpa ();

  subdivide_classes_by_equality (true);

  if (dump_file)
    fprintf (dump_file, "Dump after WPA based types groups\n");

  dump_cong_classes ();

  process_cong_reduction ();
  checking_verify_classes ();

  if (dump_file)
    fprintf (dump_file, "Dump after callgraph-based congruence reduction\n");

  dump_cong_classes ();

  parse_nonsingleton_classes ();
  subdivide_classes_by_equality ();

  if (dump_file)
    fprintf (dump_file, "Dump after full equality comparison of groups\n");

  dump_cong_classes ();

  unsigned int prev_class_count = m_classes_count;

  process_cong_reduction ();
  dump_cong_classes ();
  checking_verify_classes ();
  bool merged_p = merge_classes (prev_class_count);

  if (dump_file && (dump_flags & TDF_DETAILS))
    symtab_node::dump_table (dump_file);

  return merged_p;
}

/* Function responsible for visiting all potential functions and
   read-only variables that can be merged.  */

void
sem_item_optimizer::parse_funcs_and_vars (void)
{
  cgraph_node *cnode;

  if (flag_ipa_icf_functions)
    FOR_EACH_DEFINED_FUNCTION (cnode)
    {
      sem_function *f = sem_function::parse (cnode, &m_bmstack);
      if (f)
	{
	  m_items.safe_push (f);
	  m_symtab_node_map.put (cnode, f);

	  if (dump_file)
	    fprintf (dump_file, "Parsed function:%s\n", f->node->asm_name ());

	  if (dump_file && (dump_flags & TDF_DETAILS))
	    f->dump_to_file (dump_file);
	}
      else if (dump_file)
	fprintf (dump_file, "Not parsed function:%s\n", cnode->asm_name ());
    }

  varpool_node *vnode;

  if (flag_ipa_icf_variables)
    FOR_EACH_DEFINED_VARIABLE (vnode)
    {
      sem_variable *v = sem_variable::parse (vnode, &m_bmstack);

      if (v)
	{
	  m_items.safe_push (v);
	  m_symtab_node_map.put (vnode, v);
	}
    }
}

/* Makes pairing between a congruence class CLS and semantic ITEM.  */

void
sem_item_optimizer::add_item_to_class (congruence_class *cls, sem_item *item)
{
  item->index_in_class = cls->members.length ();
  cls->members.safe_push (item);
  item->cls = cls;
}

/* For each semantic item, append hash values of references.  */

void
sem_item_optimizer::update_hash_by_addr_refs ()
{
  /* 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);
      if (m_items[i]->type == FUNC)
	{
	  if (TREE_CODE (TREE_TYPE (m_items[i]->decl)) == METHOD_TYPE
	      && contains_polymorphic_type_p
		   (TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl)))
	      && (DECL_CXX_CONSTRUCTOR_P (m_items[i]->decl)
		  || (static_cast<sem_function *> (m_items[i])->param_used_p (0)
		      && static_cast<sem_function *> (m_items[i])
			   ->compare_polymorphic_p ())))
	     {
	        tree class_type
		  = TYPE_METHOD_BASETYPE (TREE_TYPE (m_items[i]->decl));
		inchash::hash hstate (m_items[i]->get_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]->set_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
     references by a semantic item. Newly computed values
     are saved to global_hash member variable.  */
  for (unsigned i = 0; i < m_items.length (); i++)
    m_items[i]->update_hash_by_local_refs (m_symtab_node_map);

  /* Global hash value replace current hash values.  */
  for (unsigned i = 0; i < m_items.length (); i++)
    m_items[i]->set_hash (m_items[i]->global_hash);
}

/* Congruence classes are built by hash value.  */

void
sem_item_optimizer::build_hash_based_classes (void)
{
  for (unsigned i = 0; i < m_items.length (); i++)
    {
      sem_item *item = m_items[i];

      congruence_class_group *group
	= get_group_by_hash (item->get_hash (), item->type);

      if (!group->classes.length ())
	{
	  m_classes_count++;
	  group->classes.safe_push (new congruence_class (class_id++));
	}

      add_item_to_class (group->classes[0], item);
    }
}

/* Build references according to call graph.  */

void
sem_item_optimizer::build_graph (void)
{
  for (unsigned i = 0; i < m_items.length (); i++)
    {
      sem_item *item = m_items[i];
      m_symtab_node_map.put (item->node, item);

      /* Initialize hash values if we are not in LTO mode.  */
      if (!in_lto_p)
	item->get_hash ();
    }

  for (unsigned i = 0; i < m_items.length (); i++)
    {
      sem_item *item = m_items[i];

      if (item->type == FUNC)
	{
	  cgraph_node *cnode = dyn_cast <cgraph_node *> (item->node);

	  cgraph_edge *e = cnode->callees;
	  while (e)
	    {
	      sem_item **slot = m_symtab_node_map.get
		(e->callee->ultimate_alias_target ());
	      if (slot)
		item->add_reference (*slot);

	      e = e->next_callee;
	    }
	}

      ipa_ref *ref = NULL;
      for (unsigned i = 0; item->node->iterate_reference (i, ref); i++)
	{
	  sem_item **slot = m_symtab_node_map.get
	    (ref->referred->ultimate_alias_target ());
	  if (slot)
	    item->add_reference (*slot);
	}
    }
}

/* Semantic items in classes having more than one element and initialized.
   In case of WPA, we load function body.  */

void
sem_item_optimizer::parse_nonsingleton_classes (void)
{
  unsigned int init_called_count = 0;

  for (unsigned i = 0; i < m_items.length (); i++)
    if (m_items[i]->cls->members.length () > 1)
      {
	m_items[i]->init ();
	init_called_count++;
      }

  if (dump_file)
    fprintf (dump_file, "Init called for %u items (%.2f%%).\n",
	     init_called_count,
	     m_items.length () ? 100.0f * init_called_count / m_items.length ()
			       : 0.0f);
}

/* Equality function for semantic items is used to subdivide existing
   classes. If IN_WPA, fast equality function is invoked.  */

void
sem_item_optimizer::subdivide_classes_by_equality (bool in_wpa)
{
  for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    {
      unsigned int class_count = (*it)->classes.length ();

      for (unsigned i = 0; i < class_count; i++)
	{
	  congruence_class *c = (*it)->classes[i];

	  if (c->members.length() > 1)
	    {
	      auto_vec <sem_item *> new_vector;

	      sem_item *first = c->members[0];
	      new_vector.safe_push (first);

	      unsigned class_split_first = (*it)->classes.length ();

	      for (unsigned j = 1; j < c->members.length (); j++)
		{
		  sem_item *item = c->members[j];

		  bool equals
		    = in_wpa ? first->equals_wpa (item, m_symtab_node_map)
			     : first->equals (item, m_symtab_node_map);

		  if (equals)
		    new_vector.safe_push (item);
		  else
		    {
		      bool integrated = false;

		      for (unsigned k = class_split_first;
			   k < (*it)->classes.length (); k++)
			{
			  sem_item *x = (*it)->classes[k]->members[0];
			  bool equals
			    = in_wpa ? x->equals_wpa (item, m_symtab_node_map)
				     : x->equals (item, m_symtab_node_map);

			  if (equals)
			    {
			      integrated = true;
			      add_item_to_class ((*it)->classes[k], item);

			      break;
			    }
			}

		      if (!integrated)
			{
			  congruence_class *c
			    = new congruence_class (class_id++);
			  m_classes_count++;
			  add_item_to_class (c, item);

			  (*it)->classes.safe_push (c);
			}
		    }
		}

	      // We replace newly created new_vector for the class we've just
	      // splitted.
	      c->members.release ();
	      c->members.create (new_vector.length ());

	      for (unsigned int j = 0; j < new_vector.length (); j++)
		add_item_to_class (c, new_vector[j]);
	    }
	}
    }

  checking_verify_classes ();
}

/* Subdivide classes by address references that members of the class
   reference. Example can be a pair of functions that have an address
   taken from a function. If these addresses are different the class
   is split.  */

unsigned
sem_item_optimizer::subdivide_classes_by_sensitive_refs ()
{
  typedef hash_map <symbol_compare_hash, vec <sem_item *> > subdivide_hash_map;

  unsigned newly_created_classes = 0;

  for (hash_table <congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    {
      unsigned int class_count = (*it)->classes.length ();
      auto_vec<congruence_class *> new_classes;

      for (unsigned i = 0; i < class_count; i++)
	{
	  congruence_class *c = (*it)->classes[i];

	  if (c->members.length() > 1)
	    {
	      subdivide_hash_map split_map;

	      for (unsigned j = 0; j < c->members.length (); j++)
	        {
		  sem_item *source_node = c->members[j];

		  symbol_compare_collection *collection
		    = new symbol_compare_collection (source_node->node);

		  bool existed;
		  vec <sem_item *> *slot
		    = &split_map.get_or_insert (collection, &existed);
		  gcc_checking_assert (slot);

		  slot->safe_push (source_node);

		  if (existed)
		    delete collection;
	        }

	       /* If the map contains more than one key, we have to split
		  the map appropriately.  */
	      if (split_map.elements () != 1)
	        {
		  bool first_class = true;

		  for (subdivide_hash_map::iterator it2 = split_map.begin ();
		       it2 != split_map.end (); ++it2)
		    {
		      congruence_class *new_cls;
		      new_cls = new congruence_class (class_id++);

		      for (unsigned k = 0; k < (*it2).second.length (); k++)
			add_item_to_class (new_cls, (*it2).second[k]);

		      worklist_push (new_cls);
		      newly_created_classes++;

		      if (first_class)
		        {
			  (*it)->classes[i] = new_cls;
			  first_class = false;
			}
		      else
		        {
		          new_classes.safe_push (new_cls);
			  m_classes_count++;
		        }
		    }
		}

	      /* Release memory.  */
	      for (subdivide_hash_map::iterator it2 = split_map.begin ();
		   it2 != split_map.end (); ++it2)
		{
		  delete (*it2).first;
		  (*it2).second.release ();
		}
	    }
	  }

	for (unsigned i = 0; i < new_classes.length (); i++)
	  (*it)->classes.safe_push (new_classes[i]);
    }

  return newly_created_classes;
}

/* Verify congruence classes, if checking is enabled.  */

void
sem_item_optimizer::checking_verify_classes (void)
{
  if (flag_checking)
    verify_classes ();
}

/* Verify congruence classes.  */

void
sem_item_optimizer::verify_classes (void)
{
  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    {
      for (unsigned int i = 0; i < (*it)->classes.length (); i++)
	{
	  congruence_class *cls = (*it)->classes[i];

	  gcc_assert (cls);
	  gcc_assert (cls->members.length () > 0);

	  for (unsigned int j = 0; j < cls->members.length (); j++)
	    {
	      sem_item *item = cls->members[j];

	      gcc_assert (item);
	      gcc_assert (item->cls == cls);

	      for (unsigned k = 0; k < item->usages.length (); k++)
		{
		  sem_usage_pair *usage = item->usages[k];
		  gcc_assert (usage->item->index_in_class
			      < usage->item->cls->members.length ());
		}
	    }
	}
    }
}

/* Disposes split map traverse function. CLS_PTR is pointer to congruence
   class, BSLOT is bitmap slot we want to release. DATA is mandatory,
   but unused argument.  */

bool
sem_item_optimizer::release_split_map (congruence_class * const &,
				       bitmap const &b, traverse_split_pair *)
{
  bitmap bmp = b;

  BITMAP_FREE (bmp);

  return true;
}

/* Process split operation for a class given as pointer CLS_PTR,
   where bitmap B splits congruence class members. DATA is used
   as argument of split pair.  */

bool
sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls,
					       bitmap const &b,
					       traverse_split_pair *pair)
{
  sem_item_optimizer *optimizer = pair->optimizer;
  const congruence_class *splitter_cls = pair->cls;

  /* If counted bits are greater than zero and less than the number of members
     a group will be splitted.  */
  unsigned popcount = bitmap_count_bits (b);

  if (popcount > 0 && popcount < cls->members.length ())
    {
      auto_vec <congruence_class *, 2> newclasses;
      newclasses.quick_push (new congruence_class (class_id++));
      newclasses.quick_push (new congruence_class (class_id++));

      for (unsigned int i = 0; i < cls->members.length (); i++)
	{
	  int target = bitmap_bit_p (b, i);
	  congruence_class *tc = newclasses[target];

	  add_item_to_class (tc, cls->members[i]);
	}

      if (flag_checking)
	{
	  for (unsigned int i = 0; i < 2; i++)
	    gcc_assert (newclasses[i]->members.length ());
	}

      if (splitter_cls == cls)
	optimizer->splitter_class_removed = true;

      /* Remove old class from worklist if presented.  */
      bool in_worklist = cls->in_worklist;

      if (in_worklist)
	cls->in_worklist = false;

      congruence_class_group g;
      g.hash = cls->members[0]->get_hash ();
      g.type = cls->members[0]->type;

      congruence_class_group *slot = optimizer->m_classes.find (&g);

      for (unsigned int i = 0; i < slot->classes.length (); i++)
	if (slot->classes[i] == cls)
	  {
	    slot->classes.ordered_remove (i);
	    break;
	  }

      /* New class will be inserted and integrated to work list.  */
      for (unsigned int i = 0; i < 2; i++)
	optimizer->add_class (newclasses[i]);

      /* Two classes replace one, so that increment just by one.  */
      optimizer->m_classes_count++;

      /* If OLD class was presented in the worklist, we remove the class
         and replace it will both newly created classes.  */
      if (in_worklist)
	for (unsigned int i = 0; i < 2; i++)
	  optimizer->worklist_push (newclasses[i]);
      else /* Just smaller class is inserted.  */
	{
	  unsigned int smaller_index
	    = (newclasses[0]->members.length ()
	       < newclasses[1]->members.length ()
	       ? 0 : 1);
	  optimizer->worklist_push (newclasses[smaller_index]);
	}

      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "  congruence class splitted:\n");
	  cls->dump (dump_file, 4);

	  fprintf (dump_file, "  newly created groups:\n");
	  for (unsigned int i = 0; i < 2; i++)
	    newclasses[i]->dump (dump_file, 4);
	}

      /* Release class if not presented in work list.  */
      if (!in_worklist)
	delete cls;
    }


  return true;
}

/* Tests if a class CLS used as INDEXth splits any congruence classes.
   Bitmap stack BMSTACK is used for bitmap allocation.  */

void
sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
						  unsigned int index)
{
  hash_map <congruence_class *, bitmap> split_map;

  for (unsigned int i = 0; i < cls->members.length (); i++)
    {
      sem_item *item = cls->members[i];

      /* Iterate all usages that have INDEX as usage of the item.  */
      for (unsigned int j = 0; j < item->usages.length (); j++)
	{
	  sem_usage_pair *usage = item->usages[j];

	  if (usage->index != index)
	    continue;

	  bitmap *slot = split_map.get (usage->item->cls);
	  bitmap b;

	  if(!slot)
	    {
	      b = BITMAP_ALLOC (&m_bmstack);
	      split_map.put (usage->item->cls, b);
	    }
	  else
	    b = *slot;

	  gcc_checking_assert (usage->item->cls);
	  gcc_checking_assert (usage->item->index_in_class
			       < usage->item->cls->members.length ());

	  bitmap_set_bit (b, usage->item->index_in_class);
	}
    }

  traverse_split_pair pair;
  pair.optimizer = this;
  pair.cls = cls;

  splitter_class_removed = false;
  split_map.traverse <traverse_split_pair *,
		      sem_item_optimizer::traverse_congruence_split> (&pair);

  /* Bitmap clean-up.  */
  split_map.traverse <traverse_split_pair *,
		      sem_item_optimizer::release_split_map> (NULL);
}

/* Every usage of a congruence class CLS is a candidate that can split the
   collection of classes. Bitmap stack BMSTACK is used for bitmap
   allocation.  */

void
sem_item_optimizer::do_congruence_step (congruence_class *cls)
{
  bitmap_iterator bi;
  unsigned int i;

  bitmap usage = BITMAP_ALLOC (&m_bmstack);

  for (unsigned int i = 0; i < cls->members.length (); i++)
    bitmap_ior_into (usage, cls->members[i]->usage_index_bitmap);

  EXECUTE_IF_SET_IN_BITMAP (usage, 0, i, bi)
  {
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "  processing congruence step for class: %u, "
	       "index: %u\n", cls->id, i);

    do_congruence_step_for_index (cls, i);

    if (splitter_class_removed)
      break;
  }

  BITMAP_FREE (usage);
}

/* Adds a newly created congruence class CLS to worklist.  */

void
sem_item_optimizer::worklist_push (congruence_class *cls)
{
  /* Return if the class CLS is already presented in work list.  */
  if (cls->in_worklist)
    return;

  cls->in_worklist = true;
  worklist.push_back (cls);
}

/* Pops a class from worklist. */

congruence_class *
sem_item_optimizer::worklist_pop (void)
{
  congruence_class *cls;

  while (!worklist.empty ())
    {
      cls = worklist.front ();
      worklist.pop_front ();
      if (cls->in_worklist)
	{
	  cls->in_worklist = false;

	  return cls;
	}
      else
	{
	  /* Work list item was already intended to be removed.
	     The only reason for doing it is to split a class.
	     Thus, the class CLS is deleted.  */
	  delete cls;
	}
    }

  return NULL;
}

/* Iterative congruence reduction function.  */

void
sem_item_optimizer::process_cong_reduction (void)
{
  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    for (unsigned i = 0; i < (*it)->classes.length (); i++)
      if ((*it)->classes[i]->is_class_used ())
	worklist_push ((*it)->classes[i]);

  if (dump_file)
    fprintf (dump_file, "Worklist has been filled with: %lu\n",
	     (unsigned long) worklist.size ());

  if (dump_file && (dump_flags & TDF_DETAILS))
    fprintf (dump_file, "Congruence class reduction\n");

  congruence_class *cls;

  /* Process complete congruence reduction.  */
  while ((cls = worklist_pop ()) != NULL)
    do_congruence_step (cls);

  /* Subdivide newly created classes according to references.  */
  unsigned new_classes = subdivide_classes_by_sensitive_refs ();

  if (dump_file)
    fprintf (dump_file, "Address reference subdivision created: %u "
	     "new classes.\n", new_classes);
}

/* Debug function prints all informations about congruence classes.  */

void
sem_item_optimizer::dump_cong_classes (void)
{
  if (!dump_file)
    return;

  fprintf (dump_file,
	   "Congruence classes: %u (unique hash values: %lu), with total: "
	   "%u items\n", m_classes_count,
	   (unsigned long) m_classes.elements (), m_items.length ());

  /* Histogram calculation.  */
  unsigned int max_index = 0;
  unsigned int* histogram = XCNEWVEC (unsigned int, m_items.length () + 1);

  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    for (unsigned i = 0; i < (*it)->classes.length (); i++)
      {
	unsigned int c = (*it)->classes[i]->members.length ();
	histogram[c]++;

	if (c > max_index)
	  max_index = c;
      }

  fprintf (dump_file,
	   "Class size histogram [num of members]: number of classe number "
	   "of classess\n");

  for (unsigned int i = 0; i <= max_index; i++)
    if (histogram[i])
      fprintf (dump_file, "[%u]: %u classes\n", i, histogram[i]);

  fprintf (dump_file, "\n\n");

  if (dump_flags & TDF_DETAILS)
  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
      {
	fprintf (dump_file, "  group: with %u classes:\n",
		 (*it)->classes.length ());

	for (unsigned i = 0; i < (*it)->classes.length (); i++)
	  {
	    (*it)->classes[i]->dump (dump_file, 4);

	    if (i < (*it)->classes.length () - 1)
	      fprintf (dump_file, " ");
	  }
      }

  free (histogram);
}

/* Sort pair of sem_items A and B by DECL_UID.  */

static int
sort_sem_items_by_decl_uid (const void *a, const void *b)
{
  const sem_item *i1 = *(const sem_item * const *)a;
  const sem_item *i2 = *(const sem_item * const *)b;

  int uid1 = DECL_UID (i1->decl);
  int uid2 = DECL_UID (i2->decl);

  if (uid1 < uid2)
    return -1;
  else if (uid1 > uid2)
    return 1;
  else
    return 0;
}

/* Sort pair of congruence_classes A and B by DECL_UID of the first member.  */

static int
sort_congruence_classes_by_decl_uid (const void *a, const void *b)
{
  const congruence_class *c1 = *(const congruence_class * const *)a;
  const congruence_class *c2 = *(const congruence_class * const *)b;

  int uid1 = DECL_UID (c1->members[0]->decl);
  int uid2 = DECL_UID (c2->members[0]->decl);

  if (uid1 < uid2)
    return -1;
  else if (uid1 > uid2)
    return 1;
  else
    return 0;
}

/* Sort pair of congruence_class_groups A and B by
   DECL_UID of the first member of a first group.  */

static int
sort_congruence_class_groups_by_decl_uid (const void *a, const void *b)
{
  const congruence_class_group *g1
    = *(const congruence_class_group * const *)a;
  const congruence_class_group *g2
    = *(const congruence_class_group * const *)b;

  int uid1 = DECL_UID (g1->classes[0]->members[0]->decl);
  int uid2 = DECL_UID (g2->classes[0]->members[0]->decl);

  if (uid1 < uid2)
    return -1;
  else if (uid1 > uid2)
    return 1;
  else
    return 0;
}

/* After reduction is done, we can declare all items in a group
   to be equal. PREV_CLASS_COUNT is start number of classes
   before reduction. True is returned if there's a merge operation
   processed. */

bool
sem_item_optimizer::merge_classes (unsigned int prev_class_count)
{
  unsigned int item_count = m_items.length ();
  unsigned int class_count = m_classes_count;
  unsigned int equal_items = item_count - class_count;

  unsigned int non_singular_classes_count = 0;
  unsigned int non_singular_classes_sum = 0;

  bool merged_p = false;

  /* PR lto/78211
     Sort functions in congruence classes by DECL_UID and do the same
     for the classes to not to break -fcompare-debug.  */

  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    {
      for (unsigned int i = 0; i < (*it)->classes.length (); i++)
	{
	  congruence_class *c = (*it)->classes[i];
	  c->members.qsort (sort_sem_items_by_decl_uid);
	}

      (*it)->classes.qsort (sort_congruence_classes_by_decl_uid);
    }

  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    for (unsigned int i = 0; i < (*it)->classes.length (); i++)
      {
	congruence_class *c = (*it)->classes[i];
	if (c->members.length () > 1)
	  {
	    non_singular_classes_count++;
	    non_singular_classes_sum += c->members.length ();
	  }
      }

  auto_vec <congruence_class_group *> classes (m_classes.elements ());
  for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
       it != m_classes.end (); ++it)
    classes.quick_push (*it);

  classes.qsort (sort_congruence_class_groups_by_decl_uid);

  if (dump_file)
    {
      fprintf (dump_file, "\nItem count: %u\n", item_count);
      fprintf (dump_file, "Congruent classes before: %u, after: %u\n",
	       prev_class_count, class_count);
      fprintf (dump_file, "Average class size before: %.2f, after: %.2f\n",
	       prev_class_count ? 1.0f * item_count / prev_class_count : 0.0f,
	       class_count ? 1.0f * item_count / class_count : 0.0f);
      fprintf (dump_file, "Average non-singular class size: %.2f, count: %u\n",
	       non_singular_classes_count ? 1.0f * non_singular_classes_sum /
	       non_singular_classes_count : 0.0f,
	       non_singular_classes_count);
      fprintf (dump_file, "Equal symbols: %u\n", equal_items);
      fprintf (dump_file, "Fraction of visited symbols: %.2f%%\n\n",
	       item_count ? 100.0f * equal_items / item_count : 0.0f);
    }

  unsigned int l;
  congruence_class_group *it;
  FOR_EACH_VEC_ELT (classes, l, it)
    for (unsigned int i = 0; i < it->classes.length (); i++)
      {
	congruence_class *c = it->classes[i];

	if (c->members.length () == 1)
	  continue;

	sem_item *source = c->members[0];

	if (DECL_NAME (source->decl)
	    && MAIN_NAME_P (DECL_NAME (source->decl)))
	  /* If merge via wrappers, picking main as the target can be
	     problematic.  */
	  source = c->members[1];

	for (unsigned int j = 0; j < c->members.length (); j++)
	  {
	    sem_item *alias = c->members[j];

	    if (alias == source)
	      continue;

	    if (dump_file)
	      {
		fprintf (dump_file, "Semantic equality hit:%s->%s\n",
			 xstrdup_for_dump (source->node->name ()),
			 xstrdup_for_dump (alias->node->name ()));
		fprintf (dump_file, "Assembler symbol names:%s->%s\n",
			 xstrdup_for_dump (source->node->asm_name ()),
			 xstrdup_for_dump (alias->node->asm_name ()));
	      }

	    if (lookup_attribute ("no_icf", DECL_ATTRIBUTES (alias->decl)))
	      {
	        if (dump_file)
		  fprintf (dump_file,
			   "Merge operation is skipped due to no_icf "
			   "attribute.\n\n");

		continue;
	      }

	    if (dump_file && (dump_flags & TDF_DETAILS))
	      {
		source->dump_to_file (dump_file);
		alias->dump_to_file (dump_file);
	      }

	    if (dbg_cnt (merged_ipa_icf))
	      {
		bool merged = source->merge (alias);
		merged_p |= merged;

		if (merged && alias->type == VAR)
		  {
		    symtab_pair p = symtab_pair (source->node, alias->node);
		    m_merged_variables.safe_push (p);
		  }
	      }
	  }
      }

  if (!m_merged_variables.is_empty ())
    fixup_points_to_sets ();

  return merged_p;
}

/* Fixup points to set PT.  */

void
sem_item_optimizer::fixup_pt_set (struct pt_solution *pt)
{
  if (pt->vars == NULL)
    return;

  unsigned i;
  symtab_pair *item;
  FOR_EACH_VEC_ELT (m_merged_variables, i, item)
    if (bitmap_bit_p (pt->vars, DECL_UID (item->second->decl)))
      bitmap_set_bit (pt->vars, DECL_UID (item->first->decl));
}

/* Set all points-to UIDs of aliases pointing to node N as UID.  */

static void
set_alias_uids (symtab_node *n, int uid)
{
  ipa_ref *ref;
  FOR_EACH_ALIAS (n, ref)
    {
      if (dump_file)
	fprintf (dump_file, "  Setting points-to UID of [%s] as %d\n",
		 xstrdup_for_dump (ref->referring->asm_name ()), uid);

      SET_DECL_PT_UID (ref->referring->decl, uid);
      set_alias_uids (ref->referring, uid);
    }
}

/* Fixup points to analysis info.  */

void
sem_item_optimizer::fixup_points_to_sets (void)
{
  /* TODO: remove in GCC 9 and trigger PTA re-creation after IPA passes.  */
  cgraph_node *cnode;

  FOR_EACH_DEFINED_FUNCTION (cnode)
    {
      tree name;
      unsigned i;
      function *fn = DECL_STRUCT_FUNCTION (cnode->decl);
      if (!gimple_in_ssa_p (fn))
	continue;

      FOR_EACH_SSA_NAME (i, name, fn)
	if (POINTER_TYPE_P (TREE_TYPE (name))
	    && SSA_NAME_PTR_INFO (name))
	  fixup_pt_set (&SSA_NAME_PTR_INFO (name)->pt);
      fixup_pt_set (&fn->gimple_df->escaped);

       /* The above get's us to 99% I guess, at least catching the
	  address compares.  Below also gets us aliasing correct
	  but as said we're giving leeway to the situation with
	  readonly vars anyway, so ... */
       basic_block bb;
       FOR_EACH_BB_FN (bb, fn)
	for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
	     gsi_next (&gsi))
	  {
	    gcall *call = dyn_cast<gcall *> (gsi_stmt (gsi));
	    if (call)
	      {
		fixup_pt_set (gimple_call_use_set (call));
		fixup_pt_set (gimple_call_clobber_set (call));
	      }
	  }
    }

  unsigned i;
  symtab_pair *item;
  FOR_EACH_VEC_ELT (m_merged_variables, i, item)
    set_alias_uids (item->first, DECL_UID (item->first->decl));
}

/* Dump function prints all class members to a FILE with an INDENT.  */

void
congruence_class::dump (FILE *file, unsigned int indent) const
{
  FPRINTF_SPACES (file, indent, "class with id: %u, hash: %u, items: %u\n",
		  id, members[0]->get_hash (), members.length ());

  FPUTS_SPACES (file, indent + 2, "");
  for (unsigned i = 0; i < members.length (); i++)
    fprintf (file, "%s(%p/%u) ", members[i]->node->asm_name (),
	     (void *) members[i]->decl,
	     members[i]->node->order);

  fprintf (file, "\n");
}

/* Returns true if there's a member that is used from another group.  */

bool
congruence_class::is_class_used (void)
{
  for (unsigned int i = 0; i < members.length (); i++)
    if (members[i]->usages.length ())
      return true;

  return false;
}

/* Generate pass summary for IPA ICF pass.  */

static void
ipa_icf_generate_summary (void)
{
  if (!optimizer)
    optimizer = new sem_item_optimizer ();

  optimizer->register_hooks ();
  optimizer->parse_funcs_and_vars ();
}

/* Write pass summary for IPA ICF pass.  */

static void
ipa_icf_write_summary (void)
{
  gcc_assert (optimizer);

  optimizer->write_summary ();
}

/* Read pass summary for IPA ICF pass.  */

static void
ipa_icf_read_summary (void)
{
  if (!optimizer)
    optimizer = new sem_item_optimizer ();

  optimizer->read_summary ();
  optimizer->register_hooks ();
}

/* Semantic equality exection function.  */

static unsigned int
ipa_icf_driver (void)
{
  gcc_assert (optimizer);

  bool merged_p = optimizer->execute ();

  delete optimizer;
  optimizer = NULL;

  return merged_p ? TODO_remove_functions : 0;
}

const pass_data pass_data_ipa_icf =
{
  IPA_PASS,		    /* type */
  "icf",		    /* name */
  OPTGROUP_IPA,             /* optinfo_flags */
  TV_IPA_ICF,		    /* tv_id */
  0,                        /* properties_required */
  0,                        /* properties_provided */
  0,                        /* properties_destroyed */
  0,                        /* todo_flags_start */
  0,                        /* todo_flags_finish */
};

class pass_ipa_icf : public ipa_opt_pass_d
{
public:
  pass_ipa_icf (gcc::context *ctxt)
    : ipa_opt_pass_d (pass_data_ipa_icf, ctxt,
		      ipa_icf_generate_summary, /* generate_summary */
		      ipa_icf_write_summary, /* write_summary */
		      ipa_icf_read_summary, /* read_summary */
		      NULL, /*
		      write_optimization_summary */
		      NULL, /*
		      read_optimization_summary */
		      NULL, /* stmt_fixup */
		      0, /* function_transform_todo_flags_start */
		      NULL, /* function_transform */
		      NULL) /* variable_transform */
  {}

  /* opt_pass methods: */
  virtual bool gate (function *)
  {
    return in_lto_p || flag_ipa_icf_variables || flag_ipa_icf_functions;
  }

  virtual unsigned int execute (function *)
  {
    return ipa_icf_driver();
  }
}; // class pass_ipa_icf

} // ipa_icf namespace

ipa_opt_pass_d *
make_pass_ipa_icf (gcc::context *ctxt)
{
  return new ipa_icf::pass_ipa_icf (ctxt);
}
