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