From f9ceb30223aaebae54f94dc80ab77c91aefd5440 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Mon, 4 Jun 2018 22:12:51 +0000 Subject: [PATCH] * gimple-ssa-store-merging.c (struct merged_store_group): Move up bit_insertion field and declare can_be_merged_into method. (merged_store_group::can_be_merged_into): New method. (imm_store_chain_info::coalesce_immediate): Call it to decide whether consecutive non-overlapping stores can be merged. Turn MEM_REF stores into BIT_INSERT_EXPR stores if the group contains a non-MEM_REF store. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@261173 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++ gcc/gimple-ssa-store-merging.c | 97 +++++++++++++++++++------ gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.dg/store_merging_21.c | 41 +++++++++++ gcc/testsuite/gnat.dg/{opt71.adb => opt71a.adb} | 2 +- gcc/testsuite/gnat.dg/{opt71.adb => opt71b.adb} | 4 +- 6 files changed, 136 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/store_merging_21.c copy gcc/testsuite/gnat.dg/{opt71.adb => opt71a.adb} (81%) rename gcc/testsuite/gnat.dg/{opt71.adb => opt71b.adb} (67%) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fda150a0426..074e1492afc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-06-04 Eric Botcazou + + * gimple-ssa-store-merging.c (struct merged_store_group): Move up + bit_insertion field and declare can_be_merged_into method. + (merged_store_group::can_be_merged_into): New method. + (imm_store_chain_info::coalesce_immediate): Call it to decide whether + consecutive non-overlapping stores can be merged. Turn MEM_REF stores + into BIT_INSERT_EXPR stores if the group contains a non-MEM_REF store. + 2018-06-04 Richard Biener PR tree-optimization/85955 diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index b972f9bef84..1cefdeb69b8 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -1426,6 +1426,7 @@ struct merged_store_group unsigned int load_align[2]; unsigned int first_order; unsigned int last_order; + bool bit_insertion; auto_vec stores; /* We record the first and last original statements in the sequence because @@ -1435,10 +1436,10 @@ struct merged_store_group gimple *first_stmt; unsigned char *val; unsigned char *mask; - bool bit_insertion; merged_store_group (store_immediate_info *); ~merged_store_group (); + bool can_be_merged_into (store_immediate_info *); void merge_into (store_immediate_info *); void merge_overlapping (store_immediate_info *); bool apply_stores (); @@ -1851,8 +1852,47 @@ merged_store_group::~merged_store_group () XDELETEVEC (val); } +/* Return true if the store described by INFO can be merged into the group. */ + +bool +merged_store_group::can_be_merged_into (store_immediate_info *info) +{ + /* Do not merge bswap patterns. */ + if (info->rhs_code == LROTATE_EXPR) + return false; + + /* The canonical case. */ + if (info->rhs_code == stores[0]->rhs_code) + return true; + + /* BIT_INSERT_EXPR is compatible with INTEGER_CST. */ + if (info->rhs_code == BIT_INSERT_EXPR && stores[0]->rhs_code == INTEGER_CST) + return true; + + 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. */ + 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) + 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) + return true; + + return false; +} + /* Helper method for merge_into and merge_overlapping to do the common part. */ + void merged_store_group::do_merge (store_immediate_info *info) { @@ -2673,12 +2713,7 @@ imm_store_chain_info::coalesce_immediate_stores () Merge it into the current store group. There can be gaps in between the stores, but there can't be gaps in between bitregions. */ else if (info->bitregion_start <= merged_store->bitregion_end - && info->rhs_code != LROTATE_EXPR - && (info->rhs_code == merged_store->stores[0]->rhs_code - || (info->rhs_code == INTEGER_CST - && merged_store->stores[0]->rhs_code == BIT_INSERT_EXPR) - || (info->rhs_code == BIT_INSERT_EXPR - && merged_store->stores[0]->rhs_code == INTEGER_CST))) + && merged_store->can_be_merged_into (info)) { store_immediate_info *infof = merged_store->stores[0]; @@ -2696,21 +2731,41 @@ imm_store_chain_info::coalesce_immediate_stores () std::swap (info->ops[0], info->ops[1]); info->ops_swapped_p = true; } - if ((infof->ops[0].base_addr - ? compatible_load_p (merged_store, info, base_addr, 0) - : !info->ops[0].base_addr) - && (infof->ops[1].base_addr - ? compatible_load_p (merged_store, info, base_addr, 1) - : !info->ops[1].base_addr) - && check_no_overlap (m_store_info, i, info->rhs_code, - MAX (merged_store->last_order, - info->order), - MAX (merged_store->start - + merged_store->width, - info->bitpos + info->bitsize))) + if (check_no_overlap (m_store_info, i, info->rhs_code, + MAX (merged_store->last_order, + info->order), + MAX (merged_store->start + + merged_store->width, + info->bitpos + info->bitsize))) { - merged_store->merge_into (info); - goto done; + /* Turn MEM_REF into BIT_INSERT_EXPR for bit-field stores. */ + if (info->rhs_code == MEM_REF && infof->rhs_code != MEM_REF) + { + info->rhs_code = BIT_INSERT_EXPR; + info->ops[0].val = gimple_assign_rhs1 (info->stmt); + info->ops[0].base_addr = NULL_TREE; + } + else if (infof->rhs_code == MEM_REF && info->rhs_code != MEM_REF) + { + store_immediate_info *infoj; + unsigned int j; + FOR_EACH_VEC_ELT (merged_store->stores, j, infoj) + { + infoj->rhs_code = BIT_INSERT_EXPR; + infoj->ops[0].val = gimple_assign_rhs1 (infoj->stmt); + infoj->ops[0].base_addr = NULL_TREE; + } + } + if ((infof->ops[0].base_addr + ? compatible_load_p (merged_store, info, base_addr, 0) + : !info->ops[0].base_addr) + && (infof->ops[1].base_addr + ? compatible_load_p (merged_store, info, base_addr, 1) + : !info->ops[1].base_addr)) + { + merged_store->merge_into (info); + goto done; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 821e08865fa..0d7bd34864b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-06-04 Eric Botcazou + + * gcc.dg/store_merging_21.c: New test. + * gnat.dg/opt71b.adb: Likewise. + * gnat.dg/opt71.adb: Rename into... + * gnat.dg/opt71a.adb: ...this. + 2018-06-04 Richard Biener PR tree-optimization/85955 diff --git a/gcc/testsuite/gcc.dg/store_merging_21.c b/gcc/testsuite/gcc.dg/store_merging_21.c new file mode 100644 index 00000000000..ec0c8e240b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/store_merging_21.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target store_merge } */ +/* { dg-options "-O2 -fdump-tree-store-merging" } */ + +extern void abort (void); + +struct S1 { + unsigned int flag : 1; + unsigned int size : 31; +}; + +void foo1 (struct S1 *s, struct S1 *m) +{ + s->flag = 1; + s->size = m->size; +} + +void bar1 (struct S1 *s, struct S1 *m, _Bool flag) +{ + s->flag = flag; + s->size = m->size; +} + +struct S2 { + unsigned int size : 31; + unsigned int flag : 1; +}; + +void foo2 (struct S2 *s, struct S2 *m) +{ + s->size = m->size; + s->flag = 1; +} + +void bar2 (struct S2 *s, struct S2 *m, _Bool flag) +{ + s->flag = flag; + s->size = m->size; +} + +/* { dg-final { scan-tree-dump-times "Merging successful" 4 "store-merging" } } */ diff --git a/gcc/testsuite/gnat.dg/opt71.adb b/gcc/testsuite/gnat.dg/opt71a.adb similarity index 81% copy from gcc/testsuite/gnat.dg/opt71.adb copy to gcc/testsuite/gnat.dg/opt71a.adb index d7ddee6e6c7..d2bd2b39840 100644 --- a/gcc/testsuite/gnat.dg/opt71.adb +++ b/gcc/testsuite/gnat.dg/opt71a.adb @@ -4,7 +4,7 @@ with Opt71_Pkg; use Opt71_Pkg; -procedure Opt71 (X : not null access Rec; Size : Positive) is +procedure Opt71a (X : not null access Rec; Size : Positive) is begin X.all := (Flag => True, Size => Size); end; diff --git a/gcc/testsuite/gnat.dg/opt71.adb b/gcc/testsuite/gnat.dg/opt71b.adb similarity index 67% rename from gcc/testsuite/gnat.dg/opt71.adb rename to gcc/testsuite/gnat.dg/opt71b.adb index d7ddee6e6c7..9fd91180b15 100644 --- a/gcc/testsuite/gnat.dg/opt71.adb +++ b/gcc/testsuite/gnat.dg/opt71b.adb @@ -4,9 +4,9 @@ with Opt71_Pkg; use Opt71_Pkg; -procedure Opt71 (X : not null access Rec; Size : Positive) is +procedure Opt71b (X : not null access Rec; Y : not null access Rec) is begin - X.all := (Flag => True, Size => Size); + X.all := (Flag => True, Size => Y.Size); end; -- { dg-final { scan-tree-dump "Merging successful" "store-merging" } } -- 2.11.4.GIT