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

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