This patch improves on the code generated for an assignment to a component of
a bit-packed array, when lhs and rhs have a different representation.

Executing the following :

   gcc -c -gnatG p1.adb | grep -c '\$system__pack_40'

must yield:

   1
---

package Conf is
   type UINT32_T is mod 2**32;
   for UINT32_T'SIZE use 32;

   type UINT4_T is mod 2**4;
   for UINT4_T'SIZE use 4;

   -- record type

   type REC_T is record
      SIZE : UINT32_T;
      V1, V2 : Uint4_T;
   end record;

   -- packed record type

   type REC_pack_T is new REC_T;
   for REC_pack_T use record
      SIZE at 0 range 0 .. 31;     -- 32 bits
      V1   at 0 range 32 .. 35;    -- 4 bits
      V2   at 0 range 36 .. 39;    -- 4 bits
   end record;
   for REC_pack_T'Size use 40;

   -- packed arrays of each record type

   subtype ARRAY_INDEX_T is Integer range 1 .. 10;

   type PARR_R_T is array (ARRAY_INDEX_T) of REC_T;
   pragma Pack (PARR_R_T);

   type PARR_PR_T is array(ARRAY_INDEX_T) of REC_PACK_T;
   pragma Pack (PARR_PR_T);

   -- data

   Csz : constant Uint32_T := 0;
   Cv1 : constant Uint4_T := 0;
   Cv2 : constant Uint4_T := 3;

   A_R : PARR_R_T := (others => (SIZE => Csz, V1 => Cv1, V2 => Cv2));
   
   --
   
   procedure Assert (Cond : Boolean);

   PR : REC_PACK_T;
   A_PR : PARR_PR_T;
   
   INDEX : constant := 8;
end;
---
with Conf; use Conf;
procedure P1 is
begin
   PR := REC_PACK_T(A_R (INDEX));
   A_PR (INDEX) := PR;
end;

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-08-29  Ed Schonberg  <schonb...@adacore.com>

        * exp_ch5.adb (Expand_N_Assignment_Statement): if the left-hand side is
        an indexed component of a packed array whose element type is a record
        with a representation clause different from that of the right-hand
        side, generate a temporary to minimuze the number of bit-field
        operations generated.

Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 178177)
+++ exp_ch5.adb (working copy)
@@ -1890,11 +1890,42 @@
 
       if Nkind (Lhs) = N_Indexed_Component
         and then Is_Bit_Packed_Array (Etype (Prefix (Lhs)))
-        and then not Crep
       then
-         Expand_Bit_Packed_Element_Set (N);
-         return;
+         if not Crep then
+            Expand_Bit_Packed_Element_Set (N);
+            return;
+         else
 
+            --  Generate the following, to force component-by-component
+            --  assignments in an efficient way. Otherwise each component
+            --  will require a temporary and two bit-field manipulations.
+
+            --  T1 : Elmt_Type;
+            --  T1 := RhS;
+            --  Lhs := T1;
+
+            declare
+               Tnn : constant Entity_Id := Make_Temporary (Loc, 'T');
+               Stats : List_Id;
+
+            begin
+               Stats := New_List (
+                 Make_Object_Declaration (Loc,
+                   Defining_Identifier => Tnn,
+                   Object_Definition => New_Occurrence_Of (Etype (Lhs), Loc)),
+                Make_Assignment_Statement (Loc,
+                  Name => New_Occurrence_Of (Tnn, Loc),
+                  Expression => Relocate_Node (Rhs)),
+                Make_Assignment_Statement (Loc,
+                  Name => Relocate_Node (Lhs),
+                  Expression => New_Occurrence_Of (Tnn, Loc)));
+
+               Insert_Actions (N, Stats);
+               Rewrite (N, Make_Null_Statement (Loc));
+               Analyze (N);
+            end;
+         end if;
+
       --  Build-in-place function call case. Note that we're not yet doing
       --  build-in-place for user-written assignment statements (the assignment
       --  here came from an aggregate.)

Reply via email to