This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Fix wrong code with VCE to bit-field type at -O
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 11 Feb 2014 11:40:11 +0100
- Subject: [patch] Fix wrong code with VCE to bit-field type at -O
- Authentication-results: sourceware.org; auth=none
Hi,
this is an interesting regression from GCC 4.5 present on all active branches
and triggered by recent SRA improvements. For the attached testcase, we have
an unchecked conversion of a 3-byte slice of an array of 4 bytes to a record
type containing a 3-byte bit-field; an unchecked conversion in this case
directly translates into a VIEW_CONVERT_EXPR. Then SRA scalarizes the bit-
field and turns the original VCE into a VCE of the 3-byte slice to the bit-
field type, which is a 32-bit integer with precision 24.
But the expansion of VCE isn't prepared for this and generates a full 32-bit
read, which thus reads 1 additional byte and doesn't mask it afterwards, thus
resulting in a wrong value for the scalarized bit-field.
Proposed fix attached, tested on x86-64/Linux, OK for the mainline?
2014-02-11 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (REDUCE_BIT_FIELD): Extend the scope of the macro.
(expand_expr_real_1) <case VIEW_CONVERT_EXPR>: Deal with bit-field
destination types.
2014-02-11 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/opt31.adb: New test.
--
Eric Botcazou
Index: expr.c
===================================================================
--- expr.c (revision 207685)
+++ expr.c (working copy)
@@ -9221,7 +9221,6 @@ expand_expr_real_2 (sepops ops, rtx targ
return temp;
return REDUCE_BIT_FIELD (temp);
}
-#undef REDUCE_BIT_FIELD
/* Return TRUE if expression STMT is suitable for replacement.
@@ -10444,15 +10443,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 it's a MEM with a different 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
@@ -10483,7 +10488,7 @@ expand_expr_real_1 (tree exp, rtx target
/* Nor can the insn generator. */
insn = GEN_FCN (icode) (reg, op0);
emit_insn (insn);
- return reg;
+ return REDUCE_BIT_FIELD (reg);
}
else if (STRICT_ALIGNMENT)
{
@@ -10513,7 +10518,7 @@ expand_expr_real_1 (tree exp, rtx target
op0 = adjust_address (op0, mode, 0);
}
- return op0;
+ return REDUCE_BIT_FIELD (op0);
case MODIFY_EXPR:
{
@@ -10613,6 +10618,7 @@ expand_expr_real_1 (tree exp, rtx target
return expand_expr_real_2 (&ops, target, tmode, modifier);
}
}
+#undef REDUCE_BIT_FIELD
/* Subroutine of above: reduce EXP to the precision of TYPE (in the
signedness of TYPE), possibly returning the result in TARGET. */
-- { dg-do run }
-- { dg-options "-O" }
with Interfaces; use Interfaces;
with Unchecked_Conversion;
procedure Opt31 is
type Unsigned_24 is new Unsigned_32 range 0 .. 2**24 - 1;
subtype Time_T is Unsigned_24 range 0 .. 24 * 60 * 60 * 128 - 1;
type Messages_T is array (Positive range <>) of Unsigned_8;
subtype T_3Bytes is Messages_T (1 .. 3);
type Rec1 is record
F : Time_T;
end record;
for Rec1 use record
F at 0 range 0 .. 23;
end record;
for Rec1'Size use 24;
type Rec2 is record
I1,I2,I3,I4 : Integer;
R1 : Rec1;
end record;
function Conv is new Unchecked_Conversion (T_3Bytes, Rec1);
procedure Decode (M : Messages_T) is
My_Rec2 : Rec2;
begin
My_Rec2.R1 := Conv (M (1 .. 3));
if not My_Rec2.R1.F'Valid then
raise Program_Error;
end if;
end;
Message : Messages_T (1 .. 4) := (16#18#, 16#0C#, 16#0C#, 16#18#);
begin
Decode (Message);
end;