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 <ja...@redhat.com> Backported from mainline 2018-10-19 Jakub Jelinek <ja...@redhat.com> 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 <ja...@redhat.com> Backported from mainline 2018-10-20 Jakub Jelinek <ja...@redhat.com> 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 <ja...@redhat.com> Backported from mainline 2018-10-24 Jakub Jelinek <ja...@redhat.com> 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 <ja...@redhat.com> Backported from mainline 2018-10-25 Jakub Jelinek <ja...@redhat.com> 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 <ja...@redhat.com> 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 <ja...@redhat.com> 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; +}