This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch tree-optimization]: Fix for PR 45397 part 2 of 2
- From: Kai Tietz <ktietz70 at googlemail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 15 Mar 2012 14:09:41 +0100
- Subject: [patch tree-optimization]: Fix for PR 45397 part 2 of 2
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 <ktietz@redhat.com>
PR tree-optimization/45397
* tree-ssa-forwprop.c (compare_equal_optimized_1): Add
simplification patterns for ==/!= comparison.
2012-03-15 Kai Tietz <ktietz@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" } } */
+