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 <[email protected]>
Backported from mainline
2017-11-20 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-21 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-21 James Cowgill <[email protected]>
Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-22 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-23 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-23 Dirk Broemmel <[email protected]>
Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-23 Jakub Jelinek <[email protected]>
* 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 <[email protected]>
Backported from mainline
2017-11-24 Jakub Jelinek <[email protected]>
* 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 <[email protected]>
Backported from mainline
2017-11-24 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-24 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-25 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-27 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-27 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-11-29 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-02 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-02 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-06 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-08 Joseph Myers <[email protected]>
Alexander Monakov <[email protected]>
Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-12 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-14 Jakub Jelinek <[email protected]>
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 <[email protected]>
Backported from mainline
2017-12-14 Jakub Jelinek <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 } }
+}