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);

Reply via email to