aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-icf-gimple.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2020-11-13 11:41:13 +0100
committerJan Hubicka <jh@suse.cz>2020-11-13 16:04:48 +0100
commita1fdc16da341187846dd0577e96ee00df5f28608 (patch)
tree78db15ad478a4d755ad7282e1f824d1c32f9e95f /gcc/ipa-icf-gimple.c
parent156edf21fab7dd5891c72db7ec58b38ef7d52bfa (diff)
downloadgcc-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.c109
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