diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2018-06-04 22:12:51 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2018-06-04 22:12:51 +0000 |
commit | 7f5a3982462c30aab676a3bf09ef4a62a30c7696 (patch) | |
tree | 65cd8834a5ebf2e1e26081175b3fc1a4b46b0b3d | |
parent | d552d8190dd2d9927fa55d09b73067eb6f40b7dd (diff) | |
download | gcc-7f5a3982462c30aab676a3bf09ef4a62a30c7696.zip gcc-7f5a3982462c30aab676a3bf09ef4a62a30c7696.tar.gz gcc-7f5a3982462c30aab676a3bf09ef4a62a30c7696.tar.bz2 |
gimple-ssa-store-merging.c (struct merged_store_group): Move up bit_insertion field and declare can_be_merged_into method.
* 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.
From-SVN: r261173
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/gimple-ssa-store-merging.c | 97 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/store_merging_21.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt71a.adb (renamed from gcc/testsuite/gnat.dg/opt71.adb) | 2 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt71b.adb | 12 |
6 files changed, 146 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fda150a..074e149 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-06-04 Eric Botcazou <ebotcazou@adacore.com> + + * 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 <rguenther@suse.de> PR tree-optimization/85955 diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index b972f9b..1cefdeb 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<store_immediate_info *> 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 821e088..0d7bd34 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-06-04 Eric Botcazou <ebotcazou@adacore.com> + + * 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 <rguenther@suse.de> 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 0000000..ec0c8e2 --- /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 index d7ddee6..d2bd2b3 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/opt71b.adb b/gcc/testsuite/gnat.dg/opt71b.adb new file mode 100644 index 0000000..9fd9118 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt71b.adb @@ -0,0 +1,12 @@ +-- { dg-do compile } +-- { dg-require-effective-target store_merge } +-- { dg-options "-O2 -fdump-tree-store-merging" } + +with Opt71_Pkg; use Opt71_Pkg; + +procedure Opt71b (X : not null access Rec; Y : not null access Rec) is +begin + X.all := (Flag => True, Size => Y.Size); +end; + +-- { dg-final { scan-tree-dump "Merging successful" "store-merging" } } |