expmed.c (store_bit_field): Handle paradoxical subregs on big endian machines.
authorAndreas Krebbel <krebbel1@de.ibm.com>
Tue, 25 Apr 2006 12:11:25 +0000 (12:11 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Tue, 25 Apr 2006 12:11:25 +0000 (12:11 +0000)
2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>

* expmed.c (store_bit_field): Handle paradoxical subregs on big endian
machines.

2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>

* gcc.dg/20060425-1.c: New testcase.

From-SVN: r113248

gcc/ChangeLog
gcc/expmed.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20060425-1.c [new file with mode: 0644]

index 2d88406635cadf1da6786d6317c23eac84ad6137..eb38288dd3ba93ac43f366337c841f9c498ac589 100644 (file)
@@ -1,3 +1,8 @@
+2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * expmed.c (store_bit_field): Handle paradoxical subregs on big endian
+       machines.
+
 2006-04-25  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        * genmodes.c (make_vector_mode): Allow making VECTOR_MODE_INT of a
index a4396c214e2afca88e64aa737a4d9ed6a9954e31..31b8241f29b3fab536276b47cffa66b9f8b427c0 100644 (file)
@@ -363,7 +363,25 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
         meaningful at a much higher level; when structures are copied
         between memory and regs, the higher-numbered regs
         always get higher addresses.  */
-      bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
+      int inner_mode_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)));
+      int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0));
+      
+      byte_offset = 0;
+
+      /* Paradoxical subregs need special handling on big endian machines.  */
+      if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
+       {
+         int difference = inner_mode_size - outer_mode_size;
+
+         if (WORDS_BIG_ENDIAN)
+           byte_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+         if (BYTES_BIG_ENDIAN)
+           byte_offset += difference % UNITS_PER_WORD;
+       }
+      else
+       byte_offset = SUBREG_BYTE (op0);
+
+      bitnum += byte_offset * BITS_PER_UNIT;
       op0 = SUBREG_REG (op0);
     }
 
index 3392b96288de91478b6e0e4e31311b8e59eb2dbe..f29ab274c5e304b3feff6d1cacbde4a1bdf4cf7d 100644 (file)
@@ -1,3 +1,7 @@
+2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>
+
+       * gcc.dg/20060425-1.c: New testcase.
+
 2006-04-25  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/26865
diff --git a/gcc/testsuite/gcc.dg/20060425-1.c b/gcc/testsuite/gcc.dg/20060425-1.c
new file mode 100644 (file)
index 0000000..7d899b2
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+/* This failed because if conversion didn't handle insv patterns properly.  */
+
+void abort (void);
+
+union y
+{
+  int a;
+  unsigned short b;
+};
+
+void __attribute__ ((noinline))
+bar (unsigned short u, union y v)
+{
+  if (u != 1)
+    abort ();
+}
+
+void __attribute__ ((noinline))
+foo (int check)
+{
+  union y x;
+
+  if (check != 0)
+    x.b = 1;
+  else
+    x.b = 2;
+  bar (x.b, x);
+}
+
+int
+main ()
+{
+  foo (1);
+  return 0;
+}