[PATCH] Fix extract_fixed_bit_field (PR middle-end/49029)

Jakub Jelinek jakub@redhat.com
Wed May 18 15:47:00 GMT 2011


Hi!

The attached testcase ICEs on arm, because extract_fixed_bit_field
with tmode SImode (and SImode non-NULL target) decides to use DImode for
the signed shifts, but doesn't clear target and thus attempts to use
that SImode target for DImode shifts.
The code apparently already has if (mode != tmode) target = 0;, just
done at a wrong spot before mode can be changed.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux
and tested with a cross to arm-linux on the testcase, ok for trunk/4.6?

2011-05-18  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/49029
	* expmed.c (extract_fixed_bit_field): Test whether target can be used
	only after deciding which mode to use.

	* gcc.c-torture/compile/pr49029.c: New test.

--- gcc/expmed.c.jj	2011-05-11 19:39:04.000000000 +0200
+++ gcc/expmed.c	2011-05-18 11:38:43.000000000 +0200
@@ -1769,8 +1769,6 @@ extract_fixed_bit_field (enum machine_mo
   /* To extract a signed bit-field, first shift its msb to the msb of the word,
      then arithmetic-shift its lsb to the lsb of the word.  */
   op0 = force_reg (mode, op0);
-  if (mode != tmode)
-    target = 0;
 
   /* Find the narrowest integer mode that contains the field.  */
 
@@ -1782,6 +1780,9 @@ extract_fixed_bit_field (enum machine_mo
 	break;
       }
 
+  if (mode != tmode)
+    target = 0;
+
   if (GET_MODE_BITSIZE (mode) != (bitsize + bitpos))
     {
       int amount = GET_MODE_BITSIZE (mode) - (bitsize + bitpos);
--- gcc/testsuite/gcc.c-torture/compile/pr49029.c.jj	2011-05-18 11:55:25.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr49029.c	2011-05-18 11:54:22.000000000 +0200
@@ -0,0 +1,10 @@
+/* PR middle-end/49029 */
+struct S { volatile unsigned f : 11; signed g : 30; } __attribute__((packed));
+struct T { volatile struct S h; } __attribute__((packed)) a;
+void foo (int);
+
+void
+bar ()
+{
+  foo (a.h.g);
+}

	Jakub



More information about the Gcc-patches mailing list