diff options
author | Jakub Jelinek <jakub@redhat.com> | 2016-01-30 19:04:13 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2016-01-30 19:04:13 +0100 |
commit | db7a2818002ba7e0c1863d15aca3212911161267 (patch) | |
tree | 3a978b34d4a749f949ab5c378dd10d65e6b9c5b1 | |
parent | e520d5f02a0cfa5d07a48a14f2b67af63884e9ed (diff) | |
download | gcc-db7a2818002ba7e0c1863d15aca3212911161267.zip gcc-db7a2818002ba7e0c1863d15aca3212911161267.tar.gz gcc-db7a2818002ba7e0c1863d15aca3212911161267.tar.bz2 |
re PR middle-end/69546 (wrong code with -O and simple int128 arithmetics)
PR tree-optimization/69546
* wide-int.cc (wi::divmod_internal): For unsigned division
where both operands fit into uhwi, if o1 is 1 and o0 has
msb set, if divident_prec is larger than bits per hwi,
clear another quotient word and return 2 instead of 1.
Similarly for remainder with msb in HWI set, if dividend_prec
is larger than bits per hwi.
* gcc.dg/torture/pr69546.c: New test.
From-SVN: r233012
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr69546-1.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr69546-2.c | 18 | ||||
-rw-r--r-- | gcc/wide-int.cc | 23 |
5 files changed, 79 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1d60690..0d405cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2016-01-30 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/69546 + * wide-int.cc (wi::divmod_internal): For unsigned division + where both operands fit into uhwi, if o1 is 1 and o0 has + msb set, if divident_prec is larger than bits per hwi, + clear another quotient word and return 2 instead of 1. + Similarly for remainder with msb in HWI set, if dividend_prec + is larger than bits per hwi. + 2016-01-29 Martin Jambor <mjambor@suse.cz> * hsa-gen.c (get_memory_order_name): Mask with MEMMODEL_BASE_MASK. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index df468e1..63a4bfa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-01-30 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/69546 + * gcc.dg/torture/pr69546.c: New test. + 2016-01-30 Paul Thomas <pault@gcc.gnu.org> PR fortran/69566 diff --git a/gcc/testsuite/gcc.dg/torture/pr69546-1.c b/gcc/testsuite/gcc.dg/torture/pr69546-1.c new file mode 100644 index 0000000..39db179 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr69546-1.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/69546 */ +/* { dg-do run { target int128 } } */ + +unsigned __int128 __attribute__ ((noinline, noclone)) +foo (unsigned long long x) +{ + unsigned __int128 y = ~0ULL; + x >>= 63; + return y / (x | 1); +} + +unsigned __int128 __attribute__ ((noinline, noclone)) +bar (unsigned long long x) +{ + unsigned __int128 y = ~33ULL; + x >>= 63; + return y / (x | 1); +} + +int +main () +{ + if (foo (1) != ~0ULL || bar (17) != ~33ULL) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr69546-2.c b/gcc/testsuite/gcc.dg/torture/pr69546-2.c new file mode 100644 index 0000000..f004310 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr69546-2.c @@ -0,0 +1,18 @@ +/* PR tree-optimization/69546 */ +/* { dg-do run { target int128 } } */ + +unsigned __int128 +foo (void) +{ + unsigned __int128 a = 0xfffffffffffffffeULL; + unsigned __int128 b = 0xffffffffffffffffULL; + return a % b; +} + +int +main () +{ + if (foo () != 0xfffffffffffffffeULL) + __builtin_abort (); + return 0; +} diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc index 195ac26..5fcec2e 100644 --- a/gcc/wide-int.cc +++ b/gcc/wide-int.cc @@ -1788,15 +1788,32 @@ wi::divmod_internal (HOST_WIDE_INT *quotient, unsigned int *remainder_len, { unsigned HOST_WIDE_INT o0 = dividend.to_uhwi (); unsigned HOST_WIDE_INT o1 = divisor.to_uhwi (); + unsigned int quotient_len = 1; if (quotient) - quotient[0] = o0 / o1; + { + quotient[0] = o0 / o1; + if (o1 == 1 + && (HOST_WIDE_INT) o0 < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + quotient[1] = 0; + quotient_len = 2; + } + } if (remainder) { remainder[0] = o0 % o1; - *remainder_len = 1; + if ((HOST_WIDE_INT) remainder[0] < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + remainder[1] = 0; + *remainder_len = 2; + } + else + *remainder_len = 1; } - return 1; + return quotient_len; } /* Make the divisor and dividend positive and remember what we |