Hi!

I've bootstrapped/regtested and committed following 4 backports from trunk
to gcc-8-branch.

        Jakub
2018-10-11  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2018-09-12  Jakub Jelinek  <ja...@redhat.com>
                    Andreas Krebbel  <kreb...@linux.ibm.com>

        PR tree-optimization/86844
        * gimple-ssa-store-merging.c
        (imm_store_chain_info::coalesce_immediate): For overlapping stores, if
        there are any overlapping stores in between them, make sure they are
        also coalesced or we give up completely.

        * gcc.c-torture/execute/pr86844.c: New test.
        * gcc.dg/store_merging_22.c: New test.
        * gcc.dg/store_merging_23.c: New test.

--- gcc/gimple-ssa-store-merging.c      (revision 264231)
+++ gcc/gimple-ssa-store-merging.c      (revision 264232)
@@ -2648,15 +2648,80 @@ imm_store_chain_info::coalesce_immediate
        {
          /* Only allow overlapping stores of constants.  */
          if (info->rhs_code == INTEGER_CST
-             && merged_store->stores[0]->rhs_code == INTEGER_CST
-             && check_no_overlap (m_store_info, i, INTEGER_CST,
-                                  MAX (merged_store->last_order, info->order),
-                                  MAX (merged_store->start
-                                       + merged_store->width,
-                                       info->bitpos + info->bitsize)))
+             && merged_store->stores[0]->rhs_code == INTEGER_CST)
            {
-             merged_store->merge_overlapping (info);
-             continue;
+             unsigned int last_order
+               = MAX (merged_store->last_order, info->order);
+             unsigned HOST_WIDE_INT end
+               = MAX (merged_store->start + merged_store->width,
+                      info->bitpos + info->bitsize);
+             if (check_no_overlap (m_store_info, i, INTEGER_CST,
+                                   last_order, end))
+               {
+                 /* check_no_overlap call above made sure there are no
+                    overlapping stores with non-INTEGER_CST rhs_code
+                    in between the first and last of the stores we've
+                    just merged.  If there are any INTEGER_CST rhs_code
+                    stores in between, we need to merge_overlapping them
+                    even if in the sort_by_bitpos order there are other
+                    overlapping stores in between.  Keep those stores as is.
+                    Example:
+                       MEM[(int *)p_28] = 0;
+                       MEM[(char *)p_28 + 3B] = 1;
+                       MEM[(char *)p_28 + 1B] = 2;
+                       MEM[(char *)p_28 + 2B] = MEM[(char *)p_28 + 6B];
+                    We can't merge the zero store with the store of two and
+                    not merge anything else, because the store of one is
+                    in the original order in between those two, but in
+                    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)
+                   {
+                     store_immediate_info *info2 = m_store_info[j];
+                     if (info2->bitpos >= end)
+                       break;
+                     if (info2->order < last_order)
+                       {
+                         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;
+                         end = MAX (end, info2->bitpos + info2->bitsize);
+                       }
+                   }
+
+                 if (k != 0)
+                   {
+                     merged_store->merge_overlapping (info);
+
+                     for (unsigned int j = i + 1; j <= k; j++)
+                       {
+                         store_immediate_info *info2 = m_store_info[j];
+                         gcc_assert (info2->bitpos < end);
+                         if (info2->order < last_order)
+                           {
+                             gcc_assert (info2->rhs_code == INTEGER_CST);
+                             merged_store->merge_overlapping (info2);
+                           }
+                         /* Other stores are kept and not merged in any
+                            way.  */
+                       }
+                     ignore = k;
+                     continue;
+                   }
+               }
            }
        }
       /* |---store 1---||---store 2---|
--- gcc/testsuite/gcc.c-torture/execute/pr86844.c       (nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr86844.c       (revision 264232)
@@ -0,0 +1,24 @@
+/* PR tree-optimization/86844 */
+
+__attribute__((noipa)) void
+foo (int *p)
+{
+  *p = 0;
+  *((char *)p + 3) = 1;
+  *((char *)p + 1) = 2;
+  *((char *)p + 2) = *((char *)p + 6);
+}
+
+int
+main ()
+{
+  int a[2] = { -1, 0 };
+  if (sizeof (int) != 4)
+    return 0;
+  ((char *)a)[6] = 3;
+  foo (a);
+  if (((char *)a)[0] != 0 || ((char *)a)[1] != 2
+      || ((char *)a)[2] != 3 || ((char *)a)[3] != 1)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.dg/store_merging_22.c     (nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_22.c     (revision 264232)
@@ -0,0 +1,16 @@
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+  *((char *)p + 3) = 1;
+  *((char *)p + 1) = 2;
+  *((char *)p + 2) = *((char *)p + 38);
+}
+
+/* { dg-final { scan-tree-dump-times "Merging successful" 1 "store-merging" } 
} */
+/* { dg-final { scan-tree-dump-times "New sequence of 1 stmts to replace old 
one of 3 stmts" 1 "store-merging" } } */
--- gcc/testsuite/gcc.dg/store_merging_23.c     (nonexistent)
+++ gcc/testsuite/gcc.dg/store_merging_23.c     (revision 264232)
@@ -0,0 +1,16 @@
+/* PR tree-optimization/86844 */
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+void
+foo (int *p)
+{
+  *p = 0;
+  int one = 1;
+  __builtin_memcpy ((char *) p + 3, &one, sizeof (int));
+  *((char *)p + 4) = *((char *)p + 36);
+  *((char *)p + 1) = 2;
+}
+
+/* { dg-final { scan-tree-dump-not "Merging successful" "store-merging" } } */
2018-10-11  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2018-09-26  Jakub Jelinek  <ja...@redhat.com>

        PR target/87414
        * config/i386/i386.c: Include debug.h and dwarf2out.h.
        (output_indirect_thunk): Emit DW_CFA_def_cfa_offset after the
        call.

--- gcc/config/i386/i386.c      (revision 264650)
+++ gcc/config/i386/i386.c      (revision 264651)
@@ -91,6 +91,8 @@ along with GCC; see the file COPYING3.
 #include "ipa-prop.h"
 #include "ipa-fnsummary.h"
 #include "wide-int-bitmask.h"
+#include "debug.h"
+#include "dwarf2out.h"
 
 /* This file should be included last.  */
 #include "target-def.h"
@@ -11014,6 +11016,23 @@ output_indirect_thunk (enum indirect_thu
 
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
 
+  /* The above call insn pushed a word to stack.  Adjust CFI info.  */
+  if (flag_asynchronous_unwind_tables && dwarf2out_do_frame ())
+    {
+      if (! dwarf2out_do_cfi_asm ())
+       {
+         dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> ();
+         xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
+         xcfi->dw_cfi_oprnd1.dw_cfi_addr = ggc_strdup (indirectlabel2);
+         vec_safe_push (cfun->fde->dw_fde_cfi, xcfi);
+       }
+      dw_cfi_ref xcfi = ggc_cleared_alloc<dw_cfi_node> ();
+      xcfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+      xcfi->dw_cfi_oprnd1.dw_cfi_offset = 2 * UNITS_PER_WORD;
+      vec_safe_push (cfun->fde->dw_fde_cfi, xcfi);
+      dwarf2out_emit_cfi (xcfi);
+    }
+
   if (regno != INVALID_REGNUM)
     {
       /* MOV.  */
2018-10-11  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2018-10-10  Jakub Jelinek  <ja...@redhat.com>

        PR target/87550
        * config/i386/i386-builtin.def (IX86_BUILTIN_RDPMC): Move from args set
        to special_args set.

        * gcc.target/i386/pr87550.c: New test.

--- gcc/config/i386/i386-builtin.def    (revision 265006)
+++ gcc/config/i386/i386-builtin.def    (revision 265007)
@@ -90,6 +90,7 @@ BDESC_END (PCMPISTR, SPECIAL_ARGS)
 BDESC_FIRST (special_args, SPECIAL_ARGS,
        0, CODE_FOR_nothing, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, 
UNKNOWN, (int) UINT64_FTYPE_VOID)
 BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, 
UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED)
+BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, 
UNKNOWN, (int) UINT64_FTYPE_INT)
 BDESC (0, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, 
(int) VOID_FTYPE_VOID)
 
 /* 80387 (for use internally for atomic compound assignment).  */
@@ -427,7 +428,6 @@ BDESC_END (SPECIAL_ARGS, ARGS)
 BDESC_FIRST (args, ARGS,
        0, CODE_FOR_bsr, "__builtin_ia32_bsrsi", IX86_BUILTIN_BSRSI, UNKNOWN, 
(int) INT_FTYPE_INT)
 BDESC (OPTION_MASK_ISA_64BIT, CODE_FOR_bsr_rex64, "__builtin_ia32_bsrdi", 
IX86_BUILTIN_BSRDI, UNKNOWN, (int) INT64_FTYPE_INT64)
-BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, 
UNKNOWN, (int) UINT64_FTYPE_INT)
 BDESC (0, CODE_FOR_rotlqi3, "__builtin_ia32_rolqi", IX86_BUILTIN_ROLQI, 
UNKNOWN, (int) UINT8_FTYPE_UINT8_INT)
 BDESC (0, CODE_FOR_rotlhi3, "__builtin_ia32_rolhi", IX86_BUILTIN_ROLHI, 
UNKNOWN, (int) UINT16_FTYPE_UINT16_INT)
 BDESC (0, CODE_FOR_rotrqi3, "__builtin_ia32_rorqi", IX86_BUILTIN_RORQI, 
UNKNOWN, (int) UINT8_FTYPE_UINT8_INT)
--- gcc/testsuite/gcc.target/i386/pr87550.c     (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr87550.c     (revision 265007)
@@ -0,0 +1,21 @@
+/* PR target/87550 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <x86intrin.h>
+
+int
+foo (int x)
+{
+  return __rdtsc () + __rdtsc ();
+}
+
+/* { dg-final { scan-assembler-times "\trdtsc\[\n\r]" 2 } } */
+
+int
+bar (int x)
+{
+  return __rdpmc (0) + __rdpmc (0);
+}
+
+/* { dg-final { scan-assembler-times "\trdpmc\[\n\r]" 2 } } */
2018-10-11  Jakub Jelinek  <ja...@redhat.com>

        PR c++/87582
        * typeck.c (maybe_warn_about_returning_address_of_local): If
        whats_returned is a structured binding identifier and the structured
        binding is a reference, recurse on its initializer.

        * g++.dg/cpp1z/decomp48.C: New test.

--- gcc/cp/typeck.c     (revision 265040)
+++ gcc/cp/typeck.c     (revision 265041)
@@ -9067,6 +9067,22 @@ maybe_warn_about_returning_address_of_lo
       && !(TREE_STATIC (whats_returned)
           || TREE_PUBLIC (whats_returned)))
     {
+      if (VAR_P (whats_returned)
+         && DECL_DECOMPOSITION_P (whats_returned)
+         && DECL_DECOMP_BASE (whats_returned)
+         && DECL_HAS_VALUE_EXPR_P (whats_returned))
+       {
+         /* When returning address of a structured binding, if the structured
+            binding is not a reference, continue normally, if it is a
+            reference, recurse on the initializer of the structured
+            binding.  */
+         tree base = DECL_DECOMP_BASE (whats_returned);
+         if (TREE_CODE (TREE_TYPE (base)) == REFERENCE_TYPE)
+           {
+             tree init = DECL_INITIAL (base);
+             return maybe_warn_about_returning_address_of_local (init);
+           }
+       }
       if (TREE_CODE (valtype) == REFERENCE_TYPE)
        warning_at (DECL_SOURCE_LOCATION (whats_returned),
                    OPT_Wreturn_local_addr,
--- gcc/testsuite/g++.dg/cpp1z/decomp48.C       (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp48.C       (revision 265041)
@@ -0,0 +1,134 @@
+// PR c++/87582
+// { dg-do run { target c++11 } }
+// { dg-options "-Wreturn-local-addr" }
+
+struct S { int s, t; };
+S v {1, 2};
+int a[3] = {1, 2, 3};
+
+int &
+f1 ()
+{
+  auto& [s, t] = v;    // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-bogus "reference to local variable '.' 
returned" }
+}
+
+int &
+f2 ()
+{
+  S v {1, 2};          // { dg-warning "reference to local variable 'v' 
returned" }
+  auto& [s, t] = v;    // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;
+}
+
+int &
+f3 ()
+{
+  auto& [s, t, u] = a; // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-bogus "reference to local variable '.' 
returned" }
+}
+
+int &
+f4 ()
+{
+  int a[3] = {1, 2, 3};        // { dg-warning "reference to local variable 
'a' returned" }
+  auto& [s, t, u] = a; // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;
+}
+
+int &
+f5 ()
+{
+  auto [s, t] = v;     // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-warning "reference to local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f6 ()
+{
+  S v {1, 2};
+  auto [s, t] = v;     // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-warning "reference to local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f7 ()
+{
+  auto [s, t, u] = a;  // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-warning "reference to local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int &
+f8 ()
+{
+  int a[3] = {1, 2, 3};
+  auto [s, t, u] = a;  // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return s;            // { dg-warning "reference to local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f9 ()
+{
+  auto& [s, t] = v;    // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-bogus "address of local variable '.' returned" }
+}
+
+int *
+f10 ()
+{
+  S v {1, 2};          // { dg-warning "address of local variable 'v' 
returned" }
+  auto& [s, t] = v;    // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;
+}
+
+int *
+f11 ()
+{
+  auto& [s, t, u] = a; // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-bogus "address of local variable '.' returned" }
+}
+
+int *
+f12 ()
+{
+  int a[3] = {1, 2, 3};        // { dg-warning "address of local variable 'a' 
returned" }
+  auto& [s, t, u] = a; // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;
+}
+
+int *
+f13 ()
+{
+  auto [s, t] = v;     // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-warning "address of local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f14 ()
+{
+  S v {1, 2};
+  auto [s, t] = v;     // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-warning "address of local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f15 ()
+{
+  auto [s, t, u] = a;  // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-warning "address of local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int *
+f16 ()
+{
+  int a[3] = {1, 2, 3};
+  auto [s, t, u] = a;  // { dg-warning "structured bindings only available 
with" "" { target c++14_down } }
+  return &s;           // { dg-warning "address of local variable 's' 
returned" "" { target *-*-* } .-1 }
+}
+
+int
+main ()
+{
+  if (&f1 () != &v.s || &f3 () != &a[0] || f9 () != &v.s || f11 () != &a[0])
+    __builtin_abort ();
+}

Reply via email to