From 4630573709177f43b6b755326c90d6b777fbb2ab Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 2 Mar 2015 01:54:46 +0100 Subject: [PATCH] ipa-icf.c: Include stor-layout.h * ipa-icf.c: Include stor-layout.h (sem_function::compare_cgraph_references): Rename to ... (sem_item::compare_cgraph_references): ... this one. (sem_variable::equals_wpa): New function (sem_variable::equals): Do not check stuff already verified by equals_wpa. (sem_variable::equals): Reorg based on varasm.c:compare_constant. * ipa-icf.h (sem_item): Add compare_cgraph_references. (sem_function): Remove compare_cgraph_references. (sem_variable): Turns equals_wpa into non-inline. From-SVN: r221096 --- gcc/ChangeLog | 13 ++++ gcc/ipa-icf.c | 210 ++++++++++++++++++++++++++++++++++++++++++-------- gcc/ipa-icf.h | 25 +++--- 3 files changed, 201 insertions(+), 47 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dcaa0f32830..7b002bbcdfc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2015-02-28 Jan Hubicka + + * ipa-icf.c: Include stor-layout.h + (sem_function::compare_cgraph_references): Rename to ... + (sem_item::compare_cgraph_references): ... this one. + (sem_variable::equals_wpa): New function + (sem_variable::equals): Do not check stuff already verified by + equals_wpa. + (sem_variable::equals): Reorg based on varasm.c:compare_constant. + * ipa-icf.h (sem_item): Add compare_cgraph_references. + (sem_function): Remove compare_cgraph_references. + (sem_variable): Turns equals_wpa into non-inline. + 2015-02-28 Jan Hubicka * ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT. diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 68d02e47332..a2d99e9a8e8 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" +#include #include "coretypes.h" #include "hash-set.h" #include "machmode.h" @@ -119,9 +120,9 @@ along with GCC; see the file COPYING3. If not see #include "lto-streamer.h" #include "data-streamer.h" #include "ipa-utils.h" -#include #include "ipa-icf-gimple.h" #include "ipa-icf.h" +#include "stor-layout.h" using namespace ipa_icf_gimple; @@ -338,7 +339,7 @@ sem_function::get_hash (void) contains these nodes. ADDRESS indicate if address is taken. */ bool -sem_function::compare_cgraph_references ( +sem_item::compare_cgraph_references ( hash_map &ignored_nodes, symtab_node *n1, symtab_node *n2, bool address) { @@ -1395,6 +1396,56 @@ sem_variable::sem_variable (varpool_node *node, hashval_t _hash, gcc_checking_assert (get_node ()); } +/* Fast equality function based on knowledge known in WPA. */ + +bool +sem_variable::equals_wpa (sem_item *item, + hash_map &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"); + + if (DECL_ALIGN (decl) != DECL_ALIGN (item->decl)) + return return_false_with_msg ("alignment mismatch"); + + 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 (!compare_cgraph_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 @@ -1408,17 +1459,6 @@ sem_variable::equals (sem_item *item, if (!ctor || !v->ctor) return return_false_with_msg ("ctor is missing for semantic variable"); - if (DECL_IN_CONSTANT_POOL (decl) - && (DECL_IN_CONSTANT_POOL (item->decl) - || item->node->address_matters_p ())) - return return_false_with_msg ("constant pool"); - - if (DECL_IN_TEXT_SECTION (decl) != DECL_IN_TEXT_SECTION (item->decl)) - return return_false_with_msg ("text section"); - - if (DECL_TLS_MODEL (decl) || DECL_TLS_MODEL (item->decl)) - return return_false_with_msg ("TLS model"); - return sem_variable::equals (ctor, v->ctor); } @@ -1427,28 +1467,57 @@ sem_variable::equals (sem_item *item, 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 false; + return return_false_with_msg ("TREE_CODE mismatch"); switch (tc1) { case CONSTRUCTOR: { - unsigned len1 = vec_safe_length (CONSTRUCTOR_ELTS (t1)); - unsigned len2 = vec_safe_length (CONSTRUCTOR_ELTS (t2)); + vec *v1, *v2; + unsigned HOST_WIDE_INT idx; - if (len1 != len2) - return false; + 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"); - for (unsigned i = 0; i < len1; i++) - if (!sem_variable::equals (CONSTRUCTOR_ELT (t1, i)->value, - CONSTRUCTOR_ELT (t2, i)->value) - || CONSTRUCTOR_ELT (t1, i)->index != CONSTRUCTOR_ELT (t2, i)->index) - return false; + 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: @@ -1463,32 +1532,100 @@ sem_variable::equals (tree t1, tree t2) return return_false (); /* Type of the offset on MEM_REF does not matter. */ - return sem_variable::equals (x1, x2) - && wi::to_offset (y1) == wi::to_offset (y2); + return return_with_debug (sem_variable::equals (x1, x2) + && wi::to_offset (y1) + == wi::to_offset (y2)); } - case NOP_EXPR: 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 t1 == t2; + return return_false_with_msg ("Declaration mismatch"); case INTEGER_CST: - return func_checker::compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2), - true) - && wi::to_offset (t1) == wi::to_offset (t2); + /* 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: - case REAL_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 operand_equal_p (t1, t2, OEP_ONLY_CONST); - case COMPONENT_REF: + 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_VALUES_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); @@ -1497,6 +1634,13 @@ sem_variable::equals (tree t1, tree t2) 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), + true)) + 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: diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h index 3e5d458247c..b4862b75357 100644 --- a/gcc/ipa-icf.h +++ b/gcc/ipa-icf.h @@ -241,9 +241,18 @@ public: protected: /* Cached, once calculated hash for the item. */ hashval_t hash; + /* Accumulate to HSTATE a hash of constructor expression EXP. */ static void add_expr (const_tree exp, inchash::hash &hstate); + /* 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 compare_cgraph_references (hash_map + &ignored_nodes, + symtab_node *n1, symtab_node *n2, + bool address); + private: /* Initialize internal data structures. Bitmap STACK is used for bitmap memory allocation process. */ @@ -353,14 +362,6 @@ private: ICF flags are the same. */ bool compare_edge_flags (cgraph_edge *e1, cgraph_edge *e2); - /* 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 compare_cgraph_references (hash_map - &ignored_nodes, - symtab_node *n1, symtab_node *n2, - bool address); - /* Processes function equality comparison. */ bool equals_private (sem_item *item, hash_map &ignored_nodes); @@ -402,12 +403,8 @@ public: hash_map &ignored_nodes); /* Fast equality variable based on knowledge known in WPA. */ - inline virtual bool equals_wpa (sem_item *item, - hash_map & ARG_UNUSED(ignored_nodes)) - { - gcc_assert (item->type == VAR); - return true; - } + virtual bool equals_wpa (sem_item *item, + hash_map &ignored_nodes); /* Returns varpool_node. */ inline varpool_node *get_node (void) -- 2.30.2