aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-02-10 11:54:14 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-02-10 11:54:14 +0000
commitd977cb9cfd0543fcda482c0400806dd1e987d4d5 (patch)
tree6113ddc6064eef820caaf65171d7e8681efc3368 /gcc
parent563cb662c833b2233b5682bcc55e99cf584de1a4 (diff)
downloadgcc-d977cb9cfd0543fcda482c0400806dd1e987d4d5.zip
gcc-d977cb9cfd0543fcda482c0400806dd1e987d4d5.tar.gz
gcc-d977cb9cfd0543fcda482c0400806dd1e987d4d5.tar.bz2
re PR c/43007 (No longer folds (unsigned int) ((long long unsigned int) spi_bias / 1008))
2010-02-10 Richard Guenther <rguenther@suse.de> PR c/43007 * tree.c (get_unwidened): Handle constants. * convert.c (convert_to_integer): Handle TRUNC_DIV_EXPR. * gcc.c-torture/execute/20100209-1.c: New testcase. * gcc.dg/fold-div-3.c: Likewise. From-SVN: r156653
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/convert.c25
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20100209-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/fold-div-3.c15
-rw-r--r--gcc/tree.c8
6 files changed, 72 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ecda788..ce3d086 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-02-10 Richard Guenther <rguenther@suse.de>
+
+ PR c/43007
+ * tree.c (get_unwidened): Handle constants.
+ * convert.c (convert_to_integer): Handle TRUNC_DIV_EXPR.
+
2010-02-10 Martin Jambor <mjambor@suse.cz>
PR lto/42985
diff --git a/gcc/convert.c b/gcc/convert.c
index 4fe95ce..39fbd4d 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -673,6 +673,31 @@ convert_to_integer (tree type, tree expr)
}
break;
+ case TRUNC_DIV_EXPR:
+ {
+ tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);
+ tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);
+
+ /* Don't distribute unless the output precision is at least as big
+ as the actual inputs and it has the same signedness. */
+ if (outprec >= TYPE_PRECISION (TREE_TYPE (arg0))
+ && outprec >= TYPE_PRECISION (TREE_TYPE (arg1))
+ /* If signedness of arg0 and arg1 don't match,
+ we can't necessarily find a type to compare them in. */
+ && (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ == TYPE_UNSIGNED (TREE_TYPE (arg1)))
+ /* Do not change the sign of the division. */
+ && (TYPE_UNSIGNED (TREE_TYPE (expr))
+ == TYPE_UNSIGNED (TREE_TYPE (arg0)))
+ /* Either require unsigned division or a division by
+ a constant that is not -1. */
+ && (TYPE_UNSIGNED (TREE_TYPE (arg0))
+ || (TREE_CODE (arg1) == INTEGER_CST
+ && !integer_all_onesp (arg1))))
+ goto trunc1;
+ break;
+ }
+
case MAX_EXPR:
case MIN_EXPR:
case MULT_EXPR:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59181d7..273636c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-02-10 Richard Guenther <rguenther@suse.de>
+
+ PR c/43007
+ * gcc.c-torture/execute/20100209-1.c: New testcase.
+ * gcc.dg/fold-div-3.c: Likewise.
+
2010-02-10 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/builtin-ffs-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20100209-1.c b/gcc/testsuite/gcc.c-torture/execute/20100209-1.c
new file mode 100644
index 0000000..bf0597b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20100209-1.c
@@ -0,0 +1,12 @@
+int bar(int foo)
+{
+ return (int)(((unsigned long long)(long long)foo) / 8);
+}
+extern void abort (void);
+int main()
+{
+ if (sizeof (long long) > sizeof (int)
+ && bar(-1) != -1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/fold-div-3.c b/gcc/testsuite/gcc.dg/fold-div-3.c
new file mode 100644
index 0000000..2e78757
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fold-div-3.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-original" } */
+
+unsigned int
+apply_frontend_param (unsigned int spi_bias)
+{
+ static const int ppm = 8000;
+ spi_bias /= 1000ULL + ppm/1000;
+ return spi_bias;
+}
+
+/* Make sure we perform the division in the narrower type. */
+
+/* { dg-final { scan-tree-dump "spi_bias = spi_bias / 1008;" "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/tree.c b/gcc/tree.c
index 5d44841..c51cca7 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7623,6 +7623,14 @@ get_unwidened (tree op, tree for_type)
}
}
+ /* If we finally reach a constant see if it fits in for_type and
+ in that case convert it. */
+ if (for_type
+ && TREE_CODE (win) == INTEGER_CST
+ && TREE_TYPE (win) != for_type
+ && int_fits_type_p (win, for_type))
+ win = fold_convert (for_type, win);
+
return win;
}