From ed01d707f8594827de95304371d5b62752410842 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Mon, 25 May 2020 22:13:11 +0200 Subject: [PATCH] Fix internal error on store to FP component at -O2 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 | 9 ++++ gcc/gimple-ssa-store-merging.c | 20 +++++++-- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/opt84.adb | 74 +++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/opt84.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 52a7e507740..a96dedc8838 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2020-05-25 Eric Botcazou + + * 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 * config/i386/mmx.md (*vec_dupv2sf): Redefine as define_insn. diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index c8e1877f540..400a0010c34 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_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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4cc2d4188bf..aec3a219953 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-05-25 Eric Botcazou + + * gnat.dg/opt84.adb: New test. + 2020-05-25 Uroš Bizjak * 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 index 00000000000..45bce7eb625 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt84.adb @@ -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; -- 2.30.2