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
This commit is contained in:
parent
d552d8190d
commit
7f5a398246
6 changed files with 146 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
41
gcc/testsuite/gcc.dg/store_merging_21.c
Normal file
41
gcc/testsuite/gcc.dg/store_merging_21.c
Normal file
|
@ -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" } } */
|
|
@ -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;
|
12
gcc/testsuite/gnat.dg/opt71b.adb
Normal file
12
gcc/testsuite/gnat.dg/opt71b.adb
Normal file
|
@ -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" } }
|
Loading…
Add table
Reference in a new issue