2007-11-12 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Nov 2007 13:24:06 +0000 (13:24 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Nov 2007 13:24:06 +0000 (13:24 +0000)
PR middle-end/34027
* fold-const.c (fold_binary): Fold n - (n / m) * m to n % m.
(fold_binary): Fold unsinged FLOOR_DIV_EXPR to TRUNC_DIV_EXPR.

* gcc.dg/pr34027-1.c: New testcase.
* gcc.dg/pr34027-2.c: Likewise.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr34027-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr34027-2.c [new file with mode: 0644]

index 1093ef3..b95f35d 100644 (file)
@@ -1,3 +1,12 @@
+2007-11-12  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/34027
+       * fold-const.c (fold_binary): Fold n - (n / m) * m to n % m.
+       (fold_binary): Fold unsinged FLOOR_DIV_EXPR to TRUNC_DIV_EXPR.
+
+       * gcc.dg/pr34027-1.c: New testcase.
+       * gcc.dg/pr34027-2.c: Likewise.
+
 2007-11-12  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/33953
index a09c9ea..5b81d88 100644 (file)
@@ -9653,6 +9653,21 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  return omit_one_operand (type, t1, arg0);
                }
            }
+
+         /* X + (X / CST) * -CST is X % CST.  */
+         if (TREE_CODE (arg1) == MULT_EXPR
+             && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
+             && operand_equal_p (arg0,
+                                 TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
+           {
+             tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1);
+             tree cst1 = TREE_OPERAND (arg1, 1);
+             tree sum = fold_binary (PLUS_EXPR, TREE_TYPE (cst1), cst1, cst0);
+             if (sum && integer_zerop (sum))
+               return fold_convert (type,
+                                    fold_build2 (TRUNC_MOD_EXPR,
+                                                 TREE_TYPE (arg0), arg0, cst0));
+           }
        }
 
       /* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the
@@ -10061,6 +10076,19 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && integer_all_onesp (arg0))
        return fold_build1 (BIT_NOT_EXPR, type, op1);
 
+
+      /* X - (X / CST) * CST is X % CST.  */
+      if (INTEGRAL_TYPE_P (type)
+         && TREE_CODE (arg1) == MULT_EXPR
+         && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
+         && operand_equal_p (arg0,
+                             TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
+         && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
+                             TREE_OPERAND (arg1, 1), 0))
+       return fold_convert (type,
+                            fold_build2 (TRUNC_MOD_EXPR, TREE_TYPE (arg0),
+                                         arg0, TREE_OPERAND (arg1, 1)));
+
       if (! FLOAT_TYPE_P (type))
        {
          if (integer_zerop (arg0))
@@ -11221,6 +11249,14 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                  fold_convert (type, arg0), sh_cnt);
            }
        }
+
+      /* For unsigned integral types, FLOOR_DIV_EXPR is the same as
+        TRUNC_DIV_EXPR.  Rewrite into the latter in this case.  */
+      if (INTEGRAL_TYPE_P (type)
+         && TYPE_UNSIGNED (type)
+         && code == FLOOR_DIV_EXPR)
+       return fold_build2 (TRUNC_DIV_EXPR, type, op0, op1);
+
       /* Fall thru */
 
     case ROUND_DIV_EXPR:
index 476b82b..e224859 100644 (file)
@@ -1,3 +1,9 @@
+2007-11-12  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/34027
+       * gcc.dg/pr34027-1.c: New testcase.
+       * gcc.dg/pr34027-2.c: Likewise.
+
 2007-11-12  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/33953
diff --git a/gcc/testsuite/gcc.dg/pr34027-1.c b/gcc/testsuite/gcc.dg/pr34027-1.c
new file mode 100644 (file)
index 0000000..532e497
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fdump-tree-optimized" } */
+
+unsigned long foobar(unsigned long ns)
+{
+  while(ns >= 10000L)
+    ns -= 10000L;
+  return ns;
+}
+
+/* { dg-final { scan-tree-dump "ns % 10000" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr34027-2.c b/gcc/testsuite/gcc.dg/pr34027-2.c
new file mode 100644 (file)
index 0000000..70c4561
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-gimple" } */
+
+long foo(long n, long m)
+{
+  return n - (n / m) * m;
+}
+
+/* { dg-final { scan-tree-dump "n % m" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */