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