Commit a62b3dc5 by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/22141 (Missing optimization when storing structures)

	PR middle-end/22141
	* gimple-ssa-store-merging.c: Include rtl.h and expr.h.
	(struct store_immediate_info): Add bitregion_start and bitregion_end
	fields.
	(store_immediate_info::store_immediate_info): Add brs and bre
	arguments and initialize bitregion_{start,end} from those.
	(struct merged_store_group): Add bitregion_start, bitregion_end,
	align_base and mask fields.  Drop unnecessary struct keyword from
	struct store_immediate_info.  Add do_merge method.
	(clear_bit_region_be): Use memset instead of loop storing zeros.
	(merged_store_group::do_merge): New method.
	(merged_store_group::merge_into): Use do_merge.  Allow gaps in between
	stores as long as the surrounding bitregions have no gaps.
	(merged_store_group::merge_overlapping): Use do_merge.
	(merged_store_group::apply_stores): Test that bitregion_{start,end}
	is byte aligned, rather than requiring that start and width are
	byte aligned.  Drop unnecessary struct keyword from
	struct store_immediate_info.  Allocate and populate also mask array.
	Make start of the arrays relative to bitregion_start rather than
	start and size them according to bitregion_{end,start} difference.
	(struct imm_store_chain_info): Drop unnecessary struct keyword from
	struct store_immediate_info.
	(pass_store_merging::gate): Punt if BITS_PER_UNIT or CHAR_BIT is not 8.
	(pass_store_merging::terminate_all_aliasing_chains): Drop unnecessary
	struct keyword from struct store_immediate_info.
	(imm_store_chain_info::coalesce_immediate_stores): Allow gaps in
	between stores as long as the surrounding bitregions have no gaps.
	Formatting fixes.
	(struct split_store): Add orig non-static data member.
	(split_store::split_store): Initialize orig to false.
	(find_constituent_stmts): Return store_immediate_info *, non-NULL
	if there is exactly a single original stmt.  Change stmts argument
	to pointer from reference, if NULL, don't push anything to it.  Add
	first argument, use it to optimize skipping over orig stmts that
	are known to be before bitpos already.  Simplify.
	(split_group): Return unsigned int count how many stores are or
	would be needed rather than a bool.  Add allow_unaligned argument.
	Change split_stores argument from reference to pointer, if NULL,
	only do a dry run computing how many stores would be produced.
	Rewritten algorithm to use both alignment and misalign if
	!allow_unaligned and handle bitfield stores with gaps.
	(imm_store_chain_info::output_merged_store): Set start_byte_pos
	from bitregion_start instead of start.  Compute allow_unaligned
	here, if true, do 2 split_group dry runs to compute which one
	produces fewer stores and prefer aligned if equal.  Punt if
	new count is bigger or equal than original before emitting any
	statements, rather than during that.  Remove no longer needed
	new_ssa_names tracking.  Replace num_stmts with
	split_stores.length ().  Use 32-bit stack allocated entries
	in split_stores auto_vec.  Try to reuse original store lhs/rhs1
	if possible.  Handle bitfields with gaps.
	(pass_store_merging::execute): Ignore bitsize == 0 stores.
	Compute bitregion_{start,end} for the stores and construct
	store_immediate_info with that.  Formatting fixes.

	* gcc.dg/store_merging_10.c: New test.
	* gcc.dg/store_merging_11.c: New test.
	* gcc.dg/store_merging_12.c: New test.
	* g++.dg/pr71694.C: Add -fno-store-merging to dg-options.

