Hi!

I've backported today following 23 patches after bootstrapping/regtesting
them on x86_64-linux and i686-linux.

Some of the backports are just partial backports, in particular for
r255133 I've just backported the removal of case BUILT_IN_STPNCPY_CHK:,
for r255354 the patch didn't apply at all, because we don't have the
C++ __builtin_unreachables with BUILTINS_LOCATION, so rewrote it manually,
and finally r255574 is just the fix, so am not trying to extend it to
reversed loops and of course it didn't apply cleanly either.

        Jakub
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-20  Jakub Jelinek  <ja...@redhat.com>

        PR c++/82781
        * constexpr.c (cxx_eval_vector_conditional_expression): New function.
        (cxx_eval_constant_expression) <case VEC_COND_EXPR>: Use it instead
        of cxx_eval_conditional_expression.

        * g++.dg/ext/constexpr-pr82781.C: New test.

--- gcc/cp/constexpr.c  (revision 254951)
+++ gcc/cp/constexpr.c  (revision 254952)
@@ -2086,6 +2086,45 @@ cxx_eval_conditional_expression (const c
                                       jump_target);
 }
 
+/* Subroutine of cxx_eval_constant_expression.
+   Attempt to evaluate vector condition expressions.  Unlike
+   cxx_eval_conditional_expression, VEC_COND_EXPR acts like a normal
+   ternary arithmetics operation, where all 3 arguments have to be
+   evaluated as constants and then folding computes the result from
+   them.  */
+
+static tree
+cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
+                                       bool *non_constant_p, bool *overflow_p)
+{
+  tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
+                                           /*lval*/false,
+                                           non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg1);
+  tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
+                                           /*lval*/false,
+                                           non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg2);
+  tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
+                                           /*lval*/false,
+                                           non_constant_p, overflow_p);
+  VERIFY_CONSTANT (arg3);
+  location_t loc = EXPR_LOCATION (t);
+  tree type = TREE_TYPE (t);
+  tree r = fold_ternary_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
+  if (r == NULL_TREE)
+    {
+      if (arg1 == TREE_OPERAND (t, 0)
+         && arg2 == TREE_OPERAND (t, 1)
+         && arg3 == TREE_OPERAND (t, 2))
+       r = t;
+      else
+       r = build3_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3);
+    }
+  VERIFY_CONSTANT (r);
+  return r;
+}
+
 /* Returns less than, equal to, or greater than zero if KEY is found to be
    less than, to match, or to be greater than the constructor_elt's INDEX.  */
 
@@ -4398,12 +4437,14 @@ cxx_eval_constant_expression (const cons
                                              jump_target);
          break;
        }
-      /* FALLTHRU */
-    case VEC_COND_EXPR:
       r = cxx_eval_conditional_expression (ctx, t, lval,
                                           non_constant_p, overflow_p,
                                           jump_target);
       break;
+    case VEC_COND_EXPR:
+      r = cxx_eval_vector_conditional_expression (ctx, t, non_constant_p,
+                                                 overflow_p);
+      break;
 
     case CONSTRUCTOR:
       if (TREE_CONSTANT (t))
--- gcc/testsuite/g++.dg/ext/constexpr-pr82781.C        (nonexistent)
+++ gcc/testsuite/g++.dg/ext/constexpr-pr82781.C        (revision 254952)
@@ -0,0 +1,12 @@
+// PR c++/82781
+// { dg-do compile { target c++11 } }
+
+typedef int V __attribute__ ((vector_size (16)));
+constexpr V b1 = { 0, 1, 10, 20 };
+constexpr V b2 = { 0, 2, 10, 0 };
+constexpr V b3 = b1 == b2;
+
+static_assert (b3[0] == -1, "");
+static_assert (b3[1] == 0, "");
+static_assert (b3[2] == -1, "");
+static_assert (b3[3] == 0, "");
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-21  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83059
        * c-common.c (get_atomic_generic_size): Use TREE_INT_CST_LOW
        instead of tree_to_uhwi, formatting fix.

        * c-c++-common/pr83059.c: New test.

