This is an implementation to fix a missed optimization pointed out to me
by Kai.
In all these examples, assume a & b are single bit types.
~a && b --> a < b
a && ~b --> b < a
~a || b --> a <= b
a && ~b --> b <= a
This happens with some regularity in GCC itself, though it's not as
pervasive as some of the other missed optimizations I've run into.
This could have gone into fold-const.c or tree-forwprop. fold-const.c
isn't as useful as would need to see the entire expression as a single
tree node. tree-forwprop.c can follow the use-def links and discover
more opportunities even when the expressions span two source statements
or are exposed by other optimizations.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu.
OK for the trunk?
commit 2b61de6f70576105fe6ada31618db23857f9c902
Author: Jeff Law <l...@redhat.com>
Date: Fri May 31 14:16:27 2013 -0600
* tree-ssa-forwprop.c (simplify_bitwise_binary_boolean): New
* function.
(simplify_bitwise_binary): Use it to simpify certain binary ops on
booleans.
* gcc.dg/tree-ssa/forwprop-27.c: New test.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 396111e..7f027b0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-05-31 Jeff Law <l...@redhat.com>
+
+ * tree-ssa-forwprop.c (simplify_bitwise_binary_boolean): New function.
+ (simplify_bitwise_binary): Use it to simpify certain binary ops on
+ booleans.
+
2013-05-28 Steve Ellcey <sell...@mips.com>
* config/mips/mips-cpus.def (mips32r2): Change processor type.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 869371a..6f80afb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2013-05-31 Jeff Law <l...@redhat.com>
+
+ * gcc.dg/tree-ssa/forwprop-27.c: New test.
+
2013-05-28 Balaji V. Iyer <balaji.v.i...@intel.com>
* c-c++-common/cilk-plus/AN/array_test1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
new file mode 100644
index 0000000..75e935d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-27.c
@@ -0,0 +1,78 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
+
+extern char * frob (void);
+extern _Bool testit(void);
+
+test (int code)
+{
+ char * temp = frob();;
+ int rotate = (code == 22);
+ if (temp == 0 && !rotate)
+ oof();
+}
+
+test_2 (int code)
+{
+ char * temp = frob();
+ int rotate = (code == 22);
+ if (!rotate && temp == 0)
+ oof();
+}
+
+
+test_3 (int code)
+{
+ char * temp = frob();
+ int rotate = (code == 22);
+ if (!rotate || temp == 0)
+ oof();
+}
+
+
+test_4 (int code)
+{
+ char * temp = frob();
+ int rotate = (code == 22);
+ if (temp == 0 || !rotate)
+ oof();
+}
+
+
+test_5 (int code)
+{
+ _Bool temp = testit();;
+ _Bool rotate = (code == 22);
+ if (temp == 0 && !rotate)
+ oof();
+}
+
+test_6 (int code)
+{
+ _Bool temp = testit();
+ _Bool rotate = (code == 22);
+ if (!rotate && temp == 0)
+ oof();
+}
+
+
+test_7 (int code)
+{
+ _Bool temp = testit();
+ _Bool rotate = (code == 22);
+ if (!rotate || temp == 0)
+ oof();
+}
+
+
+test_8 (int code)
+{
+ _Bool temp = testit();
+ _Bool rotate = (code == 22);
+ if (temp == 0 || !rotate)
+ oof();
+}
+
+/* { dg-final { scan-tree-dump-times "Replaced" 8 "forwprop1"} } */
+
+
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 6043d31..8c3f08b 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1870,6 +1870,45 @@ hoist_conversion_for_bitop_p (tree to, tree from)
return false;
}
+/* GSI points to a statement of the form
+
+ result = OP0 CODE OP1
+
+ Where OP0 and OP1 are single bit SSA_NAMEs and CODE is either
+ BIT_AND_EXPR or BIT_IOR_EXPR.
+
+ If OP0 is fed by a bitwise negation of another single bit SSA_NAME,
+ then we can simplify the two statements into a single LT_EXPR or LE_EXPR
+ when code is BIT_AND_EXPR and BIT_IOR_EXPR respectively.
+
+ If a simplification is mode, return TRUE, else return FALSE. */
+static bool
+simplify_bitwise_binary_boolean (gimple_stmt_iterator *gsi,
+ enum tree_code code,
+ tree op0, tree op1)
+{
+ gimple op0_def_stmt = SSA_NAME_DEF_STMT (op0);
+
+ if (!is_gimple_assign (op0_def_stmt)
+ || (gimple_assign_rhs_code (op0_def_stmt) != BIT_NOT_EXPR))
+ return false;
+
+ tree x = gimple_assign_rhs1 (op0_def_stmt);
+ if (TREE_CODE (x) == SSA_NAME
+ && INTEGRAL_TYPE_P (TREE_TYPE (x))
+ && TYPE_PRECISION (TREE_TYPE (x)) == 1)
+ {
+ gimple stmt = gsi_stmt (*gsi);
+ gimple_assign_set_rhs1 (stmt, x);
+ gimple_assign_set_rhs2 (stmt, op1);
+ gimple_assign_set_rhs_code (stmt, code == BIT_AND_EXPR ? LT_EXPR :
LE_EXPR);
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+ }
+ return false;
+
+}
+
/* Simplify bitwise binary operations.
Return true if a transformation applied, otherwise return false. */
@@ -2118,8 +2157,26 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
return true;
}
}
- }
+ /* If arg1 and arg2 are booleans (or any single bit type)
+ then try to simplify:
+
+ (~X & Y) -> X < Y
+ (X & ~Y) -> Y < X
+ (~X | Y) -> X <= Y
+ (X | ~Y) -> Y <= X */
+ if (TREE_CODE (arg1) == SSA_NAME
+ && TREE_CODE (arg2) == SSA_NAME
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+ && TYPE_PRECISION (TREE_TYPE (arg1)) == 1
+ && TYPE_PRECISION (TREE_TYPE (arg2)) == 1)
+ {
+ if (simplify_bitwise_binary_boolean (gsi, code, arg1, arg2))
+ return true;
+ if (simplify_bitwise_binary_boolean (gsi, code, arg2, arg1))
+ return true;
+ }
+ }
return false;
}