aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@gcc.gnu.org>2020-05-25 22:13:11 +0200
committerEric Botcazou <ebotcazou@gcc.gnu.org>2020-05-25 22:19:03 +0200
commited01d707f8594827de95304371d5b62752410842 (patch)
treef42cb873d39181ee91f8fe52962b57a66c1b0c3e /gcc
parent14cd049afcb992ac334b4a2ad7be42ee78fe31eb (diff)
downloadgcc-ed01d707f8594827de95304371d5b62752410842.zip
gcc-ed01d707f8594827de95304371d5b62752410842.tar.gz
gcc-ed01d707f8594827de95304371d5b62752410842.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/gimple-ssa-store-merging.c20
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gnat.dg/opt84.adb74
4 files changed, 103 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 52a7e50..a96dedc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index c8e1877..400a001 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 4cc2d41..aec3a21 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..45bce7e
--- /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;