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" } } */ > +