On Thu, Mar 15, 2012 at 2:09 PM, Kai Tietz <ktiet...@googlemail.com> wrote:
> Hi,
>
> this is the second part of the patch for this problem.  It adds some
> basic simplifications for ==/!=
> comparisons for eliminating redudant operands.
>
> It adds the following patterns:
>  -X ==/!= Z - X -> Z ==/!= 0.
>  ~X ==/!= Z ^ X -> Z ==/!= ~0
>  X ==/!= X - Y -> Y == 0
>  X ==/!= X + Y -> Y == 0
>  X ==/!= X ^ Y -> Y == 0
>  (X - Y) ==/!= (Z - Y) -> X ==/!= Z
>  (Y - X) ==/!= (Y - Z) -> X ==/!= Z
>  (X + Y) ==/!= (X + Z) -> Y ==/!= Z
>  (X + Y) ==/!= (Z + X) -> Y ==/!= Z
>  (X ^ Y) ==/!= (Z ^ X) -> Y ==/!= Z

Can you re-base this patch to work without the previous one?  Also
please coordinate with Andrew.  Note that all of these(?) simplifications
are already done by fold_comparison which we could share if you'd split
out the EXPR_P op0/op1 cases with separated operands/code.

Richard.

> ChangeLog
>
> 2012-03-15  Kai Tietz  <kti...@redhat.com>
>
>        PR tree-optimization/45397
>        * tree-ssa-forwprop.c (compare_equal_optimized_1): Add
>        simplification patterns for ==/!= comparison.
>
> 2012-03-15  Kai Tietz  <kti...@redhat.com>
>
>        * gcc.dg/tree-ssa/pr45397-2.c: New test.
>
> Regression tested for all languages (including Ada and Obj-C) on
> x86_64-unknown-linux-gnu.  Ok for apply?
>
> Regards,
> Kai
>
> Index: gcc-trunk/gcc/tree-ssa-forwprop.c
> ===================================================================
> --- gcc-trunk.orig/gcc/tree-ssa-forwprop.c
> +++ gcc-trunk/gcc/tree-ssa-forwprop.c
> @@ -381,6 +381,99 @@ compare_equal_optimize_1 (gimple stmt, e
>       || !INTEGRAL_TYPE_P (type_outer))
>     return NULL_TREE;
>
> +  /* Simplify -X ==/!= Z - X -> Z ==/!= 0.  */
> +  if (TREE_CODE (op0) == NEGATE_EXPR
> +      && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 0))
> +      && TREE_CODE (op1) == MINUS_EXPR
> +      && TREE_OPERAND (op0, 0) == TREE_OPERAND (op1, 1))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op1, 0),
> +                               build_zero_cst (TREE_TYPE (op1)));
> +
> +  /* Simplify X - Z ==/!= -X -> Z ==/!= 0.  */
> +  if (TREE_CODE (op1) == NEGATE_EXPR
> +      && !TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0))
> +      && TREE_CODE (op0) == MINUS_EXPR
> +      && TREE_OPERAND (op1, 0) == TREE_OPERAND (op0, 1))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 0),
> +                               build_zero_cst (TREE_TYPE (op0)));
> +
> +  /* Simplify ~X ==/!= X ^ Y to Y ==/!= ~0.  */
> +  if (TREE_CODE (op0) == BIT_NOT_EXPR
> +      && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 0))
> +      && TREE_CODE (op1) == BIT_XOR_EXPR)
> +    {
> +      if (TREE_OPERAND (op0, 0) == TREE_OPERAND (op1, 1))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op1, 0),
> +                               fold_build1 (BIT_NOT_EXPR,
> +                                            TREE_TYPE (op1),
> +                                            build_zero_cst (TREE_TYPE 
> (op1))));
> +      if (TREE_OPERAND (op0, 0) == TREE_OPERAND (op1, 0))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op1, 1),
> +                               fold_build1 (BIT_NOT_EXPR,
> +                                            TREE_TYPE (op1),
> +                                            build_zero_cst (TREE_TYPE 
> (op1))));
> +    }
> +
> +  /* Simplify X ^ Y ==/!= ~X to Y ==/!= ~0.  */
> +  if (TREE_CODE (op1) == BIT_NOT_EXPR
> +      && !TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0))
> +      && TREE_CODE (op0) == BIT_XOR_EXPR)
> +    {
> +      if (TREE_OPERAND (op1, 0) == TREE_OPERAND (op0, 1))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 0),
> +                               fold_build1 (BIT_NOT_EXPR,
> +                                            TREE_TYPE (op0),
> +                                            build_zero_cst (TREE_TYPE 
> (op0))));
> +      if (TREE_OPERAND (op1, 0) == TREE_OPERAND (op0, 0))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 1),
> +                               fold_build1 (BIT_NOT_EXPR,
> +                                            TREE_TYPE (op0),
> +                                            build_zero_cst (TREE_TYPE 
> (op0))));
> +    }
> +
> +  /* For code being +, -, or ^-expression simplify (X code Y) ==/!= (Z code 
> Y)
> +     to (X ==/!= Z), and (X code Y) ==/!= (X code Z) to (Y ==/!= Z).  */
> +  if (TREE_CODE (op0) == TREE_CODE (op1)
> +      && (TREE_CODE (op0) == PLUS_EXPR
> +          || TREE_CODE (op0) == MINUS_EXPR
> +          || TREE_CODE (op0) == BIT_XOR_EXPR))
> +    {
> +      /* Simplify (X code Y) ==/!= (X code Z) to Y ==/!= Z.  */
> +      if (TREE_OPERAND (op0, 0) == TREE_OPERAND (op1, 0)
> +          && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 0)))
> +       return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 1),
> +                               TREE_OPERAND (op1, 1));
> +      /* Simplify (X code Y) ==/!= (Z code X) to Y ==/!= Z, if code isn't
> +        minus operation.  */
> +      if (TREE_CODE (op0) != MINUS_EXPR
> +          && TREE_OPERAND (op0, 0) == TREE_OPERAND (op1, 1)
> +          && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 0)))
> +        return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 1),
> +                               TREE_OPERAND (op1, 0));
> +      /* Simplify (Y code X) ==/!= (X code Z) to Y ==/!= Z, if code isn't
> +        minus operation.  */
> +      if (TREE_CODE (op0) != MINUS_EXPR
> +          && TREE_OPERAND (op0, 1) == TREE_OPERAND (op1, 0)
> +          && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 1)))
> +        return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 0),
> +                               TREE_OPERAND (op1, 1));
> +      /* Simplify (Y code X) ==/!= (Z code X) to Y ==/!= Z.  */
> +      if (TREE_OPERAND (op0, 1) == TREE_OPERAND (op1, 1)
> +          && !TREE_SIDE_EFFECTS (TREE_OPERAND (op0, 1)))
> +        return fold_build2_loc (gimple_location (stmt), code, type,
> +                               TREE_OPERAND (op0, 0),
> +                               TREE_OPERAND (op1, 0));
> +    }
> +
>   /* If OP0 isn't a conversion, then check if OP1 might be one.  If so
>      swap arguments, otherwise return NULL_TREE.  */
>   if (!CONVERT_EXPR_P (op0))
> Index: gcc-trunk/gcc/testsuite/gcc.dg/tree-ssa/pr45397-2.c
> ===================================================================
> --- /dev/null
> +++ gcc-trunk/gcc/testsuite/gcc.dg/tree-ssa/pr45397-2.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +int
> +foo (const unsigned char *a, int b, int c)
> +{
> +  int x = (unsigned char) (a[b] + c);
> +  int y = a[b] + c;
> +  int z = (unsigned char) y;
> +  return x == z;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
> +/* { dg-final { cleanup-tree-dump "optimized" } } */
> +

Reply via email to