mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-06 02:20:34 +08:00
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
This commit is contained in:
parent
3c37b96b87
commit
4630573709
@ -1,3 +1,16 @@
|
||||
2015-02-28 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* 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 <hubicka@ucw.cz>
|
||||
|
||||
* ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT.
|
||||
|
210
gcc/ipa-icf.c
210
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 <list>
|
||||
#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 <list>
|
||||
#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 <symtab_node *, sem_item *> &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 <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");
|
||||
|
||||
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<constructor_elt, va_gc> *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");
|
||||
|
||||
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;
|
||||
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:
|
||||
@ -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:
|
||||
|
@ -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 <symtab_node *, sem_item *>
|
||||
&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 <symtab_node *, sem_item *>
|
||||
&ignored_nodes,
|
||||
symtab_node *n1, symtab_node *n2,
|
||||
bool address);
|
||||
|
||||
/* Processes function equality comparison. */
|
||||
bool equals_private (sem_item *item,
|
||||
hash_map <symtab_node *, sem_item *> &ignored_nodes);
|
||||
@ -402,12 +403,8 @@ public:
|
||||
hash_map <symtab_node *, sem_item *> &ignored_nodes);
|
||||
|
||||
/* Fast equality variable based on knowledge known in WPA. */
|
||||
inline virtual bool equals_wpa (sem_item *item,
|
||||
hash_map <symtab_node *, sem_item *> & ARG_UNUSED(ignored_nodes))
|
||||
{
|
||||
gcc_assert (item->type == VAR);
|
||||
return true;
|
||||
}
|
||||
virtual bool equals_wpa (sem_item *item,
|
||||
hash_map <symtab_node *, sem_item *> &ignored_nodes);
|
||||
|
||||
/* Returns varpool_node. */
|
||||
inline varpool_node *get_node (void)
|
||||
|
Loading…
x
Reference in New Issue
Block a user