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> 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 PR ipa/64503
* sreal.c (sreal::dump): Change unsigned format to signed for * sreal.c (sreal::dump): Change unsigned format to signed for
m_exp value. m_exp value.
......
...@@ -110,6 +110,9 @@ func_checker::~func_checker () ...@@ -110,6 +110,9 @@ func_checker::~func_checker ()
bool bool
func_checker::compare_ssa_name (tree t1, tree t2) 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 i1 = SSA_NAME_VERSION (t1);
unsigned i2 = SSA_NAME_VERSION (t2); unsigned i2 = SSA_NAME_VERSION (t2);
...@@ -123,6 +126,20 @@ func_checker::compare_ssa_name (tree t1, tree t2) ...@@ -123,6 +126,20 @@ func_checker::compare_ssa_name (tree t1, tree t2)
else if (m_target_ssa_names[i2] != (int) i1) else if (m_target_ssa_names[i2] != (int) i1)
return false; 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; return true;
} }
...@@ -178,9 +195,10 @@ func_checker::compare_decl (tree t1, tree t2) ...@@ -178,9 +195,10 @@ func_checker::compare_decl (tree t1, tree t2)
} }
/* Return true if types are compatible from perspective of ICF. */ /* Return true if types are compatible from perspective of ICF. */
bool func_checker::compatible_types_p (tree t1, tree t2, bool
bool compare_polymorphic, func_checker::compatible_types_p (tree t1, tree t2,
bool first_argument) bool compare_polymorphic,
bool first_argument)
{ {
if (TREE_CODE (t1) != TREE_CODE (t2)) if (TREE_CODE (t1) != TREE_CODE (t2))
return return_false_with_msg ("different tree types"); return return_false_with_msg ("different tree types");
...@@ -214,15 +232,112 @@ bool func_checker::compatible_types_p (tree t1, tree t2, ...@@ -214,15 +232,112 @@ bool func_checker::compatible_types_p (tree t1, tree t2,
return true; 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 If these components, from functions FUNC1 and FUNC2, are equal, true
is returned. */ is returned. */
bool bool
func_checker::compare_operand (tree t1, tree t2) func_checker::compare_operand (tree t1, tree t2)
{ {
tree base1, base2, x1, x2, y1, y2, z1, z2; tree x1, x2, y1, y2, z1, z2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
bool ret; bool ret;
if (!t1 && !t2) if (!t1 && !t2)
...@@ -233,24 +348,9 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -233,24 +348,9 @@ func_checker::compare_operand (tree t1, tree t2)
tree tt1 = TREE_TYPE (t1); tree tt1 = TREE_TYPE (t1);
tree tt2 = TREE_TYPE (t2); 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)) if (!func_checker::compatible_types_p (tt1, tt2))
return false; 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)) if (TREE_CODE (t1) != TREE_CODE (t2))
return return_false (); return return_false ();
...@@ -273,6 +373,7 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -273,6 +373,7 @@ func_checker::compare_operand (tree t1, tree t2)
} }
case ARRAY_REF: case ARRAY_REF:
case ARRAY_RANGE_REF: case ARRAY_RANGE_REF:
/* First argument is the array, second is the index. */
x1 = TREE_OPERAND (t1, 0); x1 = TREE_OPERAND (t1, 0);
x2 = TREE_OPERAND (t2, 0); x2 = TREE_OPERAND (t2, 0);
y1 = TREE_OPERAND (t1, 1); y1 = TREE_OPERAND (t1, 1);
...@@ -284,6 +385,7 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -284,6 +385,7 @@ func_checker::compare_operand (tree t1, tree t2)
if (!compare_operand (array_ref_element_size (t1), if (!compare_operand (array_ref_element_size (t1),
array_ref_element_size (t2))) array_ref_element_size (t2)))
return return_false_with_msg (""); return return_false_with_msg ("");
if (!compare_operand (x1, x2)) if (!compare_operand (x1, x2))
return return_false_with_msg (""); return return_false_with_msg ("");
return compare_operand (y1, y2); return compare_operand (y1, y2);
...@@ -308,16 +410,6 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -308,16 +410,6 @@ func_checker::compare_operand (tree t1, tree t2)
if (!compare_operand (x1, x2)) if (!compare_operand (x1, x2))
return return_false_with_msg (""); 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. */ /* Type of the offset on MEM_REF does not matter. */
return wi::to_offset (y1) == wi::to_offset (y2); return wi::to_offset (y1) == wi::to_offset (y2);
} }
...@@ -329,7 +421,7 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -329,7 +421,7 @@ func_checker::compare_operand (tree t1, tree t2)
y2 = TREE_OPERAND (t2, 1); y2 = TREE_OPERAND (t2, 1);
ret = compare_operand (x1, x2) ret = compare_operand (x1, x2)
&& compare_operand (y1, y2); && compare_cst_or_decl (y1, y2);
return return_with_debug (ret); return return_with_debug (ret);
} }
...@@ -343,9 +435,9 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -343,9 +435,9 @@ func_checker::compare_operand (tree t1, tree t2)
z1 = TREE_OPERAND (t1, 2); z1 = TREE_OPERAND (t1, 2);
z2 = TREE_OPERAND (t2, 2); z2 = TREE_OPERAND (t2, 2);
ret = compare_operand (x1, x2) ret = compare_ssa_name (x1, x2)
&& compare_operand (y1, y2) && compare_ssa_name (y1, y2)
&& compare_operand (z1, z2); && compare_cst_or_decl (z1, z2);
return return_with_debug (ret); return return_with_debug (ret);
} }
...@@ -357,89 +449,26 @@ func_checker::compare_operand (tree t1, tree t2) ...@@ -357,89 +449,26 @@ func_checker::compare_operand (tree t1, tree t2)
ret = compare_operand (x1, x2); ret = compare_operand (x1, x2);
return return_with_debug (ret); return return_with_debug (ret);
} }
case SSA_NAME: case BIT_FIELD_REF:
{
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:
{ {
ret = compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)) ret = compare_decl (t1, t2);
&& wi::to_offset (t1) == wi::to_offset (t2);
return return_with_debug (ret); return return_with_debug (ret);
} }
case SSA_NAME:
return compare_ssa_name (t1, t2);
case INTEGER_CST:
case COMPLEX_CST: case COMPLEX_CST:
case VECTOR_CST: case VECTOR_CST:
case STRING_CST: case STRING_CST:
case REAL_CST: case REAL_CST:
{
ret = operand_equal_p (t1, t2, OEP_ONLY_CONST);
return return_with_debug (ret);
}
case FUNCTION_DECL: case FUNCTION_DECL:
{
ret = compare_function_decl (t1, t2);
return return_with_debug (ret);
}
case VAR_DECL: case VAR_DECL:
return return_with_debug (compare_variable_decl (t1, t2));
case FIELD_DECL: 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: 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 PARM_DECL:
case RESULT_DECL: case RESULT_DECL:
case CONST_DECL: case CONST_DECL:
case BIT_FIELD_REF: return compare_cst_or_decl (t1, t2);
{
ret = compare_decl (t1, t2);
return return_with_debug (ret);
}
default: default:
return return_false_with_msg ("Unknown TREE code reached"); return return_false_with_msg ("Unknown TREE code reached");
} }
...@@ -706,15 +735,15 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) ...@@ -706,15 +735,15 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2)
t1 = gimple_call_arg (s1, i); t1 = gimple_call_arg (s1, i);
t2 = gimple_call_arg (s2, i); t2 = gimple_call_arg (s2, i);
if (!compare_operand (t1, t2)) if (!compare_memory_operand (t1, t2))
return false; return return_false_with_msg ("memory operands are different");
} }
/* Return value checking. */ /* Return value checking. */
t1 = gimple_get_lhs (s1); t1 = gimple_get_lhs (s1);
t2 = gimple_get_lhs (s2); 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) ...@@ -745,8 +774,8 @@ func_checker::compare_gimple_assign (gimple s1, gimple s2)
arg1 = gimple_op (s1, i); arg1 = gimple_op (s1, i);
arg2 = gimple_op (s2, i); arg2 = gimple_op (s2, i);
if (!compare_operand (arg1, arg2)) if (!compare_memory_operand (arg1, arg2))
return false; return return_false_with_msg ("memory operands are different");
} }
......
...@@ -203,7 +203,14 @@ public: ...@@ -203,7 +203,14 @@ public:
/* Verifies that tree labels T1 and T2 correspond. */ /* Verifies that tree labels T1 and T2 correspond. */
bool compare_tree_ssa_label (tree t1, tree t2); 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 If these components, from functions FUNC1 and FUNC2, are equal, true
is returned. */ is returned. */
bool compare_operand (tree t1, tree t2); 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