From-SVN: r254213
parent 5603c1d9
2017-10-30 Jakub Jelinek <jakub@redhat.com>
PR middle-end/22141
* gimple-ssa-store-merging.c: Include rtl.h and expr.h.
(struct store_immediate_info): Add bitregion_start and bitregion_end
fields.
(store_immediate_info::store_immediate_info): Add brs and bre
arguments and initialize bitregion_{start,end} from those.
(struct merged_store_group): Add bitregion_start, bitregion_end,
align_base and mask fields. Drop unnecessary struct keyword from
struct store_immediate_info. Add do_merge method.
(clear_bit_region_be): Use memset instead of loop storing zeros.
(merged_store_group::do_merge): New method.
(merged_store_group::merge_into): Use do_merge. Allow gaps in between
stores as long as the surrounding bitregions have no gaps.
(merged_store_group::merge_overlapping): Use do_merge.
(merged_store_group::apply_stores): Test that bitregion_{start,end}
is byte aligned, rather than requiring that start and width are
byte aligned. Drop unnecessary struct keyword from
struct store_immediate_info. Allocate and populate also mask array.
Make start of the arrays relative to bitregion_start rather than
start and size them according to bitregion_{end,start} difference.
(struct imm_store_chain_info): Drop unnecessary struct keyword from
struct store_immediate_info.
(pass_store_merging::gate): Punt if BITS_PER_UNIT or CHAR_BIT is not 8.
(pass_store_merging::terminate_all_aliasing_chains): Drop unnecessary
struct keyword from struct store_immediate_info.
(imm_store_chain_info::coalesce_immediate_stores): Allow gaps in
between stores as long as the surrounding bitregions have no gaps.
Formatting fixes.
(struct split_store): Add orig non-static data member.
(split_store::split_store): Initialize orig to false.
(find_constituent_stmts): Return store_immediate_info *, non-NULL
if there is exactly a single original stmt. Change stmts argument
to pointer from reference, if NULL, don't push anything to it. Add
first argument, use it to optimize skipping over orig stmts that
are known to be before bitpos already. Simplify.
(split_group): Return unsigned int count how many stores are or
would be needed rather than a bool. Add allow_unaligned argument.
Change split_stores argument from reference to pointer, if NULL,
only do a dry run computing how many stores would be produced.
Rewritten algorithm to use both alignment and misalign if
!allow_unaligned and handle bitfield stores with gaps.
(imm_store_chain_info::output_merged_store): Set start_byte_pos
from bitregion_start instead of start. Compute allow_unaligned
here, if true, do 2 split_group dry runs to compute which one
produces fewer stores and prefer aligned if equal. Punt if
new count is bigger or equal than original before emitting any
statements, rather than during that. Remove no longer needed
new_ssa_names tracking. Replace num_stmts with
split_stores.length (). Use 32-bit stack allocated entries
in split_stores auto_vec. Try to reuse original store lhs/rhs1
if possible. Handle bitfields with gaps.
(pass_store_merging::execute): Ignore bitsize == 0 stores.
Compute bitregion_{start,end} for the stores and construct
store_immediate_info with that. Formatting fixes.
2017-10-30 Uros Bizjak <ubizjak@gmail.com> 2017-10-30 Uros Bizjak <ubizjak@gmail.com>
PR target/82725 PR target/82725
2017-10-30 Jakub Jelinek <jakub@redhat.com>
PR middle-end/22141
* gcc.dg/store_merging_10.c: New test.
* gcc.dg/store_merging_11.c: New test.
* gcc.dg/store_merging_12.c: New test.
* g++.dg/pr71694.C: Add -fno-store-merging to dg-options.
2017-10-30 Uros Bizjak <ubizjak@gmail.com> 2017-10-30 Uros Bizjak <ubizjak@gmail.com>
PR target/82725 PR target/82725
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2" } */ /* { dg-options "-O2 -fno-store-merging" } */
struct B { struct B {
B() {} B() {}
......
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
struct S {
unsigned int b1:1;
unsigned int b2:1;
unsigned int b3:1;
unsigned int b4:1;
unsigned int b5:1;
unsigned int b6:27;
};
struct T {
unsigned int b1:1;
unsigned int b2:16;
unsigned int b3:14;
unsigned int b4:1;
};
__attribute__((noipa)) void
foo (struct S *x)
{
x->b1 = 1;
x->b2 = 0;
x->b3 = 1;
x->b4 = 1;
x->b5 = 0;
}
__attribute__((noipa)) void
bar (struct T *x)
{
x->b1 = 1;
x->b2 = 0;
x->b4 = 0;
}
struct S s = { 0, 1, 0, 0, 1, 0x3a5f05a };
struct T t = { 0, 0xf5af, 0x3a5a, 1 };
int
main ()
{
asm volatile ("" : : : "memory");
foo (&s);
bar (&t);
asm volatile ("" : : : "memory");
if (s.b1 != 1 || s.b2 != 0 || s.b3 != 1 || s.b4 != 1 || s.b5 != 0 || s.b6 != 0x3a5f05a)
__builtin_abort ();
if (t.b1 != 1 || t.b2 != 0 || t.b3 != 0x3a5a || t.b4 != 0)
__builtin_abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "Merging successful" 2 "store-merging" } } */
/* { dg-do compile } */
/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
struct S { unsigned char b[2]; unsigned short c; unsigned char d[4]; unsigned long e; };
__attribute__((noipa)) void
foo (struct S *p)
{
p->b[1] = 1;
p->c = 23;
p->d[0] = 4;
p->d[1] = 5;
p->d[2] = 6;
p->d[3] = 7;
p->e = 8;
}
__attribute__((noipa)) void
bar (struct S *p)
{
p->b[1] = 9;
p->c = 112;
p->d[0] = 10;
p->d[1] = 11;
}
struct S s = { { 30, 31 }, 32, { 33, 34, 35, 36 }, 37 };
int
main ()
{
asm volatile ("" : : : "memory");
foo (&s);
asm volatile ("" : : : "memory");
if (s.b[0] != 30 || s.b[1] != 1 || s.c != 23 || s.d[0] != 4 || s.d[1] != 5
|| s.d[2] != 6 || s.d[3] != 7 || s.e != 8)
__builtin_abort ();
bar (&s);
asm volatile ("" : : : "memory");
if (s.b[0] != 30 || s.b[1] != 9 || s.c != 112 || s.d[0] != 10 || s.d[1] != 11
|| s.d[2] != 6 || s.d[3] != 7 || s.e != 8)
__builtin_abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "Merging successful" 2 "store-merging" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -Wall" } */
struct S { unsigned int b1:1, b2:1, b3:1, b4:1, b5:1, b6:27; };
void bar (struct S *);
void foo (int x)
{
struct S s;
s.b2 = 1; s.b3 = 0; s.b4 = 1; s.b5 = 0; s.b1 = x; s.b6 = x; /* { dg-bogus "is used uninitialized in this function" } */
bar (&s);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment