Commit 520b3022 by Martin Liska Committed by Martin Liska

IPA ICF: compare_operand is split to multiple functions.

	* ipa-icf-gimple.c (func_checker::compare_ssa_name): Enhance SSA
	name comparison.
	(func_checker::compare_memory_operand): New function.
	(func_checker::compare_operand): Split case to newly
	added functions.
	(func_checker::compare_cst_or_decl): New function.
	(func_checker::compare_gimple_call): Identify
	memory operands.
	(func_checker::compare_gimple_assign): Likewise.
	* ipa-icf-gimple.h: New function.

From-SVN: r219379
parent ce9401b4
2015-01-09 Martin Liska <mliska@suse.cz>
* ipa-icf-gimple.c (func_checker::compare_ssa_name): Enhance SSA
name comparison.
(func_checker::compare_memory_operand): New function.
(func_checker::compare_operand): Split case to newly
added functions.
(func_checker::compare_cst_or_decl): New function.
(func_checker::compare_gimple_call): Identify
memory operands.
(func_checker::compare_gimple_assign): Likewise.
* ipa-icf-gimple.h: New function.
2015-01-09 Martin Liska <mliska@suse.cz>
PR ipa/64503
* sreal.c (sreal::dump): Change unsigned format to signed for
m_exp value.
......
......@@ -110,6 +110,9 @@ func_checker::~func_checker ()
bool
func_checker::compare_ssa_name (tree t1, tree t2)
{
gcc_assert (TREE_CODE (t1) == SSA_NAME);
gcc_assert (TREE_CODE (t2) == SSA_NAME);
unsigned i1 = SSA_NAME_VERSION (t1);
unsigned i2 = SSA_NAME_VERSION (t2);
......@@ -123,6 +126,20 @@ func_checker::compare_ssa_name (tree t1, tree t2)
else if (m_target_ssa_names[i2] != (int) i1)
return false;
if (SSA_NAME_IS_DEFAULT_DEF (t1))
{
tree b1 = SSA_NAME_VAR (t1);
tree b2 = SSA_NAME_VAR (t2);
if (b1 == NULL && b2 == NULL)
return true;
if (b1 == NULL || b2 == NULL || TREE_CODE (b1) != TREE_CODE (b2))
return return_false ();
return compare_cst_or_decl (b1, b2);
}
return true;
}
......@@ -178,9 +195,10 @@ func_checker::compare_decl (tree t1, tree t2)
}
/* Return true if types are compatible from perspective of ICF. */
bool func_checker::compatible_types_p (tree t1, tree t2,
bool compare_polymorphic,
bool first_argument)
bool
func_checker::compatible_types_p (tree t1, tree t2,
bool compare_polymorphic,
bool first_argument)
{
if (TREE_CODE (t1) != TREE_CODE (t2))
return return_false_with_msg ("different tree types");
......@@ -214,15 +232,112 @@ bool func_checker::compatible_types_p (tree t1, tree t2,
return true;
}
/* Function responsible for comparison of handled components T1 and T2.
/* Function compare for equality given memory operands T1 and T2. */
bool
func_checker::compare_memory_operand (tree t1, tree t2)
{
if (!t1 && !t2)
return true;
else if (!t1 || !t2)
return false;
ao_ref r1, r2;
ao_ref_init (&r1, t1);
ao_ref_init (&r2, t2);
tree b1 = ao_ref_base (&r1);
tree b2 = ao_ref_base (&r2);
bool source_is_memop = DECL_P (b1) || INDIRECT_REF_P (b1)
|| TREE_CODE (b1) == MEM_REF
|| TREE_CODE (b1) == TARGET_MEM_REF;
bool target_is_memop = DECL_P (b2) || INDIRECT_REF_P (b2)
|| TREE_CODE (b2) == MEM_REF
|| TREE_CODE (b2) == TARGET_MEM_REF;
/* Compare alias sets for memory operands. */
if (source_is_memop && target_is_memop)
{
if (TREE_THIS_VOLATILE (b1) != TREE_THIS_VOLATILE (b2))
return return_false_with_msg ("different operand volatility");
if (ao_ref_alias_set (&r1) != ao_ref_alias_set (&r2)
|| ao_ref_base_alias_set (&r1) != ao_ref_base_alias_set (&r2))
return return_false_with_msg ("ao alias sets are different");
}
return compare_operand (t1, t2);
}
/* Function compare for equality given trees T1 and T2 which
can be either a constant or a declaration type. */
bool
func_checker::compare_cst_or_decl (tree t1, tree t2)
{
bool ret;
switch (TREE_CODE (t1))
{
case INTEGER_CST:
case COMPLEX_CST:
case VECTOR_CST:
case STRING_CST:
case REAL_CST:
{
ret = compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& operand_equal_p (t1, t2, OEP_ONLY_CONST);
return return_with_debug (ret);
}
case FUNCTION_DECL:
{
ret = compare_function_decl (t1, t2);
return return_with_debug (ret);
}
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:
{
int *bb1 = m_label_bb_map.get (t1);
int *bb2 = m_label_bb_map.get (t2);
return return_with_debug (*bb1 == *bb2);
}
case PARM_DECL:
case RESULT_DECL:
case CONST_DECL:
{
ret = compare_decl (t1, t2);
return return_with_debug (ret);
}
default:
gcc_unreachable ();
}
}
/* 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)
{
tree base1, base2, x1, x2, y1, y2, z1, z2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
tree x1, x2, y1, y2, z1, z2;
bool ret;
if (!t1 && !t2)
......@@ -233,24 +348,9 @@ func_checker::compare_operand (tree t1, tree t2)
tree tt1 = TREE_TYPE (t1);
tree tt2 = TREE_TYPE (t2);
if (TREE_THIS_VOLATILE (t1) != TREE_THIS_VOLATILE (t2))
return return_false_with_msg ("different operand volatility");
if (!func_checker::compatible_types_p (tt1, tt2))
return false;
base1 = get_addr_base_and_unit_offset (t1, &offset1);
base2 = get_addr_base_and_unit_offset (t2, &offset2);
if (base1 && base2)
{
if (offset1 != offset2)
return return_false_with_msg ("base offsets are different");
t1 = base1;
t2 = base2;
}
if (TREE_CODE (t1) != TREE_CODE (t2))
return return_false ();
......@@ -273,6 +373,7 @@ func_checker::compare_operand (tree t1, tree t2)
}
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);
......@@ -284,6 +385,7 @@ func_checker::compare_operand (tree t1, tree t2)
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);
......@@ -308,16 +410,6 @@ func_checker::compare_operand (tree t1, tree t2)
if (!compare_operand (x1, x2))
return return_false_with_msg ("");
if (get_alias_set (TREE_TYPE (y1)) != get_alias_set (TREE_TYPE (y2)))
return return_false_with_msg ("alias set for MEM_REF offsets are different");
ao_ref r1, r2;
ao_ref_init (&r1, t1);
ao_ref_init (&r2, t2);
if (ao_ref_alias_set (&r1) != ao_ref_alias_set (&r2)
|| ao_ref_base_alias_set (&r1) != ao_ref_base_alias_set (&r2))
return return_false_with_msg ("ao alias sets are different");
/* Type of the offset on MEM_REF does not matter. */
return wi::to_offset (y1) == wi::to_offset (y2);
}
......@@ -329,7 +421,7 @@ func_checker::compare_operand (tree t1, tree t2)
y2 = TREE_OPERAND (t2, 1);
ret = compare_operand (x1, x2)
&& compare_operand (y1, y2);
&& compare_cst_or_decl (y1, y2);
return return_with_debug (ret);
}
......@@ -343,9 +435,9 @@ func_checker::compare_operand (tree t1, tree t2)
z1 = TREE_OPERAND (t1, 2);
z2 = TREE_OPERAND (t2, 2);
ret = compare_operand (x1, x2)
&& compare_operand (y1, y2)
&& compare_operand (z1, z2);
ret = compare_ssa_name (x1, x2)
&& compare_ssa_name (y1, y2)
&& compare_cst_or_decl (z1, z2);
return return_with_debug (ret);
}
......@@ -357,89 +449,26 @@ func_checker::compare_operand (tree t1, tree t2)
ret = compare_operand (x1, x2);
return return_with_debug (ret);
}
case SSA_NAME:
{
ret = compare_ssa_name (t1, t2);
if (!ret)
return return_with_debug (ret);
if (SSA_NAME_IS_DEFAULT_DEF (t1))
{
tree b1 = SSA_NAME_VAR (t1);
tree b2 = SSA_NAME_VAR (t2);
if (b1 == NULL && b2 == NULL)
return true;
if (b1 == NULL || b2 == NULL || TREE_CODE (b1) != TREE_CODE (b2))
return return_false ();
switch (TREE_CODE (b1))
{
case VAR_DECL:
return return_with_debug (compare_variable_decl (t1, t2));
case PARM_DECL:
case RESULT_DECL:
ret = compare_decl (b1, b2);
return return_with_debug (ret);
default:
return return_false_with_msg ("Unknown TREE code reached");
}
}
else
return true;
}
case INTEGER_CST:
case BIT_FIELD_REF:
{
ret = compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& wi::to_offset (t1) == wi::to_offset (t2);
ret = compare_decl (t1, t2);
return return_with_debug (ret);
}
case SSA_NAME:
return compare_ssa_name (t1, t2);
case INTEGER_CST:
case COMPLEX_CST:
case VECTOR_CST:
case STRING_CST:
case REAL_CST:
{
ret = operand_equal_p (t1, t2, OEP_ONLY_CONST);
return return_with_debug (ret);
}
case FUNCTION_DECL:
{
ret = compare_function_decl (t1, t2);
return return_with_debug (ret);
}
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:
{
int *bb1 = m_label_bb_map.get (t1);
int *bb2 = m_label_bb_map.get (t2);
return return_with_debug (*bb1 == *bb2);
}
case PARM_DECL:
case RESULT_DECL:
case CONST_DECL:
case BIT_FIELD_REF:
{
ret = compare_decl (t1, t2);
return return_with_debug (ret);
}
return compare_cst_or_decl (t1, t2);
default:
return return_false_with_msg ("Unknown TREE code reached");
}
......@@ -706,15 +735,15 @@ 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))
return false;
if (!compare_memory_operand (t1, t2))
return return_false_with_msg ("memory operands are different");
}
/* Return value checking. */
t1 = gimple_get_lhs (s1);
t2 = gimple_get_lhs (s2);
return compare_operand (t1, t2);
return compare_memory_operand (t1, t2);
}
......@@ -745,8 +774,8 @@ func_checker::compare_gimple_assign (gimple s1, gimple s2)
arg1 = gimple_op (s1, i);
arg2 = gimple_op (s2, i);
if (!compare_operand (arg1, arg2))
return false;
if (!compare_memory_operand (arg1, arg2))
return return_false_with_msg ("memory operands are different");
}
......
......@@ -203,7 +203,14 @@ public:
/* Verifies that tree labels T1 and T2 correspond. */
bool compare_tree_ssa_label (tree t1, tree t2);
/* Function responsible for comparison of handled components T1 and T2.
/* Function compare for equality given memory operands T1 and T2. */
bool 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 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 compare_operand (tree t1, tree t2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment