Hello, This patch adds to the break-up code the conversion for X ==/!= ~0 to ~X ==/!= 0.
ChangeLog 2011-10-07 Kai Tietz <kti...@redhat.com> * tree-ssa-reassoc.c (break_up_bitwise_combined_stmt): Add handling for X !=/== 0 transformation to ~X !=/== 0. 2011-10-07 Kai Tietz <kti...@redhat.com> * gcc.dg/tree-ssa/reassoc-cmpior-4.c: New file. * gcc.dg/tree-ssa/reassoc-cmpior-5.c: New file. * gcc.dg/tree-ssa/reassoc-cmpior-6.c: New file. Bootstrapped and regression-tested for all languages plus Ada and Obj-C++ on x86_64-pc-linux-gnu. Ok for apply? Regards, Kai Index: gcc/gcc/tree-ssa-reassoc.c =================================================================== --- gcc.orig/gcc/tree-ssa-reassoc.c +++ gcc/gcc/tree-ssa-reassoc.c @@ -795,8 +795,8 @@ expand_cmp_ior (tree op, tree type, enum /* Break up STMT if it is a combined statement made out of - bitwise operations. Handle expansion of ~(A op B), and - (A | B) !=/== 0. */ + bitwise operations. Handle expansion for ~(A op B), + for (A | B) !=/== 0, and transform X ==/!= ~0 to ~X ==/!= 0. */ static bool break_up_bitwise_combined_stmt (gimple stmt) @@ -821,6 +821,28 @@ break_up_bitwise_combined_stmt (gimple s || TREE_CODE (op1) != SSA_NAME) return false; + /* Transform X !=/== ~0 -> ~X !=/== 0. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && INTEGRAL_TYPE_P (TREE_TYPE (op1)) + && TREE_CODE (op2) == INTEGER_CST + && integer_all_onesp (op2)) + { + op1_def = SSA_NAME_DEF_STMT (op1); + if (!op1_def + || !is_gimple_assign (op1_def) + || !has_single_use (op1)) + op1_def = NULL; + op1 = expand_not_bitwise_binary (TREE_TYPE (op1), op1, op1_def); + op2 = build_zero_cst (TREE_TYPE (op1)); + + gsi = gsi_for_stmt (stmt); + gimple_assign_set_rhs_with_ops (&gsi, code, op1, op2); + update_stmt (gsi_stmt (gsi)); + remove_stmt_chain (old_op1); + remove_stmt_chain (old_op2); + return true; + } + /* If left-hand operand isn't a gimple-assign, or isn't single-used, the we can't do anything. */ op1_def = SSA_NAME_DEF_STMT (op1); @@ -3216,6 +3238,8 @@ can_reassociate_p (tree op) Break up (X | Y) != 0 into (X != 0) | (Y != 0). + Break up X ==/!= ~0 to ~X ==/!= 0. + En passant, clear the GIMPLE visited flag on every statement. */ static void Index: gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-4.c =================================================================== --- /dev/null +++ gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -ffast-math" } */ + +int foo (int a, int b, int c, int d) +{ + int r1 = ~(a | b | c) == -1; + int r2 = (~(a | d | c) != -1) | (b == 0); + return ((~r1 == -1) | (~r2 != -1)); +} + +/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + Index: gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-5.c =================================================================== --- /dev/null +++ gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -ffast-math" } */ + +int foo (int a, int b, int c, int d) +{ + int r1 = a != 0 & c != 0 & b != 0; + int r2 = a == 0 | b != 0 | d == 0; + return ((~r1 == -1) | (~r2 != -1)); +} + +/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + Index: gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-6.c =================================================================== --- /dev/null +++ gcc/gcc/testsuite/gcc.dg/tree-ssa/reassoc-cmpior-6.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -ffast-math" } */ + +int foo (int a, int b, int c, int d) +{ + int r1 = a != 0 & c != 0 & b != 0; + int r2 = a == 0 | b != 0 | d == 0; + return ((~r1 != -1) & (~r2 == -1)); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ +