From: Andreas Krebbel Date: Thu, 11 Mar 2010 13:51:00 +0000 (+0000) Subject: re PR tree-optimization/43280 (gcc4.5 -m32 -O2: misoptimizes sha256!) X-Git-Tag: releases/gcc-4.5.0~421 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b509e1fcea9c6ba2dcaaee5159e19f65b407f031;p=thirdparty%2Fgcc.git re PR tree-optimization/43280 (gcc4.5 -m32 -O2: misoptimizes sha256!) 2010-03-11 Andreas Krebbel PR tree-optimization/43280 * tree-ssa-math-opts.c (find_bswap_1): Modify symbolic number generation. Move calculation of size out of the if branch. (find_bswap): Modify compare number generation. 2010-03-11 Andreas Krebbel * gcc.dg/optimize-bswapdi-1.c: Add OpenSSL bswap variant. * gcc.dg/pr43280.c: New testcase. From-SVN: r157386 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f10f8088b119..5e07486aa72c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2010-03-11 Andreas Krebbel + + PR tree-optimization/43280 + * tree-ssa-math-opts.c (find_bswap_1): Modify symbolic number generation. + Move calculation of size out of the if branch. + (find_bswap): Modify compare number generation. + 2010-03-11 Richard Guenther PR lto/43200 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bf7d44bea93d..fc9f8e649462 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-03-11 Andreas Krebbel + + * gcc.dg/optimize-bswapdi-1.c: Add OpenSSL bswap variant. + * gcc.dg/pr43280.c: New testcase. + 2010-03-11 Richard Guenther PR lto/43200 diff --git a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c index 315ea6c253d7..7d557f369c37 100644 --- a/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c +++ b/gcc/testsuite/gcc.dg/optimize-bswapdi-1.c @@ -43,6 +43,19 @@ swap64_b (DItype u) | (((u) & 0x00000000000000ffull) << 56)); } +/* The OpenSSL variant. */ -/* { dg-final { scan-tree-dump-times "64 bit bswap implementation found at" 2 "bswap" } } */ +uint64_t +swap64_c (uint64_t x) +{ + uint32_t a = x >> 32; + uint32_t b = (uint32_t) x; + return ((uint64_t) ((((((b)) >> (8)) | (((b)) << (32 - (8)))) & 0xff00ff00L) + | (((((b)) << (8)) | (((b)) >> (32 - (8)))) & 0x00ff00ffL)) << 32) + | (uint64_t) ((((((a)) >> (8)) | (((a)) << (32 - (8)))) & 0xff00ff00L) + | (((((a)) << (8)) | (((a)) >> (32 - (8)))) & 0x00ff00ffL)); +} + + +/* { dg-final { scan-tree-dump-times "64 bit bswap implementation found at" 3 "bswap" } } */ /* { dg-final { cleanup-tree-dump "bswap" } } */ diff --git a/gcc/testsuite/gcc.dg/pr43280.c b/gcc/testsuite/gcc.dg/pr43280.c new file mode 100644 index 000000000000..dfb369b5de18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43280.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-require-effective-target stdint_types } */ +/* { dg-options "-O2" } */ + +#include + +extern void abort (void); + +uint64_t __attribute__((noinline)) +byteswap64(uint64_t x) +{ + uint32_t a = x >> 32; + uint32_t b = (uint32_t) x; + return ((uint64_t) ((((((b)) >> (8)) | (((b)) << (32 - (8)))) & 0xff00ff00L) + | (((((b)) << (8)) | (((b)) >> (32 - (8)))) & 0x00ff00ffL)) << 32) + | (uint64_t) ((((((a)) >> (8)) | (((a)) << (32 - (8)))) & 0xff00ff00L) + | (((((a)) << (8)) | (((a)) >> (32 - (8)))) & 0x00ff00ffL)); +} + +int +main () +{ + uint64_t in = (uint64_t)0x01020304 << 32 | 0x05060708; + uint64_t cmp = (uint64_t)0x08070605 << 32 | 0x04030201; + + if (cmp != byteswap64 (in)) + abort (); + + return 0; +} diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index c46a57fa0482..d38df8d3d00a 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -940,15 +940,18 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit) { /* Set up the symbolic number N by setting each byte to a value between 1 and the byte size of rhs1. The highest - order byte is set to 1 and the lowest order byte to - n.size. */ + order byte is set to n->size and the lowest order + byte to 1. */ n->size = TYPE_PRECISION (TREE_TYPE (rhs1)); if (n->size % BITS_PER_UNIT != 0) return NULL_TREE; n->size /= BITS_PER_UNIT; n->n = (sizeof (HOST_WIDEST_INT) < 8 ? 0 : - (unsigned HOST_WIDEST_INT)0x01020304 << 32 | 0x05060708); - n->n >>= (sizeof (HOST_WIDEST_INT) - n->size) * BITS_PER_UNIT; + (unsigned HOST_WIDEST_INT)0x08070605 << 32 | 0x04030201); + + if (n->size < (int)sizeof (HOST_WIDEST_INT)) + n->n &= ((unsigned HOST_WIDEST_INT)1 << + (n->size * BITS_PER_UNIT)) - 1; source_expr1 = rhs1; } @@ -988,9 +991,9 @@ find_bswap_1 (gimple stmt, struct symbolic_number *n, int limit) { /* If STMT casts to a smaller type mask out the bits not belonging to the target type. */ - n->size = type_size / BITS_PER_UNIT; n->n &= ((unsigned HOST_WIDEST_INT)1 << type_size) - 1; } + n->size = type_size / BITS_PER_UNIT; } break; default: @@ -1051,11 +1054,11 @@ static tree find_bswap (gimple stmt) { /* The number which the find_bswap result should match in order to - have a full byte swap. The insignificant bytes are masked out - before using it. */ + have a full byte swap. The number is shifted to the left according + to the size of the symbolic number before using it. */ unsigned HOST_WIDEST_INT cmp = sizeof (HOST_WIDEST_INT) < 8 ? 0 : - (unsigned HOST_WIDEST_INT)0x08070605 << 32 | 0x04030201; + (unsigned HOST_WIDEST_INT)0x01020304 << 32 | 0x05060708; struct symbolic_number n; tree source_expr; @@ -1079,7 +1082,7 @@ find_bswap (gimple stmt) ((unsigned HOST_WIDEST_INT)1 << (n.size * BITS_PER_UNIT)) - 1; n.n &= mask; - cmp &= mask; + cmp >>= (sizeof (HOST_WIDEST_INT) - n.size) * BITS_PER_UNIT; } /* A complete byte swap should make the symbolic number to start