diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 6089faf7ac8..17a4250d77f 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -1450,6 +1450,7 @@ public: bool bit_insertion; bool string_concatenation; bool only_constants; + bool consecutive; unsigned int first_nonmergeable_order; int lp_nr; @@ -1822,6 +1823,7 @@ merged_store_group::merged_store_group (store_immediate_info *info) bit_insertion = info->rhs_code == BIT_INSERT_EXPR; string_concatenation = info->rhs_code == STRING_CST; only_constants = info->rhs_code == INTEGER_CST; + consecutive = true; first_nonmergeable_order = ~0U; lp_nr = info->lp_nr; unsigned HOST_WIDE_INT align_bitpos = 0; @@ -1957,6 +1959,9 @@ merged_store_group::do_merge (store_immediate_info *info) first_stmt = stmt; } + if (info->bitpos != start + width) + consecutive = false; + /* We need to use extraction if there is any bit-field. */ if (info->rhs_code == BIT_INSERT_EXPR) { @@ -1964,13 +1969,17 @@ merged_store_group::do_merge (store_immediate_info *info) gcc_assert (!string_concatenation); } - /* We need to use concatenation if there is any string. */ + /* We want to use concatenation if there is any string. */ if (info->rhs_code == STRING_CST) { string_concatenation = true; gcc_assert (!bit_insertion); } + /* But we cannot use it if we don't have consecutive stores. */ + if (!consecutive) + string_concatenation = false; + if (info->rhs_code != INTEGER_CST) only_constants = false; } @@ -1982,12 +1991,13 @@ merged_store_group::do_merge (store_immediate_info *info) void merged_store_group::merge_into (store_immediate_info *info) { + do_merge (info); + /* Make sure we're inserting in the position we think we're inserting. */ gcc_assert (info->bitpos >= start + width && info->bitregion_start <= bitregion_end); width = info->bitpos + info->bitsize - start; - do_merge (info); } /* Merge a store described by INFO into this merged store. @@ -1997,11 +2007,11 @@ merged_store_group::merge_into (store_immediate_info *info) void merged_store_group::merge_overlapping (store_immediate_info *info) { + do_merge (info); + /* If the store extends the size of the group, extend the width. */ if (info->bitpos + info->bitsize > start + width) width = info->bitpos + info->bitsize - start; - - do_merge (info); } /* Go through all the recorded stores in this group in program order and diff --git a/gcc/testsuite/gnat.dg/opt90a.adb b/gcc/testsuite/gnat.dg/opt90a.adb new file mode 100644 index 00000000000..7de628914cc --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90a.adb @@ -0,0 +1,16 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Calendar; use Ada.Calendar; +with Opt90a_Pkg; use Opt90a_Pkg; + +procedure Opt90a is + B : constant Integer := Year (Clock); + V : Data; + +begin + V := (R => (A => 0, B => B, C => "000000000000")); + if V.R.B /= B then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt90a_pkg.ads b/gcc/testsuite/gnat.dg/opt90a_pkg.ads new file mode 100644 index 00000000000..10a527b8d81 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90a_pkg.ads @@ -0,0 +1,15 @@ +package Opt90a_Pkg is + + type Rec is record + A : Short_Short_Integer; + B : Integer; + C : String (1 .. 12); + end record; + pragma Pack (Rec); + for Rec'Alignment use 1; + + type Data is tagged record + R : Rec; + end record; + +end Opt90a_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt90b.adb b/gcc/testsuite/gnat.dg/opt90b.adb new file mode 100644 index 00000000000..6da58bbcc7e --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90b.adb @@ -0,0 +1,16 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Calendar; use Ada.Calendar; +with Opt90b_Pkg; use Opt90b_Pkg; + +procedure Opt90b is + B : constant Integer := Year (Clock); + V : Data; + +begin + V := (R => (A => 0, B => B, C => 0, D => "000000000000")); + if V.R.B /= B then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt90b_pkg.ads b/gcc/testsuite/gnat.dg/opt90b_pkg.ads new file mode 100644 index 00000000000..f0b233c528e --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90b_pkg.ads @@ -0,0 +1,16 @@ +package Opt90b_Pkg is + + type Rec is record + A : Short_Short_Integer; + B : Integer; + C : Short_Integer; + D : String (1 .. 12); + end record; + pragma Pack (Rec); + for Rec'Alignment use 1; + + type Data is tagged record + R : Rec; + end record; + +end Opt90b_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt90c.adb b/gcc/testsuite/gnat.dg/opt90c.adb new file mode 100644 index 00000000000..b4f4c2790eb --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90c.adb @@ -0,0 +1,16 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Calendar; use Ada.Calendar; +with Opt90c_Pkg; use Opt90c_Pkg; + +procedure Opt90c is + B : constant Integer := Year (Clock); + V : Data; + +begin + V := (R => (A => 0, B => B, C => 0, D => "000000000000")); + if V.R.B /= B then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt90c_pkg.ads b/gcc/testsuite/gnat.dg/opt90c_pkg.ads new file mode 100644 index 00000000000..e772340dc1d --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90c_pkg.ads @@ -0,0 +1,16 @@ +package Opt90c_Pkg is + + type Rec is record + D : String (1 .. 12); + B : Integer; + A : Short_Short_Integer; + C : Short_Integer; + end record; + pragma Pack (Rec); + for Rec'Alignment use 1; + + type Data is tagged record + R : Rec; + end record; + +end Opt90c_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt90d.adb b/gcc/testsuite/gnat.dg/opt90d.adb new file mode 100644 index 00000000000..32ecb68964e --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90d.adb @@ -0,0 +1,16 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Calendar; use Ada.Calendar; +with Opt90d_Pkg; use Opt90d_Pkg; + +procedure Opt90d is + B : constant Integer := Year (Clock); + V : Data; + +begin + V := (R => (A => 0, B => B, C => 0, D => "000000000000")); + if V.R.B /= B then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt90d_pkg.ads b/gcc/testsuite/gnat.dg/opt90d_pkg.ads new file mode 100644 index 00000000000..a68b224893c --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90d_pkg.ads @@ -0,0 +1,16 @@ +package Opt90d_Pkg is + + type Rec is record + D : String (1 .. 12); + C : Short_Integer; + A : Short_Short_Integer; + B : Integer; + end record; + pragma Pack (Rec); + for Rec'Alignment use 1; + + type Data is tagged record + R : Rec; + end record; + +end Opt90d_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt90e.adb b/gcc/testsuite/gnat.dg/opt90e.adb new file mode 100644 index 00000000000..6d62774b6d9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90e.adb @@ -0,0 +1,16 @@ +-- { dg-do run } +-- { dg-options "-O2" } + +with Ada.Calendar; use Ada.Calendar; +with Opt90e_Pkg; use Opt90e_Pkg; + +procedure Opt90e is + B : constant Integer := Year (Clock); + V : Data; + +begin + V := (R => (A => 0, B => B, C => 0, D => "000000000000")); + if V.R.B /= B then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/opt90e_pkg.ads b/gcc/testsuite/gnat.dg/opt90e_pkg.ads new file mode 100644 index 00000000000..fba16d7a738 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt90e_pkg.ads @@ -0,0 +1,16 @@ +package Opt90e_Pkg is + + type Rec is record + D : String (1 .. 12); + A : Short_Short_Integer; + B : Integer; + C : Short_Integer; + end record; + pragma Pack (Rec); + for Rec'Alignment use 1; + + type Data is tagged record + R : Rec; + end record; + +end Opt90e_Pkg;