OSDN Git Service

PR middle-end/30704
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Apr 2007 09:05:38 +0000 (09:05 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Apr 2007 09:05:38 +0000 (09:05 +0000)
* fold-const.c (native_encode_real): Encode real.c provided longs
as a series of 32-bit native integers.
(native_interpret_real): Interpret buffer as a series of 32-bit
native integers.

* gcc.c-torture/execute/ieee/pr30704.c: New test.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/ieee/pr30704.c [new file with mode: 0644]

index f7d8aa4..de6bea5 100644 (file)
@@ -1,3 +1,11 @@
+2007-04-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/30704
+       * fold-const.c (native_encode_real): Encode real.c provided longs
+       as a series of 32-bit native integers.
+       (native_interpret_real): Interpret buffer as a series of 32-bit
+       native integers.
+
 2007-04-03  Richard Guenther  <rguenther@suse.de>
 
        * genpreds.c (write_insn_constraint_len): Write function
index 5ee9cf1..a8b6f34 100644 (file)
@@ -7162,7 +7162,7 @@ native_encode_real (tree expr, unsigned char *ptr, int len)
 {
   tree type = TREE_TYPE (expr);
   int total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
-  int byte, offset, word, words;
+  int byte, offset, word, words, bitpos;
   unsigned char value;
 
   /* There are always 32 bits in each long, no matter the size of
@@ -7172,19 +7172,20 @@ native_encode_real (tree expr, unsigned char *ptr, int len)
 
   if (total_bytes > len)
     return 0;
-  words = total_bytes / UNITS_PER_WORD;
+  words = 32 / UNITS_PER_WORD;
 
   real_to_target (tmp, TREE_REAL_CST_PTR (expr), TYPE_MODE (type));
 
-  for (byte = 0; byte < total_bytes; byte++)
+  for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
+       bitpos += BITS_PER_UNIT)
     {
-      int bitpos = byte * BITS_PER_UNIT;
+      byte = (bitpos / BITS_PER_UNIT) & 3;
       value = (unsigned char) (tmp[bitpos / 32] >> (bitpos & 31));
 
-      if (total_bytes > UNITS_PER_WORD)
+      if (UNITS_PER_WORD < 4)
        {
          word = byte / UNITS_PER_WORD;
-         if (FLOAT_WORDS_BIG_ENDIAN)
+         if (WORDS_BIG_ENDIAN)
            word = (words - 1) - word;
          offset = word * UNITS_PER_WORD;
          if (BYTES_BIG_ENDIAN)
@@ -7193,8 +7194,8 @@ native_encode_real (tree expr, unsigned char *ptr, int len)
            offset += byte % UNITS_PER_WORD;
        }
       else
-       offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte;
-      ptr[offset] = value;
+       offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+      ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)] = value;
     }
   return total_bytes;
 }
@@ -7350,7 +7351,7 @@ native_interpret_real (tree type, unsigned char *ptr, int len)
 {
   enum machine_mode mode = TYPE_MODE (type);
   int total_bytes = GET_MODE_SIZE (mode);
-  int byte, offset, word, words;
+  int byte, offset, word, words, bitpos;
   unsigned char value;
   /* There are always 32 bits in each long, no matter the size of
      the hosts long.  We handle floating point representations with
@@ -7361,16 +7362,17 @@ native_interpret_real (tree type, unsigned char *ptr, int len)
   total_bytes = GET_MODE_SIZE (TYPE_MODE (type));
   if (total_bytes > len || total_bytes > 24)
     return NULL_TREE;
-  words = total_bytes / UNITS_PER_WORD;
+  words = 32 / UNITS_PER_WORD;
 
   memset (tmp, 0, sizeof (tmp));
-  for (byte = 0; byte < total_bytes; byte++)
+  for (bitpos = 0; bitpos < total_bytes * BITS_PER_UNIT;
+       bitpos += BITS_PER_UNIT)
     {
-      int bitpos = byte * BITS_PER_UNIT;
-      if (total_bytes > UNITS_PER_WORD)
+      byte = (bitpos / BITS_PER_UNIT) & 3;
+      if (UNITS_PER_WORD < 4)
        {
          word = byte / UNITS_PER_WORD;
-         if (FLOAT_WORDS_BIG_ENDIAN)
+         if (WORDS_BIG_ENDIAN)
            word = (words - 1) - word;
          offset = word * UNITS_PER_WORD;
          if (BYTES_BIG_ENDIAN)
@@ -7379,8 +7381,8 @@ native_interpret_real (tree type, unsigned char *ptr, int len)
            offset += byte % UNITS_PER_WORD;
        }
       else
-       offset = BYTES_BIG_ENDIAN ? (total_bytes - 1) - byte : byte;
-      value = ptr[offset];
+       offset = BYTES_BIG_ENDIAN ? 3 - byte : byte;
+      value = ptr[offset + ((bitpos / BITS_PER_UNIT) & ~3)];
 
       tmp[bitpos / 32] |= (unsigned long)value << (bitpos & 31);
     }
index ca83014..5570d48 100644 (file)
@@ -1,3 +1,8 @@
+2007-04-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/30704
+       * gcc.c-torture/execute/ieee/pr30704.c: New test.
+
 2007-04-02  Jason Merrill  <jason@redhat.com>
 
        PR c++/31187
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/pr30704.c b/gcc/testsuite/gcc.c-torture/execute/ieee/pr30704.c
new file mode 100644 (file)
index 0000000..2d062a9
--- /dev/null
@@ -0,0 +1,57 @@
+/* PR middle-end/30704 */
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern int memcmp (const void *, const void *, size_t);
+extern void *memcpy (void *, const void *, size_t);
+
+long long
+__attribute__((noinline))
+f1 (void)
+{
+  long long t;
+  double d = 0x0.fffffffffffff000p-1022;
+  memcpy (&t, &d, sizeof (long long));
+  return t;
+}
+
+double
+__attribute__((noinline))
+f2 (void)
+{
+  long long t = 0x000fedcba9876543LL;
+  double d;
+  memcpy (&d, &t, sizeof (long long));
+  return d;
+}
+
+int
+main ()
+{
+  union
+  {
+    long long ll;
+    double d;
+  } u;
+
+  if (sizeof (long long) != sizeof (double) || __DBL_MIN_EXP__ != -1021)
+    return 0;
+
+  u.ll = f1 ();
+  if (u.d != 0x0.fffffffffffff000p-1022)
+    abort ();
+
+  u.d = f2 ();
+  if (u.ll != 0x000fedcba9876543LL)
+    abort ();
+
+  double b = 234.0;
+  long long c;
+  double d = b;
+  memcpy (&c, &b, sizeof (double));
+  long long e = c;
+  if (memcmp (&e, &d, sizeof (double)) != 0)
+    abort ();
+
+  return 0;
+}