80 lines
2.0 KiB
Diff
80 lines
2.0 KiB
Diff
2008-10-29 Jakub Jelinek <jakub@redhat.com>
|
|
|
|
PR middle-end/37870
|
|
* expmed.c (extract_bit_field_1): If int_mode_for_mode returns
|
|
BLKmode for non-memory, convert using a wider MODE_INT mode
|
|
or through memory.
|
|
|
|
* gcc.target/i386/pr37870.c: New test.
|
|
|
|
--- gcc/expmed.c (revision 141429)
|
|
+++ gcc/expmed.c (revision 141430)
|
|
@@ -1278,9 +1278,8 @@ extract_bit_field_1 (rtx str_rtx, unsign
|
|
{
|
|
if (MEM_P (op0))
|
|
op0 = adjust_address (op0, imode, 0);
|
|
- else
|
|
+ else if (imode != BLKmode)
|
|
{
|
|
- gcc_assert (imode != BLKmode);
|
|
op0 = gen_lowpart (imode, op0);
|
|
|
|
/* If we got a SUBREG, force it into a register since we
|
|
@@ -1288,6 +1287,24 @@ extract_bit_field_1 (rtx str_rtx, unsign
|
|
if (GET_CODE (op0) == SUBREG)
|
|
op0 = force_reg (imode, op0);
|
|
}
|
|
+ else if (REG_P (op0))
|
|
+ {
|
|
+ rtx reg, subreg;
|
|
+ imode = smallest_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op0)),
|
|
+ MODE_INT);
|
|
+ reg = gen_reg_rtx (imode);
|
|
+ subreg = gen_lowpart_SUBREG (GET_MODE (op0), reg);
|
|
+ emit_move_insn (subreg, op0);
|
|
+ op0 = reg;
|
|
+ bitnum += SUBREG_BYTE (subreg) * BITS_PER_UNIT;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ rtx mem = assign_stack_temp (GET_MODE (op0),
|
|
+ GET_MODE_SIZE (GET_MODE (op0)), 0);
|
|
+ emit_move_insn (mem, op0);
|
|
+ op0 = adjust_address (mem, BLKmode, 0);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
--- gcc/testsuite/gcc.target/i386/pr37870.c (revision 0)
|
|
+++ gcc/testsuite/gcc.target/i386/pr37870.c (revision 141430)
|
|
@@ -0,0 +1,29 @@
|
|
+/* PR middle-end/37870 */
|
|
+/* { dg-do run } */
|
|
+/* { dg-options "-O2" } */
|
|
+
|
|
+unsigned int
|
|
+foo (long double x)
|
|
+{
|
|
+ struct { char a[8]; unsigned int b:7; } c;
|
|
+ __builtin_memcpy (&c, &x, sizeof (c));
|
|
+ return c.b;
|
|
+}
|
|
+
|
|
+unsigned int
|
|
+bar (long double x)
|
|
+{
|
|
+ union { struct { char a[8]; unsigned int b:7; } c; long double d; } u;
|
|
+ u.d = x;
|
|
+ return u.c.b;
|
|
+}
|
|
+
|
|
+int
|
|
+main (void)
|
|
+{
|
|
+ if (foo (1.245L) != bar (1.245L)
|
|
+ || foo (245.67L) != bar (245.67L)
|
|
+ || foo (0.00567L) != bar (0.00567L))
|
|
+ __builtin_abort ();
|
|
+ return 0;
|
|
+}
|