> There is nothing obvious I think, i.e. that's debatable. I agree that a VCE
> from a 32-bit object to a 32-bit integer with 24-bit precision should not
> clear the upper 8 bits (so the REDUCE_BIT_FIELD part of my patch is wrong).
> But here we have a VCE from a 24-bit object to a 32-bit integer with 24-bit
> precision which reads *more bits* than the size of the source type; that I
> think is plain wrong and is fixed by the bit-field extraction in the patch.
Revised patch along these lines attached. Although I agree that it's a bit of
a kludge, it's quite localized and plausible IMO.
* expr.c (expand_expr_real_1) <case VIEW_CONVERT_EXPR>: For a bit-field
destination type, extract exactly the number of valid bits if the source
type isn't integral or has a different precision.
--
Eric Botcazou
Index: expr.c
===================================================================
--- expr.c (revision 207796)
+++ expr.c (working copy)
@@ -10458,15 +10458,21 @@ expand_expr_real_1 (tree exp, rtx target
op0 = target;
}
- /* At this point, OP0 is in the correct mode. If the output type is
+ /* If OP0 is a MEM without the correct mode and we need to reduce it to
+ a bit-field type, do an extraction. Otherwise, we can read all bits
+ of MODE but need to deal with the alignment. If the output type is
such that the operand is known to be aligned, indicate that it is.
- Otherwise, we need only be concerned about alignment for non-BLKmode
- results. */
+ Otherwise, we actually need only be concerned about alignment for
+ non-BLKmode results. */
if (MEM_P (op0))
{
enum insn_code icode;
- if (TYPE_ALIGN_OK (type))
+ if (reduce_bit_field && GET_MODE (op0) != mode)
+ return extract_bit_field (op0, TYPE_PRECISION (type), 0,
+ TYPE_UNSIGNED (type), NULL_RTX,
+ mode, mode);
+ else if (TYPE_ALIGN_OK (type))
{
/* ??? Copying the MEM without substantially changing it might
run afoul of the code handling volatile memory references in