diff options
author | Steve Ellcey <sellcey@imgtec.com> | 2015-10-23 15:58:33 +0000 |
---|---|---|
committer | Steve Ellcey <sje@gcc.gnu.org> | 2015-10-23 15:58:33 +0000 |
commit | 5edab54b6c5de8ae5fca7b4ce08ddcd31948997d (patch) | |
tree | cbce70958f3c8234d21792896415be92a8d1c1da | |
parent | 2c40b14dfdde747212f10fcdbd105034f1b738df (diff) | |
download | gcc-5edab54b6c5de8ae5fca7b4ce08ddcd31948997d.zip gcc-5edab54b6c5de8ae5fca7b4ce08ddcd31948997d.tar.gz gcc-5edab54b6c5de8ae5fca7b4ce08ddcd31948997d.tar.bz2 |
re PR rtl-optimization/67736 (Wrong optimization with -fexpensive-optimizations on mips64el)
2015-10-23 Steve Ellcey <sellcey@imgtec.com>
Andrew Pinski <apinski@cavium.com>
PR rtl-optimization/67736
* gcc.dg/torture/pr67736.c: New test.
* gcc.dg/combine-subregs.c: New test.
Co-Authored-By: Andrew Pinski <apinski@cavium.com>
From-SVN: r229260
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/combine-subregs.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr67736.c | 32 |
3 files changed, 75 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f13e8dc..1d21435 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-10-23 Steve Ellcey <sellcey@imgtec.com> + Andrew Pinski <apinski@cavium.com> + + PR rtl-optimization/67736 + * combine.c (simplify_comparison): Use gen_lowpart_or_truncate instead + of gen_lowpart. + 2015-10-23 Alan Hayward <alan.hayward@arm.com> PR tree-optimization/65947 diff --git a/gcc/testsuite/gcc.dg/combine-subregs.c b/gcc/testsuite/gcc.dg/combine-subregs.c new file mode 100644 index 0000000..ccace23 --- /dev/null +++ b/gcc/testsuite/gcc.dg/combine-subregs.c @@ -0,0 +1,36 @@ +/* { dg-do run { target { stdint_types } } } */ +/* { dg-options "-O2" } */ + +#include <stdint.h> +#include <stdlib.h> + +void __attribute__ ((noinline)) +foo (uint64_t state, uint32_t last) +{ + if (state == last) abort (); +} + +/* This function may do a bad comparision by trying to + use SUBREGS during the compare on machines where comparing + two registers always compares the entire register regardless + of mode. */ + +int __attribute__ ((noinline)) +compare (uint64_t state, uint32_t *last, uint8_t buf) +{ + if (*last == ((state | buf) & 0xFFFFFFFF)) { + foo (state, *last); + return 0; + } + return 1; +} + +int +main(int argc, char **argv) { + uint64_t state = 0xF00000100U; + uint32_t last = 0x101U; + int ret = compare(state, &last, 0x01); + if (ret != 0) + abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr67736.c b/gcc/testsuite/gcc.dg/torture/pr67736.c new file mode 100644 index 0000000..024bb20 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr67736.c @@ -0,0 +1,32 @@ +/* { dg-do run { target { stdint_types } } } */ + +#include <stdint.h> +#include <stdlib.h> + +void f(uint64_t *a, uint64_t aa) __attribute__((noinline)); +void f(uint64_t *a, uint64_t aa) +{ + uint64_t new_value = aa; + uint64_t old_value = *a; + int bit_size = 32; + uint64_t mask = (uint64_t)(unsigned)(-1); + uint64_t tmp = old_value & mask; + new_value &= mask; + /* On overflow we need to add 1 in the upper bits */ + if (tmp > new_value) + new_value += 1ull<<bit_size; + /* Add in the upper bits from the old value */ + new_value += old_value & ~mask; + *a = new_value; +} +int main(void) +{ + uint64_t value, new_value, old_value; + value = 0x100000001; + old_value = value; + new_value = (value+1)&(uint64_t)(unsigned)(-1); + f(&value, new_value); + if (value != old_value+1) + __builtin_abort (); + return 0; +} |