--- gcc/c-family/c-common.c     (revision 254989)
+++ gcc/c-family/c-common.c     (revision 254990)
@@ -6671,13 +6671,14 @@ get_atomic_generic_size (location_t loc,
       tree p = (*params)[x];
       if (TREE_CODE (p) == INTEGER_CST)
         {
-         int i = tree_to_uhwi (p);
-         if (i < 0 || (memmodel_base (i) >= MEMMODEL_LAST))
-           {
-             warning_at (loc, OPT_Winvalid_memory_model,
-                         "invalid memory model argument %d of %qE", x + 1,
-                         function);
-           }
+         /* memmodel_base masks the low 16 bits, thus ignore any bits above
+            it by using TREE_INT_CST_LOW instead of tree_to_*hwi.  Those high
+            bits will be checked later during expansion in target specific
+            way.  */
+         if (memmodel_base (TREE_INT_CST_LOW (p)) >= MEMMODEL_LAST)
+           warning_at (loc, OPT_Winvalid_memory_model,
+                       "invalid memory model argument %d of %qE", x + 1,
+                       function);
        }
       else
        if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
--- gcc/testsuite/c-c++-common/pr83059.c        (nonexistent)
+++ gcc/testsuite/c-c++-common/pr83059.c        (revision 254990)
@@ -0,0 +1,10 @@
+/* PR c++/83059 */
+/* { dg-do compile } */
+
+void
+foo (int *p, int *q, int *r)
+{
+  __atomic_compare_exchange (p, q, r, 0, 0, -1);       /* { dg-warning 
"invalid memory model argument 6" } */
+  /* { dg-warning "\[uU]nknown architecture specifi" "" { target *-*-* } .-1 } 
*/
+  /* { dg-warning "failure memory model cannot be stronger than success memory 
model" "" { target *-*-* } .-2 } */
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-21  James Cowgill  <james.cowg...@imgtec.com>
                    Jakub Jelinek  <ja...@redhat.com>

        PR target/82880
        * config/mips/frame-header-opt.c (mips_register_frame_header_opt):
        Remove static keyword from f variable.

        * gcc.dg/opts-8.c: New test.

--- gcc/config/mips/frame-header-opt.c  (revision 255003)
+++ gcc/config/mips/frame-header-opt.c  (revision 255004)
@@ -99,8 +99,7 @@ void
 mips_register_frame_header_opt (void)
 {
   opt_pass *p = make_pass_ipa_frame_header_opt (g);
-  static struct register_pass_info f =
-    {p, "comdats", 1, PASS_POS_INSERT_AFTER };
+  struct register_pass_info f = { p, "comdats", 1, PASS_POS_INSERT_AFTER };
   register_pass (&f);
 }
 
--- gcc/testsuite/gcc.dg/opts-8.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/opts-8.c       (revision 255004)
@@ -0,0 +1,6 @@
+/* PR target/82880 */
+/* Test we don't ICE or hang.  */
+/* { dg-do compile } */
+/* { dg-options "--help=target --help=optimizers" } */
+/* { dg-allow-blank-lines-in-output 1 } */
+/* { dg-prune-output ".*" } */
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-22  Jakub Jelinek  <ja...@redhat.com>

        PR debug/83084
        * valtrack.c (propagate_for_debug_subst, propagate_for_debug): Reset
        debug insns if they would contain UNSPEC_VOLATILE or volatile asm.
        (dead_debug_insert_temp): Likewise, but also ignore even non-volatile
        asm.

        * g++.dg/opt/pr83084.C: New test.

--- gcc/valtrack.c      (revision 255050)
+++ gcc/valtrack.c      (revision 255051)
@@ -171,10 +171,13 @@ propagate_for_debug_subst (rtx from, con
        if (REG_P (*iter) && ++cnt > 1)
          {
            rtx dval = make_debug_expr_from_rtl (old_rtx);
+           rtx to = pair->to;
+           if (volatile_insn_p (to))
+             to = gen_rtx_UNKNOWN_VAR_LOC ();
            /* Emit a debug bind insn.  */
            rtx bind
              = gen_rtx_VAR_LOCATION (GET_MODE (old_rtx),
-                                     DEBUG_EXPR_TREE_DECL (dval), pair->to,
+                                     DEBUG_EXPR_TREE_DECL (dval), to,
                                      VAR_INIT_STATUS_INITIALIZED);
            rtx_insn *bind_insn = emit_debug_insn_before (bind, pair->insn);
            df_insn_rescan (bind_insn);
@@ -217,6 +220,8 @@ propagate_for_debug (rtx_insn *insn, rtx
                                         dest, propagate_for_debug_subst, &p);
          if (loc == INSN_VAR_LOCATION_LOC (insn))
            continue;
+         if (volatile_insn_p (loc))
+           loc = gen_rtx_UNKNOWN_VAR_LOC ();
          INSN_VAR_LOCATION_LOC (insn) = loc;
          df_insn_rescan (insn);
        }
@@ -660,6 +665,12 @@ dead_debug_insert_temp (struct dead_debu
                }
              return 0;
            }
+         /* Asm in DEBUG_INSN is never useful, we can't emit debug info for
+            that.  And for volatile_insn_p, it is actually harmful
+            - DEBUG_INSNs shouldn't have any side-effects.  */
+         else if (GET_CODE (src) == ASM_OPERANDS
+                  || volatile_insn_p (src))
+           set = NULL_RTX;
        }
 
       /* ??? Should we try to extract it from a PARALLEL?  */
--- gcc/testsuite/g++.dg/opt/pr83084.C  (nonexistent)
+++ gcc/testsuite/g++.dg/opt/pr83084.C  (revision 255051)
@@ -0,0 +1,16 @@
+// PR debug/83084
+// { dg-do compile }
+// { dg-options "-O2 -fcompare-debug -Wno-return-type" }
+
+enum E { F };
+template <E = F> struct A {
+  bool foo ();
+  int b;
+};
+template <> bool A<>::foo () {
+  int a;
+  do
+    if (a)
+      return false;
+  while (__atomic_compare_exchange_n (&b, &a, 0, 1, 4, 0));
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-23  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/82253
        * expr.c (expand_assignment): For CONCAT to_rtx, complex type from and
        bitpos/bitsize covering the whole destination, use store_expr only if
        the complex mode is the same.  Otherwise, use expand_normal and if
        it returns CONCAT, subreg each part separately instead of trying to
        subreg the whole result.

        * gfortran.dg/pr82253.f90: New test.

--- gcc/expr.c  (revision 255094)
+++ gcc/expr.c  (revision 255095)
@@ -5107,7 +5107,8 @@ expand_assignment (tree to, tree from, b
       else if (GET_CODE (to_rtx) == CONCAT)
        {
          unsigned short mode_bitsize = GET_MODE_BITSIZE (GET_MODE (to_rtx));
-         if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
+         if (TYPE_MODE (TREE_TYPE (from)) == GET_MODE (to_rtx)
+             && COMPLEX_MODE_P (GET_MODE (to_rtx))
              && bitpos == 0
              && bitsize == mode_bitsize)
            result = store_expr (from, to_rtx, false, nontemporal, reversep);
@@ -5128,14 +5129,30 @@ expand_assignment (tree to, tree from, b
                                  nontemporal, reversep);
          else if (bitpos == 0 && bitsize == mode_bitsize)
            {
-             rtx from_rtx;
              result = expand_normal (from);
-             from_rtx = simplify_gen_subreg (GET_MODE (to_rtx), result,
-                                             TYPE_MODE (TREE_TYPE (from)), 0);
-             emit_move_insn (XEXP (to_rtx, 0),
-                             read_complex_part (from_rtx, false));
-             emit_move_insn (XEXP (to_rtx, 1),
-                             read_complex_part (from_rtx, true));
+             if (GET_CODE (result) == CONCAT)
+               {
+                 machine_mode to_mode = GET_MODE_INNER (GET_MODE (to_rtx));
+                 machine_mode from_mode = GET_MODE_INNER (GET_MODE (result));
+                 rtx from_real
+                   = simplify_gen_subreg (to_mode, XEXP (result, 0),
+                                          from_mode, 0);
+                 rtx from_imag
+                   = simplify_gen_subreg (to_mode, XEXP (result, 1),
+                                          from_mode, 1);
+                 emit_move_insn (XEXP (to_rtx, 0), from_real);
+                 emit_move_insn (XEXP (to_rtx, 1), from_imag);
+               }
+             else
+               {
+                 rtx from_rtx
+                   = simplify_gen_subreg (GET_MODE (to_rtx), result,
+                                          TYPE_MODE (TREE_TYPE (from)), 0);
+                 emit_move_insn (XEXP (to_rtx, 0),
+                                 read_complex_part (from_rtx, false));
+                 emit_move_insn (XEXP (to_rtx, 1),
+                                 read_complex_part (from_rtx, true));
+               }
            }
          else
            {
--- gcc/testsuite/gfortran.dg/pr82253.f90       (nonexistent)
+++ gcc/testsuite/gfortran.dg/pr82253.f90       (revision 255095)
@@ -0,0 +1,40 @@
+! PR middle-end/82253
+! { dg-do compile { target fortran_real_16 } }
+! { dg-options "-Og" }
+
+module pr82253
+  implicit none
+  private
+  public :: static_type
+  type, public :: T
+    procedure(), nopass, pointer :: testProc => null()
+  end type
+  type, public :: S
+    complex(kind=16), pointer :: ptr
+  end type
+  type(T), target :: type_complex32
+  interface static_type
+    module procedure foo
+  end interface
+  interface
+    subroutine bar (testProc)
+      procedure(), optional :: testProc
+    end subroutine
+  end interface
+  contains
+    function foo (self) result(res)
+      complex(kind=16) :: self
+      type(T), pointer :: res
+      call bar (testProc = baz)
+    end function
+    subroutine baz (buffer, status)
+      character(len=*) :: buffer
+      integer(kind=4) :: status
+      complex(kind=16), target :: obj
+      type(S) :: self
+      integer(kind=1), parameter :: zero(storage_size(obj)/8) = 0
+      obj = transfer (zero, obj)
+      self%ptr => obj
+      write (buffer, *, iostat=status) self%ptr, '#'
+    end subroutine
+end module pr82253
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-23  Dirk Broemmel  <d.broem...@fz-juelich.de>
                    Jakub Jelinek  <ja...@redhat.com>

        PR fortran/81841
        * parse.c (parse_spec): Allow ST_OMP_THREADPRIVATE inside of
        BLOCK DATA.

        * libgomp.fortran/pr81841.f90: New test.

--- gcc/fortran/parse.c (revision 255114)
+++ gcc/fortran/parse.c (revision 255115)
@@ -3699,6 +3699,7 @@ loop:
        case ST_EQUIVALENCE:
        case ST_IMPLICIT:
        case ST_IMPLICIT_NONE:
+       case ST_OMP_THREADPRIVATE:
        case ST_PARAMETER:
        case ST_STRUCTURE_DECL:
        case ST_TYPE:
--- libgomp/testsuite/libgomp.fortran/pr81841.f90       (nonexistent)
+++ libgomp/testsuite/libgomp.fortran/pr81841.f90       (revision 255115)
@@ -0,0 +1,26 @@
+! PR fortran/81841
+! { dg-do run }
+
+block data
+  integer :: a
+  real :: b(2)
+  common /c/ a, b
+  !$omp threadprivate (/c/)
+  data a / 32 /
+  data b /2*1./
+end
+
+program pr81841
+  use omp_lib
+  integer :: e
+  real :: f(2)
+  common /c/ e, f
+  !$omp threadprivate (/c/)
+  !$omp parallel num_threads(8)
+  if ((e /= 32) .or. any(f /= 1.)) call abort
+  e = omp_get_thread_num ()
+  f = e + 19.
+  !$omp barrier
+  if ((e /= omp_get_thread_num ()) .or. any(f /= e + 19.)) call abort
+  !$omp end parallel
+end
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-23  Jakub Jelinek  <ja...@redhat.com>

        * parser.c (cp_parser_omp_declare): Change return type to bool from
        void, return true for declare simd.
        (cp_parser_pragma): Return cp_parser_omp_declare returned value
        rather than always false.

--- gcc/cp/parser.c     (revision 255116)
+++ gcc/cp/parser.c     (revision 255117)
@@ -37903,7 +37903,7 @@ cp_parser_omp_declare_reduction (cp_pars
       initializer-clause[opt] new-line
    #pragma omp declare target new-line  */
 
-static void
+static bool
 cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
                       enum pragma_context context)
 {
@@ -37917,7 +37917,7 @@ cp_parser_omp_declare (cp_parser *parser
          cp_lexer_consume_token (parser->lexer);
          cp_parser_omp_declare_simd (parser, pragma_tok,
                                      context);
-         return;
+         return true;
        }
       cp_ensure_no_omp_declare_simd (parser);
       if (strcmp (p, "reduction") == 0)
@@ -37925,23 +37925,24 @@ cp_parser_omp_declare (cp_parser *parser
          cp_lexer_consume_token (parser->lexer);
          cp_parser_omp_declare_reduction (parser, pragma_tok,
                                           context);
-         return;
+         return false;
        }
       if (!flag_openmp)  /* flag_openmp_simd  */
        {
          cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-         return;
+         return false;
        }
       if (strcmp (p, "target") == 0)
        {
          cp_lexer_consume_token (parser->lexer);
          cp_parser_omp_declare_target (parser, pragma_tok);
-         return;
+         return false;
        }
     }
   cp_parser_error (parser, "expected %<simd%> or %<reduction%> "
                           "or %<target%>");
   cp_parser_require_pragma_eol (parser, pragma_tok);
+  return false;
 }
 
 /* OpenMP 4.5:
@@ -38860,8 +38861,7 @@ cp_parser_pragma (cp_parser *parser, enu
       return false;
 
     case PRAGMA_OMP_DECLARE:
-      cp_parser_omp_declare (parser, pragma_tok, context);
-      return false;
+      return cp_parser_omp_declare (parser, pragma_tok, context);
 
     case PRAGMA_OACC_DECLARE:
       cp_parser_oacc_declare (parser, pragma_tok);
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-24  Jakub Jelinek  <ja...@redhat.com>

        * tree-object-size.c (pass_through_call): Do not handle
        BUILT_IN_STPNCPY_CHK which is not a pass through call.

        * gcc.dg/builtin-object-size-18.c: New test.

--- gcc/tree-object-size.c      (revision 255132)
+++ gcc/tree-object-size.c      (revision 255133)
@@ -481,7 +481,6 @@ pass_through_call (const gcall *call)
       case BUILT_IN_MEMSET_CHK:
       case BUILT_IN_STRCPY_CHK:
       case BUILT_IN_STRNCPY_CHK:
-      case BUILT_IN_STPNCPY_CHK:
       case BUILT_IN_STRCAT_CHK:
       case BUILT_IN_STRNCAT_CHK:
       case BUILT_IN_ASSUME_ALIGNED:
--- gcc/testsuite/gcc.dg/builtin-object-size-18.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/builtin-object-size-18.c       (revision 255133)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* __stpncpy_chk could return buf up to buf + 64, so
+   the minimum object size might be far smaller than 64.  */
+/* { dg-final { scan-tree-dump-not "return 64;" "optimized" } } */
+
+typedef __SIZE_TYPE__ size_t;
+
+size_t
+foo (const char *p, size_t s, size_t t)
+{
+  char buf[64];
+  char *q = __builtin___stpncpy_chk (buf, p, s, t);
+  return __builtin_object_size (q, 2);
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-24  Jakub Jelinek  <ja...@redhat.com>
 
        PR sanitizer/83014
        * ubsan.c (ubsan_type_descriptor): Use pp_unsigned_wide_integer
        instead of pp_printf with HOST_WIDE_INT_PRINT_DEC.  Avoid calling
        tree_to_uhwi twice.

        * gcc.dg/ubsan/pr83014.c: New test.

--- gcc/ubsan.c (revision 255133)
+++ gcc/ubsan.c (revision 255134)
@@ -436,10 +436,10 @@ ubsan_type_descriptor (tree type, enum u
              && TYPE_MAX_VALUE (dom) != NULL_TREE
              && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
            {
+             unsigned HOST_WIDE_INT m;
              if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
-                 && tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1 != 0)
-               pp_printf (&pretty_name, HOST_WIDE_INT_PRINT_DEC,
-                           tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
+                 && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
+               pp_unsigned_wide_integer (&pretty_name, m + 1);
              else
                pp_wide_int (&pretty_name,
                             wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
--- gcc/testsuite/gcc.dg/ubsan/pr83014.c        (nonexistent)
+++ gcc/testsuite/gcc.dg/ubsan/pr83014.c        (revision 255134)
@@ -0,0 +1,12 @@
+/* PR sanitizer/83014 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+int
+foo (void)
+{
+  int data[5];
+  data[0] = 0;
+  data[5] = 0;
+  return data[0];
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-24  Jakub Jelinek  <ja...@redhat.com>

        PR fortran/81304
        * trans-openmp.c (gfc_trans_omp_array_reduction_or_udr): Set
        attr.implicit_type in intrinsic_sym to avoid undesirable warning.

        * testsuite/libgomp.fortran/pr81304.f90: New test.

--- gcc/fortran/trans-openmp.c  (revision 255143)
+++ gcc/fortran/trans-openmp.c  (revision 255144)
@@ -1623,6 +1623,7 @@ gfc_trans_omp_array_reduction_or_udr (tr
       intrinsic_sym.attr.referenced = 1;
       intrinsic_sym.attr.intrinsic = 1;
       intrinsic_sym.attr.function = 1;
+      intrinsic_sym.attr.implicit_type = 1;
       intrinsic_sym.result = &intrinsic_sym;
       intrinsic_sym.declared_at = where;
 
--- libgomp/testsuite/libgomp.fortran/pr81304.f90       (nonexistent)
+++ libgomp/testsuite/libgomp.fortran/pr81304.f90       (revision 255144)
@@ -0,0 +1,17 @@
+! PR fortran/81304
+! { dg-do run }
+! { dg-options "-Wsurprising" }
+
+program pr81304
+   integer :: i
+   real, dimension(1:3) :: a, b, c
+   a = 128
+   b = 0
+!$omp parallel do reduction(min: a) reduction(max: b) private (c)      ! { 
dg-bogus "Type specified for intrinsic function" }
+   do i = 1, 16
+     c = (/ i, i - 5, i + 5 /)
+     a = min (a, c)
+     b = max (b, c)
+   end do
+   if (any (a /= (/ 1, -4, 6 /)) .or. any (b /= (/ 16, 11, 21 /))) call abort
+end
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-25  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/81553
        * combine.c (simplify_if_then_else): In (if_then_else COND (OP Z C1) Z)
        to (OP Z (mult COND (C1 * STORE_FLAG_VALUE))) optimization, if OP
        is a shift where C1 has different mode than the whole shift, use C1's
        mode for MULT rather than the shift's mode.

        * gcc.c-torture/compile/pr81553.c: New test.

--- gcc/combine.c       (revision 255149)
+++ gcc/combine.c       (revision 255150)
@@ -6639,11 +6639,15 @@ simplify_if_then_else (rtx x)
 
       if (z)
        {
-         temp = subst (simplify_gen_relational (true_code, m, VOIDmode,
+         machine_mode cm = m;
+         if ((op == ASHIFT || op == LSHIFTRT || op == ASHIFTRT)
+             && GET_MODE (c1) != VOIDmode)
+           cm = GET_MODE (c1);
+         temp = subst (simplify_gen_relational (true_code, cm, VOIDmode,
                                                 cond_op0, cond_op1),
                        pc_rtx, pc_rtx, 0, 0, 0);
-         temp = simplify_gen_binary (MULT, m, temp,
-                                     simplify_gen_binary (MULT, m, c1,
+         temp = simplify_gen_binary (MULT, cm, temp,
+                                     simplify_gen_binary (MULT, cm, c1,
                                                           const_true_rtx));
          temp = subst (temp, pc_rtx, pc_rtx, 0, 0, 0);
          temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
--- gcc/testsuite/gcc.c-torture/compile/pr81553.c       (nonexistent)
+++ gcc/testsuite/gcc.c-torture/compile/pr81553.c       (revision 255150)
@@ -0,0 +1,10 @@
+/* PR rtl-optimization/81553 */
+
+int a, b, c, d;
+
+void
+foo (void)
+{
+  d = 1 >> c >> 1;
+  b = ~(209883449764912897ULL & d) << (0 >= a) | ~d;
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-27  Jakub Jelinek  <ja...@redhat.com>

        PR c++/81675
        * cp-gimplify.c (cp_fold) <case COND_EXPR>: Don't return immediately
        for VOID_TYPE_P COND_EXPRs, instead fold the operands and if op0 is
        INTEGER_CST, ensure that both op1 and op2 are non-NULL and fall
        through into normal folding, otherwise just rebuild x if any op
        changed.

        * g++.dg/warn/pr81675.C: New test.

--- gcc/cp/cp-gimplify.c        (revision 255166)
+++ gcc/cp/cp-gimplify.c        (revision 255167)
@@ -2299,13 +2299,6 @@ cp_fold (tree x)
 
     case VEC_COND_EXPR:
     case COND_EXPR:
-
-      /* Don't bother folding a void condition, since it can't produce a
-        constant value.  Also, some statement-level uses of COND_EXPR leave
-        one of the branches NULL, so folding would crash.  */
-      if (VOID_TYPE_P (TREE_TYPE (x)))
-       return x;
-
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
       op1 = cp_fold (TREE_OPERAND (x, 1));
@@ -2319,6 +2312,29 @@ cp_fold (tree x)
          if (!VOID_TYPE_P (TREE_TYPE (op2)))
            op2 = cp_truthvalue_conversion (op2);
        }
+      else if (VOID_TYPE_P (TREE_TYPE (x)))
+       {
+         if (TREE_CODE (op0) == INTEGER_CST)
+           {
+             /* If the condition is constant, fold can fold away
+                the COND_EXPR.  If some statement-level uses of COND_EXPR
+                have one of the branches NULL, avoid folding crash.  */
+             if (!op1)
+               op1 = build_empty_stmt (loc);
+             if (!op2)
+               op2 = build_empty_stmt (loc);
+           }
+         else
+           {
+             /* Otherwise, don't bother folding a void condition, since
+                it can't produce a constant value.  */
+             if (op0 != TREE_OPERAND (x, 0)
+                 || op1 != TREE_OPERAND (x, 1)
+                 || op2 != TREE_OPERAND (x, 2))
+               x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+             break;
+           }
+       }
 
       if (op0 != TREE_OPERAND (x, 0)
          || op1 != TREE_OPERAND (x, 1)
--- gcc/testsuite/g++.dg/warn/pr81675.C (nonexistent)
+++ gcc/testsuite/g++.dg/warn/pr81675.C (revision 255167)
@@ -0,0 +1,15 @@
+// PR c++/81675
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+struct S
+{
+  ~S () __attribute__((noreturn));
+  int a;
+};
+
+int
+foo ()
+{
+  false ? 5 : S ().a;
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-27  Jakub Jelinek  <ja...@redhat.com>

        PR c++/81888
        * parser.c (cp_parser_decomposition_declaration): Reject just
        BRACE_ENCLOSED_INITIALIZER_P initializers with nelts != 1 rather
        than all such CONSTRUCTORs, and only if is_direct_init is true.

        * g++.dg/cpp1z/decomp30.C: Add a test for structured binding with
        = {} and = { a, a } initializers.
        * g++.dg/cpp1z/decomp31.C: New test.

--- gcc/cp/parser.c     (revision 255179)
+++ gcc/cp/parser.c     (revision 255180)
@@ -13382,7 +13382,8 @@ cp_parser_decomposition_declaration (cp_
       if (initializer == NULL_TREE
          || (TREE_CODE (initializer) == TREE_LIST
              && TREE_CHAIN (initializer))
-         || (TREE_CODE (initializer) == CONSTRUCTOR
+         || (is_direct_init
+             && BRACE_ENCLOSED_INITIALIZER_P (initializer)
              && CONSTRUCTOR_NELTS (initializer) != 1))
        {
          error_at (loc, "invalid initializer for structured binding "
--- gcc/testsuite/g++.dg/cpp1z/decomp30.C       (revision 255179)
+++ gcc/testsuite/g++.dg/cpp1z/decomp30.C       (revision 255180)
@@ -10,3 +10,5 @@ auto [j, k] { a, a }; // { dg-error "inv
 auto [l, m] = { a };   // { dg-error "deducing from brace-enclosed initializer 
list requires" }
 auto [n, o] {};                // { dg-error "invalid initializer for 
structured binding declaration" }
 auto [p, q] ();                // { dg-error "invalid initializer for 
structured binding declaration" }
+auto [r, s] = {};      // { dg-error "deducing from brace-enclosed initializer 
list requires" }
+auto [t, u] = { a, a };        // { dg-error "deducing from brace-enclosed 
initializer list requires" }
--- gcc/testsuite/g++.dg/cpp1z/decomp31.C       (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp31.C       (revision 255180)
@@ -0,0 +1,18 @@
+// PR c++/81888
+// { dg-do compile { target c++1z } }
+
+struct S {
+  bool s = true;
+};
+
+auto [a] = S{};
+
+template <class T>
+bool
+foo () noexcept
+{
+  auto [c] = T{};
+  return c;
+}
+
+const bool b = foo<S> ();
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-11-29  Jakub Jelinek  <ja...@redhat.com>

        PR target/80819
        * config/i386/sse.md (vec_concatv2di): Remove * from (=Yr,0,*rm)
        alternative.

        * gcc.target/i386/pr80819-1.c: New test.
        * gcc.target/i386/pr80819-2.c: New test.

--- gcc/config/i386/sse.md      (revision 255225)
+++ gcc/config/i386/sse.md      (revision 255226)
@@ -13919,7 +13919,7 @@ (define_insn "vec_concatv2di"
          (match_operand:DI 1 "nonimmediate_operand"
          "  0, 0,x ,Yv,r ,vm,?!*Yn,0,Yv,0,0,v")
          (match_operand:DI 2 "vector_move_operand"
-         "*rm,rm,rm,rm,C ,C ,C ,x,Yv,x,m,m")))]
+         " rm,rm,rm,rm,C ,C ,C ,x,Yv,x,m,m")))]
   "TARGET_SSE"
   "@
    pinsrq\t{$1, %2, %0|%0, %2, 1}
--- gcc/testsuite/gcc.target/i386/pr80819-1.c   (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80819-1.c   (revision 255226)
@@ -0,0 +1,13 @@
+/* PR target/80819 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse4 -mno-avx -mtune=haswell -masm=att" } */
+
+typedef unsigned long long V __attribute__((vector_size (16)));
+
+V
+foo (unsigned long long x, unsigned long long y)
+{
+  return (V) { x, y };
+}
+
+/* { dg-final { scan-assembler-not "movq\[ \t]*%rsi, \[-0-9]*\\(" } } */
--- gcc/testsuite/gcc.target/i386/pr80819-2.c   (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80819-2.c   (revision 255226)
@@ -0,0 +1,13 @@
+/* PR target/80819 */
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse4 -mno-avx -mtune=generic -masm=att" } */
+
+typedef unsigned long long V __attribute__((vector_size (16)));
+
+V
+foo (unsigned long long x, unsigned long long y)
+{
+  return (V) { x, y };
+}
+
+/* { dg-final { scan-assembler-not "movq\[ \t]*%rsi, \[-0-9]*\\(" } } */
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-02  Jakub Jelinek  <ja...@redhat.com>

        PR target/78643
        PR target/80583
        * expr.c (get_inner_reference): If DECL_MODE of a non-bitfield
        is BLKmode for vector field with vector raw mode, use TYPE_MODE
        instead of DECL_MODE.

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

--- gcc/expr.c  (revision 255352)
+++ gcc/expr.c  (revision 255353)
@@ -7032,7 +7032,16 @@ get_inner_reference (tree exp, HOST_WIDE
             size.  */
        mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field));
       else if (!DECL_BIT_FIELD (field))
-       mode = DECL_MODE (field);
+       {
+         mode = DECL_MODE (field);
+         /* For vector fields re-check the target flags, as DECL_MODE
+            could have been set with different target flags than
+            the current function has.  */
+         if (mode == BLKmode
+             && VECTOR_TYPE_P (TREE_TYPE (field))
+             && VECTOR_MODE_P (TYPE_MODE_RAW (TREE_TYPE (field))))
+           mode = TYPE_MODE (TREE_TYPE (field));
+       }
       else if (DECL_MODE (field) == BLKmode)
        blkmode_bitfield = true;
 
--- gcc/testsuite/gcc.target/i386/pr80583.c     (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr80583.c     (revision 255353)
@@ -0,0 +1,13 @@
+/* PR target/80583 */
+/* { dg-do compile } */
+/* { dg-options "-O0 -mno-avx" } */
+
+typedef int V __attribute__((__vector_size__(32)));
+struct S { V a; };
+
+V __attribute__((target ("avx")))
+foo (struct S *b)
+{
+  V x = b->a;
+  return x;
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-02  Jakub Jelinek  <ja...@redhat.com>

        PR c++/81212
        * tree-cfg.c (pass_warn_function_return::execute): Handle
        __builtin_ubsan_handle_missing_return like __builtin_unreachable
        with BUILTINS_LOCATION.

        * g++.dg/ubsan/pr81212.C: New test.

--- gcc/tree-cfg.c      (revision 255353)
+++ gcc/tree-cfg.c      (revision 255354)
@@ -8917,7 +8917,6 @@ pass_warn_function_return::execute (func
      without returning a value.  */
   else if (warn_return_type
           && !TREE_NO_WARNING (fun->decl)
-          && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0
           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -8931,11 +8930,40 @@ pass_warn_function_return::execute (func
              location = gimple_location (last);
              if (location == UNKNOWN_LOCATION)
                location = fun->function_end_locus;
-             warning_at (location, OPT_Wreturn_type, "control reaches end of 
non-void function");
+             warning_at (location, OPT_Wreturn_type,
+                         "control reaches end of non-void function");
              TREE_NO_WARNING (fun->decl) = 1;
              break;
            }
        }
+      /* -fsanitize=return turns fallthrough from the end of non-void function
+        into __builtin___ubsan_handle_missing_return () call.
+        Recognize those too.  */
+      basic_block bb;
+      if (!TREE_NO_WARNING (fun->decl) && (flag_sanitize & SANITIZE_RETURN))
+       FOR_EACH_BB_FN (bb, fun)
+         if (EDGE_COUNT (bb->succs) == 0)
+           {
+             gimple *last = last_stmt (bb);
+             const enum built_in_function ubsan_missing_ret
+               = BUILT_IN_UBSAN_HANDLE_MISSING_RETURN;
+             if (last && gimple_call_builtin_p (last, ubsan_missing_ret))
+               {
+                 gimple_stmt_iterator gsi = gsi_for_stmt (last);
+                 gsi_prev_nondebug (&gsi);
+                 gimple *prev = gsi_stmt (gsi);
+                 if (prev == NULL)
+                   location = UNKNOWN_LOCATION;
+                 else
+                   location = gimple_location (prev);
+                 if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
+                   location = fun->function_end_locus;
+                 warning_at (location, OPT_Wreturn_type,
+                             "control reaches end of non-void function");
+                 TREE_NO_WARNING (fun->decl) = 1;
+                 break;
+               }
+           }
     }
   return 0;
 }
--- gcc/testsuite/g++.dg/ubsan/pr81212.C        (nonexistent)
+++ gcc/testsuite/g++.dg/ubsan/pr81212.C        (revision 255354)
@@ -0,0 +1,16 @@
+// PR c++/81212
+// { dg-do compile }
+// { dg-options "-Wreturn-type -fsanitize=return" }
+
+struct S
+{
+  S (void *);
+  void *s;
+};
+
+S
+foo (bool x, void *y)
+{
+  if (x)
+    return S (y);
+}      // { dg-warning "control reaches end of non-void function" }
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-06  Jakub Jelinek  <ja...@redhat.com>

        PR c++/80259
        * decl2.c (grokfield): Diagnose = delete redefinition of a friend.

        * g++.dg/cpp0x/pr80259.C: New test.

--- gcc/cp/decl2.c      (revision 255455)
+++ gcc/cp/decl2.c      (revision 255456)
@@ -911,9 +911,18 @@ grokfield (const cp_declarator *declarat
        {
          if (init == ridpointers[(int)RID_DELETE])
            {
-             DECL_DELETED_FN (value) = 1;
-             DECL_DECLARED_INLINE_P (value) = 1;
-             DECL_INITIAL (value) = error_mark_node;
+             if (friendp && decl_defined_p (value))
+               {
+                 error ("redefinition of %q#D", value);
+                 inform (DECL_SOURCE_LOCATION (value),
+                         "%q#D previously defined here", value);
+               }
+             else
+               {
+                 DECL_DELETED_FN (value) = 1;
+                 DECL_DECLARED_INLINE_P (value) = 1;
+                 DECL_INITIAL (value) = error_mark_node;
+               }
            }
          else if (init == ridpointers[(int)RID_DEFAULT])
            {
--- gcc/testsuite/g++.dg/cpp0x/pr80259.C        (nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/pr80259.C        (revision 255456)
@@ -0,0 +1,13 @@
+// PR c++/80259
+// { dg-do compile { target c++11 } }
+
+void foo () {} // { dg-message "previously defined here" }
+void bar ();
+
+struct A
+{
+  friend void foo () = delete; // { dg-error "redefinition of" }
+  friend void bar () = delete; // { dg-message "previously defined here" }
+};
+
+void bar () {} // { dg-error "redefinition of" }
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-08  Joseph Myers  <jos...@codesourcery.com>
                    Alexander Monakov  <amona...@ispras.ru>
                    Jakub Jelinek  <ja...@redhat.com>

        PR target/81906
        * config/i386/i386.c (ix86_expand_rint): Handle flag_rounding_math.

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

--- gcc/config/i386/i386.c      (revision 255485)
+++ gcc/config/i386/i386.c      (revision 255486)
@@ -44255,8 +44255,7 @@ ix86_expand_lfloorceil (rtx op0, rtx op1
   emit_move_insn (op0, ireg);
 }
 
-/* Expand rint (IEEE round to nearest) rounding OPERAND1 and storing the
-   result in OPERAND0.  */
+/* Expand rint rounding OPERAND1 and storing the result in OPERAND0.  */
 void
 ix86_expand_rint (rtx operand0, rtx operand1)
 {
@@ -44264,11 +44263,17 @@ ix86_expand_rint (rtx operand0, rtx oper
        xa = fabs (operand1);
         if (!isless (xa, 2**52))
          return operand1;
-        xa = xa + 2**52 - 2**52;
+        two52 = 2**52;
+        if (flag_rounding_math)
+         {
+           two52 = copysign (two52, operand1);
+           xa = operand1;
+         }
+        xa = xa + two52 - two52;
         return copysign (xa, operand1);
    */
   machine_mode mode = GET_MODE (operand0);
-  rtx res, xa, TWO52, mask;
+  rtx res, xa, TWO52, two52, mask;
   rtx_code_label *label;
 
   res = gen_reg_rtx (mode);
@@ -44281,8 +44286,16 @@ ix86_expand_rint (rtx operand0, rtx oper
   TWO52 = ix86_gen_TWO52 (mode);
   label = ix86_expand_sse_compare_and_jump (UNLE, TWO52, xa, false);
 
-  xa = expand_simple_binop (mode, PLUS, xa, TWO52, NULL_RTX, 0, OPTAB_DIRECT);
-  xa = expand_simple_binop (mode, MINUS, xa, TWO52, xa, 0, OPTAB_DIRECT);
+  two52 = TWO52;
+  if (flag_rounding_math)
+    {
+      two52 = gen_reg_rtx (mode);
+      ix86_sse_copysign_to_positive (two52, TWO52, res, mask);
+      xa = res;
+    }
+
+  xa = expand_simple_binop (mode, PLUS, xa, two52, NULL_RTX, 0, OPTAB_DIRECT);
+  xa = expand_simple_binop (mode, MINUS, xa, two52, xa, 0, OPTAB_DIRECT);
 
   ix86_sse_copysign_to_positive (res, xa, res, mask);
 
--- gcc/testsuite/gcc.target/i386/pr81906.c     (nonexistent)
+++ gcc/testsuite/gcc.target/i386/pr81906.c     (revision 255486)
@@ -0,0 +1,37 @@
+/* PR target/81906 */
+/* { dg-do run { target *-*-linux* *-*-gnu* } }
+/* { dg-options "-O2 -frounding-math" } */
+
+#include <fenv.h>
+
+int
+main ()
+{
+  #define N 12
+  double a[N] = { 2.0, 2.25, 2.5, 2.75, 3.5, -2.0, -2.25, -2.5, -2.75, -3.5, 
0x2.0p53, -0x2.0p53 };
+  double b[N], c[N], d[N], e[N];
+  double be[N] = { 2.0, 2.0, 2.0, 3.0, 4.0, -2.0, -2.0, -2.0, -3.0, -4.0, 
0x2.0p53, -0x2.0p53 };
+  double ce[N] = { 2.0, 2.0, 2.0, 2.0, 3.0, -2.0, -3.0, -3.0, -3.0, -4.0, 
0x2.0p53, -0x2.0p53 };
+  double de[N] = { 2.0, 3.0, 3.0, 3.0, 4.0, -2.0, -2.0, -2.0, -2.0, -3.0, 
0x2.0p53, -0x2.0p53 };
+  double ee[N] = { 2.0, 2.0, 2.0, 2.0, 3.0, -2.0, -2.0, -2.0, -2.0, -3.0, 
0x2.0p53, -0x2.0p53 };
+  asm volatile ("" : : "g" (a), "g" (be), "g" (ce), "g" (de), "g" (ee) : 
"memory");
+
+  int i;
+  fesetround (FE_TONEAREST);
+  for (i = 0; i < N; ++i)
+    b[i] = __builtin_rint (a[i]);
+  fesetround (FE_DOWNWARD);
+  for (i = 0; i < N; ++i)
+    c[i] = __builtin_rint (a[i]);
+  fesetround (FE_UPWARD);
+  for (i = 0; i < N; ++i)
+    d[i] = __builtin_rint (a[i]);
+  fesetround (FE_TOWARDZERO);
+  for (i = 0; i < N; ++i)
+    e[i] = __builtin_rint (a[i]);
+  fesetround (FE_TONEAREST);
+  for (i = 0; i < N; ++i)
+    if (b[i] != be[i] || c[i] != ce[i] || d[i] != de[i] || e[i] != ee[i])
+      __builtin_abort ();
+  return 0;
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-12  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/80631
        * tree-vect-loop.c (get_initial_def_for_reduction): Fix comment typo.
        (vect_create_epilog_for_reduction): Add INDUC_VAL argument, for
        INTEGER_INDUC_COND_REDUCTION use INDUC_VAL instead of
        hardcoding zero as the value if COND_EXPR is never true.  For
        INTEGER_INDUC_COND_REDUCTION don't emit the final COND_EXPR if
        INDUC_VAL is equal to INITIAL_DEF.
        (vectorizable_reduction): Compute INDUC_VAL for
        vect_create_epilog_for_reduction, if no value is suitable, don't
        use INTEGER_INDUC_COND_REDUCTION for now.  Formatting fixes.

        * gcc.dg/vect/pr80631-1.c: New test.
        * gcc.dg/vect/pr80631-2.c: New test.

        PR tree-optimization/80631
        * gcc.target/i386/avx2-pr80631.c: New test.

--- gcc/tree-vect-loop.c        (revision 255573)
+++ gcc/tree-vect-loop.c        (revision 255574)
@@ -4262,7 +4262,7 @@ get_initial_def_for_reduction (gimple *s
       case BIT_XOR_EXPR:
       case MULT_EXPR:
       case BIT_AND_EXPR:
-        /* ADJUSMENT_DEF is NULL when called from
+        /* ADJUSTMENT_DEF is NULL when called from
            vect_create_epilog_for_reduction to vectorize double reduction.  */
         if (adjustment_def)
          *adjustment_def = init_val;
@@ -4358,6 +4358,9 @@ get_initial_def_for_reduction (gimple *s
      first one in this group is STMT.
    INDUCTION_INDEX is the index of the loop for condition reductions.
      Otherwise it is undefined.
+   INDUC_VAL is for INTEGER_INDUC_COND_REDUCTION the value to use for the case
+     when the COND_EXPR is never true in the loop.  It needs to
+     be smaller than any value of the IV in the loop.
 
    This function:
    1. Creates the reduction def-use cycles: sets the arguments for 
@@ -4403,7 +4406,8 @@ vect_create_epilog_for_reduction (vec<tr
                                  int ncopies, enum tree_code reduc_code,
                                  vec<gimple *> reduction_phis,
                                   int reduc_index, bool double_reduc, 
-                                 slp_tree slp_node, tree induction_index)
+                                 slp_tree slp_node, tree induction_index,
+                                 tree induc_val)
 {
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   stmt_vec_info prev_phi_info;
@@ -4488,6 +4492,15 @@ vect_create_epilog_for_reduction (vec<tr
       gimple *def_stmt = SSA_NAME_DEF_STMT (reduction_op);
       initial_def = PHI_ARG_DEF_FROM_EDGE (def_stmt,
                                           loop_preheader_edge (loop));
+      /* Optimize: if initial_def is for REDUC_MAX smaller than the base
+        and we can't use zero for induc_val, use initial_def.  Similarly
+        for REDUC_MIN and initial_def larger than the base.  */
+      if (TREE_CODE (initial_def) == INTEGER_CST
+         && (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+             == INTEGER_INDUC_COND_REDUCTION)
+         && !integer_zerop (induc_val)
+         && tree_int_cst_lt (initial_def, induc_val))
+       induc_val = initial_def;
       vect_is_simple_use (initial_def, loop_vinfo, &def_stmt, &initial_def_dt);
       vec_initial_def = get_initial_def_for_reduction (stmt, initial_def,
                                                       &adjustment_def);
@@ -4528,9 +4541,10 @@ vect_create_epilog_for_reduction (vec<tr
              gcc_assert (i == 0);
 
              tree vec_init_def_type = TREE_TYPE (vec_init_def);
-             tree zero_vec = build_zero_cst (vec_init_def_type);
+             tree induc_val_vec
+               = build_vector_from_val (vec_init_def_type, induc_val);
 
-             add_phi_arg (as_a <gphi *> (phi), zero_vec,
+             add_phi_arg (as_a <gphi *> (phi), induc_val_vec,
                           loop_preheader_edge (loop), UNKNOWN_LOCATION);
            }
          else
@@ -4879,14 +4893,16 @@ vect_create_epilog_for_reduction (vec<tr
       gimple_assign_set_lhs (epilog_stmt, new_temp);
       gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
 
-      if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-         == INTEGER_INDUC_COND_REDUCTION)
+      if ((STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+          == INTEGER_INDUC_COND_REDUCTION)
+         && !operand_equal_p (initial_def, induc_val, 0))
        {
-         /* Earlier we set the initial value to be zero.  Check the result
-            and if it is zero then replace with the original initial
-            value.  */
-         tree zero = build_zero_cst (scalar_type);
-         tree zcompare = build2 (EQ_EXPR, boolean_type_node, new_temp, zero);
+         /* Earlier we set the initial value to be a vector if induc_val
+            values.  Check the result and if it is induc_val then replace
+            with the original initial value, unless induc_val is
+            the same as initial_def already.  */
+         tree zcompare = build2 (EQ_EXPR, boolean_type_node, new_temp,
+                                 induc_val);
 
          tmp = make_ssa_name (new_scalar_dest);
          epilog_stmt = gimple_build_assign (tmp, COND_EXPR, zcompare,
@@ -5001,7 +5017,7 @@ vect_create_epilog_for_reduction (vec<tr
               else
                 vec_temp = gimple_assign_lhs (new_phi);
               tree rhs = build3 (BIT_FIELD_REF, scalar_type, vec_temp, bitsize,
-                            bitsize_zero_node);
+                                bitsize_zero_node);
               epilog_stmt = gimple_build_assign (new_scalar_dest, rhs);
               new_temp = make_ssa_name (new_scalar_dest, epilog_stmt);
               gimple_assign_set_lhs (epilog_stmt, new_temp);
@@ -5485,6 +5501,7 @@ vectorizable_reduction (gimple *stmt, gi
   gimple *def_stmt;
   enum vect_def_type dt, cond_reduc_dt = vect_unknown_def_type;
   gphi *new_phi = NULL;
+  gimple *cond_reduc_def_stmt = NULL;
   tree scalar_type;
   bool is_simple_use;
   gimple *orig_stmt;
@@ -5672,9 +5689,13 @@ vectorizable_reduction (gimple *stmt, gi
              cond_reduc_dt = dt;
              cond_reduc_val = ops[i];
            }
-         if (dt == vect_induction_def && def_stmt != NULL
+         if (dt == vect_induction_def
+             && def_stmt != NULL
              && is_nonwrapping_integer_induction (def_stmt, loop))
-           cond_reduc_dt = dt;
+           {
+             cond_reduc_dt = dt;
+             cond_reduc_def_stmt = def_stmt;
+           }
        }
     }
 
@@ -5713,12 +5734,28 @@ vectorizable_reduction (gimple *stmt, gi
     {
       if (cond_reduc_dt == vect_induction_def)
        {
-         if (dump_enabled_p ())
-           dump_printf_loc (MSG_NOTE, vect_location,
-                            "condition expression based on "
-                            "integer induction.\n");
-         STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-           = INTEGER_INDUC_COND_REDUCTION;
+         stmt_vec_info cond_stmt_vinfo = vinfo_for_stmt (cond_reduc_def_stmt);
+         tree base
+           = STMT_VINFO_LOOP_PHI_EVOLUTION_BASE_UNCHANGED (cond_stmt_vinfo);
+
+         gcc_assert (TREE_CODE (base) == INTEGER_CST);
+         cond_reduc_val = NULL_TREE;
+         /* Find a suitable value below base; punt if base is the minimum
+            value of the type for now.  */
+         if (tree_int_cst_sgn (base) == 1)
+           cond_reduc_val = build_int_cst (TREE_TYPE (base), 0);
+         else if (tree_int_cst_lt (TYPE_MIN_VALUE (TREE_TYPE (base)), base))
+           cond_reduc_val
+             = int_const_binop (MINUS_EXPR, base, integer_one_node);
+         if (cond_reduc_val)
+           {
+             if (dump_enabled_p ())
+               dump_printf_loc (MSG_NOTE, vect_location,
+                                "condition expression based on "
+                                "integer induction.\n");
+             STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
+               = INTEGER_INDUC_COND_REDUCTION;
+           }
        }
 
       /* Loop peeling modifies initial value of reduction PHI, which
@@ -5915,7 +5952,7 @@ vectorizable_reduction (gimple *stmt, gi
          gcc_assert (orig_code == MAX_EXPR || orig_code == MIN_EXPR);
        }
       else if (STMT_VINFO_VEC_REDUCTION_TYPE (stmt_info)
-                == INTEGER_INDUC_COND_REDUCTION)
+              == INTEGER_INDUC_COND_REDUCTION)
        orig_code = MAX_EXPR;
     }
 
@@ -6382,7 +6419,8 @@ vectorizable_reduction (gimple *stmt, gi
 
   vect_create_epilog_for_reduction (vect_defs, stmt, epilog_copies,
                                     epilog_reduc_code, phis, reduc_index,
-                                   double_reduc, slp_node, cond_name);
+                                   double_reduc, slp_node, cond_name,
+                                   cond_reduc_val);
 
   return true;
 }
--- gcc/testsuite/gcc.dg/vect/pr80631-1.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/pr80631-1.c       (revision 255574)
@@ -0,0 +1,76 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+int v[8] = { 77, 1, 79, 3, 4, 3, 6, 7 };
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+  int k, r = -1;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 77)
+      r = k;
+  if (r != 0)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+  int k, r = 4;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 79)
+      r = k;
+  if (r != 2)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+  int k, r = -17;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 78)
+      r = k;
+  if (r != -17)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+  int k, r = 7;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 78)
+      r = k;
+  if (r != 7)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+  int k, r = -1;
+  for (k = 0; k < 8; k++)
+    if (v[k] == 3)
+      r = k;
+  if (r != 5)
+    abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 5 "vect" { xfail { ! 
vect_max_reduc } } } } */
+/* { dg-final { scan-tree-dump-times "condition expression based on integer 
induction." 10 "vect" { xfail { ! vect_max_reduc } } } } */
--- gcc/testsuite/gcc.dg/vect/pr80631-2.c       (nonexistent)
+++ gcc/testsuite/gcc.dg/vect/pr80631-2.c       (revision 255574)
@@ -0,0 +1,73 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+
+#include "tree-vect.h"
+
+int v[8] = { 77, 1, 79, 3, 4, 3, 6, 7 };
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+  int k, r = -1;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 77)
+      r = k;
+  if (r != 0)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+  int k, r = 4;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 79)
+      r = k;
+  if (r != 2)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+  int k, r = -17;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 78)
+      r = k;
+  if (r != -17)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+  int k, r = 7;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 78)
+      r = k;
+  if (r != 7)
+    abort ();
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+  int k, r = -1;
+  for (k = 7; k >= 0; k--)
+    if (v[k] == 3)
+      r = k;
+  if (r != 3)
+    abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  return 0;
+}
--- gcc/testsuite/gcc.target/i386/avx2-pr80631.c        (nonexistent)
+++ gcc/testsuite/gcc.target/i386/avx2-pr80631.c        (revision 255701)
@@ -0,0 +1,23 @@
+/* PR tree-optimization/80631 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -mavx2 -fno-vect-cost-model" } */
+/* { dg-require-effective-target avx2 } */
+
+#include "avx2-check.h"
+
+#define N 8
+
+static void
+avx2_test (void)
+{
+  int v[N], k;
+  for(k = 0; k < N; k++)
+    v[k] = k;
+  v[0] = 77;
+  int found_index = -1;
+  for (k = 0; k < N; k++)
+    if (v[k] == 77)
+      found_index = k;
+  if (found_index != 0)
+    abort ();
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-14  Jakub Jelinek  <ja...@redhat.com>

        PR c++/79650
        * pt.c (convert_nontype_argument): Diagnose
        reduced_constant_expression_p expressions that aren't INTEGER_CST.

        * g++.dg/template/pr79650.C: New test.

--- gcc/cp/pt.c (revision 255622)
+++ gcc/cp/pt.c (revision 255623)
@@ -6523,7 +6523,20 @@ convert_nontype_argument (tree type, tre
                return NULL_TREE;
              /* else cxx_constant_value complained but gave us
                 a real constant, so go ahead.  */
-             gcc_assert (TREE_CODE (expr) == INTEGER_CST);
+             if (TREE_CODE (expr) != INTEGER_CST)
+               {
+                 /* Some assemble time constant expressions like
+                    (intptr_t)&&lab1 - (intptr_t)&&lab2 or
+                    4 + (intptr_t)&&var satisfy reduced_constant_expression_p
+                    as we can emit them into .rodata initializers of
+                    variables, yet they can't fold into an INTEGER_CST at
+                    compile time.  Refuse them here.  */
+                 gcc_checking_assert (reduced_constant_expression_p (expr));
+                 location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+                 error_at (loc, "template argument %qE for type %qT not "
+                                "a constant integer", expr, type);
+                 return NULL_TREE;
+               }
            }
          else
            return NULL_TREE;
--- gcc/testsuite/g++.dg/template/pr79650.C     (nonexistent)
+++ gcc/testsuite/g++.dg/template/pr79650.C     (revision 255623)
@@ -0,0 +1,20 @@
+// PR c++/79650
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+typedef __INTPTR_TYPE__ intptr_t;
+template<intptr_t> struct A {};
+
+void
+foo ()
+{
+  static int a, b;
+lab1:
+lab2:
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c;     // { dg-error "not a 
constant integer" }
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d;
+  A<(intptr_t)&a - (intptr_t)&b> e;                    // { dg-error "is not a 
constant expression" }
+  A<(intptr_t)&a - (intptr_t)&a> f;
+  A<(intptr_t)sizeof(a) + (intptr_t)&a> g;             // { dg-error "not a 
constant integer" }
+  A<(intptr_t)&a> h;                                   // { dg-error 
"conversion from pointer type" }
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-14  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/83198
        * gimple-ssa-sprintf.c (format_floating): Set type solely based on
        dir.modifier, regardless of TREE_TYPE (arg).  Assume non-REAL_CST
        value if arg is a REAL_CST with incompatible type.

        * gcc.dg/pr83198.c: New test.
        * gcc.dg/tree-ssa/pr83198.c: New test.

--- gcc/gimple-ssa-sprintf.c    (revision 255625)
+++ gcc/gimple-ssa-sprintf.c    (revision 255626)
@@ -1885,6 +1885,8 @@ static fmtresult
 format_floating (const directive &dir, tree arg)
 {
   HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
+  tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
+              ? long_double_type_node : double_type_node);
 
   /* For an indeterminate precision the lower bound must be assumed
      to be zero.  */
@@ -1892,10 +1894,6 @@ format_floating (const directive &dir, t
     {
       /* Get the number of fractional decimal digits needed to represent
         the argument without a loss of accuracy.  */
-      tree type = arg ? TREE_TYPE (arg) :
-       (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
-        ? long_double_type_node : double_type_node);
-
       unsigned fmtprec
        = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
 
@@ -1946,7 +1944,9 @@ format_floating (const directive &dir, t
        }
     }
 
-  if (!arg || TREE_CODE (arg) != REAL_CST)
+  if (!arg
+      || TREE_CODE (arg) != REAL_CST
+      || !useless_type_conversion_p (type, TREE_TYPE (arg)))
     return format_floating (dir, prec);
 
   /* The minimum and maximum number of bytes produced by the directive.  */
--- gcc/testsuite/gcc.dg/pr83198.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/pr83198.c      (revision 255626)
@@ -0,0 +1,18 @@
+/* PR tree-optimization/83198 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -Wno-format" } */
+
+int
+foo (char *d[6], int x)
+{
+  int r = 0;
+  r += __builtin_sprintf (d[0], "%f", x);
+  r += __builtin_sprintf (d[1], "%a", x);
+  r += __builtin_sprintf (d[2], "%f", "foo");
+  r += __builtin_sprintf (d[3], "%a", "bar");
+#ifdef __SIZEOF_FLOAT128__
+  r += __builtin_sprintf (d[4], "%a", 1.0Q);
+  r += __builtin_sprintf (d[5], "%Lf", 1.0Q);
+#endif
+  return r;
+}
--- gcc/testsuite/gcc.dg/tree-ssa/pr83198.c     (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr83198.c     (revision 255626)
@@ -0,0 +1,23 @@
+/* PR tree-optimization/83198 */
+/* { dg-do compile { target __float128 } } */
+/* { dg-options "-O2 -fprintf-return-value -Wno-format -fdump-tree-optimized" 
} */
+/* { dg-add-options __float128 } */
+
+void bar (void);
+void link_error (void);
+
+void
+foo (char *x)
+{
+  int a = __builtin_sprintf (x, "%f", 1.0Q);
+  if (a < 8)
+    link_error ();
+  if (a > 13)
+    bar ();
+  if (a > 322)
+    link_error ();
+}
+
+/* Verify we don't optimize return value to [8, 13].  */
+/* { dg-final { scan-tree-dump-not "link_error \\(\\);" "optimized" } } */
+/* { dg-final { scan-tree-dump "bar \\(\\);" "optimized" } } */
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/83269
        * fold-const.c (fold_binary_loc): Perform (-A) - B -> (-B) - A
        subtraction in arg0's type if type is signed and arg0 is unsigned.
        Formatting fix.

        * gcc.c-torture/execute/pr83269.c: New test.

--- gcc/fold-const.c    (revision 255696)
+++ gcc/fold-const.c    (revision 255697)
@@ -9123,8 +9123,8 @@ expr_not_equal_to (tree t, const wide_in
    return NULL_TREE.  */
 
 tree
-fold_binary_loc (location_t loc,
-            enum tree_code code, tree type, tree op0, tree op1)
+fold_binary_loc (location_t loc, enum tree_code code, tree type,
+                tree op0, tree op1)
 {
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   tree arg0, arg1, tem;
@@ -9728,10 +9728,17 @@ fold_binary_loc (location_t loc,
     case MINUS_EXPR:
       /* (-A) - B -> (-B) - A  where B is easily negated and we can swap.  */
       if (TREE_CODE (arg0) == NEGATE_EXPR
-         && negate_expr_p (op1))
-       return fold_build2_loc (loc, MINUS_EXPR, type,
-                               negate_expr (op1),
-                               fold_convert_loc (loc, type,
+         && negate_expr_p (op1)
+         /* If arg0 is e.g. unsigned int and type is int, then this could
+            introduce UB, because if A is INT_MIN at runtime, the original
+            expression can be well defined while the latter is not.
+            See PR83269.  */
+         && !(ANY_INTEGRAL_TYPE_P (type)
+              && TYPE_OVERFLOW_UNDEFINED (type)
+              && ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
+              && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
+       return fold_build2_loc (loc, MINUS_EXPR, type, negate_expr (op1),
+                               fold_convert_loc (loc, type,
                                                  TREE_OPERAND (arg0, 0)));
 
       /* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
--- gcc/testsuite/gcc.c-torture/execute/pr83269.c       (nonexistent)
+++ gcc/testsuite/gcc.c-torture/execute/pr83269.c       (revision 255697)
@@ -0,0 +1,14 @@
+/* PR tree-optimization/83269 */
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ > 4 && __CHAR_BIT__ == 8
+  volatile unsigned char a = 1;
+  long long b = 0x80000000L;
+  int c = -((int)(-b) - (-0x7fffffff * a));
+  if (c != 1)
+    __builtin_abort ();
+#endif
+  return 0;
+}
2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83217
        * decl.c (cp_finish_decomp): If decl's type is REFERENCE_TYPE,
        call complete_type (TREE_TYPE (type)).

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

--- gcc/cp/decl.c       (revision 255701)
+++ gcc/cp/decl.c       (revision 255702)
@@ -7404,7 +7404,9 @@ cp_finish_decomp (tree decl, tree first,
   if (TREE_CODE (type) == REFERENCE_TYPE)
     {
       dexp = convert_from_reference (dexp);
-      type = TREE_TYPE (type);
+      type = complete_type (TREE_TYPE (type));
+      if (type == error_mark_node)
+       goto error_out;
     }
 
   tree eltype = NULL_TREE;
--- gcc/testsuite/g++.dg/cpp1z/decomp33.C       (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp33.C       (revision 255702)
@@ -0,0 +1,21 @@
+// PR c++/83217
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+template <typename T>
+struct S
+{
+  T a;
+};
+
+void
+foo (S<int> *b)
+{
+  auto & [c] = *b;     // { dg-warning "decomposition declaration only 
available with" "" { target c++14_down } }
+}
+
+void
+bar (S<char> *d)
+{
+  auto [e] = *d;       // { dg-warning "decomposition declaration only 
available with" "" { target c++14_down } }
+}

Reply via email to