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 } } +}