Hi,

the attached Ada testcase triggers a GIMPLE verification failure at -O2 or 
above because the GIMPLE store merging pass generates a NOP_EXPR between a FP 
type and an integral type.  This happens when the bit-field insertion path is 
taken for a FP field, which can happen in Ada for bit-packed record types.

It is fixed by generating an intermediate VIEW_CONVERT_EXPR.  The patch also 
tames a little the bit-field insertion path because, for bit-packed record 
types in Ada, you can end up with large bit-field regions, which results in a 
lot of mask-and-shifts instructions.

Tested on x86-64/Linux, OK for the mainline?


2020-05-25  Eric Botcazou  <ebotca...@adacore.com>

        * gimple-ssa-store-merging.c (merged_store_group::can_be_merged_into):
        Only turn MEM_REFs into bit-field stores for small bit-field regions.
        (imm_store_chain_info::output_merged_store): Be prepared for sources
        with non-integral type in the bit-field insertion case.
        (pass_store_merging::process_store): Use MAX_BITSIZE_MODE_ANY_INT as
        the largest size for the bit-field case.


2020-05-25  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/opt84.adb: New test.

-- 
Eric Botcazou
--  { dg-do compile }
--  { dg-options "-O2" }

with Ada.Text_IO;
with Interfaces;

procedure Opt84 is

   type Integer_8  is new Interfaces.Integer_8;
   type Integer_16 is new Interfaces.Integer_16;
   type Integer_32 is new Interfaces.Integer_32;

   type Float_32 is new Interfaces.IEEE_Float_32;

   type Natural_4 is range 0 .. 2 ** 4 - 1;
   for Natural_4'Size use 4;

   type Rec_Type is
      record
         Field_A_Int_8    : Integer_8;
         Field_B_Nat_4    : Natural_4;
         Field_C_Nat_4    : Natural_4;
         Field_D_Int_32   : Integer_32;
         Field_E_Int_32   : Integer_32;
         Field_F_Float_32 : Float_32;
         Field_G_Float_32 : Float_32;
         Field_H_Float_32 : Float_32;
         Field_I_Float_32 : Float_32;
         Field_J_Int_16   : Integer_16;
         Field_K_Int_16   : Integer_16;
         Field_L_Int_16   : Integer_16;
         Field_M_Int_16   : Integer_16;
         Field_N_Float_32 : Float_32;
         Field_O_Float_32 : Float_32;
      end record;
   pragma Pack (Rec_Type);
   for Rec_Type'Alignment use 1;

   procedure Print
     (Item : in Rec_Type) is
   begin
      Ada.Text_IO.Put_Line (Item.Field_F_Float_32'Image);
      Ada.Text_IO.Put_Line (Item.Field_G_Float_32'Image);
      Ada.Text_IO.Put_Line (Item.Field_H_Float_32'Image);
      Ada.Text_IO.Put_Line (Item.Field_I_Float_32'Image);
   end Print;

   procedure Test_Foo is
      Source : Rec_Type;
      Dest   : Rec_Type;
   begin
      Source.Field_A_Int_8 := 0;
      Dest.Field_A_Int_8    := 1;
      Dest.Field_B_Nat_4    := Source.Field_B_Nat_4;
      Dest.Field_C_Nat_4    := Source.Field_C_Nat_4;
      Dest.Field_D_Int_32   := Source.Field_D_Int_32;
      Dest.Field_E_Int_32   := Source.Field_E_Int_32;
      Dest.Field_F_Float_32 := Source.Field_F_Float_32;
      Dest.Field_G_Float_32 := Source.Field_G_Float_32;
      Dest.Field_H_Float_32 := Source.Field_H_Float_32;
      Dest.Field_I_Float_32 := Source.Field_I_Float_32;
      Dest.Field_J_Int_16   := Source.Field_J_Int_16;
      Dest.Field_K_Int_16   := Source.Field_K_Int_16;
      Dest.Field_L_Int_16   := Source.Field_L_Int_16;
      Dest.Field_M_Int_16   := Source.Field_M_Int_16;
      Dest.Field_N_Float_32 := Source.Field_N_Float_32;
      Dest.Field_O_Float_32 := Source.Field_O_Float_32;
      Print (Source);
      Print (Dest);
   end Test_Foo;

begin
   Test_Foo;
end;
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index c8e1877f540..65e27f38fd4 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -1867,19 +1867,22 @@ merged_store_group::can_be_merged_into (store_immediate_info *info)
   if (stores[0]->rhs_code == BIT_INSERT_EXPR && info->rhs_code == INTEGER_CST)
     return true;
 
-  /* We can turn MEM_REF into BIT_INSERT_EXPR for bit-field stores.  */
+  /* We can turn MEM_REF into BIT_INSERT_EXPR for bit-field stores, but do it
+     only for small regions since this can generate a lot of instructions.  */
   if (info->rhs_code == MEM_REF
       && (stores[0]->rhs_code == INTEGER_CST
 	  || stores[0]->rhs_code == BIT_INSERT_EXPR)
       && info->bitregion_start == stores[0]->bitregion_start
-      && info->bitregion_end == stores[0]->bitregion_end)
+      && info->bitregion_end == stores[0]->bitregion_end
+      && info->bitregion_end - info->bitregion_start < MAX_BITSIZE_MODE_ANY_INT)
     return true;
 
   if (stores[0]->rhs_code == MEM_REF
       && (info->rhs_code == INTEGER_CST
 	  || info->rhs_code == BIT_INSERT_EXPR)
       && info->bitregion_start == stores[0]->bitregion_start
-      && info->bitregion_end == stores[0]->bitregion_end)
+      && info->bitregion_end == stores[0]->bitregion_end
+      && info->bitregion_end - info->bitregion_start < MAX_BITSIZE_MODE_ANY_INT)
     return true;
 
   return false;
@@ -4172,6 +4175,15 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
 		  const HOST_WIDE_INT end_gap
 		    = (try_bitpos + try_size) - (info->bitpos + info->bitsize);
 		  tree tem = info->ops[0].val;
+		  if (!INTEGRAL_TYPE_P (TREE_TYPE (tem)))
+		    {
+		      const unsigned HOST_WIDE_INT size
+			= tree_to_uhwi (TYPE_SIZE (TREE_TYPE (tem)));
+		      tree integer_type
+			= build_nonstandard_integer_type (size, UNSIGNED);
+		      tem = gimple_build (&seq, loc, VIEW_CONVERT_EXPR,
+					  integer_type, tem);
+		    }
 		  if (TYPE_PRECISION (TREE_TYPE (tem)) <= info->bitsize)
 		    {
 		      tree bitfield_type
@@ -4788,7 +4800,7 @@ pass_store_merging::process_store (gimple *stmt)
 	  && bitsize.is_constant (&const_bitsize)
 	  && ((const_bitsize % BITS_PER_UNIT) != 0
 	      || !multiple_p (bitpos, BITS_PER_UNIT))
-	  && const_bitsize <= 64)
+	  && const_bitsize <= MAX_BITSIZE_MODE_ANY_INT)
 	{
 	  /* Bypass a conversion to the bit-field type.  */
 	  if (!bit_not_p

Reply via email to