Fix internal error on store to FP component at -O2
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 25 May 2020 20:13:11 +0000 (22:13 +0200)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 25 May 2020 20:19:03 +0000 (22:19 +0200)
This is about 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.

gcc/ChangeLog
* 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.

gcc/testsuite/ChangeLog
* gnat.dg/opt84.adb: New test.

gcc/ChangeLog
gcc/gimple-ssa-store-merging.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt84.adb [new file with mode: 0644]

index 52a7e507740306fadb94b5583e5fbcd2ba246a9c..a96dedc88382a36aec3b87b19ae4565787fea183 100644 (file)
@@ -1,3 +1,12 @@
+2020-05-25  Eric Botcazou  <ebotcazou@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  Uroš Bizjak  <ubizjak@gmail.com>
 
        * config/i386/mmx.md (*vec_dupv2sf): Redefine as define_insn.
index c8e1877f54077b2c905994e177d85f3649d0a0e2..400a0010c343828550b5c81643a5260a0bbd16a2 100644 (file)
@@ -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_FIXED_MODE_SIZE)
     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_FIXED_MODE_SIZE)
     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_FIXED_MODE_SIZE)
        {
          /* Bypass a conversion to the bit-field type.  */
          if (!bit_not_p
index 4cc2d4188bfea04786ceb5acd0c51ff5ccaa13a6..aec3a21995313fe761208ec110cb7cca4c2a54dd 100644 (file)
@@ -1,3 +1,7 @@
+2020-05-25  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt84.adb: New test.
+
 2020-05-25  Uroš Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/sse2-mmx-18a.c (dg-options): Remove -mno-avx512vl.
diff --git a/gcc/testsuite/gnat.dg/opt84.adb b/gcc/testsuite/gnat.dg/opt84.adb
new file mode 100644 (file)
index 0000000..45bce7e
--- /dev/null
@@ -0,0 +1,74 @@
+--  { 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;