Re: [PATCH 6/9] Integrate that for IPA ICF.
I'm sending updated version of the patch. Note: there are some (tree)const_cast (t2) casting. I've got a clean up patch for that which will improve it. Martin >From 20020586beabf1fc9f7860f46bb0c092f8536539 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 10 Jun 2019 14:34:15 +0200 Subject: [PATCH 6/9] Integrate that for IPA ICF. gcc/ChangeLog: 2019-08-15 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. --- gcc/ipa-icf-gimple.c | 228 +++ gcc/ipa-icf-gimple.h | 12 ++- gcc/ipa-icf.c| 7 +- 3 files changed, 95 insertions(+), 152 deletions(-) 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 , + 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, )) +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 = TRE
[PATCH 6/9] Integrate that for IPA ICF.
gcc/ChangeLog: 2019-07-24 Martin Liska * ipa-icf-gimple.c (func_checker::hash_operand_valueize): New function created from compare_operand. (func_checker::compare_cst_or_decl): Remove handling of FIELD_DECLs as it's handled in operand_equal_p. (func_checker::compare_operand): Transform to func_checker::operand_equal_valueize. (func_checker::operand_equal_valueize): New. * ipa-icf-gimple.h (class func_checker): Inherit from operand_compare. * ipa-icf.c (sem_function::equals_private): Properly set push_cfun and pop_cfun. --- gcc/ipa-icf-gimple.c | 226 +-- gcc/ipa-icf-gimple.h | 8 +- gcc/ipa-icf.c| 7 +- 3 files changed, 81 insertions(+), 160 deletions(-) diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c index 4060c0e8eb3..8448d387428 100644 --- a/gcc/ipa-icf-gimple.c +++ b/gcc/ipa-icf-gimple.c @@ -324,6 +324,28 @@ 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. */ +bool +func_checker::hash_operand_valueize (const_tree arg, inchash::hash , + unsigned int flags) +{ + 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 true; + +default: + break; +} + + return false; +} + bool func_checker::compare_cst_or_decl (tree t1, tree t2) { @@ -347,19 +369,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 +392,68 @@ 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) +int +func_checker::operand_equal_valueize (const_tree ct1, const_tree ct2, + unsigned int) { - tree x1, x2, y1, y2, z1, z2; - bool ret; - - 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 t1 = const_cast (ct1); + tree t2 = const_cast (ct2); 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 (t1, t2)); +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 (t1); + int *bb2 = m_label_bb_map.get (t2); + /* 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