Hi!
I've backported from trunk, bootstrapped/regtested on x86_64-linux and
i686-linux and committed to gcc-8-branch the following 6 patches.
Jakub
2018-11-05 Jakub Jelinek <[email protected]>
Backported from mainline
2018-10-19 Jakub Jelinek <[email protected]>
PR middle-end/85488
PR middle-end/87649
* omp-low.c (check_omp_nesting_restrictions): Diagnose ordered without
depend closely nested inside of loop with ordered clause with
a parameter.
* c-c++-common/gomp/doacross-2.c: New test.
* c-c++-common/gomp/sink-3.c: Expect another error during error
recovery.
--- gcc/omp-low.c (revision 265334)
+++ gcc/omp-low.c (revision 265335)
@@ -2762,14 +2762,25 @@ check_omp_nesting_restrictions (gimple *
case GIMPLE_OMP_FOR:
if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
goto ordered_in_taskloop;
- if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
- OMP_CLAUSE_ORDERED) == NULL)
+ tree o;
+ o = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
+ OMP_CLAUSE_ORDERED);
+ if (o == NULL)
{
error_at (gimple_location (stmt),
"%<ordered%> region must be closely nested inside "
"a loop region with an %<ordered%> clause");
return false;
}
+ if (OMP_CLAUSE_ORDERED_EXPR (o) != NULL_TREE
+ && omp_find_clause (c, OMP_CLAUSE_DEPEND) == NULL_TREE)
+ {
+ error_at (gimple_location (stmt),
+ "%<ordered%> region without %<depend%> clause may "
+ "not be closely nested inside a loop region with "
+ "an %<ordered%> clause with a parameter");
+ return false;
+ }
return true;
case GIMPLE_OMP_TARGET:
if (gimple_omp_target_kind (ctx->stmt)
--- gcc/testsuite/c-c++-common/gomp/sink-3.c (revision 265334)
+++ gcc/testsuite/c-c++-common/gomp/sink-3.c (revision 265335)
@@ -14,7 +14,7 @@ foo ()
for (i=0; i < 100; ++i)
{
#pragma omp ordered depend(sink:poo-1,paa+1) /* { dg-error
"poo.*declared.*paa.*declared" } */
- bar(&i);
+ bar(&i); /* { dg-error "may not be closely
nested" "" { target *-*-* } .-1 } */
#pragma omp ordered depend(source)
}
}
--- gcc/testsuite/c-c++-common/gomp/doacross-2.c (nonexistent)
+++ gcc/testsuite/c-c++-common/gomp/doacross-2.c (revision 265335)
@@ -0,0 +1,49 @@
+/* PR middle-end/87649 */
+
+void
+foo (void)
+{
+ int i;
+ #pragma omp for ordered(1)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered /* { dg-error "'ordered' region
without 'depend' clause may not be closely nested inside a loop region with an
'ordered' clause with a parameter" } */
+ ;
+ }
+ #pragma omp for ordered(1)
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered threads /* { dg-error "'ordered' region
without 'depend' clause may not be closely nested inside a loop region with an
'ordered' clause with a parameter" } */
+ ;
+ }
+}
+
+void
+bar (void)
+{
+ int i;
+ #pragma omp for ordered
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(source) /* { dg-error "'ordered'
construct with 'depend' clause must be closely nested inside a loop with
'ordered' clause with a parameter" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered'
construct with 'depend' clause must be closely nested inside a loop with
'ordered' clause with a parameter" } */
+ }
+ #pragma omp for
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(source) /* { dg-error "'ordered'
construct with 'depend' clause must be closely nested inside a loop with
'ordered' clause with a parameter" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "'ordered'
construct with 'depend' clause must be closely nested inside a loop with
'ordered' clause with a parameter" } */
+ }
+ #pragma omp for
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered /* { dg-error "'ordered' region
must be closely nested inside a loop region with an 'ordered' clause" } */
+ ;
+ }
+ #pragma omp for
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered threads /* { dg-error "'ordered' region
must be closely nested inside a loop region with an 'ordered' clause" } */
+ ;
+ }
+}
2018-11-05 Jakub Jelinek <[email protected]>
Backported from mainline
2018-10-20 Jakub Jelinek <[email protected]>
PR middle-end/87647
* varasm.c (decode_addr_const): Handle COMPOUND_LITERAL_EXPR.
* gcc.c-torture/compile/pr87647.c: New test.
--- gcc/varasm.c (revision 265340)
+++ gcc/varasm.c (revision 265341)
@@ -2953,6 +2953,11 @@ decode_addr_const (tree exp, struct addr
gen_rtx_SYMBOL_REF (Pmode, "origin of addresses"));
break;
+ case COMPOUND_LITERAL_EXPR:
+ gcc_assert (COMPOUND_LITERAL_EXPR_DECL (target));
+ x = DECL_RTL (COMPOUND_LITERAL_EXPR_DECL (target));
+ break;
+
default:
gcc_unreachable ();
}
--- gcc/testsuite/gcc.c-torture/compile/pr87647.c (nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr87647.c (revision 265341)
@@ -0,0 +1,15 @@
+/* PR middle-end/87647 */
+
+struct A {};
+struct A *const b = &(struct A) {};
+struct B { char *s; struct A *t; };
+void bar (struct B *);
+
+void
+foo (void)
+{
+ struct B a[] = { "", b, "", b, "", b, "", b, "", b, "", b, "", b, "", b,
+ "", b, "", b, "", b, "", b, "", b, "", b, "", b, "", b,
+ "", b };
+ bar (a);
+}
2018-11-05 Jakub Jelinek <[email protected]>
Backported from mainline
2018-10-24 Jakub Jelinek <[email protected]>
PR c++/86288
* parser.c (cp_parser_std_attribute): Canonicalize attr_ns, and when
:: is not present and attr_ns non-NULL, canonicalize also attr_id.
(cp_parser_attribute_spec): Fix comment typo.
* g++.dg/cpp0x/gen-attrs-66.C: New test.
--- gcc/cp/parser.c (revision 265469)
+++ gcc/cp/parser.c (revision 265470)
@@ -25327,14 +25327,19 @@ cp_parser_std_attribute (cp_parser *pars
return error_mark_node;
}
+ attr_ns = canonicalize_attr_name (attr_ns);
attr_id = canonicalize_attr_name (attr_id);
attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
NULL_TREE);
token = cp_lexer_peek_token (parser->lexer);
}
else if (attr_ns)
- attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
- NULL_TREE);
+ {
+ attr_ns = canonicalize_attr_name (attr_ns);
+ attr_id = canonicalize_attr_name (attr_id);
+ attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
+ NULL_TREE);
+ }
else
{
attr_id = canonicalize_attr_name (attr_id);
@@ -25526,7 +25531,7 @@ cp_parser_std_attribute_spec (cp_parser
|| !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
cp_parser_skip_to_end_of_statement (parser);
else
- /* Warn about parsing c++11 attribute in non-c++1 mode, only
+ /* Warn about parsing c++11 attribute in non-c++11 mode, only
when we are sure that we have actually parsed them. */
maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
}
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-66.C (nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-66.C (revision 265470)
@@ -0,0 +1,12 @@
+// PR c++/86288
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wattributes" }
+
+int a [[gnu::aligned(alignof(int))]];
+int b [[gnu::__aligned__(alignof(int))]];
+int c [[__gnu__::aligned(alignof(int))]];
+int d [[__gnu__::__aligned__(alignof(int))]];
+int e [[using gnu : aligned(alignof(int))]]; // { dg-warning
"attribute using prefix only available" "" { target c++14_down } }
+int f [[using gnu : __aligned__(alignof(int))]]; // { dg-warning
"attribute using prefix only available" "" { target c++14_down } }
+int g [[using __gnu__ : aligned(alignof(int))]]; // { dg-warning
"attribute using prefix only available" "" { target c++14_down } }
+int h [[using __gnu__ : __aligned__(alignof(int))]]; // { dg-warning
"attribute using prefix only available" "" { target c++14_down } }
2018-11-05 Jakub Jelinek <[email protected]>
Backported from mainline
2018-10-25 Jakub Jelinek <[email protected]>
PR fortran/87725
* openmp.c (gfc_match_omp_clauses): Parse simd, monotonic and
nonmonotonic modifiers regardless of if they have been parsed
already or if the opposite one has. Fix up check whether
comma after modifier should be parsed.
(resolve_omp_clauses): Diagnose schedule modifier restrictions.
* c-c++-common/gomp/schedule-modifiers-1.c (bar): Separate modifier
from kind with a colon rather than comma.
* gfortran.dg/gomp/schedule-modifiers-1.f90: New test.
* gfortran.dg/gomp/schedule-modifiers-2.f90: New test.
--- gcc/fortran/openmp.c (revision 265478)
+++ gcc/fortran/openmp.c (revision 265479)
@@ -1710,22 +1710,17 @@ gfc_match_omp_clauses (gfc_omp_clauses *
locus old_loc2 = gfc_current_locus;
do
{
- if (!c->sched_simd
- && gfc_match ("simd") == MATCH_YES)
+ if (gfc_match ("simd") == MATCH_YES)
{
c->sched_simd = true;
nmodifiers++;
}
- else if (!c->sched_monotonic
- && !c->sched_nonmonotonic
- && gfc_match ("monotonic") == MATCH_YES)
+ else if (gfc_match ("monotonic") == MATCH_YES)
{
c->sched_monotonic = true;
nmodifiers++;
}
- else if (!c->sched_monotonic
- && !c->sched_nonmonotonic
- && gfc_match ("nonmonotonic") == MATCH_YES)
+ else if (gfc_match ("nonmonotonic") == MATCH_YES)
{
c->sched_nonmonotonic = true;
nmodifiers++;
@@ -1736,7 +1731,7 @@ gfc_match_omp_clauses (gfc_omp_clauses *
gfc_current_locus = old_loc2;
break;
}
- if (nmodifiers == 0
+ if (nmodifiers == 1
&& gfc_match (" , ") == MATCH_YES)
continue;
else if (gfc_match (" : ") == MATCH_YES)
@@ -4075,6 +4070,30 @@ resolve_omp_clauses (gfc_code *code, gfc
gfc_warning (0, "INTEGER expression of SCHEDULE clause's chunk_size "
"at %L must be positive", &expr->where);
}
+ if (omp_clauses->sched_kind != OMP_SCHED_NONE
+ && omp_clauses->sched_nonmonotonic)
+ {
+ if (omp_clauses->sched_kind != OMP_SCHED_DYNAMIC
+ && omp_clauses->sched_kind != OMP_SCHED_GUIDED)
+ {
+ const char *p;
+ switch (omp_clauses->sched_kind)
+ {
+ case OMP_SCHED_STATIC: p = "STATIC"; break;
+ case OMP_SCHED_RUNTIME: p = "RUNTIME"; break;
+ case OMP_SCHED_AUTO: p = "AUTO"; break;
+ default: gcc_unreachable ();
+ }
+ gfc_error ("NONMONOTONIC modifier specified for %s schedule kind "
+ "at %L", p, &code->loc);
+ }
+ else if (omp_clauses->sched_monotonic)
+ gfc_error ("Both MONOTONIC and NONMONOTONIC schedule modifiers "
+ "specified at %L", &code->loc);
+ else if (omp_clauses->ordered)
+ gfc_error ("NONMONOTONIC schedule modifier specified with ORDERED "
+ "clause at %L", &code->loc);
+ }
/* Check that no symbol appears on multiple clauses, except that
a symbol can appear on both firstprivate and lastprivate. */
--- gcc/testsuite/c-c++-common/gomp/schedule-modifiers-1.c (revision
265478)
+++ gcc/testsuite/c-c++-common/gomp/schedule-modifiers-1.c (revision
265479)
@@ -80,21 +80,21 @@ bar (void)
#pragma omp for schedule (nonmonotonic : auto) /* { dg-error
".nonmonotonic. modifier specified for .auto. schedule kind" } */
for (i = 0; i < 64; i++)
;
- #pragma omp for schedule (nonmonotonic, dynamic) ordered /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ #pragma omp for schedule (nonmonotonic : dynamic) ordered /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
for (i = 0; i < 64; i++)
#pragma omp ordered
;
- #pragma omp for ordered schedule(nonmonotonic, dynamic, 5) /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ #pragma omp for ordered schedule(nonmonotonic : dynamic, 5) /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
for (i = 0; i < 64; i++)
#pragma omp ordered
;
- #pragma omp for schedule (nonmonotonic, guided) ordered(1) /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ #pragma omp for schedule (nonmonotonic : guided) ordered(1) /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
for (i = 0; i < 64; i++)
{
#pragma omp ordered depend(sink: i - 1)
#pragma omp ordered depend(source)
}
- #pragma omp for ordered(1) schedule(nonmonotonic, guided, 2) /* { dg-error
".nonmonotonic. schedule modifier specified together with .ordered. clause" } */
+ #pragma omp for ordered(1) schedule(nonmonotonic : guided, 2) /* {
dg-error ".nonmonotonic. schedule modifier specified together with .ordered.
clause" } */
for (i = 0; i < 64; i++)
{
#pragma omp ordered depend(source)
--- gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-1.f90 (nonexistent)
+++ gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-1.f90 (revision
265479)
@@ -0,0 +1,63 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+subroutine foo
+ integer :: i
+ !$omp do simd schedule (simd, simd: static, 5)
+ do i = 0, 64
+ end do
+ !$omp do simd schedule (monotonic, simd: static)
+ do i = 0, 64
+ end do
+ !$omp do simd schedule (simd , monotonic : static, 6)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic, monotonic : static, 7)
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic, nonmonotonic : dynamic)
+ do i = 0, 64
+ end do
+ !$omp do simd schedule (nonmonotonic , simd : dynamic, 3)
+ do i = 0, 64
+ end do
+ !$omp do simd schedule (nonmonotonic,simd:guided,4)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic: static, 2)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : static)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : dynamic)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : dynamic, 3)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : guided)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : guided, 7)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : runtime)
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic : auto)
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : dynamic)
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : dynamic, 3)
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : guided)
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : guided, 7)
+ do i = 0, 64
+ end do
+end subroutine foo
--- gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90 (nonexistent)
+++ gcc/testsuite/gfortran.dg/gomp/schedule-modifiers-2.f90 (revision
265479)
@@ -0,0 +1,44 @@
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+
+subroutine foo
+ integer :: i
+ !$omp do schedule (nonmonotonic: static, 2) ! { dg-error "NONMONOTONIC
modifier specified for STATIC schedule kind" }
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : static) ! { dg-error "NONMONOTONIC
modifier specified for STATIC schedule kind" }
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : runtime) ! { dg-error "NONMONOTONIC
modifier specified for RUNTIME schedule kind" }
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : auto) ! { dg-error "NONMONOTONIC
modifier specified for AUTO schedule kind" }
+ do i = 0, 64
+ end do
+ !$omp do schedule (nonmonotonic : dynamic) ordered ! { dg-error
"NONMONOTONIC schedule modifier specified with ORDERED clause" }
+ do i = 0, 64
+ !$omp ordered
+ !$omp end ordered
+ end do
+ !$omp do ordered schedule(nonmonotonic : dynamic, 5) ! { dg-error
"NONMONOTONIC schedule modifier specified with ORDERED clause" }
+ do i = 0, 64
+ !$omp ordered
+ !$omp end ordered
+ end do
+ !$omp do schedule (nonmonotonic : guided) ordered(1) ! { dg-error
"NONMONOTONIC schedule modifier specified with ORDERED clause" }
+ do i = 0, 64
+ !$omp ordered depend(sink: i - 1)
+ !$omp ordered depend(source)
+ end do
+ !$omp do ordered(1) schedule(nonmonotonic : guided, 2) ! { dg-error
"NONMONOTONIC schedule modifier specified with ORDERED clause" }
+ do i = 0, 64
+ !$omp ordered depend(source)
+ !$ordered depend(sink: i - 1)
+ end do
+ !$omp do schedule (nonmonotonic , monotonic : dynamic) ! { dg-error
"Both MONOTONIC and NONMONOTONIC schedule modifiers specified" }
+ do i = 0, 64
+ end do
+ !$omp do schedule (monotonic,nonmonotonic:dynamic) ! { dg-error "Both
MONOTONIC and NONMONOTONIC schedule modifiers specified" }
+ do i = 0, 64
+ end do
+end subroutine foo
2018-11-05 Jakub Jelinek <[email protected]>
PR sanitizer/87837
* match.pd (X + Y < X): Don't optimize if TYPE_OVERFLOW_SANITIZED.
* c-c++-common/ubsan/pr87837.c: New test.
--- gcc/match.pd (revision 265792)
+++ gcc/match.pd (revision 265793)
@@ -1572,6 +1572,7 @@ (define_operator_list COND_TERNARY
(op:c (plus:c@2 @0 @1) @1)
(if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
&& (CONSTANT_CLASS_P (@0) || single_use (@2)))
(op @0 { build_zero_cst (TREE_TYPE (@0)); }))))
/* For equality, this is also true with wrapping overflow. */
--- gcc/testsuite/c-c++-common/ubsan/pr87837.c (nonexistent)
+++ gcc/testsuite/c-c++-common/ubsan/pr87837.c (revision 265793)
@@ -0,0 +1,18 @@
+/* PR sanitizer/87837 */
+/* { dg-do run } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-unused-variable" } */
+
+int
+foo (int n)
+{
+ return n + __INT_MAX__ < n;
+}
+
+int
+main ()
+{
+ volatile int a = foo (1);
+ return 0;
+}
+
+/* { dg-output "signed integer overflow: 1 \\+ 2147483647 cannot be
represented in type 'int'" } */
2018-11-05 Jakub Jelinek <[email protected]>
PR tree-optimization/87859
* gimple-ssa-store-merging.c (struct merged_store_group): Add
first_nonmergeable_order member.
(merged_store_group::merged_store_group): Initialize them.
(imm_store_chain_info::coalesce_immediate_stores): Don't merge
stores with order >= first_nonmergeable_order.
Set merged_store->first_nonmergeable_order if we've skipped any
stores. Attempt to merge overlapping INTEGER_CST stores that
we would otherwise skip.
* gcc.dg/store_merging_24.c: New test.
* gcc.dg/store_merging_25.c: New test.
--- gcc/gimple-ssa-store-merging.c (revision 265793)
+++ gcc/gimple-ssa-store-merging.c (revision 265794)
@@ -1416,6 +1416,7 @@ struct merged_store_group
unsigned int load_align[2];
unsigned int first_order;
unsigned int last_order;
+ unsigned int first_nonmergeable_order;
auto_vec<store_immediate_info *> stores;
/* We record the first and last original statements in the sequence because
@@ -1806,6 +1807,7 @@ merged_store_group::merged_store_group (
width has been finalized. */
val = NULL;
mask = NULL;
+ first_nonmergeable_order = ~0U;
unsigned HOST_WIDE_INT align_bitpos = 0;
get_object_alignment_1 (gimple_assign_lhs (info->stmt),
&align, &align_bitpos);
@@ -2640,11 +2642,14 @@ imm_store_chain_info::coalesce_immediate
}
}
+ if (info->order >= merged_store->first_nonmergeable_order)
+ ;
+
/* |---store 1---|
|---store 2---|
Overlapping stores. */
- if (IN_RANGE (info->bitpos, merged_store->start,
- merged_store->start + merged_store->width - 1))
+ else if (IN_RANGE (info->bitpos, merged_store->start,
+ merged_store->start + merged_store->width - 1))
{
/* Only allow overlapping stores of constants. */
if (info->rhs_code == INTEGER_CST
@@ -2676,36 +2681,97 @@ imm_store_chain_info::coalesce_immediate
store_by_bitpos order it comes after the last store that
we can't merge with them. We can merge the first 3 stores
and keep the last store as is though. */
- unsigned int len = m_store_info.length (), k = i;
- for (unsigned int j = i + 1; j < len; ++j)
+ unsigned int len = m_store_info.length ();
+ unsigned int try_order = last_order;
+ unsigned int first_nonmergeable_order;
+ unsigned int k;
+ bool last_iter = false;
+ int attempts = 0;
+ do
{
- store_immediate_info *info2 = m_store_info[j];
- if (info2->bitpos >= end)
- break;
- if (info2->order < last_order)
+ unsigned int max_order = 0;
+ unsigned first_nonmergeable_int_order = ~0U;
+ unsigned HOST_WIDE_INT this_end = end;
+ k = i;
+ first_nonmergeable_order = ~0U;
+ for (unsigned int j = i + 1; j < len; ++j)
{
- if (info2->rhs_code != INTEGER_CST)
+ store_immediate_info *info2 = m_store_info[j];
+ if (info2->bitpos >= this_end)
+ break;
+ if (info2->order < try_order)
{
- /* Normally check_no_overlap makes sure this
- doesn't happen, but if end grows below, then
- we need to process more stores than
- check_no_overlap verified. Example:
- MEM[(int *)p_5] = 0;
- MEM[(short *)p_5 + 3B] = 1;
- MEM[(char *)p_5 + 4B] = _9;
- MEM[(char *)p_5 + 2B] = 2; */
- k = 0;
- break;
+ if (info2->rhs_code != INTEGER_CST)
+ {
+ /* Normally check_no_overlap makes sure this
+ doesn't happen, but if end grows below,
+ then we need to process more stores than
+ check_no_overlap verified. Example:
+ MEM[(int *)p_5] = 0;
+ MEM[(short *)p_5 + 3B] = 1;
+ MEM[(char *)p_5 + 4B] = _9;
+ MEM[(char *)p_5 + 2B] = 2; */
+ k = 0;
+ break;
+ }
+ k = j;
+ this_end = MAX (this_end,
+ info2->bitpos + info2->bitsize);
}
- k = j;
- end = MAX (end, info2->bitpos + info2->bitsize);
+ else if (info2->rhs_code == INTEGER_CST
+ && !last_iter)
+ {
+ max_order = MAX (max_order, info2->order + 1);
+ first_nonmergeable_int_order
+ = MIN (first_nonmergeable_int_order,
+ info2->order);
+ }
+ else
+ first_nonmergeable_order
+ = MIN (first_nonmergeable_order, info2->order);
}
+ if (k == 0)
+ {
+ if (last_order == try_order)
+ break;
+ /* If this failed, but only because we grew
+ try_order, retry with the last working one,
+ so that we merge at least something. */
+ try_order = last_order;
+ last_iter = true;
+ continue;
+ }
+ last_order = try_order;
+ /* Retry with a larger try_order to see if we could
+ merge some further INTEGER_CST stores. */
+ if (max_order
+ && (first_nonmergeable_int_order
+ < first_nonmergeable_order))
+ {
+ try_order = MIN (max_order,
+ first_nonmergeable_order);
+ try_order
+ = MIN (try_order,
+ merged_store->first_nonmergeable_order);
+ if (try_order > last_order && ++attempts < 16)
+ continue;
+ }
+ first_nonmergeable_order
+ = MIN (first_nonmergeable_order,
+ first_nonmergeable_int_order);
+ end = this_end;
+ break;
}
+ while (1);
if (k != 0)
{
merged_store->merge_overlapping (info);
+ merged_store->first_nonmergeable_order
+ = MIN (merged_store->first_nonmergeable_order,
+ first_nonmergeable_order);
+
for (unsigned int j = i + 1; j <= k; j++)
{
store_immediate_info *info2 = m_store_info[j];
@@ -2713,7 +2779,8 @@ imm_store_chain_info::coalesce_immediate
if (info2->order < last_order)
{
gcc_assert (info2->rhs_code == INTEGER_CST);
- merged_store->merge_overlapping (info2);
+ if (info != info2)
+ merged_store->merge_overlapping (info2);
}
/* Other stores are kept and not merged in any
way. */
--- gcc/testsuite/gcc.dg/store_merging_24.c (nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_24.c (revision 265794)
@@ -0,0 +1,75 @@
+/* PR tree-optimization/87859 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
+/* { dg-final { scan-tree-dump "New sequence of \[23] stmts to replace old one
of 19 stmts" "store-merging" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-tree-dump "New sequence of 1 stmts to replace old one of
6 stmts" "store-merging" { target i?86-*-* x86_64-*-* } } } */
+
+struct S {
+ union F {
+ struct T {
+#define A(n) unsigned n:1;
+#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) \
+ A(n##5) A(n##6) A(n##7) A(n##8) A(n##9)
+ B(f) B(f1) B(f2) B(f3) B(f4) B(f5)
+ A(f60) A(f61) A(f62) A(f63) A(f64) A(f65) A(f66)
+ } q;
+ unsigned int i[3];
+ } f;
+};
+
+struct S s = {
+ .f.q.f0 = 1, .f.q.f1 = 1, .f.q.f2 = 1, .f.q.f5 = 1, .f.q.f6 = 1,
+ .f.q.f7 = 1, .f.q.f8 = 1, .f.q.f9 = 1, .f.q.f13 = 1, .f.q.f14 = 1,
+ .f.q.f15 = 1, .f.q.f16 = 1, .f.q.f17 = 1, .f.q.f19 = 1, .f.q.f21 = 1,
+ .f.q.f66 = 1
+};
+
+__attribute__((noipa)) void
+bar (unsigned *x)
+{
+ if (x[0] != s.f.i[0] || x[1] != s.f.i[1] || x[2] != s.f.i[2])
+ __builtin_abort ();
+}
+
+__attribute__((noipa)) void
+foo (unsigned char *state)
+{
+ struct S i;
+ i.f.i[0] = 0;
+ i.f.i[1] = 0;
+ i.f.i[2] = 0;
+ i.f.q.f7 = 1;
+ i.f.q.f2 = 1;
+ i.f.q.f21 = 1;
+ i.f.q.f19 = 1;
+ i.f.q.f14 = 1;
+ i.f.q.f5 = 1;
+ i.f.q.f0 = 1;
+ i.f.q.f15 = 1;
+ i.f.q.f16 = 1;
+ i.f.q.f6 = 1;
+ i.f.q.f9 = 1;
+ i.f.q.f17 = 1;
+ i.f.q.f1 = 1;
+ i.f.q.f8 = 1;
+ i.f.q.f13 = 1;
+ i.f.q.f66 = 1;
+ if (*state)
+ {
+ i.f.q.f37 = 1;
+ i.f.q.f38 = 1;
+ i.f.q.f39 = 1;
+ i.f.q.f40 = 1;
+ i.f.q.f41 = 1;
+ i.f.q.f36 = 1;
+ }
+ bar (i.f.i);
+}
+
+int
+main ()
+{
+ unsigned char z = 0;
+ foo (&z);
+ return 0;
+}
--- gcc/testsuite/gcc.dg/store_merging_25.c (nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_25.c (revision 265794)
@@ -0,0 +1,75 @@
+/* PR tree-optimization/87859 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
+/* { dg-final { scan-tree-dump "New sequence of \[23] stmts to replace old one
of 14 stmts" "store-merging" { target i?86-*-* x86_64-*-* } } } */
+/* { dg-final { scan-tree-dump "New sequence of 1 stmts to replace old one of
6 stmts" "store-merging" { target i?86-*-* x86_64-*-* } } } */
+
+struct S {
+ union F {
+ struct T {
+#define A(n) unsigned n:1;
+#define B(n) A(n##0) A(n##1) A(n##2) A(n##3) A(n##4) \
+ A(n##5) A(n##6) A(n##7) A(n##8) A(n##9)
+ B(f) B(f1) B(f2) B(f3) B(f4) B(f5)
+ A(f60) A(f61) A(f62) A(f63) A(f64) A(f65) A(f66)
+ } q;
+ unsigned int i[3];
+ } f;
+};
+
+struct S s = {
+ .f.q.f0 = 1, .f.q.f1 = 1, .f.q.f2 = 1, .f.q.f5 = 1, .f.q.f6 = 1,
+ .f.q.f7 = 1, .f.q.f8 = 1, .f.q.f9 = 1, .f.q.f13 = 1, .f.q.f14 = 1,
+ .f.q.f15 = 1, .f.q.f16 = 1, .f.q.f17 = 1, .f.q.f19 = 1, .f.q.f21 = 1,
+ .f.q.f66 = 1
+};
+
+__attribute__((noipa)) void
+bar (unsigned *x)
+{
+ if (x[0] != s.f.i[0] || x[1] != s.f.i[1] || x[2] != s.f.i[2])
+ __builtin_abort ();
+}
+
+__attribute__((noipa)) void
+foo (unsigned char *state, unsigned char c)
+{
+ struct S i;
+ i.f.i[0] = 0;
+ i.f.i[1] = 0;
+ i.f.i[2] = 0;
+ i.f.q.f7 = 1;
+ i.f.q.f2 = 1;
+ i.f.q.f21 = 1;
+ i.f.q.f19 = 1;
+ i.f.q.f14 = 1;
+ i.f.q.f5 = 1;
+ i.f.q.f0 = 1;
+ i.f.q.f15 = 1;
+ i.f.q.f16 = 1;
+ i.f.q.f6 = 1;
+ i.f.q.f9 = 1;
+ i.f.q.f17 = c;
+ i.f.q.f1 = 1;
+ i.f.q.f8 = 1;
+ i.f.q.f13 = 1;
+ i.f.q.f66 = 1;
+ if (*state)
+ {
+ i.f.q.f37 = 1;
+ i.f.q.f38 = 1;
+ i.f.q.f39 = 1;
+ i.f.q.f40 = 1;
+ i.f.q.f41 = 1;
+ i.f.q.f36 = 1;
+ }
+ bar (i.f.i);
+}
+
+int
+main ()
+{
+ unsigned char z = 0;
+ foo (&z, 1);
+ return 0;
+}