From patchwork Fri Nov 8 08:31:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 1194154 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-513217-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="RNKYJOOG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47CfL52vzgz9sNT for ; Wed, 13 Nov 2019 20:23:25 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :resent-from:resent-to:resent-date:resent-message-id:message-id :in-reply-to:references:from:date:subject:to:mime-version :content-type; q=dns; s=default; b=TFUTegUPL5NJcAyzUu5Nmk1S8aSpx cww0y3+M9tXp0+QsHwm5INcmv7HQ2uOUZbUWNxisgATWrirHmdBzxnidKQFn7LGd ZCqvl1x8EPKLfXvWNN7U2AG2PBynK6AB6o5ZHTVkML4r9xnR0n2kYgQ8n5fCRcML FLboY1LhGejvow= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :resent-from:resent-to:resent-date:resent-message-id:message-id :in-reply-to:references:from:date:subject:to:mime-version :content-type; s=default; bh=v3AINnJpiMefvEwjWK0JyDHvlp0=; b=RNK YJOOGRpNQQTXksEGg5D4+1gQB9X9IKtyqpqTLjDkUFHMHH8DJg4MWcfVQjQErbEO hXY3PA3Dc6ZNYOihESIpIyO6a7MlCXwZrEmbatNehbYEWpDkRoxqv3n6gZJeI0Sx 1KM3oqfBx1oRzU8mIGC1t7MF4EpushZP8/djXZ5Q= Received: (qmail 45263 invoked by alias); 13 Nov 2019 09:22:26 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 45199 invoked by uid 89); 13 Nov 2019 09:22:25 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.1 spammy=HX-detected-operating-system:timestamps, CONSTRUCTOR, MEM_REF X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (209.51.188.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 13 Nov 2019 09:22:22 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iUoqw-0002fe-29 for gcc-patches@gcc.gnu.org; Wed, 13 Nov 2019 04:22:20 -0500 Received: from mx2.suse.de ([195.135.220.15]:58254 helo=mx1.suse.de) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iUoqv-0002cq-En for gcc-patches@gcc.gnu.org; Wed, 13 Nov 2019 04:22:17 -0500 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 7693CB225 for ; Wed, 13 Nov 2019 09:22:13 +0000 (UTC) Resent-From: =?utf-8?q?Martin_Li=C5=A1ka?= Resent-To: GCC Patches Resent-Date: Wed, 13 Nov 2019 10:22:13 +0100 Resent-Message-ID: Message-Id: <0c58e8ead4ac3d2daa3a8c5380d31c5e9a07a576.1573636740.git.mliska@suse.cz> In-Reply-To: References: From: Martin Liska Date: Fri, 8 Nov 2019 09:31:45 +0100 Subject: [PATCH 3/5] Use func_checker::hash_operand for hashing of GIMPLE operands. To: gcc-patches@gcc.gnu.org MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 195.135.220.15 X-IsSubscribed: yes gcc/ChangeLog: 2019-11-11 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. --- gcc/ipa-icf-gimple.h | 11 ++ gcc/ipa-icf.c | 239 ++++++++----------------------------------- gcc/ipa-icf.h | 20 ++-- 3 files changed, 60 insertions(+), 210 deletions(-) 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. */