r141430 as a fix for PR37870 added a memory fallback to
extract_bit_field_1 and another case punning through a larger integer
mode (as suggested by Ian). That path is broken as it happily creates
(set (subreg:XF (reg:TI ..)) (...))
on i?86 when we optimize the added testcase
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;
}
on GIMPLE to
bar (long double x)
{
unsigned int _3;
<unnamed-unsigned:7> _4;
;; basic block 2, loop depth 0
;; pred: ENTRY
_4 = BIT_FIELD_REF <x_2(D), 7, 64>;
_3 = (unsigned int) _4;
return _3;
Bootstrapped and tested on x86_64-unknown-linux-gnu (also with -m32)
and the code replaced with a gcc_unreachable ().
I don't see how a subreg can be ever valid as it will be necessarily
converting to a non-integer mode of different size (otherwise
int_mode_for_mode would have returned non-BLKmode). I can't think
of a condition that would need to be satisfied where the subreg
would be valid either.
Ok for GCC 7? (it'll be done as part of said GIMPLE optimization).
The testcase gcc.target/i386/pr37870.c will already ICE with that
patch, so no additional testcase.
Thanks,
Richard.
2016-04-04 Richard Biener <[email protected]>
PR middle-end/37870
* expmed.c (extract_bit_field_1): Remove broken case
using a wider MODE_INT mode.
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c (revision 234708)
+++ gcc/expmed.c (working copy)
@@ -1647,17 +1647,6 @@ 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
{
HOST_WIDE_INT size = GET_MODE_SIZE (GET_MODE (op0));