diff options
author | Jan Hubicka <jh@suse.cz> | 2020-11-13 11:41:13 +0100 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2020-11-13 16:04:48 +0100 |
commit | a1fdc16da341187846dd0577e96ee00df5f28608 (patch) | |
tree | 78db15ad478a4d755ad7282e1f824d1c32f9e95f /gcc/ipa-icf-gimple.c | |
parent | 156edf21fab7dd5891c72db7ec58b38ef7d52bfa (diff) | |
download | gcc-a1fdc16da341187846dd0577e96ee00df5f28608.zip gcc-a1fdc16da341187846dd0577e96ee00df5f28608.tar.gz gcc-a1fdc16da341187846dd0577e96ee00df5f28608.tar.bz2 |
Determine access types in ipa-icf-gimple.c
This patch adds logic to determine access type (normal or memory) for every
operand. This makes it possible to compare memory accesses more carefully
which will be implemented in a followup patch.
* ipa-icf-gimple.c: Include gimple-walk.h.
(func_checker::compare_ssa_name): Update call of compare_operand.
(func_checker::hash_operand): Fix comment and add variant taking
operand_access_type parameter.
(func_checker::compare_operand): Add operand_access_type parameter.
(func_checker::compare_asm_inputs_outputs): Add
operand_access_type_map parameter; update use of
func_checker::compare_operand.
(func_checker::compare_gimple_call): Update use of
func_checker::compare_operand.
(func_checker::compare_gimple_assign): Likewise.
(func_checker::compare_gimple_cond): Likewise.
(func_checker::compare_gimple_switch): Likewise.
(func_checker::compare_gimple_return): Likewise.
(func_checker::compare_gimple_goto): Likewise.
(func_checker::compare_gimple_asm): Likewise.
(visit_load_store): New static functio.
(func_checker::classify_operands): New member function.
(func_checker::get_operand_access_type): New member function.
* ipa-icf-gimple.h (func_checker::operand_access_type): New enum
(func_checker::operand_access_type_map): New typedef.
(func_checker::compare_operand): Update prototype.
(func_checker::compare_asm_inputs_outputs): Likewise.
(func_checker::cleassify_operands): Declare.
(func_checker::get_operand_access_type): Declare.
(func_checker::hash_operand): New variant with operand_access_type.
* ipa-icf.c (sem_function::hash_stmt): Update uses of hash_operand.
(sem_function::compare_phi_node): Update use of compare_operand.
Diffstat (limited to 'gcc/ipa-icf-gimple.c')
-rw-r--r-- | gcc/ipa-icf-gimple.c | 109 |
1 files changed, 88 insertions, 21 deletions
diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c index b755d7e..0276b20 100644 --- a/gcc/ipa-icf-gimple.c +++ b/gcc/ipa-icf-gimple.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "cfgloop.h" #include "attribs.h" +#include "gimple-walk.h" #include "ipa-icf-gimple.h" @@ -109,7 +110,7 @@ func_checker::compare_ssa_name (const_tree t1, const_tree t2) tree b1 = SSA_NAME_VAR (t1); tree b2 = SSA_NAME_VAR (t2); - return compare_operand (b1, b2); + return compare_operand (b1, b2, OP_NORMAL); } return true; @@ -212,8 +213,8 @@ func_checker::compatible_types_p (tree t1, tree t2) return true; } -/* Function compare for equality given trees T1 and T2 which - can be either a constant or a declaration type. */ +/* Add hash of ARG to HSTATE. FLAGS have same meaning + as for operand_equal_p. Works only if operand acces type is OP_NORMAL. */ void func_checker::hash_operand (const_tree arg, inchash::hash &hstate, @@ -246,6 +247,16 @@ func_checker::hash_operand (const_tree arg, inchash::hash &hstate, return operand_compare::hash_operand (arg, hstate, flags); } +/* Add hash of ARG accesses according to ACCESS to HSTATE. + FLAGS have same meaning as for operand_equal_p. */ + +void +func_checker::hash_operand (const_tree arg, inchash::hash &hstate, + unsigned int flags, operand_access_type) +{ + return hash_operand (arg, hstate, flags); +} + bool func_checker::operand_equal_p (const_tree t1, const_tree t2, unsigned int flags) @@ -291,12 +302,13 @@ func_checker::operand_equal_p (const_tree t1, const_tree t2, return operand_compare::operand_equal_p (t1, t2, flags); } -/* Function responsible for comparison of various operands T1 and T2. +/* Function responsible for comparison of various operands T1 and T2 + which are accessed as ACCESS. If these components, from functions FUNC1 and FUNC2, are equal, true is returned. */ bool -func_checker::compare_operand (tree t1, tree t2) +func_checker::compare_operand (tree t1, tree t2, operand_access_type access) { if (!t1 && !t2) return true; @@ -304,11 +316,21 @@ func_checker::compare_operand (tree t1, tree t2) return false; if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS)) return true; - return return_false_with_msg ("operand_equal_p failed"); + switch (access) + { + case OP_MEMORY: + return return_false_with_msg + ("operand_equal_p failed (access == memory)"); + case OP_NORMAL: + return return_false_with_msg + ("operand_equal_p failed (access == normal)"); + } + gcc_unreachable (); } bool -func_checker::compare_asm_inputs_outputs (tree t1, tree t2) +func_checker::compare_asm_inputs_outputs (tree t1, tree t2, + operand_access_type_map *map) { gcc_assert (TREE_CODE (t1) == TREE_LIST); gcc_assert (TREE_CODE (t2) == TREE_LIST); @@ -318,7 +340,8 @@ func_checker::compare_asm_inputs_outputs (tree t1, tree t2) if (!t2) return false; - if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2))) + if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2), + get_operand_access_type (map, t1))) return return_false (); tree p1 = TREE_PURPOSE (t1); @@ -545,9 +568,12 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) if (gimple_call_num_args (s1) != gimple_call_num_args (s2)) return false; + operand_access_type_map map (5); + classify_operands (s1, &map); + t1 = gimple_call_fn (s1); t2 = gimple_call_fn (s2); - if (!compare_operand (t1, t2)) + if (!compare_operand (t1, t2, get_operand_access_type (&map, t1))) return return_false (); /* Compare flags. */ @@ -579,7 +605,8 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) tree chain2 = gimple_call_chain (s2); if ((chain1 && !chain2) || (!chain1 && chain2) - || !compare_operand (chain1, chain2)) + || !compare_operand (chain1, chain2, + get_operand_access_type (&map, chain1))) return return_false_with_msg ("static call chains are different"); /* Checking of argument. */ @@ -588,7 +615,7 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) t1 = gimple_call_arg (s1, i); t2 = gimple_call_arg (s2, i); - if (!compare_operand (t1, t2)) + if (!compare_operand (t1, t2, get_operand_access_type (&map, t1))) return return_false_with_msg ("GIMPLE call operands are different"); } @@ -596,7 +623,7 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) t1 = gimple_get_lhs (s1); t2 = gimple_get_lhs (s2); - return compare_operand (t1, t2); + return compare_operand (t1, t2, get_operand_access_type (&map, t1)); } @@ -616,6 +643,9 @@ func_checker::compare_gimple_assign (gimple *s1, gimple *s2) if (code1 != code2) return false; + operand_access_type_map map (5); + classify_operands (s1, &map); + for (i = 0; i < gimple_num_ops (s1); i++) { arg1 = gimple_op (s1, i); @@ -628,7 +658,7 @@ func_checker::compare_gimple_assign (gimple *s1, gimple *s2) return return_false_with_msg ("GIMPLE NOP LHS type mismatch"); } - if (!compare_operand (arg1, arg2)) + if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1))) return return_false_with_msg ("GIMPLE assignment operands " "are different"); } @@ -655,13 +685,13 @@ func_checker::compare_gimple_cond (gimple *s1, gimple *s2) t1 = gimple_cond_lhs (s1); t2 = gimple_cond_lhs (s2); - if (!compare_operand (t1, t2)) + if (!compare_operand (t1, t2, OP_NORMAL)) return false; t1 = gimple_cond_rhs (s1); t2 = gimple_cond_rhs (s2); - return compare_operand (t1, t2); + return compare_operand (t1, t2, OP_NORMAL); } /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that @@ -700,7 +730,7 @@ func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2) tree t1 = gimple_switch_index (g1); tree t2 = gimple_switch_index (g2); - if (!compare_operand (t1, t2)) + if (!compare_operand (t1, t2, OP_NORMAL)) return false; for (i = 0; i < lsize1; i++) @@ -727,7 +757,7 @@ func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2) label1 = CASE_LABEL (label1); label2 = CASE_LABEL (label2); - if (!compare_operand (label1, label2)) + if (!compare_operand (label1, label2, OP_NORMAL)) return return_false_with_msg ("switch label_exprs are different"); } else if (!tree_int_cst_equal (label1, label2)) @@ -752,7 +782,10 @@ func_checker::compare_gimple_return (const greturn *g1, const greturn *g2) if (t1 == NULL && t2 == NULL) return true; else - return compare_operand (t1, t2); + { + operand_access_type_map map (3); + return compare_operand (t1, t2, get_operand_access_type (&map, t1)); + } } /* Verifies for given GIMPLEs S1 and S2 that @@ -769,7 +802,7 @@ func_checker::compare_gimple_goto (gimple *g1, gimple *g2) if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME) return false; - return compare_operand (dest1, dest2); + return compare_operand (dest1, dest2, OP_NORMAL); } /* Verifies for given GIMPLE_RESX stmts S1 and S2 that @@ -813,12 +846,15 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2) if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0) return return_false_with_msg ("ASM strings are different"); + operand_access_type_map map (5); + classify_operands (g1, &map); + for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++) { tree input1 = gimple_asm_input_op (g1, i); tree input2 = gimple_asm_input_op (g2, i); - if (!compare_asm_inputs_outputs (input1, input2)) + if (!compare_asm_inputs_outputs (input1, input2, &map)) return return_false_with_msg ("ASM input is different"); } @@ -827,7 +863,7 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2) tree output1 = gimple_asm_output_op (g1, i); tree output2 = gimple_asm_output_op (g2, i); - if (!compare_asm_inputs_outputs (output1, output2)) + if (!compare_asm_inputs_outputs (output1, output2, &map)) return return_false_with_msg ("ASM output is different"); } @@ -844,4 +880,35 @@ func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2) return true; } +/* Helper for func_checker::classify_operands. Record that T is a load. */ + +static bool +visit_load_store (gimple *, tree, tree t, void *data) +{ + func_checker::operand_access_type_map *map = + (func_checker::operand_access_type_map *) data; + map->add (t); + return false; +} + +/* Compute hash map determining access types of operands. */ + +void +func_checker::classify_operands (const gimple *stmt, + operand_access_type_map *map) +{ + walk_stmt_load_store_ops (const_cast <gimple *> (stmt), + (void *)map, visit_load_store, visit_load_store); +} + +/* Return access type of a given operand. */ + +func_checker::operand_access_type +func_checker::get_operand_access_type (operand_access_type_map *map, tree t) +{ + if (map->contains (t)) + return OP_MEMORY; + return OP_NORMAL; +} + } // ipa_icf_gimple namespace |