Submitted By: Bruce Dubbs Date: 2015-05-23 Initial Package Version: 5.1.0 Upstream Status: Committed Origin: https://patchwork.ozlabs.org/patch/469768/raw/ and gcc git Description: Fix acc_device_type not distinguishing between "offloaded" and host code with the host_nonshm plugin. Fix inline issues. commit adccf2e7d313263d585f63e752a4d36653d47811 Author: Julian Brown Date: Tue Apr 21 12:40:45 2015 -0700 Non-SHM acc_on_device fixes diff --git a/gcc/builtins.c b/gcc/builtins.c index 6fe1456..5930fe4 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5917,6 +5917,7 @@ expand_stack_save (void) static rtx expand_builtin_acc_on_device (tree exp, rtx target) { +#ifdef ACCEL_COMPILER if (!validate_arglist (exp, INTEGER_TYPE, VOID_TYPE)) return NULL_RTX; @@ -5925,13 +5926,8 @@ expand_builtin_acc_on_device (tree exp, rtx target) /* Return (arg == v1 || arg == v2) ? 1 : 0. */ machine_mode v_mode = TYPE_MODE (TREE_TYPE (arg)); rtx v = expand_normal (arg), v1, v2; -#ifdef ACCEL_COMPILER v1 = GEN_INT (GOMP_DEVICE_NOT_HOST); v2 = GEN_INT (ACCEL_COMPILER_acc_device); -#else - v1 = GEN_INT (GOMP_DEVICE_NONE); - v2 = GEN_INT (GOMP_DEVICE_HOST); -#endif machine_mode target_mode = TYPE_MODE (integer_type_node); if (!target || !register_operand (target, target_mode)) target = gen_reg_rtx (target_mode); @@ -5945,6 +5941,9 @@ expand_builtin_acc_on_device (tree exp, rtx target) emit_label (done_label); return target; +#else + return NULL; +#endif } diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c index 335ffd4..157147a 100644 --- a/libgomp/oacc-init.c +++ b/libgomp/oacc-init.c @@ -29,6 +29,7 @@ #include "libgomp.h" #include "oacc-int.h" #include "openacc.h" +#include "plugin/plugin-host.h" #include #include #include @@ -611,11 +612,18 @@ ialias (acc_set_device_num) int acc_on_device (acc_device_t dev) { - if (acc_get_device_type () == acc_device_host_nonshm) + struct goacc_thread *thr = goacc_thread (); + + /* We only want to appear to be the "host_nonshm" plugin from "offloaded" + code -- i.e. within a parallel region. Test a flag set by the + openacc_parallel hook of the host_nonshm plugin to determine that. */ + if (acc_get_device_type () == acc_device_host_nonshm + && thr && thr->target_tls + && ((struct nonshm_thread *)thr->target_tls)->nonshm_exec) return dev == acc_device_host_nonshm || dev == acc_device_not_host; - /* Just rely on the compiler builtin. */ - return __builtin_acc_on_device (dev); + /* For OpenACC, libgomp is only built for the host, so this is sufficient. */ + return dev == acc_device_host || dev == acc_device_none; } ialias (acc_on_device) diff --git a/libgomp/plugin/plugin-host.c b/libgomp/plugin/plugin-host.c index 1faf5bc..3cb4dab 100644 --- a/libgomp/plugin/plugin-host.c +++ b/libgomp/plugin/plugin-host.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef HOST_NONSHM_PLUGIN #define STATIC @@ -55,6 +56,10 @@ #define SELF "host: " #endif +#ifdef HOST_NONSHM_PLUGIN +#include "plugin-host.h" +#endif + STATIC const char * GOMP_OFFLOAD_get_name (void) { @@ -174,7 +179,10 @@ GOMP_OFFLOAD_openacc_parallel (void (*fn) (void *), void *targ_mem_desc __attribute__ ((unused))) { #ifdef HOST_NONSHM_PLUGIN + struct nonshm_thread *thd = GOMP_PLUGIN_acc_thread (); + thd->nonshm_exec = true; fn (devaddrs); + thd->nonshm_exec = false; #else fn (hostaddrs); #endif @@ -232,11 +240,20 @@ STATIC void * GOMP_OFFLOAD_openacc_create_thread_data (int ord __attribute__ ((unused))) { +#ifdef HOST_NONSHM_PLUGIN + struct nonshm_thread *thd + = GOMP_PLUGIN_malloc (sizeof (struct nonshm_thread)); + thd->nonshm_exec = false; + return thd; +#else return NULL; +#endif } STATIC void -GOMP_OFFLOAD_openacc_destroy_thread_data (void *tls_data - __attribute__ ((unused))) +GOMP_OFFLOAD_openacc_destroy_thread_data (void *tls_data) { +#ifdef HOST_NONSHM_PLUGIN + free (tls_data); +#endif } diff --git a/libgomp/plugin/plugin-host.h b/libgomp/plugin/plugin-host.h new file mode 100644 index 0000000..96955d1 --- /dev/null +++ b/libgomp/plugin/plugin-host.h @@ -0,0 +1,37 @@ +/* OpenACC Runtime Library: acc_device_host, acc_device_host_nonshm. + + Copyright (C) 2015 Free Software Foundation, Inc. + + Contributed by Mentor Embedded. + + This file is part of the GNU Offloading and Multi Processing Library + (libgomp). + + Libgomp is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +#ifndef PLUGIN_HOST_H +#define PLUGIN_HOST_H + +struct nonshm_thread +{ + bool nonshm_exec; +}; + +#endif diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_on_device-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_on_device-1.c index 81ea476..25cc15a 100644 --- a/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_on_device-1.c +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/acc_on_device-1.c @@ -1,7 +1,3 @@ -/* Disable the acc_on_device builtin; we want to test the libgomp library - function. */ -/* { dg-additional-options "-fno-builtin-acc_on_device" } */ - #include #include diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/if-1.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/if-1.c index 184b355..6aa3bb7 100644 --- a/libgomp/testsuite/libgomp.oacc-c-c++-common/if-1.c +++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/if-1.c @@ -1,5 +1,4 @@ /* { dg-do run } */ -/* { dg-additional-options "-fno-builtin-acc_on_device" } */ #include #include diff --git a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-1.f90 index 4488818..729b685 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-1.f90 +++ b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-1.f90 @@ -1,8 +1,4 @@ ! { dg-additional-options "-cpp" } -! TODO: Have to disable the acc_on_device builtin for we want to test the -! libgomp library function? The command line option -! '-fno-builtin-acc_on_device' is valid for C/C++/ObjC/ObjC++ but not for -! Fortran. use openacc implicit none diff --git a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-2.f b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-2.f index 0047a19..19ff4a5 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-2.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-2.f @@ -1,8 +1,4 @@ ! { dg-additional-options "-cpp" } -! TODO: Have to disable the acc_on_device builtin for we want to test -! the libgomp library function? The command line option -! '-fno-builtin-acc_on_device' is valid for C/C++/ObjC/ObjC++ but not -! for Fortran. USE OPENACC IMPLICIT NONE diff --git a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-3.f b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-3.f index 49d7a72..b01c553 100644 --- a/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-3.f +++ b/libgomp/testsuite/libgomp.oacc-fortran/acc_on_device-1-3.f @@ -1,8 +1,4 @@ ! { dg-additional-options "-cpp" } -! TODO: Have to disable the acc_on_device builtin for we want to test -! the libgomp library function? The command line option -! '-fno-builtin-acc_on_device' is valid for C/C++/ObjC/ObjC++ but not -! for Fortran. IMPLICIT NONE INCLUDE "openacc_lib.h" --- a/gcc/c/c-parser.c 2015-04-20 18:55:33.000000000 +0200 +++ b/gcc/c/c-parser.c 2015-05-23 11:32:41.664037866 +0200 @@ -13069,12 +13069,9 @@ } else { - /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES, - change it to shared (decl) in - OMP_PARALLEL_CLAUSES. */ - tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c), - OMP_CLAUSE_LASTPRIVATE); - OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c); + /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ + tree l = *c; + *c = OMP_CLAUSE_CHAIN (*c); if (code == OMP_SIMD) { OMP_CLAUSE_CHAIN (l) @@ -13086,7 +13083,6 @@ OMP_CLAUSE_CHAIN (l) = clauses; clauses = l; } - OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED); } } } @@ -13771,6 +13767,7 @@ TREE_TYPE (ret) = void_type_node; OMP_TEAMS_CLAUSES (ret) = clauses; OMP_TEAMS_BODY (ret) = block; + OMP_TEAMS_COMBINED (ret) = 1; return add_stmt (ret); } } --- a/gcc/calls.c 2015-04-07 23:02:12.000000000 +0200 +++ b/gcc/calls.c 2015-05-23 11:18:33.952634193 +0200 @@ -2099,6 +2099,26 @@ (XEXP (args[i].value, 0), size))) *sibcall_failure = 1; + if (size % UNITS_PER_WORD == 0 + || MEM_ALIGN (mem) % BITS_PER_WORD == 0) + move_block_to_reg (REGNO (reg), mem, nregs, args[i].mode); + else + { + if (nregs > 1) + move_block_to_reg (REGNO (reg), mem, nregs - 1, + args[i].mode); + rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1); + unsigned int bitoff = (nregs - 1) * BITS_PER_WORD; + unsigned int bitsize = size * BITS_PER_UNIT - bitoff; + rtx x = extract_bit_field (mem, bitsize, bitoff, 1, + dest, word_mode, word_mode); + if (BYTES_BIG_ENDIAN) + x = expand_shift (LSHIFT_EXPR, word_mode, x, + BITS_PER_WORD - bitsize, dest, 1); + if (x != dest) + emit_move_insn (dest, x); + } + /* Handle a BLKmode that needs shifting. */ if (nregs == 1 && size < UNITS_PER_WORD #ifdef BLOCK_REG_PADDING @@ -2106,22 +2126,18 @@ #else && BYTES_BIG_ENDIAN #endif - ) + ) { - rtx tem = operand_subword_force (mem, 0, args[i].mode); - rtx ri = gen_rtx_REG (word_mode, REGNO (reg)); - rtx x = gen_reg_rtx (word_mode); + rtx dest = gen_rtx_REG (word_mode, REGNO (reg)); int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT; - enum tree_code dir = BYTES_BIG_ENDIAN ? RSHIFT_EXPR - : LSHIFT_EXPR; + enum tree_code dir = (BYTES_BIG_ENDIAN + ? RSHIFT_EXPR : LSHIFT_EXPR); + rtx x; - emit_move_insn (x, tem); - x = expand_shift (dir, word_mode, x, shift, ri, 1); - if (x != ri) - emit_move_insn (ri, x); + x = expand_shift (dir, word_mode, dest, shift, dest, 1); + if (x != dest) + emit_move_insn (dest, x); } - else - move_block_to_reg (REGNO (reg), mem, nregs, args[i].mode); } /* When a parameter is a block, and perhaps in other cases, it is --- a/gcc/config/i386/i386.c 2015-04-17 23:55:05.000000000 +0200 +++ b/gcc/config/i386/i386.c 2015-05-23 11:27:55.981186322 +0200 @@ -2988,6 +2988,17 @@ return; } + if ((stringop_alg) i == rep_prefix_8_byte + && !TARGET_64BIT) + { + /* rep; movq isn't available in 32-bit code. */ + error ("stringop strategy name %s specified for option %s " + "not supported for 32-bit code", + alg_name, + is_memset ? "-mmemset_strategy=" : "-mmemcpy_strategy="); + return; + } + input_ranges[n].max = maxs; input_ranges[n].alg = (stringop_alg) i; if (!strcmp (align, "align")) @@ -5867,7 +5878,10 @@ /* Return 1 or 2, if we can pass up to SSE_REGPARM_MAX SFmode (1) and DFmode (2) arguments in SSE registers for a function with the indicated TYPE and DECL. DECL may be NULL when calling function - indirectly or considering a libcall. Otherwise return 0. */ + indirectly or considering a libcall. Return -1 if any FP parameter + should be rejected by error. This is used in siutation we imply SSE + calling convetion but the function is called from another function with + SSE disabled. Otherwise return 0. */ static int ix86_function_sseregparm (const_tree type, const_tree decl, bool warn) @@ -5916,14 +5930,13 @@ { /* Refuse to produce wrong code when local function with SSE enabled is called from SSE disabled function. - We may work hard to work out these scenarios but hopefully - it doesnot matter in practice. */ + FIXME: We need a way to detect these cases cross-ltrans partition + and avoid using SSE calling conventions on local functions called + from function with SSE disabled. For now at least delay the + warning until we know we are going to produce wrong code. + See PR66047 */ if (!TARGET_SSE && warn) - { - error ("calling %qD with SSE caling convention without " - "SSE/SSE2 enabled", decl); - return 0; - } + return -1; return TARGET_SSE2_P (target_opts_for_fn (target->decl) ->x_ix86_isa_flags) ? 2 : 1; } @@ -6479,6 +6492,7 @@ cum->bnd_regno = FIRST_BND_REG; cum->bnds_in_bt = 0; cum->force_bnd_pass = 0; + cum->decl = fndecl; if (!TARGET_64BIT) { @@ -7424,6 +7438,7 @@ HOST_WIDE_INT words) { int res = 0; + bool error_p = NULL; switch (mode) { @@ -7456,9 +7471,13 @@ gcc_unreachable (); case DFmode: + if (cum->float_in_sse == -1) + error_p = 1; if (cum->float_in_sse < 2) break; case SFmode: + if (cum->float_in_sse == -1) + error_p = 1; if (cum->float_in_sse < 1) break; /* FALLTHRU */ @@ -7514,6 +7533,14 @@ } break; } + if (error_p) + { + cum->float_in_sse = 0; + error ("calling %qD with SSE calling convention without " + "SSE/SSE2 enabled", cum->decl); + sorry ("this is a GCC bug that can be worked around by adding " + "attribute used to function called"); + } return res; } @@ -7646,10 +7673,11 @@ (otherwise it is an extra parameter matching an ellipsis). */ static rtx -function_arg_32 (const CUMULATIVE_ARGS *cum, machine_mode mode, +function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode, machine_mode orig_mode, const_tree type, HOST_WIDE_INT bytes, HOST_WIDE_INT words) { + bool error_p = false; /* Avoid the AL settings for the Unix64 ABI. */ if (mode == VOIDmode) return constm1_rtx; @@ -7690,9 +7718,13 @@ break; case DFmode: + if (cum->float_in_sse == -1) + error_p = 1; if (cum->float_in_sse < 2) break; case SFmode: + if (cum->float_in_sse == -1) + error_p = 1; if (cum->float_in_sse < 1) break; /* FALLTHRU */ @@ -7751,6 +7783,14 @@ } break; } + if (error_p) + { + cum->float_in_sse = 0; + error ("calling %qD with SSE calling convention without " + "SSE/SSE2 enabled", cum->decl); + sorry ("this is a GCC bug that can be worked around by adding " + "attribute used to function called"); + } return NULL_RTX; } @@ -8230,8 +8270,15 @@ if ((fn || fntype) && (mode == SFmode || mode == DFmode)) { int sse_level = ix86_function_sseregparm (fntype, fn, false); - if ((sse_level >= 1 && mode == SFmode) - || (sse_level == 2 && mode == DFmode)) + if (sse_level == -1) + { + error ("calling %qD with SSE caling convention without " + "SSE/SSE2 enabled", fn); + sorry ("this is a GCC bug that can be worked around by adding " + "attribute used to function called"); + } + else if ((sse_level >= 1 && mode == SFmode) + || (sse_level == 2 && mode == DFmode)) regno = FIRST_SSE_REG; } @@ -46892,15 +46939,16 @@ static bool expand_vec_perm_blend (struct expand_vec_perm_d *d) { - machine_mode vmode = d->vmode; + machine_mode mmode, vmode = d->vmode; unsigned i, mask, nelt = d->nelt; - rtx target, op0, op1, x; + rtx target, op0, op1, maskop, x; rtx rperm[32], vperm; if (d->one_operand_p) return false; if (TARGET_AVX512F && GET_MODE_SIZE (vmode) == 64 - && GET_MODE_SIZE (GET_MODE_INNER (vmode)) >= 4) + && (TARGET_AVX512BW + || GET_MODE_SIZE (GET_MODE_INNER (vmode)) >= 4)) ; else if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32) ; @@ -47074,8 +47122,33 @@ gcc_unreachable (); } + switch (vmode) + { + case V8DFmode: + case V8DImode: + mmode = QImode; + break; + case V16SFmode: + case V16SImode: + mmode = HImode; + break; + case V32HImode: + mmode = SImode; + break; + case V64QImode: + mmode = DImode; + break; + default: + mmode = VOIDmode; + } + + if (mmode != VOIDmode) + maskop = force_reg (mmode, gen_int_mode (mask, mmode)); + else + maskop = GEN_INT (mask); + /* This matches five different patterns with the different modes. */ - x = gen_rtx_VEC_MERGE (vmode, op1, op0, GEN_INT (mask)); + x = gen_rtx_VEC_MERGE (vmode, op1, op0, maskop); x = gen_rtx_SET (VOIDmode, target, x); emit_insn (x); if (target != d->target) @@ -51606,7 +51679,7 @@ for (i = 0; i < loop->num_nodes; i++) FOR_BB_INSNS (bbs[i], insn) if (NONDEBUG_INSN_P (insn)) - FOR_EACH_SUBRTX (iter, array, insn, NONCONST) + FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST) if (const_rtx x = *iter) if (MEM_P (x)) { --- a/gcc/config/i386/i386.h 2015-02-21 01:06:53.000000000 +0100 +++ b/gcc/config/i386/i386.h 2015-05-23 11:26:56.002281385 +0200 @@ -1682,6 +1682,7 @@ int stdarg; /* Set to 1 if function is stdarg. */ enum calling_abi call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise MS_ABI for ms abi. */ + tree decl; /* Callee decl. */ } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS --- a/gcc/config/i386/sse.md 2015-04-09 23:37:28.000000000 +0200 +++ b/gcc/config/i386/sse.md 2015-05-23 11:18:33.954634308 +0200 @@ -9523,7 +9523,7 @@ (mult:V4DI (sign_extend:V4DI (vec_select:V4SI - (match_operand:V8SI 1 "nonimmediate_operand" "v") + (match_operand:V8SI 1 "nonimmediate_operand" "%v") (parallel [(const_int 0) (const_int 2) (const_int 4) (const_int 6)]))) (sign_extend:V4DI --- a/gcc/cp/constexpr.c 2015-04-12 21:10:58.000000000 +0200 +++ b/gcc/cp/constexpr.c 2015-05-23 11:18:33.955634365 +0200 @@ -1355,7 +1355,14 @@ fun = DECL_CHAIN (fun)) if (DECL_SAVED_TREE (fun)) break; - gcc_assert (DECL_SAVED_TREE (fun)); + if (!DECL_SAVED_TREE (fun)) + { + /* cgraph/gimplification have released the DECL_SAVED_TREE + for this function. Fail gracefully. */ + gcc_assert (ctx->quiet); + *non_constant_p = true; + return t; + } tree parms, res; /* Unshare the whole function body. */ @@ -2603,14 +2610,29 @@ { constexpr_ctx new_ctx = *ctx; + tree init = TREE_OPERAND (t, 1); + /* First we figure out where we're storing to. */ tree target = TREE_OPERAND (t, 0); + tree type = TREE_TYPE (target); target = cxx_eval_constant_expression (ctx, target, true, non_constant_p, overflow_p); if (*non_constant_p) return t; + if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type) + && is_empty_class (type)) + { + /* For initialization of an empty base, the original target will be + *(base*)this, which the above evaluation resolves to the object + argument, which has the derived type rather than the base type. In + this situation, just evaluate the initializer and return, since + there's no actual data to store. */ + return cxx_eval_constant_expression (ctx, init, false, + non_constant_p, overflow_p); + } + /* And then find the underlying variable. */ vec *refs = make_tree_vector(); tree object = NULL_TREE; @@ -2647,7 +2669,7 @@ *non_constant_p = true; return t; } - tree type = TREE_TYPE (object); + type = TREE_TYPE (object); while (!refs->is_empty()) { if (*valp == NULL_TREE) @@ -2684,9 +2706,8 @@ new_ctx.object = target; } - tree init = cxx_eval_constant_expression (&new_ctx, TREE_OPERAND (t, 1), - false, - non_constant_p, overflow_p); + init = cxx_eval_constant_expression (&new_ctx, init, false, + non_constant_p, overflow_p); if (target == object) /* The hash table might have moved since the get earlier. */ ctx->values->put (object, init); --- a/gcc/cp/cvt.c 2015-01-09 21:18:42.000000000 +0100 +++ b/gcc/cp/cvt.c 2015-05-23 11:18:33.956634423 +0200 @@ -603,8 +603,20 @@ tree cp_fold_convert (tree type, tree expr) { - tree conv = fold_convert (type, expr); - conv = ignore_overflows (conv, expr); + tree conv; + if (TREE_TYPE (expr) == type) + conv = expr; + else if (TREE_CODE (expr) == PTRMEM_CST) + { + /* Avoid wrapping a PTRMEM_CST in NOP_EXPR. */ + conv = copy_node (expr); + TREE_TYPE (conv) = type; + } + else + { + conv = fold_convert (type, expr); + conv = ignore_overflows (conv, expr); + } return conv; } --- a/gcc/cp/decl2.c 2015-03-19 20:12:43.000000000 +0100 +++ b/gcc/cp/decl2.c 2015-05-23 11:24:52.397411028 +0200 @@ -1175,6 +1175,10 @@ && is_attribute_p ("omp declare simd", name)) return true; + /* An attribute pack is clearly dependent. */ + if (args && PACK_EXPANSION_P (args)) + return true; + /* If any of the arguments are dependent expressions, we can't evaluate the attribute until instantiation time. */ for (arg = args; arg; arg = TREE_CHAIN (arg)) --- a/gcc/cp/decl.c 2015-04-02 18:43:02.000000000 +0200 +++ b/gcc/cp/decl.c 2015-05-23 11:23:34.737303073 +0200 @@ -4825,8 +4825,11 @@ was_public = TREE_PUBLIC (decl); - /* Enter this declaration into the symbol table. */ - decl = maybe_push_decl (decl); + /* Enter this declaration into the symbol table. Don't push the plain + VAR_DECL for a variable template. */ + if (!template_parm_scope_p () + || TREE_CODE (decl) != VAR_DECL) + decl = maybe_push_decl (decl); if (processing_template_decl) decl = push_template_decl (decl); @@ -10628,7 +10631,7 @@ } else if (decl_context == FIELD) { - if (!staticp && TREE_CODE (type) != METHOD_TYPE + if (!staticp && !friendp && TREE_CODE (type) != METHOD_TYPE && type_uses_auto (type)) { error ("non-static data member declared %"); --- a/gcc/cp/lambda.c 2015-04-03 19:23:27.000000000 +0200 +++ b/gcc/cp/lambda.c 2015-05-23 11:18:33.958634538 +0200 @@ -787,7 +787,7 @@ /* In a lambda, need to go through 'this' capture. */ tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type); tree cap = lambda_expr_this_capture (lam, add_capture_p); - if (cap != error_mark_node) + if (cap && cap != error_mark_node) object = build_x_indirect_ref (EXPR_LOCATION (object), cap, RO_NULL, tf_warning_or_error); } --- a/gcc/cp/name-lookup.c 2015-04-01 23:27:55.000000000 +0200 +++ b/gcc/cp/name-lookup.c 2015-05-23 11:18:33.958634538 +0200 @@ -3408,7 +3408,7 @@ tf_warning_or_error); if (b_kind < bk_proper_base) { - if (!bases_dependent_p) + if (!bases_dependent_p || b_kind == bk_same_type) { error_not_base_type (scope, current_class_type); return NULL_TREE; --- a/gcc/cp/parser.c 2015-04-20 18:55:33.000000000 +0200 +++ b/gcc/cp/parser.c 2015-05-23 11:32:41.668037917 +0200 @@ -22500,6 +22500,13 @@ attributes = attribute; } token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_ELLIPSIS) + { + cp_lexer_consume_token (parser->lexer); + TREE_VALUE (attribute) + = make_pack_expansion (TREE_VALUE (attribute)); + token = cp_lexer_peek_token (parser->lexer); + } if (token->type != CPP_COMMA) break; cp_lexer_consume_token (parser->lexer); @@ -22578,20 +22585,27 @@ return alignas_expr; } + alignas_expr = cxx_alignas_expr (alignas_expr); + alignas_expr = build_tree_list (NULL_TREE, alignas_expr); + + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + cp_lexer_consume_token (parser->lexer); + alignas_expr = make_pack_expansion (alignas_expr); + } + if (cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN) == NULL) { cp_parser_error (parser, "expected %<)%>"); return error_mark_node; } - alignas_expr = cxx_alignas_expr (alignas_expr); - /* Build the C++-11 representation of an 'aligned' attribute. */ attributes = build_tree_list (build_tree_list (get_identifier ("gnu"), get_identifier ("aligned")), - build_tree_list (NULL_TREE, alignas_expr)); + alignas_expr); } return attributes; @@ -30466,11 +30480,9 @@ else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (*c) == real_decl) { - /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES, - change it to shared (decl) in OMP_PARALLEL_CLAUSES. */ - tree l = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE); - OMP_CLAUSE_DECL (l) = real_decl; - CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c); + /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */ + tree l = *c; + *c = OMP_CLAUSE_CHAIN (*c); if (code == OMP_SIMD) { OMP_CLAUSE_CHAIN (l) = cclauses[C_OMP_CLAUSE_SPLIT_FOR]; @@ -30481,8 +30493,6 @@ OMP_CLAUSE_CHAIN (l) = clauses; clauses = l; } - OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED); - CP_OMP_CLAUSE_INFO (*c) = NULL; add_private_clause = false; } else @@ -31316,6 +31326,7 @@ TREE_TYPE (ret) = void_type_node; OMP_TEAMS_CLAUSES (ret) = clauses; OMP_TEAMS_BODY (ret) = body; + OMP_TEAMS_COMBINED (ret) = 1; return add_stmt (ret); } } --- a/gcc/cp/pt.c 2015-04-01 23:27:55.000000000 +0200 +++ b/gcc/cp/pt.c 2015-05-23 11:27:30.146802454 +0200 @@ -1919,7 +1919,13 @@ ++header_count; if (variable_template_p (fns)) - templates = tree_cons (explicit_targs, fns, templates); + { + tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns)); + targs = coerce_template_parms (parms, explicit_targs, fns, + tf_warning_or_error, + /*req_all*/true, /*use_defarg*/true); + templates = tree_cons (targs, fns, templates); + } else for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -3338,9 +3344,9 @@ if (!arg || arg == error_mark_node) return arg; - if (TREE_CODE (arg) == TREE_LIST) + if (TREE_CODE (arg) == TREE_LIST && TREE_PURPOSE (arg)) { - /* The only time we will see a TREE_LIST here is for a base + /* A TREE_LIST with a non-null TREE_PURPOSE is for a base class initializer. In this case, the TREE_PURPOSE will be a _TYPE node (representing the base class expansion we're initializing) and the TREE_VALUE will be a TREE_LIST @@ -9065,6 +9071,21 @@ = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)), chain); } + else if (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t))) + { + /* An attribute pack expansion. */ + tree purp = TREE_PURPOSE (t); + tree pack = (tsubst_pack_expansion + (TREE_VALUE (t), args, complain, in_decl)); + int len = TREE_VEC_LENGTH (pack); + for (int i = 0; i < len; ++i) + { + tree elt = TREE_VEC_ELT (pack, i); + *q = build_tree_list (purp, elt); + q = &TREE_CHAIN (*q); + } + continue; + } else TREE_VALUE (t) = tsubst_expr (TREE_VALUE (t), args, complain, in_decl, @@ -11302,6 +11323,11 @@ tmpl = DECL_TI_TEMPLATE (t); gen_tmpl = most_general_template (tmpl); argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); + if (argvec != error_mark_node) + argvec = (coerce_innermost_template_parms + (DECL_TEMPLATE_PARMS (gen_tmpl), + argvec, t, complain, + /*all*/true, /*defarg*/true)); if (argvec == error_mark_node) RETURN (error_mark_node); hash = hash_tmpl_and_args (gen_tmpl, argvec); @@ -14249,7 +14275,7 @@ tmp = tsubst_omp_clauses (OMP_TARGET_UPDATE_CLAUSES (t), false, args, complain, in_decl); t = copy_node (t); - OMP_CLAUSES (t) = tmp; + OMP_TARGET_UPDATE_CLAUSES (t) = tmp; add_stmt (t); break; --- a/gcc/cp/tree.c 2015-04-09 22:11:44.000000000 +0200 +++ b/gcc/cp/tree.c 2015-05-23 11:27:15.316578155 +0200 @@ -1207,6 +1207,7 @@ { bool changed = false; vec *vec = make_tree_vector (); + tree r = t; for (; t; t = TREE_CHAIN (t)) { gcc_assert (!TREE_PURPOSE (t)); @@ -1215,7 +1216,6 @@ changed = true; vec_safe_push (vec, elt); } - tree r = t; if (changed) r = build_tree_list_vec (vec); release_tree_vector (vec); @@ -1350,7 +1350,7 @@ case DECLTYPE_TYPE: result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t)); if (result == DECLTYPE_TYPE_EXPR (t)) - return t; + result = NULL_TREE; else result = (finish_decltype_type (result, @@ -1424,8 +1424,8 @@ && type2 == TRAIT_EXPR_TYPE2 (t)) return t; r = copy_node (t); - TRAIT_EXPR_TYPE1 (t) = type1; - TRAIT_EXPR_TYPE2 (t) = type2; + TRAIT_EXPR_TYPE1 (r) = type1; + TRAIT_EXPR_TYPE2 (r) = type2; return r; } --- a/gcc/cp/typeck2.c 2015-01-23 17:30:00.000000000 +0100 +++ b/gcc/cp/typeck2.c 2015-05-23 11:24:32.144136275 +0200 @@ -957,9 +957,16 @@ } } else if (complain & tf_error) - error_at (EXPR_LOC_OR_LOC (init, input_location), - "narrowing conversion of %qE from %qT to %qT inside { }", - init, ftype, type); + { + int savederrorcount = errorcount; + global_dc->pedantic_errors = 1; + pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing, + "narrowing conversion of %qE from %qT to %qT " + "inside { }", init, ftype, type); + if (errorcount == savederrorcount) + ok = true; + global_dc->pedantic_errors = flag_pedantic_errors; + } } return cxx_dialect == cxx98 || ok; @@ -1089,6 +1096,19 @@ || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == COMPLEX_TYPE); + /* "If T is a class type and the initializer list has a single + element of type cv U, where U is T or a class derived from T, + the object is initialized from that element." */ + if (cxx_dialect >= cxx11 + && BRACE_ENCLOSED_INITIALIZER_P (init) + && CONSTRUCTOR_NELTS (init) == 1 + && (CLASS_TYPE_P (type) || VECTOR_TYPE_P (type))) + { + tree elt = CONSTRUCTOR_ELT (init, 0)->value; + if (reference_related_p (type, TREE_TYPE (elt))) + init = elt; + } + if (BRACE_ENCLOSED_INITIALIZER_P (init) && !TYPE_NON_AGGREGATE_CLASS (type)) return process_init_constructor (type, init, complain); --- a/gcc/fortran/check.c 2015-03-02 19:56:51.000000000 +0100 +++ b/gcc/fortran/check.c 2015-05-23 11:29:30.690530828 +0200 @@ -6213,6 +6213,15 @@ bool gfc_check_storage_size (gfc_expr *a, gfc_expr *kind) { + + if (a->expr_type == EXPR_NULL) + { + gfc_error ("Intrinsic function NULL at %L cannot be an actual " + "argument to STORAGE_SIZE, because it returns a " + "disassociated pointer", &a->where); + return false; + } + if (a->ts.type == BT_ASSUMED) { gfc_error ("%qs argument of %qs intrinsic at %L shall not be TYPE(*)", --- a/gcc/fortran/decl.c 2015-04-10 13:29:53.000000000 +0200 +++ b/gcc/fortran/decl.c 2015-05-23 11:30:42.240495466 +0200 @@ -1404,9 +1404,7 @@ } else if (init->expr_type == EXPR_ARRAY) { - gfc_constructor *c; - c = gfc_constructor_first (init->value.constructor); - clen = c->expr->value.character.length; + clen = mpz_get_si (init->ts.u.cl->length->value.integer); sym->ts.u.cl->length = gfc_get_int_expr (gfc_default_integer_kind, NULL, clen); @@ -5594,7 +5592,7 @@ "a contained subprogram"); break; default: - gfc_internal_error ("gfc_match_entry(): Bad state"); + gfc_error ("Unexpected ENTRY statement at %C"); } return MATCH_ERROR; } @@ -6970,7 +6968,8 @@ gfc_symbol *sym; match m; - if (gfc_current_ns->proc_name->attr.flavor != FL_MODULE) + if (!gfc_current_ns->proc_name + || gfc_current_ns->proc_name->attr.flavor != FL_MODULE) { gfc_error ("PROTECTED at %C only allowed in specification " "part of a module"); @@ -8512,6 +8511,11 @@ gfc_op2string (op)); break; + case INTERFACE_NAMELESS: + gfc_error ("Malformed GENERIC statement at %C"); + goto error; + break; + default: gcc_unreachable (); } --- a/gcc/fortran/expr.c 2015-02-06 19:15:01.000000000 +0100 +++ b/gcc/fortran/expr.c 2015-05-23 11:30:07.135026771 +0200 @@ -3118,19 +3118,22 @@ bad_proc = true; /* (ii) The assignment is in the main program; or */ - if (gfc_current_ns->proc_name->attr.is_main_program) + if (gfc_current_ns->proc_name + && gfc_current_ns->proc_name->attr.is_main_program) bad_proc = true; /* (iii) A module or internal procedure... */ - if ((gfc_current_ns->proc_name->attr.proc == PROC_INTERNAL - || gfc_current_ns->proc_name->attr.proc == PROC_MODULE) + if (gfc_current_ns->proc_name + && (gfc_current_ns->proc_name->attr.proc == PROC_INTERNAL + || gfc_current_ns->proc_name->attr.proc == PROC_MODULE) && gfc_current_ns->parent && (!(gfc_current_ns->parent->proc_name->attr.function || gfc_current_ns->parent->proc_name->attr.subroutine) || gfc_current_ns->parent->proc_name->attr.is_main_program)) { /* ... that is not a function... */ - if (!gfc_current_ns->proc_name->attr.function) + if (gfc_current_ns->proc_name + && !gfc_current_ns->proc_name->attr.function) bad_proc = true; /* ... or is not an entry and has a different name. */ --- a/gcc/fortran/interface.c 2015-02-01 01:29:54.000000000 +0100 +++ b/gcc/fortran/interface.c 2015-05-23 11:30:58.232706361 +0200 @@ -346,8 +346,12 @@ break; m = MATCH_ERROR; - gfc_error ("Expecting % at %C, " - "but got %s", s1, s2); + if (strcmp(s2, "none") == 0) + gfc_error ("Expecting % " + "at %C, ", s1); + else + gfc_error ("Expecting % at %C, " + "but got %s", s1, s2); } } --- a/gcc/fortran/io.c 2015-02-01 01:29:54.000000000 +0100 +++ b/gcc/fortran/io.c 2015-05-23 11:31:18.785975216 +0200 @@ -385,7 +385,7 @@ if (c == delim) { - c = next_char (INSTRING_NOWARN); + c = next_char (NONSTRING); if (c == '\0') { @@ -2382,9 +2382,7 @@ if (m == MATCH_NO) { m = gfc_match_expr (&fp->unit); - if (m == MATCH_ERROR) - goto done; - if (m == MATCH_NO) + if (m == MATCH_ERROR || m == MATCH_NO) goto syntax; } --- a/gcc/fortran/match.c 2015-01-15 21:11:12.000000000 +0100 +++ b/gcc/fortran/match.c 2015-05-23 11:30:58.232706361 +0200 @@ -110,6 +110,9 @@ case INTRINSIC_PARENTHESES: return "parens"; + case INTRINSIC_NONE: + return "none"; + default: break; } --- a/gcc/fortran/parse.c 2015-02-01 01:29:54.000000000 +0100 +++ b/gcc/fortran/parse.c 2015-05-23 11:29:15.011314175 +0200 @@ -2425,8 +2425,7 @@ break; default: - gfc_internal_error ("Unexpected %s statement in verify_st_order() at %C", - gfc_ascii_statement (st)); + return false; } /* All is well, record the statement in case we need it next time. */ --- a/gcc/fortran/scanner.c 2015-02-13 17:57:28.000000000 +0100 +++ b/gcc/fortran/scanner.c 2015-05-23 11:31:18.785975216 +0200 @@ -1272,21 +1272,11 @@ are still in a string and we are looking for a possible doubled quote and we end up here. See PR64506. */ - if (in_string) + if (in_string && c != '\n') { gfc_current_locus = old_loc; - - if (c == '!') - { - skip_comment_line (); - goto restart; - } - - if (c != '\n') - { - c = '&'; - goto done; - } + c = '&'; + goto done; } if (c != '!' && c != '\n') @@ -1392,6 +1382,8 @@ "Missing %<&%> in continued character " "constant at %C"); } + else if (!in_string && (c == '\'' || c == '"')) + goto done; /* Both !$omp and !$ -fopenmp continuation lines have & on the continuation line only optionally. */ else if (openmp_flag || openacc_flag || openmp_cond_flag) --- a/gcc/fortran/symbol.c 2015-04-10 13:29:53.000000000 +0200 +++ b/gcc/fortran/symbol.c 2015-05-23 11:28:41.895849323 +0200 @@ -458,6 +458,11 @@ } } + if (attr->dummy && ((attr->function || attr->subroutine) && + gfc_current_state () == COMP_CONTAINS)) + gfc_error_now ("internal procedure '%s' at %L conflicts with " + "DUMMY argument", name, where); + conf (dummy, entry); conf (dummy, intrinsic); conf (dummy, threadprivate); --- a/gcc/fortran/trans-openmp.c 2015-03-30 19:54:05.000000000 +0200 +++ b/gcc/fortran/trans-openmp.c 2015-05-23 11:32:41.669037929 +0200 @@ -4114,6 +4114,7 @@ stmtblock_t block; gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; tree stmt, omp_clauses = NULL_TREE; + bool combined = true; gfc_start_block (&block); if (clausesa == NULL) @@ -4130,6 +4131,7 @@ case EXEC_OMP_TARGET_TEAMS: case EXEC_OMP_TEAMS: stmt = gfc_trans_omp_code (code->block->next, true); + combined = false; break; case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: case EXEC_OMP_TEAMS_DISTRIBUTE: @@ -4143,6 +4145,8 @@ } stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt, omp_clauses); + if (combined) + OMP_TEAMS_COMBINED (stmt) = 1; gfc_add_expr_to_block (&block, stmt); return gfc_finish_block (&block); } @@ -4163,9 +4167,14 @@ if (code->op == EXEC_OMP_TARGET) stmt = gfc_trans_omp_code (code->block->next, true); else - stmt = gfc_trans_omp_teams (code, clausesa); - if (TREE_CODE (stmt) != BIND_EXPR) - stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE); + { + pushlevel (); + stmt = gfc_trans_omp_teams (code, clausesa); + if (TREE_CODE (stmt) != BIND_EXPR) + stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); + else + poplevel (0, 0); + } if (flag_openmp) stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt, omp_clauses); --- a/gcc/gimplify.c 2015-03-20 13:39:32.000000000 +0100 +++ b/gcc/gimplify.c 2015-05-23 11:32:41.671037954 +0200 @@ -111,6 +111,9 @@ /* Flag for GOVD_MAP: don't copy back. */ GOVD_MAP_TO_ONLY = 8192, + /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */ + GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 16384, + GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR | GOVD_LOCAL) @@ -126,6 +129,7 @@ ORT_TASK = 4, ORT_UNTIED_TASK = 5, ORT_TEAMS = 8, + ORT_COMBINED_TEAMS = 9, /* Data region. */ ORT_TARGET_DATA = 16, /* Data region with offloading. */ @@ -5842,7 +5846,7 @@ DECL_NAME (lang_hooks.decls.omp_report_decl (decl))); error_at (ctx->location, "enclosing task"); } - else if (ctx->region_type == ORT_TEAMS) + else if (ctx->region_type & ORT_TEAMS) { error ("%qE not specified in enclosing teams construct", DECL_NAME (lang_hooks.decls.omp_report_decl (decl))); @@ -5935,6 +5939,13 @@ need to propagate anything to an outer context. */ if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF)) return ret; + if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER)) + == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER)) + return ret; + if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE + | GOVD_LINEAR_LASTPRIVATE_NO_OUTER)) + == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER)) + return ret; if (ctx->outer_context && omp_notice_variable (ctx->outer_context, decl, in_code)) return true; @@ -6034,6 +6045,36 @@ return false; } +/* Return true if the CTX is combined with distribute and thus + lastprivate can't be supported. */ + +static bool +omp_no_lastprivate (struct gimplify_omp_ctx *ctx) +{ + do + { + if (ctx->outer_context == NULL) + return false; + ctx = ctx->outer_context; + switch (ctx->region_type) + { + case ORT_WORKSHARE: + if (!ctx->combined_loop) + return false; + if (ctx->distribute) + return true; + break; + case ORT_COMBINED_PARALLEL: + break; + case ORT_COMBINED_TEAMS: + return true; + default: + return false; + } + } + while (1); +} + /* Scan the OMP clauses in *LIST_P, installing mappings into a new and previous omp contexts. */ @@ -6077,6 +6118,35 @@ case OMP_CLAUSE_LASTPRIVATE: flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT; check_non_private = "lastprivate"; + decl = OMP_CLAUSE_DECL (c); + if (omp_no_lastprivate (ctx)) + { + notice_outer = false; + flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER; + } + else if (error_operand_p (decl)) + goto do_add; + else if (outer_ctx + && outer_ctx->region_type == ORT_COMBINED_PARALLEL + && splay_tree_lookup (outer_ctx->variables, + (splay_tree_key) decl) == NULL) + omp_add_variable (outer_ctx, decl, GOVD_SHARED | GOVD_SEEN); + else if (outer_ctx + && outer_ctx->region_type == ORT_WORKSHARE + && outer_ctx->combined_loop + && splay_tree_lookup (outer_ctx->variables, + (splay_tree_key) decl) == NULL + && !omp_check_private (outer_ctx, decl, false)) + { + omp_add_variable (outer_ctx, decl, GOVD_LASTPRIVATE | GOVD_SEEN); + if (outer_ctx->outer_context + && (outer_ctx->outer_context->region_type + == ORT_COMBINED_PARALLEL) + && splay_tree_lookup (outer_ctx->outer_context->variables, + (splay_tree_key) decl) == NULL) + omp_add_variable (outer_ctx->outer_context, decl, + GOVD_SHARED | GOVD_SEEN); + } goto do_add; case OMP_CLAUSE_REDUCTION: flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT; @@ -6089,7 +6159,68 @@ remove = true; break; } + else + { + /* For combined #pragma omp parallel for simd, need to put + lastprivate and perhaps firstprivate too on the + parallel. Similarly for #pragma omp for simd. */ + struct gimplify_omp_ctx *octx = outer_ctx; + decl = NULL_TREE; + if (omp_no_lastprivate (ctx)) + OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1; + do + { + if (OMP_CLAUSE_LINEAR_NO_COPYIN (c) + && OMP_CLAUSE_LINEAR_NO_COPYOUT (c)) + break; + decl = OMP_CLAUSE_DECL (c); + if (error_operand_p (decl)) + { + decl = NULL_TREE; + break; + } + if (octx + && octx->region_type == ORT_WORKSHARE + && octx->combined_loop) + { + if (octx->outer_context + && (octx->outer_context->region_type + == ORT_COMBINED_PARALLEL + || (octx->outer_context->region_type + == ORT_COMBINED_TEAMS))) + octx = octx->outer_context; + else if (omp_check_private (octx, decl, false)) + break; + } + else + break; + gcc_checking_assert (splay_tree_lookup (octx->variables, + (splay_tree_key) + decl) == NULL); + flags = GOVD_SEEN; + if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)) + flags |= GOVD_FIRSTPRIVATE; + if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c)) + flags |= GOVD_LASTPRIVATE; + omp_add_variable (octx, decl, flags); + if (octx->outer_context == NULL) + break; + octx = octx->outer_context; + } + while (1); + if (octx + && decl + && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c) + || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))) + omp_notice_variable (octx, decl, true); + } flags = GOVD_LINEAR | GOVD_EXPLICIT; + if (OMP_CLAUSE_LINEAR_NO_COPYIN (c) + && OMP_CLAUSE_LINEAR_NO_COPYOUT (c)) + { + notice_outer = false; + flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER; + } goto do_add; case OMP_CLAUSE_MAP: @@ -6543,34 +6674,6 @@ OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE); OMP_CLAUSE_PRIVATE_DEBUG (c) = 1; } - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR - && ctx->outer_context - && !(OMP_CLAUSE_LINEAR_NO_COPYIN (c) - && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))) - { - if (ctx->outer_context->combined_loop - && !OMP_CLAUSE_LINEAR_NO_COPYIN (c)) - { - n = splay_tree_lookup (ctx->outer_context->variables, - (splay_tree_key) decl); - if (n == NULL - || (n->value & GOVD_DATA_SHARE_CLASS) == 0) - { - int flags = GOVD_FIRSTPRIVATE; - /* #pragma omp distribute does not allow - lastprivate clause. */ - if (!ctx->outer_context->distribute) - flags |= GOVD_LASTPRIVATE; - if (n == NULL) - omp_add_variable (ctx->outer_context, decl, - flags | GOVD_SEEN); - else - n->value |= flags | GOVD_SEEN; - } - } - else if (!is_global_var (decl)) - omp_notice_variable (ctx->outer_context, decl, true); - } } break; @@ -6581,6 +6684,13 @@ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = (n->value & GOVD_FIRSTPRIVATE) != 0; + if (omp_no_lastprivate (ctx)) + { + if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) + remove = true; + else + OMP_CLAUSE_CODE (c) = OMP_CLAUSE_PRIVATE; + } break; case OMP_CLAUSE_ALIGNED: @@ -6895,6 +7005,22 @@ gcc_unreachable (); } + /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear + clause for the IV. */ + if (simd && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) + { + t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0); + gcc_assert (TREE_CODE (t) == MODIFY_EXPR); + decl = TREE_OPERAND (t, 0); + for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && OMP_CLAUSE_DECL (c) == decl) + { + OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1; + break; + } + } + gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, simd ? ORT_SIMD : ORT_WORKSHARE); if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE) @@ -6969,38 +7095,67 @@ { c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1; - if (has_decl_expr - && bitmap_bit_p (has_decl_expr, DECL_UID (decl))) - OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1; + unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN; + if ((has_decl_expr + && bitmap_bit_p (has_decl_expr, DECL_UID (decl))) + || omp_no_lastprivate (gimplify_omp_ctxp)) + { + OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1; + flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER; + } OMP_CLAUSE_DECL (c) = decl; OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt); OMP_FOR_CLAUSES (for_stmt) = c; - omp_add_variable (gimplify_omp_ctxp, decl, - GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN); + + omp_add_variable (gimplify_omp_ctxp, decl, flags); + struct gimplify_omp_ctx *outer + = gimplify_omp_ctxp->outer_context; + if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)) + { + if (outer->region_type == ORT_WORKSHARE + && outer->combined_loop) + { + if (outer->outer_context + && (outer->outer_context->region_type + == ORT_COMBINED_PARALLEL)) + outer = outer->outer_context; + else if (omp_check_private (outer, decl, false)) + outer = NULL; + } + else if (outer->region_type != ORT_COMBINED_PARALLEL) + outer = NULL; + if (outer) + { + omp_add_variable (outer, decl, + GOVD_LASTPRIVATE | GOVD_SEEN); + if (outer->outer_context) + omp_notice_variable (outer->outer_context, decl, true); + } + } } else { bool lastprivate = (!has_decl_expr - || !bitmap_bit_p (has_decl_expr, DECL_UID (decl))); - if (lastprivate - && gimplify_omp_ctxp->outer_context - && gimplify_omp_ctxp->outer_context->region_type - == ORT_WORKSHARE - && gimplify_omp_ctxp->outer_context->combined_loop - && !gimplify_omp_ctxp->outer_context->distribute) + || !bitmap_bit_p (has_decl_expr, DECL_UID (decl))) + && !omp_no_lastprivate (gimplify_omp_ctxp); + struct gimplify_omp_ctx *outer + = gimplify_omp_ctxp->outer_context; + if (outer && lastprivate) { - struct gimplify_omp_ctx *outer - = gimplify_omp_ctxp->outer_context; - n = splay_tree_lookup (outer->variables, - (splay_tree_key) decl); - if (n != NULL - && (n->value & GOVD_DATA_SHARE_CLASS) == GOVD_LOCAL) - lastprivate = false; - else if (omp_check_private (outer, decl, false)) - error ("lastprivate variable %qE is private in outer " - "context", DECL_NAME (decl)); - else + if (outer->region_type == ORT_WORKSHARE + && outer->combined_loop) + { + if (outer->outer_context + && (outer->outer_context->region_type + == ORT_COMBINED_PARALLEL)) + outer = outer->outer_context; + else if (omp_check_private (outer, decl, false)) + outer = NULL; + } + else if (outer->region_type != ORT_COMBINED_PARALLEL) + outer = NULL; + if (outer) { omp_add_variable (outer, decl, GOVD_LASTPRIVATE | GOVD_SEEN); @@ -7008,6 +7163,7 @@ omp_notice_variable (outer->outer_context, decl, true); } } + c = build_omp_clause (input_location, lastprivate ? OMP_CLAUSE_LASTPRIVATE : OMP_CLAUSE_PRIVATE); @@ -7299,7 +7455,7 @@ ort = ORT_TARGET_DATA; break; case OMP_TEAMS: - ort = ORT_TEAMS; + ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS; break; default: gcc_unreachable (); --- a/gcc/ipa-chkp.c 2015-04-06 12:41:55.000000000 +0200 +++ b/gcc/ipa-chkp.c 2015-05-23 11:31:36.800208969 +0200 @@ -264,7 +264,7 @@ if (!arg_type) return orig_type; - type = copy_node (orig_type); + type = build_distinct_type_copy (orig_type); TYPE_ARG_TYPES (type) = copy_list (TYPE_ARG_TYPES (type)); for (arg_type = TYPE_ARG_TYPES (type); --- a/gcc/ipa-inline.c 2015-04-03 20:09:13.000000000 +0200 +++ b/gcc/ipa-inline.c 2015-05-23 11:26:42.303067491 +0200 @@ -427,49 +427,55 @@ && lookup_attribute ("always_inline", DECL_ATTRIBUTES (callee->decl))); + /* Until GCC 4.9 we did not check the semantics alterning flags + bellow and inline across optimization boundry. + Enabling checks bellow breaks several packages by refusing + to inline library always_inline functions. See PR65873. + Disable the check for early inlining for now until better solution + is found. */ + if (always_inline && early) + ; /* There are some options that change IL semantics which means we cannot inline in these cases for correctness reason. Not even for always_inline declared functions. */ /* Strictly speaking only when the callee contains signed integer math where overflow is undefined. */ - if ((check_maybe_up (flag_strict_overflow) - /* this flag is set by optimize. Allow inlining across - optimize boundary. */ - && (!opt_for_fn (caller->decl, optimize) - == !opt_for_fn (callee->decl, optimize) || !always_inline)) - || check_match (flag_wrapv) - || check_match (flag_trapv) - /* Strictly speaking only when the callee contains memory - accesses that are not using alias-set zero anyway. */ - || check_maybe_down (flag_strict_aliasing) - /* Strictly speaking only when the callee uses FP math. */ - || check_maybe_up (flag_rounding_math) - || check_maybe_up (flag_trapping_math) - || check_maybe_down (flag_unsafe_math_optimizations) - || check_maybe_down (flag_finite_math_only) - || check_maybe_up (flag_signaling_nans) - || check_maybe_down (flag_cx_limited_range) - || check_maybe_up (flag_signed_zeros) - || check_maybe_down (flag_associative_math) - || check_maybe_down (flag_reciprocal_math) - /* We do not want to make code compiled with exceptions to be brought - into a non-EH function unless we know that the callee does not - throw. This is tracked by DECL_FUNCTION_PERSONALITY. */ - || (check_match (flag_non_call_exceptions) - /* TODO: We also may allow bringing !flag_non_call_exceptions - to flag_non_call_exceptions function, but that may need - extra work in tree-inline to add the extra EH edges. */ - && (!opt_for_fn (callee->decl, flag_non_call_exceptions) - || DECL_FUNCTION_PERSONALITY (callee->decl))) - || (check_maybe_up (flag_exceptions) - && DECL_FUNCTION_PERSONALITY (callee->decl)) - /* Strictly speaking only when the callee contains function - calls that may end up setting errno. */ - || check_maybe_up (flag_errno_math) - /* When devirtualization is diabled for callee, it is not safe - to inline it as we possibly mangled the type info. - Allow early inlining of always inlines. */ - || (!early && check_maybe_down (flag_devirtualize))) + else if ((check_maybe_up (flag_strict_overflow) + /* this flag is set by optimize. Allow inlining across + optimize boundary. */ + && (!opt_for_fn (caller->decl, optimize) + == !opt_for_fn (callee->decl, optimize) || !always_inline)) + || check_match (flag_wrapv) + || check_match (flag_trapv) + /* Strictly speaking only when the callee uses FP math. */ + || check_maybe_up (flag_rounding_math) + || check_maybe_up (flag_trapping_math) + || check_maybe_down (flag_unsafe_math_optimizations) + || check_maybe_down (flag_finite_math_only) + || check_maybe_up (flag_signaling_nans) + || check_maybe_down (flag_cx_limited_range) + || check_maybe_up (flag_signed_zeros) + || check_maybe_down (flag_associative_math) + || check_maybe_down (flag_reciprocal_math) + /* We do not want to make code compiled with exceptions to be + brought into a non-EH function unless we know that the callee + does not throw. + This is tracked by DECL_FUNCTION_PERSONALITY. */ + || (check_match (flag_non_call_exceptions) + /* TODO: We also may allow bringing !flag_non_call_exceptions + to flag_non_call_exceptions function, but that may need + extra work in tree-inline to add the extra EH edges. */ + && (!opt_for_fn (callee->decl, flag_non_call_exceptions) + || DECL_FUNCTION_PERSONALITY (callee->decl))) + || (check_maybe_up (flag_exceptions) + && DECL_FUNCTION_PERSONALITY (callee->decl)) + /* Strictly speaking only when the callee contains function + calls that may end up setting errno. */ + || check_maybe_up (flag_errno_math) + /* When devirtualization is diabled for callee, it is not safe + to inline it as we possibly mangled the type info. + Allow early inlining of always inlines. */ + || (!early && check_maybe_down (flag_devirtualize))) { e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false; @@ -484,6 +490,17 @@ e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false; } + /* If explicit optimize attribute are not used, the mismatch is caused + by different command line options used to build different units. + Do not care about COMDAT functions - those are intended to be + optimized with the optimization flags of module they are used in. + Also do not care about mixing up size/speed optimization when + DECL_DISREGARD_INLINE_LIMITS is set. */ + else if ((callee->merged + && !lookup_attribute ("optimize", + DECL_ATTRIBUTES (caller->decl))) + || DECL_DISREGARD_INLINE_LIMITS (callee->decl)) + ; /* If mismatch is caused by merging two LTO units with different optimizationflags we want to be bit nicer. However never inline if one of functions is not optimized at all. */ @@ -515,7 +532,7 @@ else if (opt_for_fn (callee->decl, optimize_size) < opt_for_fn (caller->decl, optimize_size) || (opt_for_fn (callee->decl, optimize) - >= opt_for_fn (caller->decl, optimize))) + > opt_for_fn (caller->decl, optimize))) { if (estimate_edge_time (e) >= 20 + inline_edge_summary (e)->call_stmt_time) --- a/gcc/lra-constraints.c 2015-04-10 18:05:26.000000000 +0200 +++ b/gcc/lra-constraints.c 2015-05-23 11:18:33.964634884 +0200 @@ -533,7 +533,7 @@ if (x == res || CONSTANT_P (res)) return res; return lra_eliminate_regs_1 (insn, res, GET_MODE (res), - 0, false, false, true); + false, false, 0, true); } /* Set up curr_operand_mode. */ --- a/gcc/lra-eliminations.c 2015-02-04 21:02:21.000000000 +0100 +++ b/gcc/lra-eliminations.c 2015-05-23 11:18:33.965634942 +0200 @@ -318,7 +318,9 @@ substitution if UPDATE_P, or the full offset if FULL_P, or otherwise zero. If FULL_P, we also use the SP offsets for elimination to SP. If UPDATE_P, use UPDATE_SP_OFFSET for updating - offsets of register elimnable to SP. + offsets of register elimnable to SP. If UPDATE_SP_OFFSET is + non-zero, don't use difference of the offset and the previous + offset. MEM_MODE is the mode of an enclosing MEM. We need this to know how much to adjust a register for, e.g., PRE_DEC. Also, if we are @@ -341,7 +343,8 @@ const char *fmt; int copied = 0; - gcc_assert (!update_p || !full_p); + lra_assert (!update_p || !full_p); + lra_assert (update_sp_offset == 0 || (!subst_p && update_p && !full_p)); if (! current_function_decl) return x; @@ -366,11 +369,14 @@ { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (update_p) - return plus_constant (Pmode, to, - ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0)); + if (update_sp_offset != 0) + { + if (ep->to_rtx == stack_pointer_rtx) + return plus_constant (Pmode, to, update_sp_offset); + return to; + } + else if (update_p) + return plus_constant (Pmode, to, ep->offset - ep->previous_offset); else if (full_p) return plus_constant (Pmode, to, ep->offset @@ -395,16 +401,15 @@ if (! update_p && ! full_p) return gen_rtx_PLUS (Pmode, to, XEXP (x, 1)); - - offset = (update_p - ? ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0) - : ep->offset); + + if (update_sp_offset != 0) + offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0; + else + offset = (update_p + ? ep->offset - ep->previous_offset : ep->offset); if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx) offset -= lra_get_insn_recog_data (insn)->sp_offset; - if (CONST_INT_P (XEXP (x, 1)) - && INTVAL (XEXP (x, 1)) == -offset) + if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset) return to; else return gen_rtx_PLUS (Pmode, to, @@ -451,12 +456,18 @@ { rtx to = subst_p ? ep->to_rtx : ep->from_rtx; - if (update_p) + if (update_sp_offset != 0) + { + if (ep->to_rtx == stack_pointer_rtx) + return plus_constant (Pmode, + gen_rtx_MULT (Pmode, to, XEXP (x, 1)), + update_sp_offset * INTVAL (XEXP (x, 1))); + return gen_rtx_MULT (Pmode, to, XEXP (x, 1)); + } + else if (update_p) return plus_constant (Pmode, gen_rtx_MULT (Pmode, to, XEXP (x, 1)), - (ep->offset - ep->previous_offset - + (ep->to_rtx == stack_pointer_rtx - ? update_sp_offset : 0)) + (ep->offset - ep->previous_offset) * INTVAL (XEXP (x, 1))); else if (full_p) { @@ -889,11 +900,12 @@ If REPLACE_P is false, just update the offsets while keeping the base register the same. If FIRST_P, use the sp offset for - elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this. - Attach the note about used elimination for insns setting frame - pointer to update elimination easy (without parsing already - generated elimination insns to find offset previously used) in - future. */ + elimination to sp. Otherwise, use UPDATE_SP_OFFSET for this. If + UPDATE_SP_OFFSET is non-zero, don't use difference of the offset + and the previous offset. Attach the note about used elimination + for insns setting frame pointer to update elimination easy (without + parsing already generated elimination insns to find offset + previously used) in future. */ void eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p, @@ -940,6 +952,10 @@ rtx src = SET_SRC (old_set); rtx off = remove_reg_equal_offset_note (insn, ep->to_rtx); + /* We should never process such insn with non-zero + UPDATE_SP_OFFSET. */ + lra_assert (update_sp_offset == 0); + if (off != NULL_RTX || src == ep->to_rtx || (GET_CODE (src) == PLUS @@ -1026,7 +1042,8 @@ if (! replace_p) { - offset += (ep->offset - ep->previous_offset); + if (update_sp_offset == 0) + offset += (ep->offset - ep->previous_offset); if (ep->to_rtx == stack_pointer_rtx) { if (first_p) --- a/gcc/lra-spills.c 2015-01-15 14:28:42.000000000 +0100 +++ b/gcc/lra-spills.c 2015-05-23 11:18:33.965634942 +0200 @@ -461,7 +461,7 @@ { rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem, GET_MODE (pseudo_slots[i].mem), - 0, false, false, true); + false, false, 0, true); *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x); } return; --- a/gcc/lto-wrapper.c 2015-01-30 17:15:00.000000000 +0100 +++ b/gcc/lto-wrapper.c 2015-05-23 11:21:27.938957086 +0200 @@ -934,7 +934,7 @@ filename[p - argv[i]] = '\0'; file_offset = (off_t) loffset; } - fd = open (argv[i], O_RDONLY); + fd = open (filename, O_RDONLY | O_BINARY); if (fd == -1) { lto_argv[lto_argc++] = argv[i]; --- a/gcc/match.pd 2015-02-13 21:17:55.000000000 +0100 +++ b/gcc/match.pd 2015-05-23 11:33:11.742416376 +0200 @@ -702,16 +702,12 @@ (for integers). Avoid this if the final type is a pointer since then we sometimes need the middle conversion. Likewise if the final type has a precision not equal to the size of its mode. */ - (if (((inter_int && inside_int) - || (inter_float && inside_float) - || (inter_vec && inside_vec)) + (if (((inter_int && inside_int) || (inter_float && inside_float)) + && (final_int || final_float) && inter_prec >= inside_prec - && (inter_float || inter_vec - || inter_unsignedp == inside_unsignedp) - && ! (final_prec != GET_MODE_PRECISION (element_mode (type)) - && element_mode (type) == element_mode (inter_type)) - && ! final_ptr - && (! final_vec || inter_prec == inside_prec)) + && (inter_float || inter_unsignedp == inside_unsignedp) + && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type)) + && TYPE_MODE (type) == TYPE_MODE (inter_type))) (ocvt @0)) /* If we have a sign-extension of a zero-extended value, we can --- a/gcc/omp-low.c 2015-04-03 15:35:49.000000000 +0200 +++ b/gcc/omp-low.c 2015-05-23 11:32:41.672037967 +0200 @@ -5377,7 +5377,10 @@ child_cfun = DECL_STRUCT_FUNCTION (child_fn); entry_bb = region->entry; - exit_bb = region->exit; + if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK) + exit_bb = region->cont; + else + exit_bb = region->exit; bool is_cilk_for = (flag_cilkplus @@ -5436,7 +5439,9 @@ variable. In which case, we need to keep the assignment. */ if (gimple_omp_taskreg_data_arg (entry_stmt)) { - basic_block entry_succ_bb = single_succ (entry_bb); + basic_block entry_succ_bb + = single_succ_p (entry_bb) ? single_succ (entry_bb) + : FALLTHRU_EDGE (entry_bb)->dest; tree arg, narg; gimple parcopy_stmt = NULL; @@ -5524,14 +5529,28 @@ e = split_block (entry_bb, stmt); gsi_remove (&gsi, true); entry_bb = e->dest; - single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; + edge e2 = NULL; + if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL) + single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; + else + { + e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL); + gcc_assert (e2->dest == region->exit); + remove_edge (BRANCH_EDGE (entry_bb)); + set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src); + gsi = gsi_last_bb (region->exit); + gcc_assert (!gsi_end_p (gsi) + && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); + gsi_remove (&gsi, true); + } - /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */ + /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */ if (exit_bb) { gsi = gsi_last_bb (exit_bb); gcc_assert (!gsi_end_p (gsi) - && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); + && (gimple_code (gsi_stmt (gsi)) + == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN))); stmt = gimple_build_return (NULL); gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); gsi_remove (&gsi, true); @@ -5552,6 +5571,14 @@ new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block); if (exit_bb) single_succ_edge (new_bb)->flags = EDGE_FALLTHRU; + if (e2) + { + basic_block dest_bb = e2->dest; + if (!exit_bb) + make_edge (new_bb, dest_bb, EDGE_FALLTHRU); + remove_edge (e2); + set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb); + } /* When the OMP expansion process cannot guarantee an up-to-date loop tree arrange for the child function to fixup loops. */ if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) @@ -10511,7 +10538,21 @@ cond_code = EQ_EXPR; } - cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2); + tree n2 = fd->loop.n2; + if (fd->collapse > 1 + && TREE_CODE (n2) != INTEGER_CST + && gimple_omp_for_combined_into_p (fd->for_stmt) + && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR) + { + gomp_for *gfor = as_a (ctx->outer->stmt); + if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR) + { + struct omp_for_data outer_fd; + extract_omp_for_data (gfor, &outer_fd, NULL); + n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2); + } + } + cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2); clauses = gimple_omp_for_clauses (fd->for_stmt); stmts = NULL; @@ -11158,6 +11199,10 @@ gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label)); gimple_seq_add_seq (&new_body, par_olist); new_body = maybe_catch_exception (new_body); + if (gimple_code (stmt) == GIMPLE_OMP_TASK) + gimple_seq_add_stmt (&new_body, + gimple_build_omp_continue (integer_zero_node, + integer_zero_node)); gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false)); gimple_omp_set_body (stmt, new_body); @@ -12272,6 +12317,10 @@ somewhere other than the next block. This will be created later. */ cur_region->exit = bb; + if (cur_region->type == GIMPLE_OMP_TASK) + /* Add an edge corresponding to not scheduling the task + immediately. */ + make_edge (cur_region->entry, bb, EDGE_ABNORMAL); fallthru = cur_region->type != GIMPLE_OMP_SECTION; cur_region = cur_region->outer; break; @@ -12320,6 +12369,10 @@ } break; + case GIMPLE_OMP_TASK: + fallthru = true; + break; + default: gcc_unreachable (); } --- a/gcc/tree.h 2015-04-08 20:41:55.000000000 +0200 +++ b/gcc/tree.h 2015-05-23 11:32:41.673037980 +0200 @@ -1320,6 +1320,11 @@ #define OMP_PARALLEL_COMBINED(NODE) \ (OMP_PARALLEL_CHECK (NODE)->base.private_flag) +/* True on an OMP_TEAMS statement if it represents an explicit + combined teams distribute constructs. */ +#define OMP_TEAMS_COMBINED(NODE) \ + (OMP_TEAMS_CHECK (NODE)->base.private_flag) + /* True if OMP_ATOMIC* is supposed to be sequentially consistent as opposed to relaxed. */ #define OMP_ATOMIC_SEQ_CST(NODE) \ --- a/gcc/tree-vrp.c 2015-02-17 16:32:05.000000000 +0100 +++ b/gcc/tree-vrp.c 2015-05-23 11:18:33.967635057 +0200 @@ -874,13 +874,18 @@ if (is_new) { /* Do not allow transitions up the lattice. The following - is slightly more awkward than just new_vr->type < old_vr->type + is slightly more awkward than just new_vr->type < old_vr->type because VR_RANGE and VR_ANTI_RANGE need to be considered the same. We may not have is_new when transitioning to - UNDEFINED or from VARYING. */ - if (new_vr->type == VR_UNDEFINED - || old_vr->type == VR_VARYING) - set_value_range_to_varying (old_vr); + UNDEFINED. If old_vr->type is VARYING, we shouldn't be + called. */ + if (new_vr->type == VR_UNDEFINED) + { + BITMAP_FREE (new_vr->equiv); + set_value_range_to_varying (old_vr); + set_value_range_to_varying (new_vr); + return true; + } else set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max, new_vr->equiv); @@ -8949,6 +8954,9 @@ fprintf (dump_file, "\n"); } + if (vr_result.type == VR_VARYING) + return SSA_PROP_VARYING; + return SSA_PROP_INTERESTING; } --- a/gcc/ubsan.c 2015-04-09 21:51:08.000000000 +0200 +++ b/gcc/ubsan.c 2015-05-23 11:22:23.302098186 +0200 @@ -87,6 +87,7 @@ #include "builtins.h" #include "tree-object-size.h" #include "tree-eh.h" +#include "tree-cfg.h" /* Map from a tree to a VAR_DECL tree. */ @@ -1420,7 +1421,7 @@ || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME) return; - bool can_throw = stmt_could_throw_p (stmt); + bool ends_bb = stmt_ends_bb_p (stmt); location_t loc = gimple_location (stmt); tree lhs = gimple_assign_lhs (stmt); tree ptype = build_pointer_type (TREE_TYPE (rhs)); @@ -1432,7 +1433,7 @@ tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g), build_int_cst (atype, 0)); tree urhs = make_ssa_name (utype); - if (can_throw) + if (ends_bb) { gimple_assign_set_lhs (stmt, urhs); g = gimple_build_assign (lhs, NOP_EXPR, urhs); @@ -1469,7 +1470,7 @@ gimple_set_location (g, loc); gsi_insert_after (gsi, g, GSI_NEW_STMT); - if (!can_throw) + if (!ends_bb) { gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs); update_stmt (stmt); --- a/libstdc++-v3/include/debug/vector 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/debug/vector 2015-05-23 11:18:33.967635057 +0200 @@ -69,13 +69,17 @@ _Safe_vector& operator=(const _Safe_vector&) noexcept - { _M_update_guaranteed_capacity(); } + { + _M_update_guaranteed_capacity(); + return *this; + } _Safe_vector& operator=(_Safe_vector&& __x) noexcept { _M_update_guaranteed_capacity(); __x._M_guaranteed_capacity = 0; + return *this; } #endif --- a/libstdc++-v3/include/experimental/any 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/experimental/any 2015-05-23 11:20:55.285156612 +0200 @@ -94,7 +94,7 @@ std::aligned_storage::type _M_buffer; }; - template, + template, bool _Fits = (sizeof(_Tp) <= sizeof(_Storage))> using _Internal = std::integral_constant; --- a/libstdc++-v3/include/std/limits 2015-01-05 13:33:28.000000000 +0100 +++ b/libstdc++-v3/include/std/limits 2015-05-23 11:22:05.903763794 +0200 @@ -1490,7 +1490,8 @@ min() _GLIBCXX_USE_NOEXCEPT { return 0; } \ \ static _GLIBCXX_CONSTEXPR unsigned TYPE \ - max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE); } \ + max() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_max_b (unsigned TYPE, BITSIZE); } \ \ UEXT \ \