From 8a319aa3c28ee2069a78cff6b09d1b2df21b0f3c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Wed, 30 Oct 2019 13:01:25 +0100 Subject: [PATCH] Integrate that for IPA ICF. 2019-10-30 Martin Liska * ipa-icf-gimple.c (func_checker::hash_operand): New. (func_checker::compare_cst_or_decl): Remove handling of FIELD_DECL. (func_checker::compare_operand): Transform to ... (func_checker::operand_equal_p): ... this. * ipa-icf-gimple.h (class func_checker): Add operand_equal_p and hash_operand. * ipa-icf.c (sem_function::equals_private): Fix pushing and popping of cfun. From-SVN: r277615 --- gcc/ChangeLog | 12 +++ gcc/ipa-icf-gimple.c | 228 +++++++++++++++---------------------------- gcc/ipa-icf-gimple.h | 12 ++- gcc/ipa-icf.c | 7 +- 4 files changed, 107 insertions(+), 152 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 487cc9606ea..a4315789ccd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2019-10-30 Martin Liska + + * ipa-icf-gimple.c (func_checker::hash_operand): New. + (func_checker::compare_cst_or_decl): Remove handling + of FIELD_DECL. + (func_checker::compare_operand): Transform to ... + (func_checker::operand_equal_p): ... this. + * ipa-icf-gimple.h (class func_checker): Add + operand_equal_p and hash_operand. + * ipa-icf.c (sem_function::equals_private): Fix + pushing and popping of cfun. + 2019-10-30 Martin Liska * fold-const.c (operand_equal_p): Move to ... diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c index 4060c0e8eb3..96e688c129d 100644 --- a/gcc/ipa-icf-gimple.c +++ b/gcc/ipa-icf-gimple.c @@ -324,6 +324,34 @@ func_checker::compare_memory_operand (tree t1, tree t2) /* Function compare for equality given trees T1 and T2 which can be either a constant or a declaration type. */ +void +func_checker::hash_operand (const_tree arg, inchash::hash &hstate, + unsigned int flags) +{ + if (arg == NULL_TREE) + { + hstate.merge_hash (0); + return; + } + + switch (TREE_CODE (arg)) + { + case FUNCTION_DECL: + case VAR_DECL: + case LABEL_DECL: + case PARM_DECL: + case RESULT_DECL: + case CONST_DECL: + case SSA_NAME: + return; + + default: + break; + } + + return operand_compare::hash_operand (arg, hstate, flags); +} + bool func_checker::compare_cst_or_decl (tree t1, tree t2) { @@ -347,19 +375,6 @@ func_checker::compare_cst_or_decl (tree t1, tree t2) return true; case VAR_DECL: return return_with_debug (compare_variable_decl (t1, t2)); - case FIELD_DECL: - { - tree offset1 = DECL_FIELD_OFFSET (t1); - tree offset2 = DECL_FIELD_OFFSET (t2); - - tree bit_offset1 = DECL_FIELD_BIT_OFFSET (t1); - tree bit_offset2 = DECL_FIELD_BIT_OFFSET (t2); - - ret = compare_operand (offset1, offset2) - && compare_operand (bit_offset1, bit_offset2); - - return return_with_debug (ret); - } case LABEL_DECL: { if (t1 == t2) @@ -383,165 +398,80 @@ func_checker::compare_cst_or_decl (tree t1, tree t2) } } -/* Function responsible for comparison of various operands T1 and T2. - If these components, from functions FUNC1 and FUNC2, are equal, true - is returned. */ - bool -func_checker::compare_operand (tree t1, tree t2) +func_checker::operand_equal_p (const_tree t1, const_tree t2, + unsigned int flags) { - tree x1, x2, y1, y2, z1, z2; - bool ret; + bool r; + if (verify_hash_value (t1, t2, flags, &r)) + return r; - if (!t1 && !t2) + if (t1 == t2) return true; else if (!t1 || !t2) return false; - tree tt1 = TREE_TYPE (t1); - tree tt2 = TREE_TYPE (t2); - - if (!func_checker::compatible_types_p (tt1, tt2)) - return false; - if (TREE_CODE (t1) != TREE_CODE (t2)) return return_false (); + tree tree1 = (tree)const_cast (t1); + tree tree2 = (tree)const_cast (t2); + switch (TREE_CODE (t1)) { - case CONSTRUCTOR: + case FUNCTION_DECL: + /* All function decls are in the symbol table and known to match + before we start comparing bodies. */ + return true; + case VAR_DECL: + return return_with_debug (compare_variable_decl (tree1, tree2)); + case LABEL_DECL: { - unsigned length1 = CONSTRUCTOR_NELTS (t1); - unsigned length2 = CONSTRUCTOR_NELTS (t2); - - if (length1 != length2) - return return_false (); - - for (unsigned i = 0; i < length1; i++) - if (!compare_operand (CONSTRUCTOR_ELT (t1, i)->value, - CONSTRUCTOR_ELT (t2, i)->value)) - return return_false(); - - return true; + int *bb1 = m_label_bb_map.get (tree1); + int *bb2 = m_label_bb_map.get (tree2); + /* Labels can point to another function (non-local GOTOs). */ + return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2); } - case ARRAY_REF: - case ARRAY_RANGE_REF: - /* First argument is the array, second is the index. */ - x1 = TREE_OPERAND (t1, 0); - x2 = TREE_OPERAND (t2, 0); - y1 = TREE_OPERAND (t1, 1); - y2 = TREE_OPERAND (t2, 1); - - if (!compare_operand (array_ref_low_bound (t1), - array_ref_low_bound (t2))) - return return_false_with_msg (""); - if (!compare_operand (array_ref_element_size (t1), - array_ref_element_size (t2))) - return return_false_with_msg (""); - - if (!compare_operand (x1, x2)) - return return_false_with_msg (""); - return compare_operand (y1, y2); - case MEM_REF: - { - x1 = TREE_OPERAND (t1, 0); - x2 = TREE_OPERAND (t2, 0); - y1 = TREE_OPERAND (t1, 1); - y2 = TREE_OPERAND (t2, 1); - - /* See if operand is an memory access (the test originate from - gimple_load_p). - - In this case the alias set of the function being replaced must - be subset of the alias set of the other function. At the moment - we seek for equivalency classes, so simply require inclussion in - both directions. */ - if (!func_checker::compatible_types_p (TREE_TYPE (x1), TREE_TYPE (x2))) - return return_false (); - - if (!compare_operand (x1, x2)) - return return_false_with_msg (""); - - /* Type of the offset on MEM_REF does not matter. */ - return known_eq (wi::to_poly_offset (y1), wi::to_poly_offset (y2)); - } - case COMPONENT_REF: + case PARM_DECL: + case RESULT_DECL: + case CONST_DECL: + return compare_decl (tree1, tree2); + case SSA_NAME: + return compare_ssa_name (tree1, tree2); + case FIELD_DECL: { - x1 = TREE_OPERAND (t1, 0); - x2 = TREE_OPERAND (t2, 0); - y1 = TREE_OPERAND (t1, 1); - y2 = TREE_OPERAND (t2, 1); + tree offset1 = DECL_FIELD_OFFSET (t1); + tree offset2 = DECL_FIELD_OFFSET (t2); - ret = compare_operand (x1, x2) - && compare_cst_or_decl (y1, y2); + tree bit_offset1 = DECL_FIELD_BIT_OFFSET (t1); + tree bit_offset2 = DECL_FIELD_BIT_OFFSET (t2); + bool ret = (compare_operand (offset1, offset2) + && compare_operand (bit_offset1, bit_offset2)); return return_with_debug (ret); } - /* Virtual table call. */ - case OBJ_TYPE_REF: - { - if (!compare_ssa_name (OBJ_TYPE_REF_EXPR (t1), OBJ_TYPE_REF_EXPR (t2))) - return return_false (); - if (opt_for_fn (m_source_func_decl, flag_devirtualize) - && virtual_method_call_p (t1)) - { - if (tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t1)) - != tree_to_uhwi (OBJ_TYPE_REF_TOKEN (t2))) - return return_false_with_msg ("OBJ_TYPE_REF token mismatch"); - if (!types_same_for_odr (obj_type_ref_class (t1), - obj_type_ref_class (t2))) - return return_false_with_msg ("OBJ_TYPE_REF OTR type mismatch"); - if (!compare_operand (OBJ_TYPE_REF_OBJECT (t1), - OBJ_TYPE_REF_OBJECT (t2))) - return return_false_with_msg ("OBJ_TYPE_REF object mismatch"); - } - - return return_with_debug (true); - } - case IMAGPART_EXPR: - case REALPART_EXPR: - case ADDR_EXPR: - { - x1 = TREE_OPERAND (t1, 0); - x2 = TREE_OPERAND (t2, 0); + default: + break; + } - ret = compare_operand (x1, x2); - return return_with_debug (ret); - } - case BIT_FIELD_REF: - { - x1 = TREE_OPERAND (t1, 0); - x2 = TREE_OPERAND (t2, 0); - y1 = TREE_OPERAND (t1, 1); - y2 = TREE_OPERAND (t2, 1); - z1 = TREE_OPERAND (t1, 2); - z2 = TREE_OPERAND (t2, 2); + return operand_compare::operand_equal_p (t1, t2, flags); +} - ret = compare_operand (x1, x2) - && compare_cst_or_decl (y1, y2) - && compare_cst_or_decl (z1, z2); +/* Function responsible for comparison of various operands T1 and T2. + If these components, from functions FUNC1 and FUNC2, are equal, true + is returned. */ - return return_with_debug (ret); - } - case SSA_NAME: - return compare_ssa_name (t1, t2); - case INTEGER_CST: - case COMPLEX_CST: - case VECTOR_CST: - case STRING_CST: - case REAL_CST: - case FUNCTION_DECL: - case VAR_DECL: - case FIELD_DECL: - case LABEL_DECL: - case PARM_DECL: - case RESULT_DECL: - case CONST_DECL: - return compare_cst_or_decl (t1, t2); - default: - return return_false_with_msg ("Unknown TREE code reached"); - } +bool +func_checker::compare_operand (tree t1, tree t2) +{ + if (!t1 && !t2) + return true; + else if (!t1 || !t2) + return false; + if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS)) + return true; + return return_false_with_msg ("operand_equal_p failed"); } bool diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h index 351bddfb2f6..f56427b13e5 100644 --- a/gcc/ipa-icf-gimple.h +++ b/gcc/ipa-icf-gimple.h @@ -118,7 +118,7 @@ public: /* A class aggregating all connections and semantic equivalents for a given pair of semantic function candidates. */ -class func_checker +class func_checker : operand_compare { public: /* Initialize internal structures for a given SOURCE_FUNC_DECL and @@ -134,7 +134,7 @@ public: hash_set *ignored_target_nodes = NULL); /* Memory release routine. */ - ~func_checker(); + virtual ~func_checker (); /* Function visits all gimple labels and creates corresponding mapping between basic blocks and labels. */ @@ -267,6 +267,14 @@ private: /* Flag if ignore labels in comparison. */ bool m_ignore_labels; + + /* 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); + + /* Generate a hash value for an expression. This can be used iteratively + by passing a previous result as the HSTATE argument. */ + virtual void hash_operand (const_tree, inchash::hash &, unsigned flags); }; } // ipa_icf_gimple namespace diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 13b46483f2d..60aaf35d49c 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -878,9 +878,14 @@ sem_function::equals_private (sem_item *item) } /* Checking all basic blocks. */ + push_cfun (DECL_STRUCT_FUNCTION (decl)); 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(); + { + pop_cfun (); + return return_false (); + } + pop_cfun (); auto_vec bb_dict; -- 2.30.2