On Sat, 9 Nov 2013, Tom de Vries wrote:
> Richard,
>
> Consider the test-case test.c:
> ...
> int z;
> int x;
>
> void
> f (int c, int d)
> {
> if (c)
> z = 5;
> else
> {
> if (d)
> x = 4;
> z = 5;
> }
> }
> ...
>
> Atm, we don't tail-merge the 'z = 5' blocks, because gimple_equal_p returns
> false for the 'z = 5' statements. The relevant code is this:
> ...
> if (TREE_CODE (lhs1) != SSA_NAME
> && TREE_CODE (lhs2) != SSA_NAME)
> return (vn_valueize (gimple_vdef (s1))
> == vn_valueize (gimple_vdef (s2)));
> ...
> The vdefs of the 'z = 5' statements are different, because the incoming vuses
> are different.
>
> This patch handles GIMPLE_ASSIGNs with different vuse in gimple_equal_p, by
> doing a structural comparison.
>
> Bootstrapped and regtested on x86_64.
>
> OK for trunk?
Comments inline
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 98b5882..43516a7 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1173,8 +1173,47 @@ gimple_equal_p (same_succ same_succ, gimple s1, gimple
s2)
lhs2 = gimple_get_lhs (s2);
if (TREE_CODE (lhs1) != SSA_NAME
&& TREE_CODE (lhs2) != SSA_NAME)
- return (vn_valueize (gimple_vdef (s1))
- == vn_valueize (gimple_vdef (s2)));
+ {
+ /* If the vdef is the same, it's the same statement. */
+ if (vn_valueize (gimple_vdef (s1))
+ == vn_valueize (gimple_vdef (s2)))
+ return true;
+
+ /* If the vdef is not the same but the vuse is the same, it's not the
+ same stmt. */
+ if (vn_valueize (gimple_vuse (s1))
+ == vn_valueize (gimple_vuse (s2)))
+ return false;
What's the logic behind this? We want to use VN to get more "positive"
results - doing a negative early out looks suspicious to me ...
+ /* If the vdef is not the same and the vuse is not the same, it might
be
+ same stmt. */
+
+ /* Test for structural equality. */
+ if (gimple_assign_rhs_code (s1) != gimple_assign_rhs_code (s1)
s2
+ || (gimple_assign_nontemporal_move_p (s1)
+ != gimple_assign_nontemporal_move_p (s2)))
I don't think we should care (it'll be false - a later pass sets it,
it's an optimization hint, not a correctness issue). More interesting
would be to assert that has_volatile_ops is the same if the operands
turned out to be the same.
+ return false;
+
+ if (!operand_equal_p (lhs1, lhs2, 0))
+ return false;
+
+ t1 = gimple_assign_rhs1 (s1);
+ t2 = gimple_assign_rhs1 (s2);
+ if (!gimple_operand_equal_value_p (t1, t2))
+ return false;
+
+ t1 = gimple_assign_rhs2 (s1);
+ t2 = gimple_assign_rhs2 (s2);
+ if (!gimple_operand_equal_value_p (t1, t2))
+ return false;
+
+ t1 = gimple_assign_rhs3 (s1);
+ t2 = gimple_assign_rhs3 (s2);
+ if (!gimple_operand_equal_value_p (t1, t2))
+ return false;
for (i = 1; i < gimple_num_ops (s1); ++i)
t1 = gimple_op (s1, i);
...
but I think you should only compare rhs1 and thus only handle
GIMPLE_ASSIGN_SINGLEs this way - the others have a SSA name
lhs.
That makes the whole thing just
if (TREE_CODE (lhs1) != SSA_NAME
&& TREE_CODE (lhs2) != SSA_NAME)
{
if (vn_valueize (gimple_vdef (s1))
== vn_valueize (gimple_vdef (s2)))
return true;
return operand_equal_p (lhs1, lhs2, 0)
&& gimple_operand_equal_value_p (gimple_assign_rhs1 (s1),
gimple_assign_rhs2 (s2));
}
Ok with doing it this way.
Thanks,
Richard.
+ /* Same structure. */
+ return true;
+ }
else if (TREE_CODE (lhs1) == SSA_NAME
&& TREE_CODE (lhs2) == SSA_NAME)
return vn_valueize (lhs1) == vn_valueize (lhs2);