2013-02-25 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Feb 2013 15:31:31 +0000 (15:31 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Feb 2013 15:31:31 +0000 (15:31 +0000)
PR tree-optimization/56175
* tree-ssa-forwprop.c (hoist_conversion_for_bitop_p): New predicate,
split out from ...
(simplify_bitwise_binary): ... here.  Also guard the conversion
of (type) X op CST to (type) (X op ((type-x) CST)) with it.

* gcc.dg/tree-ssa/forwprop-24.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196263 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/forwprop-24.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index 13fad12..ec210d6 100644 (file)
@@ -1,3 +1,11 @@
+2013-02-25  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/56175
+       * tree-ssa-forwprop.c (hoist_conversion_for_bitop_p): New predicate,
+       split out from ...
+       (simplify_bitwise_binary): ... here.  Also guard the conversion
+       of (type) X op CST to (type) (X op ((type-x) CST)) with it.
+
 2013-02-25  Catherine Moore  <clm@codesourcery.com>
 
        Revert:
index a33bed4..bd2b6d6 100644 (file)
@@ -1,3 +1,8 @@
+2013-02-25  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/56175
+       * gcc.dg/tree-ssa/forwprop-24.c: New testcase.
+
 2013-02-24  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/56403
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-24.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-24.c
new file mode 100644 (file)
index 0000000..74207cf
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */\r
+/* { dg-options "-O -fdump-tree-cddce1" } */\r
+\r
+void bar (void);\r
+unsigned short\r
+foo (unsigned char x, unsigned short y)\r
+{\r
+  unsigned char t = (unsigned char)((x & 1) ^ ((unsigned char)y & 1));\r
+  if (t == 1)\r
+    bar ();\r
+  return y;\r
+}\r
+\r
+/* We should have combined this to require only one bitwise and\r
+   as in (x ^ (char) y) & 1.  */\r
+\r
+/* { dg-final { scan-tree-dump-times " & " 1 "cddce1" } } */\r
+/* { dg-final { cleanup-tree-dump "cddce1" } } */\r
index 855c212..edcf929 100644 (file)
@@ -1772,6 +1772,29 @@ defcodefor_name (tree name, enum tree_code *code, tree *arg1, tree *arg2)
   /* Ignore arg3 currently. */
 }
 
+/* Return true if a conversion of an operand from type FROM to type TO
+   should be applied after performing the operation instead.  */
+
+static bool
+hoist_conversion_for_bitop_p (tree to, tree from)
+{
+  /* That's a good idea if the conversion widens the operand, thus
+     after hoisting the conversion the operation will be narrower.  */
+  if (TYPE_PRECISION (from) < TYPE_PRECISION (to))
+    return true;
+
+  /* It's also a good idea if the conversion is to a non-integer mode.  */
+  if (GET_MODE_CLASS (TYPE_MODE (to)) != MODE_INT)
+    return true;
+
+  /* Or if the precision of TO is not the same as the precision
+     of its mode.  */
+  if (TYPE_PRECISION (to) != GET_MODE_PRECISION (TYPE_MODE (to)))
+    return true;
+
+  return false;
+}
+
 /* Simplify bitwise binary operations.
    Return true if a transformation applied, otherwise return false.  */
 
@@ -1789,9 +1812,11 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
   defcodefor_name (arg1, &def1_code, &def1_arg1, &def1_arg2);
   defcodefor_name (arg2, &def2_code, &def2_arg1, &def2_arg2);
 
-  /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST)).  */
+  /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
+     when profitable.  */
   if (TREE_CODE (arg2) == INTEGER_CST
       && CONVERT_EXPR_CODE_P (def1_code)
+      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1))
       && INTEGRAL_TYPE_P (TREE_TYPE (def1_arg1))
       && int_fits_type_p (arg2, TREE_TYPE (def1_arg1)))
     {
@@ -1816,15 +1841,7 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
   if (CONVERT_EXPR_CODE_P (def1_code)
       && CONVERT_EXPR_CODE_P (def2_code)
       && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))
-      /* Make sure that the conversion widens the operands, or has same
-        precision,  or that it changes the operation to a bitfield
-        precision.  */
-      && ((TYPE_PRECISION (TREE_TYPE (def1_arg1))
-          <= TYPE_PRECISION (TREE_TYPE (arg1)))
-         || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1)))
-             != MODE_INT)
-         || (TYPE_PRECISION (TREE_TYPE (arg1))
-             != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1))))))
+      && hoist_conversion_for_bitop_p (TREE_TYPE (arg1), TREE_TYPE (def1_arg1)))
     {
       gimple newop;
       tree tem = make_ssa_name (TREE_TYPE (def1_arg1), NULL);