From: Jan Hubicka Date: Sun, 1 Mar 2015 22:22:26 +0000 (+0100) Subject: ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a8d9381738d229b9ebad9a91bc2cd211e368c750;p=gcc.git ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT. * ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT. (sem_item::add_expr): New function. (sem_function::hash_stmt): Handle operands of most statements. (sem_variable::get_hash): Hash the actual constructor. * ipa-icf.h (sem_item): Add add_expr. (sem_function): Update prototype of hash_stmt From-SVN: r221092 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ef9292f0f81..dcaa0f32830 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-02-28 Jan Hubicka + + * ipa-icf.c (sem_function::init): Fix formating; skip GIMPLE_PREDICT. + (sem_item::add_expr): New function. + (sem_function::hash_stmt): Handle operands of most statements. + (sem_variable::get_hash): Hash the actual constructor. + * ipa-icf.h (sem_item): Add add_expr. + (sem_function): Update prototype of hash_stmt + 2015-02-28 Martin Liska Jan Hubicka diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index 0de69a83fb5..68d02e47332 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -1030,7 +1030,8 @@ sem_function::init (void) unsigned nondbg_stmt_count = 0; edge e; - for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e); ei_next (&ei)) + for (edge_iterator ei = ei_start (bb->preds); ei_cond (ei, &e); + ei_next (&ei)) cfg_checksum = iterative_hash_host_wide_int (e->flags, cfg_checksum); @@ -1039,9 +1040,10 @@ sem_function::init (void) { gimple stmt = gsi_stmt (gsi); - if (gimple_code (stmt) != GIMPLE_DEBUG) + if (gimple_code (stmt) != GIMPLE_DEBUG + && gimple_code (stmt) != GIMPLE_PREDICT) { - hash_stmt (&hstate, stmt); + hash_stmt (stmt, hstate); nondbg_stmt_count++; } } @@ -1051,7 +1053,8 @@ sem_function::init (void) /* Inserting basic block to hash table. */ sem_bb *semantic_bb = new sem_bb (bb, nondbg_stmt_count, - EDGE_COUNT (bb->preds) + EDGE_COUNT (bb->succs)); + EDGE_COUNT (bb->preds) + + EDGE_COUNT (bb->succs)); bb_sorted.safe_push (semantic_bb); } @@ -1059,52 +1062,119 @@ sem_function::init (void) parse_tree_args (); } +/* 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_wide_int (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_wide_int (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_wide_int (int_size_in_bytes (TREE_TYPE (exp))); + return add_expr (TREE_OPERAND (exp, 0), hstate); + default: + break; + } +} + /* Improve accumulated hash for HSTATE based on a gimple statement STMT. */ void -sem_function::hash_stmt (inchash::hash *hstate, gimple stmt) +sem_function::hash_stmt (gimple stmt, inchash::hash &hstate) { enum gimple_code code = gimple_code (stmt); - hstate->add_int (code); + hstate.add_int (code); - if (code == GIMPLE_CALL) + switch (code) { - /* Checking of argument. */ - for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i) + case GIMPLE_ASSIGN: + if (commutative_tree_code (gimple_assign_rhs_code (stmt)) + || commutative_ternary_tree_code (gimple_assign_rhs_code (stmt))) { - tree argument = gimple_call_arg (stmt, i); + inchash::hash one, two; - switch (TREE_CODE (argument)) - { - case INTEGER_CST: - if (tree_fits_shwi_p (argument)) - hstate->add_wide_int (tree_to_shwi (argument)); - else if (tree_fits_uhwi_p (argument)) - hstate->add_wide_int (tree_to_uhwi (argument)); - break; - case REAL_CST: - REAL_VALUE_TYPE c; - HOST_WIDE_INT n; - - c = TREE_REAL_CST (argument); - n = real_to_integer (&c); - - hstate->add_wide_int (n); - break; - case ADDR_EXPR: - { - tree addr_operand = TREE_OPERAND (argument, 0); - - if (TREE_CODE (addr_operand) == STRING_CST) - hstate->add (TREE_STRING_POINTER (addr_operand), - TREE_STRING_LENGTH (addr_operand)); - break; - } - default: - break; - } + add_expr (gimple_assign_rhs1 (stmt), one); + add_expr (gimple_assign_rhs2 (stmt), two); + hstate.add_commutative (one, two); + add_expr (gimple_assign_lhs (stmt), hstate); + break; } + /* ... fall through ... */ + case GIMPLE_CALL: + case GIMPLE_ASM: + case GIMPLE_COND: + case GIMPLE_GOTO: + 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); + default: + break; } } @@ -1474,17 +1544,17 @@ sem_variable::get_hash (void) if (hash) return hash; + /* 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; hstate.add_int (456346417); - hstate.add_int (TREE_CODE (ctor)); - - if (TREE_CODE (ctor) == CONSTRUCTOR) - { - unsigned length = vec_safe_length (CONSTRUCTOR_ELTS (ctor)); - hstate.add_int (length); - } - + if (DECL_SIZE (decl) && tree_fits_shwi_p (DECL_SIZE (decl))) + hstate.add_wide_int (tree_to_shwi (DECL_SIZE (decl))); + add_expr (ctor, hstate); hash = hstate.end (); return hash; diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h index bf01cf09f21..3e5d458247c 100644 --- a/gcc/ipa-icf.h +++ b/gcc/ipa-icf.h @@ -241,6 +241,8 @@ 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); private: /* Initialize internal data structures. Bitmap STACK is used for @@ -290,7 +292,7 @@ public: } /* Improve accumulated hash for HSTATE based on a gimple statement STMT. */ - void hash_stmt (inchash::hash *inchash, gimple stmt); + void hash_stmt (gimple stmt, inchash::hash &inchash); /* Return true if polymorphic comparison must be processed. */ bool compare_polymorphic_p (void);