Hi! I've backported the following patches, bootstrapped/regtested on x86_64-linux and i686-linux and committed to gcc-8-branch.
Jakub
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-13 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/87898 * omp-simd-clone.c (ipa_simd_modify_function_body): Remove debug stmts where the first argument was changed into a non-decl. * gcc.dg/gomp/pr87898.c: New test. --- gcc/omp-simd-clone.c (revision 266092) +++ gcc/omp-simd-clone.c (revision 266093) @@ -1014,6 +1011,21 @@ ipa_simd_modify_function_body (struct cg if (info.modified) { update_stmt (stmt); + /* If the above changed the var of a debug bind into something + different, remove the debug stmt. We could also for all the + replaced parameters add VAR_DECLs for debug info purposes, + add debug stmts for those to be the simd array accesses and + replace debug stmt var operand with that var. Debugging of + vectorized loops doesn't work too well, so don't bother for + now. */ + if ((gimple_debug_bind_p (stmt) + && !DECL_P (gimple_debug_bind_get_var (stmt))) + || (gimple_debug_source_bind_p (stmt) + && !DECL_P (gimple_debug_source_bind_get_var (stmt)))) + { + gsi_remove (&gsi, true); + continue; + } if (maybe_clean_eh_stmt (stmt)) gimple_purge_dead_eh_edges (gimple_bb (stmt)); } --- gcc/testsuite/gcc.dg/gomp/pr87898.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr87898.c (revision 266093) @@ -0,0 +1,10 @@ +/* PR tree-optimization/87898 */ +/* { dg-do compile { target fgraphite } } */ +/* { dg-options "-O1 -floop-parallelize-all -fopenmp -ftree-parallelize-loops=2 -g" } */ + +#pragma omp declare simd +void +foo (int x) +{ + x = 0; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-15 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/88018 * cfgrtl.c (fixup_abnormal_edges): Guard moving insns to fallthru edge on the presence of fallthru edge, rather than if it is a USE or not. * g++.dg/tsan/pr88018.C: New test. --- gcc/cfgrtl.c (revision 266173) +++ gcc/cfgrtl.c (revision 266174) @@ -3332,8 +3332,15 @@ fixup_abnormal_edges (void) If it's placed after a trapping call (i.e. that call is the last insn anyway), we have no fallthru edge. Simply delete this use and don't try to insert - on the non-existent edge. */ - if (GET_CODE (PATTERN (insn)) != USE) + on the non-existent edge. + Similarly, sometimes a call that can throw is + followed in the source with __builtin_unreachable (), + meaning that there is UB if the call returns rather + than throws. If there weren't any instructions + following such calls before, supposedly even the ones + we've deleted aren't significant and can be + removed. */ + if (e) { /* We're not deleting it, we're moving it. */ insn->set_undeleted (); --- gcc/testsuite/g++.dg/tsan/pr88018.C (nonexistent) +++ gcc/testsuite/g++.dg/tsan/pr88018.C (revision 266236) @@ -0,0 +1,6 @@ +// PR rtl-optimization/88018 +// { dg-do compile } +// { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } +// { dg-options "-fsanitize=thread -fno-ipa-pure-const -O1 -fno-inline-functions-called-once -w" } + +#include "../pr69667.C"
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-16 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/87475 * cfgrtl.c (patch_jump_insn): Allow redirection failure for CROSSING_JUMP_P insns. (cfg_layout_redirect_edge_and_branch): Don't ICE if ret is NULL. * g++.dg/opt/pr87475.C: New test. --- gcc/cfgrtl.c (revision 266218) +++ gcc/cfgrtl.c (revision 266219) @@ -1268,11 +1268,13 @@ patch_jump_insn (rtx_insn *insn, rtx_ins /* If the substitution doesn't succeed, die. This can happen if the back end emitted unrecognizable instructions or if - target is exit block on some arches. */ + target is exit block on some arches. Or for crossing + jumps. */ if (!redirect_jump (as_a <rtx_jump_insn *> (insn), block_label (new_bb), 0)) { - gcc_assert (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)); + gcc_assert (new_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) + || CROSSING_JUMP_P (insn)); return false; } } @@ -4460,6 +4462,9 @@ cfg_layout_redirect_edge_and_branch (edg else ret = redirect_branch_edge (e, dest); + if (!ret) + return NULL; + fixup_partition_crossing (ret); /* We don't want simplejumps in the insn stream during cfglayout. */ gcc_assert (!simplejump_p (BB_END (src)) || CROSSING_JUMP_P (BB_END (src))); --- gcc/testsuite/g++.dg/opt/pr87475.C (nonexistent) +++ gcc/testsuite/g++.dg/opt/pr87475.C (revision 266219) @@ -0,0 +1,7 @@ +// PR rtl-optimization/87475 +// { dg-do compile { target freorder } } +// { dg-options "-O2 -freorder-blocks-and-partition -fmodulo-sched" } + +struct A { A (); ~A (); }; +int foo (A, A); +void bar (bool x) { x ? foo (A (), A ()) : 0; }
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-19 Jakub Jelinek <ja...@redhat.com> PR debug/87039 * omp-expand.c: Don't include debug.h. (adjust_context_and_scope): Add REGION argument. Find DECL_CONTEXT from innermost outer parallel, task, or target that has a child_fn set, or, if there is no such outer region, use current_function_decl. Do the DECL_CONTEXT adjustment regardless of whether a suitable BLOCK is found or not. (expand_parallel_call): Don't call adjust_context_and_scope here. (grid_expand_target_grid_body): Revert 2017-01-25 changes. (expand_omp_taskreg, expand_omp_target): Likewise. Call adjust_context_and_scope. * dwarf2out.c (dwarf2out_early_global_decl): For decl_function_context recurse instead of calling dwarf2out_decl. * g++.dg/gomp/pr78363-4.C: New test. * g++.dg/gomp/pr78363-5.C: New test. * g++.dg/gomp/pr78363-6.C: New test. * g++.dg/gomp/pr78363-7.C: New test. --- gcc/omp-expand.c (revision 266271) +++ gcc/omp-expand.c (revision 266272) @@ -56,7 +56,6 @@ along with GCC; see the file COPYING3. #include "gomp-constants.h" #include "gimple-pretty-print.h" #include "hsa-common.h" -#include "debug.h" #include "stringpool.h" #include "attribs.h" @@ -507,27 +506,43 @@ parallel_needs_hsa_kernel_p (struct omp_ function will be emitted with the correct lexical scope. */ static void -adjust_context_and_scope (tree entry_block, tree child_fndecl) +adjust_context_and_scope (struct omp_region *region, tree entry_block, + tree child_fndecl) { + tree parent_fndecl = NULL_TREE; + gimple *entry_stmt; + /* OMP expansion expands inner regions before outer ones, so if + we e.g. have explicit task region nested in parallel region, when + expanding the task region current_function_decl will be the original + source function, but we actually want to use as context the child + function of the parallel. */ + for (region = region->outer; + region && parent_fndecl == NULL_TREE; region = region->outer) + switch (region->type) + { + case GIMPLE_OMP_PARALLEL: + case GIMPLE_OMP_TASK: + entry_stmt = last_stmt (region->entry); + parent_fndecl = gimple_omp_taskreg_child_fn (entry_stmt); + break; + case GIMPLE_OMP_TARGET: + entry_stmt = last_stmt (region->entry); + parent_fndecl + = gimple_omp_target_child_fn (as_a <gomp_target *> (entry_stmt)); + break; + default: + break; + } + + if (parent_fndecl == NULL_TREE) + parent_fndecl = current_function_decl; + DECL_CONTEXT (child_fndecl) = parent_fndecl; + if (entry_block != NULL_TREE && TREE_CODE (entry_block) == BLOCK) { tree b = BLOCK_SUPERCONTEXT (entry_block); - if (TREE_CODE (b) == BLOCK) { - tree parent_fndecl; - - /* Follow supercontext chain until the parent fndecl - is found. */ - for (parent_fndecl = BLOCK_SUPERCONTEXT (b); - TREE_CODE (parent_fndecl) == BLOCK; - parent_fndecl = BLOCK_SUPERCONTEXT (parent_fndecl)) - ; - - gcc_assert (TREE_CODE (parent_fndecl) == FUNCTION_DECL); - - DECL_CONTEXT (child_fndecl) = parent_fndecl; - DECL_CHAIN (child_fndecl) = BLOCK_VARS (b); BLOCK_VARS (b) = child_fndecl; } @@ -703,8 +718,6 @@ expand_parallel_call (struct omp_region tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt); t2 = build_fold_addr_expr (child_fndecl); - adjust_context_and_scope (gimple_block (entry_stmt), child_fndecl); - vec_alloc (args, 4 + vec_safe_length (ws_args)); args->quick_push (t2); args->quick_push (t1); @@ -1294,11 +1307,6 @@ expand_omp_taskreg (struct omp_region *r else block = gimple_block (entry_stmt); - /* Make sure to generate early debug for the function before - outlining anything. */ - if (! gimple_in_ssa_p (cfun)) - (*debug_hooks->early_global_decl) (cfun->decl); - 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; @@ -1379,6 +1387,8 @@ expand_omp_taskreg (struct omp_region *r } } + adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn); + if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL) expand_parallel_call (region, new_bb, as_a <gomp_parallel *> (entry_stmt), ws_args); @@ -7042,11 +7052,6 @@ expand_omp_target (struct omp_region *re gsi_remove (&gsi, true); } - /* Make sure to generate early debug for the function before - outlining anything. */ - if (! gimple_in_ssa_p (cfun)) - (*debug_hooks->early_global_decl) (cfun->decl); - /* Move the offloading region into CHILD_CFUN. */ block = gimple_block (entry_stmt); @@ -7123,6 +7128,8 @@ expand_omp_target (struct omp_region *re dump_function_header (dump_file, child_fn, dump_flags); dump_function_to_file (child_fn, dump_file, dump_flags); } + + adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn); } /* Emit a library call to launch the offloading region, or do data @@ -7619,11 +7626,6 @@ grid_expand_target_grid_body (struct omp init_tree_ssa (cfun); pop_cfun (); - /* Make sure to generate early debug for the function before - outlining anything. */ - if (! gimple_in_ssa_p (cfun)) - (*debug_hooks->early_global_decl) (cfun->decl); - tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl); gcc_assert (!DECL_CHAIN (old_parm_decl)); tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl)); --- gcc/dwarf2out.c (revision 266271) +++ gcc/dwarf2out.c (revision 266272) @@ -26403,7 +26403,7 @@ dwarf2out_early_global_decl (tree decl) enough so that it lands in its own context. This avoids type pruning issues later on. */ if (context_die == NULL || is_declaration_die (context_die)) - dwarf2out_decl (context); + dwarf2out_early_global_decl (context); } /* Emit an abstract origin of a function first. This happens --- gcc/testsuite/g++.dg/gomp/pr78363-4.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/pr78363-4.C (revision 266272) @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-additional-options "-g" } + +int main() +{ + int n = 0; + +#pragma omp parallel +#pragma omp master +#pragma omp parallel +#pragma omp master +#pragma omp parallel for reduction (+: n) + for (int i = [](){ return 3; }(); i < 10; ++i) + n++; + + return n; +} --- gcc/testsuite/g++.dg/gomp/pr78363-5.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/pr78363-5.C (revision 266272) @@ -0,0 +1,17 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-additional-options "-g" } + +int main() +{ + int n = 0; +#pragma omp task shared(n) +#pragma omp target map(tofrom:n) +#pragma omp for reduction (+: n) + for (int i = [](){ return 3; }(); i < 10; ++i) + n++; + if (n != 7) + __builtin_abort (); +#pragma omp taskwait + return 0; +} --- gcc/testsuite/g++.dg/gomp/pr78363-6.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/pr78363-6.C (revision 266272) @@ -0,0 +1,16 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-additional-options "-g" } + +int main() +{ + int n = 0; +#pragma omp parallel +#pragma omp master +#pragma omp task shared (n) + for (int i = [](){ return 3; }(); i < 10; ++i) + n = i; +#pragma omp taskwait + if (n != 7) + __builtin_abort (); +} --- gcc/testsuite/g++.dg/gomp/pr78363-7.C (nonexistent) +++ gcc/testsuite/g++.dg/gomp/pr78363-7.C (revision 266272) @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-additional-options "-g" } + +int main() +{ + int n = 0; + +#pragma omp target map(tofrom: n) +#pragma omp parallel for reduction (+: n) + for (int i = [](){ return 3; }(); i < 10; ++i) + n++; + + return n; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-19 Jakub Jelinek <ja...@redhat.com> PR c++/60994 * g++.dg/lookup/pr60994.C: New test. --- gcc/testsuite/g++.dg/lookup/pr60994.C (nonexistent) +++ gcc/testsuite/g++.dg/lookup/pr60994.C (revision 266275) @@ -0,0 +1,13 @@ +// PR c++/60994 +// { dg-do compile } + +struct s +{ + static int i; +}; + +template <typename T> +int s() +{ + return s::i; // { dg-bogus "is not a class" } +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-19 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/88071 * tree-vect-loop.c (vectorize_fold_left_reduction): Pass true instead of false as last argument to gsi_remove. * tree-vect-stmts.c (vect_finish_replace_stmt): Pass true instead of false as last argument to gsi_replace. * gcc.dg/pr88071.c: New test. --- gcc/tree-vect-loop.c (revision 266275) +++ gcc/tree-vect-loop.c (revision 266276) @@ -5861,7 +5861,7 @@ vectorize_fold_left_reduction (stmt_vec_ /* Remove the statement, so that we can use the same code paths as for statements that we've just created. */ gimple_stmt_iterator tmp_gsi = gsi_for_stmt (new_stmt); - gsi_remove (&tmp_gsi, false); + gsi_remove (&tmp_gsi, true); } if (i == vec_num - 1) --- gcc/tree-vect-stmts.c (revision 266275) +++ gcc/tree-vect-stmts.c (revision 266276) @@ -1637,7 +1637,7 @@ vect_finish_replace_stmt (gimple *stmt, gcc_assert (gimple_get_lhs (stmt) == gimple_get_lhs (vec_stmt)); gimple_stmt_iterator gsi = gsi_for_stmt (stmt); - gsi_replace (&gsi, vec_stmt, false); + gsi_replace (&gsi, vec_stmt, true); vect_finish_stmt_generation_1 (stmt, vec_stmt); } --- gcc/testsuite/gcc.dg/pr88071.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr88071.c (revision 266276) @@ -0,0 +1,5 @@ +/* PR tree-optimization/88071 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fexceptions -fnon-call-exceptions -fopenmp-simd -ftrapv -ftree-loop-vectorize" } */ + +#include "gomp/openmp-simd-2.c"
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-20 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/87895 * omp-simd-clone.c (ipa_simd_modify_function_body): When removing or replacing GIMPLE_RETURN, set EDGE_FALLTHRU on the edge to EXIT. (simd_clone_adjust): Don't set EDGE_FALLTHRU here. In a loop that redirects edges to EXIT to edges to incr_bb, iterate while EXIT has any preds and always use EDGE_PRED (, 0). * gcc.dg/gomp/pr87895-1.c: New test. * gcc.dg/gomp/pr87895-2.c: New test. * gcc.dg/gomp/pr87895-3.c: New test. --- gcc/omp-simd-clone.c (revision 266327) +++ gcc/omp-simd-clone.c (revision 266328) @@ -994,6 +994,8 @@ ipa_simd_modify_function_body (struct cg if (greturn *return_stmt = dyn_cast <greturn *> (stmt)) { tree retval = gimple_return_retval (return_stmt); + edge e = find_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun)); + e->flags |= EDGE_FALLTHRU; if (!retval) { gsi_remove (&gsi, true); @@ -1150,14 +1152,9 @@ simd_clone_adjust (struct cgraph_node *n incr_bb = create_empty_bb (orig_exit); incr_bb->count = profile_count::zero (); add_bb_to_loop (incr_bb, body_bb->loop_father); - /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty - flag. Set it now to be a FALLTHRU_EDGE. */ - gcc_assert (EDGE_COUNT (orig_exit->succs) == 1); - EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU; - for (unsigned i = 0; - i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i) + while (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)) { - edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i); + edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0); redirect_edge_succ (e, incr_bb); incr_bb->count += e->count (); } --- gcc/testsuite/gcc.dg/gomp/pr87895-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr87895-1.c (revision 266328) @@ -0,0 +1,19 @@ +/* PR tree-optimization/87895 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O0" } */ + +#pragma omp declare simd +int +foo (int x) +{ + if (x == 0) + return 0; +} + +#pragma omp declare simd +int +bar (int *x, int y) +{ + if ((y == 0) ? (*x = 0) : *x) + return 0; +} --- gcc/testsuite/gcc.dg/gomp/pr87895-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr87895-2.c (revision 266328) @@ -0,0 +1,5 @@ +/* PR tree-optimization/87895 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O1" } */ + +#include "pr87895-1.c" --- gcc/testsuite/gcc.dg/gomp/pr87895-3.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr87895-3.c (revision 266328) @@ -0,0 +1,18 @@ +/* PR tree-optimization/87895 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O2" } */ + +#pragma omp declare simd +int foo (int x) __attribute__((noreturn)); + +#pragma omp declare simd +int +bar (int x, int y) +{ + if (y == 1) + foo (x + 2); + if (y == 10) + foo (x + 6); + if (y != 25) + return 4; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-21 Jakub Jelinek <ja...@redhat.com> PR c++/88122 * method.c (maybe_explain_implicit_delete): If FUNCTION_FIRST_USER_PARMTYPE (decl) is NULL, set const_p to false instead of ICEing. * g++.dg/cpp0x/implicit15.C: New test. --- gcc/cp/method.c (revision 266359) +++ gcc/cp/method.c (revision 266360) @@ -1821,8 +1821,12 @@ maybe_explain_implicit_delete (tree decl if (!informed) { tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); - tree parm_type = TREE_VALUE (parms); - bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); + bool const_p = false; + if (parms) + { + tree parm_type = TREE_VALUE (parms); + const_p = CP_TYPE_CONST_P (non_reference (parm_type)); + } tree raises = NULL_TREE; bool deleted_p = false; tree scope = push_scope (ctype); --- gcc/testsuite/g++.dg/cpp0x/implicit15.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/implicit15.C (revision 266360) @@ -0,0 +1,11 @@ +// PR c++/88122 +// { dg-do compile { target c++11 } } + +struct A { + A (...); // { dg-message "candidate" } + A (); // { dg-message "candidate" } +}; +struct B : A { + using A::A; // { dg-error "is ambiguous" } + // { dg-message "is implicitly deleted because the default definition would be ill-formed" "" { target *-*-* } .-1 } +} b{3}; // { dg-error "use of deleted function" }
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-22 Jakub Jelinek <ja...@redhat.com> PR target/85644 PR target/86832 * config/i386/i386.c (ix86_option_override_internal): Default ix86_stack_protector_guard to SSP_TLS only if TARGET_THREAD_SSP_OFFSET is defined. * config/i386/i386.md (stack_protect_set, stack_protect_set_<mode>, stack_protect_test, stack_protect_test_<mode>): Use empty condition instead of TARGET_SSP_TLS_GUARD. --- gcc/config/i386/i386.md (revision 266369) +++ gcc/config/i386/i386.md (revision 266370) @@ -19010,7 +19010,7 @@ (define_insn "*prefetch_prefetchwt1" (define_expand "stack_protect_set" [(match_operand 0 "memory_operand") (match_operand 1 "memory_operand")] - "TARGET_SSP_TLS_GUARD" + "" { rtx (*insn)(rtx, rtx); @@ -19028,7 +19028,7 @@ (define_insn "stack_protect_set_<mode>" UNSPEC_SP_SET)) (set (match_scratch:PTR 2 "=&r") (const_int 0)) (clobber (reg:CC FLAGS_REG))] - "TARGET_SSP_TLS_GUARD" + "" "mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" [(set_attr "type" "multi")]) @@ -19036,7 +19036,7 @@ (define_expand "stack_protect_test" [(match_operand 0 "memory_operand") (match_operand 1 "memory_operand") (match_operand 2)] - "TARGET_SSP_TLS_GUARD" + "" { rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); @@ -19059,7 +19059,7 @@ (define_insn "stack_protect_test_<mode>" (match_operand:PTR 2 "memory_operand" "m")] UNSPEC_SP_TEST)) (clobber (match_scratch:PTR 3 "=&r"))] - "TARGET_SSP_TLS_GUARD" + "" "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}" [(set_attr "type" "multi")]) --- gcc/config/i386/i386.c (revision 266369) +++ gcc/config/i386/i386.c (revision 266370) @@ -4559,8 +4559,14 @@ ix86_option_override_internal (bool main /* Handle stack protector */ if (!opts_set->x_ix86_stack_protector_guard) - opts->x_ix86_stack_protector_guard - = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS; + { +#ifdef TARGET_THREAD_SSP_OFFSET + if (!TARGET_HAS_BIONIC) + opts->x_ix86_stack_protector_guard = SSP_TLS; + else +#endif + opts->x_ix86_stack_protector_guard = SSP_GLOBAL; + } #ifdef TARGET_THREAD_SSP_OFFSET ix86_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET;
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-22 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/85794 * gcc.dg/vect/O3-pr85794.c: New test. --- gcc/testsuite/gcc.dg/vect/O3-pr85794.c (nonexistent) +++ gcc/testsuite/gcc.dg/vect/O3-pr85794.c (revision 266387) @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +int a, b, *c, d; +int *f[6]; + +void +foo (void) +{ + for (b = 1; b >= 0; b--) + for (d = 0; d <= 3; d++) + a |= f[b * 5] != c; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-26 Jakub Jelinek <ja...@redhat.com> PR c++/86900 * dwarf2out.c (secname_for_decl): For functions with DECL_SECTION_NAME if in_cold_section_p, try to return current_function_section's name if it is a named section. * g++.dg/debug/dwarf2/pr86900.C: New test. --- gcc/dwarf2out.c (revision 266484) +++ gcc/dwarf2out.c (revision 266485) @@ -16742,7 +16742,15 @@ secname_for_decl (const_tree decl) && DECL_SECTION_NAME (decl)) secname = DECL_SECTION_NAME (decl); else if (current_function_decl && DECL_SECTION_NAME (current_function_decl)) - secname = DECL_SECTION_NAME (current_function_decl); + { + if (in_cold_section_p) + { + section *sec = current_function_section (); + if (sec->common.flags & SECTION_NAMED) + return sec->named.name; + } + secname = DECL_SECTION_NAME (current_function_decl); + } else if (cfun && in_cold_section_p) secname = crtl->subsections.cold_section_label; else --- gcc/testsuite/g++.dg/debug/dwarf2/pr86900.C (nonexistent) +++ gcc/testsuite/g++.dg/debug/dwarf2/pr86900.C (revision 266485) @@ -0,0 +1,14 @@ +// PR c++/86900 +// { dg-do assemble { target function_sections } } +// { dg-options "-O2 -gdwarf-5 -ffunction-sections" } + +struct A; +struct B { B (A); }; +struct A { A (int); ~A (); }; + +void +foo (int x) +{ + A d(0); + B e(d); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-27 Jakub Jelinek <ja...@redhat.com> PR c++/88181 * class.c (fixup_attribute_variants): Also propagate TYPE_PACKED to variants. * g++.dg/debug/pr88181.C: New test. --- gcc/cp/class.c (revision 266526) +++ gcc/cp/class.c (revision 266527) @@ -1951,6 +1951,7 @@ fixup_attribute_variants (tree t) unsigned align = TYPE_ALIGN (t); bool user_align = TYPE_USER_ALIGN (t); bool may_alias = lookup_attribute ("may_alias", attrs); + bool packed = TYPE_PACKED (t); if (may_alias) fixup_may_alias (t); @@ -1968,6 +1969,7 @@ fixup_attribute_variants (tree t) else TYPE_USER_ALIGN (variants) = user_align; SET_TYPE_ALIGN (variants, valign); + TYPE_PACKED (variants) = packed; if (may_alias) fixup_may_alias (variants); } --- gcc/testsuite/g++.dg/debug/pr88181.C (nonexistent) +++ gcc/testsuite/g++.dg/debug/pr88181.C (revision 266527) @@ -0,0 +1,29 @@ +// PR c++/88181 +// { dg-do compile } +// { dg-options "-fpack-struct -g -std=c++11" } + +template <typename T> struct A { typedef T B; }; +template <typename...> class C; +template <typename e> struct D { constexpr D (e) {} }; +template <int, typename...> struct E; +template <int N, typename T, typename... U> +struct E<N, T, U...> : E<1, U...>, D<T> { + constexpr E (T x, U... y) : E<1, U...>(y...), D<T>(x) {} +}; +template <int N, typename T> struct E<N, T> : D<T> { + constexpr E (T x) : D<T>(x) {} +}; +template <typename T, typename U> struct C<T, U> : E<0, T, U> { + constexpr C (T x, U y) : E<0, T, U>(x, y) {} + void operator= (typename A<const C>::B); +}; +struct F {}; +struct G {}; + +int +main () +{ + F f; + G g; + constexpr C<F, G> c(f, g); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-28 Jakub Jelinek <ja...@redhat.com> PR c++/88215 * c-ubsan.c: Include langhooks.h. (ubsan_instrument_division): Change gcc_assert that main variants of op0 and op1 types are equal to gcc_checking_assert that the main variants are compatible types. * c-c++-common/ubsan/pr88215.c: New test. --- gcc/c-family/c-ubsan.c (revision 266545) +++ gcc/c-family/c-ubsan.c (revision 266546) @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. #include "stringpool.h" #include "attribs.h" #include "asan.h" +#include "langhooks.h" /* Instrument division by zero and INT_MIN / -1. If not instrumenting, return NULL_TREE. */ @@ -44,8 +45,9 @@ ubsan_instrument_division (location_t lo /* At this point both operands should have the same type, because they are already converted to RESULT_TYPE. Use TYPE_MAIN_VARIANT since typedefs can confuse us. */ - gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0)) - == TYPE_MAIN_VARIANT (TREE_TYPE (op1))); + tree top0 = TYPE_MAIN_VARIANT (type); + tree top1 = TYPE_MAIN_VARIANT (TREE_TYPE (op1)); + gcc_checking_assert (lang_hooks.types_compatible_p (top0, top1)); op0 = unshare_expr (op0); op1 = unshare_expr (op1); --- gcc/testsuite/c-c++-common/ubsan/pr88215.c (nonexistent) +++ gcc/testsuite/c-c++-common/ubsan/pr88215.c (revision 266546) @@ -0,0 +1,11 @@ +/* PR c++/88215 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=integer-divide-by-zero" } */ + +int +foo (void) +{ + int a = 2, __attribute__ ((__unused__)) b = 1; + int f = a / b; + return f; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-29 Jakub Jelinek <ja...@redhat.com> PR c++/87539 * g++.dg/cpp0x/pr87539.C: New test. --- gcc/testsuite/g++.dg/cpp0x/pr87539.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/pr87539.C (revision 266611) @@ -0,0 +1,85 @@ +// PR c++/87539 +// { dg-do compile { target c++11 } } +// { dg-options "-Os" } + +namespace a { +template <typename b, typename = b, typename = int> class c; +class exception {}; +template <typename d> struct e { d f; }; +struct g { g(); g(const g &); }; +} +template <class, class, class = int> class h; +template <typename, typename> struct i; +template <int j> struct aa { static const int k = j; }; +struct ac { typedef a::e<int> l; }; +struct ad; +template <int, typename m, typename> struct ae { typedef m l; }; +template <typename m, typename n> struct ae<false, m, n> { typedef n l; }; +template <typename m, typename n, typename p> struct o { + typedef typename ae<m::k, n, p>::l l; +}; +struct af { af(char *); }; +template <typename> struct ag { ag(a::g = a::g()) {} }; +template <typename ah, typename ai, typename aj, typename al> +struct i<a::c<ah, ai, aj>, al> { typedef ag<al> l; }; +namespace ak { +template <typename am, typename an, typename ao> struct ap { + typedef typename o<am, an, ao>::l ::l l; +}; +template <typename = ad> struct aq { typedef ad l; }; +} +template <typename ar> struct as { + typedef char at; + template <typename au, typename> static decltype(au(), at()) av(int); + template <typename, typename> static int av(...); + static const bool k = sizeof(av<ar, int>(0)) == 1; +}; +template <typename ar> struct aw { static const bool k = as<ar>::k; }; +template <class ar> struct ax { typedef aw<ar> l; }; +template <typename ar> struct ay { typedef typename ax<ar>::l l; }; +template <typename ar> struct az : ay<ar>::l {}; +template <class ar, class> struct ba : aa<az<ar>::k> {}; +template <class> struct bb : ak::ap<ba<int, int>, ak::aq<>, int> {}; +template <typename> struct q : ba<bb<int>::l, int> {}; +template <class, class, bool> class r; +template <class s, class t> struct r<s, t, false> { + s operator*(); + s operator++(); +}; +template <class, class, class, class, class> +class bc : public r<a::e<h<int, int>>, int, q<int>::k> {}; +template <class bd, class be, class bf, class u, class v, class bg, class w, + class x, class bh, class bi> +int operator!=(bc<bd, be, bf, u, v>, bc<bg, w, x, bh, bi>); +template <class, class, class> struct h { + typedef af bl; + bc<int, int, int, ak::ap<aa<false>, int, ac>::l, int> begin(); + bc<int, int, int, ak::ap<aa<false>, int, ac>::l, int> end(); + template <class bm> bm bn() const; + template <class> int bo() const; + template <class bm> int bx(const bl &, const bm &) const; + template <class> int bp(const bl &) const; +}; +template <class bq, class br, class am> +template <class bm> +bm h<bq, br, am>::bn() const { typename i<a::c<int>, bm>::l(); return bm(); } +template <class bq, class br, class am> +template <class> +int h<bq, br, am>::bo() const { i<a::c<int>, int>::l(); bn<int>(); return 0; } +template <class bq, class br, class am> +template <class bm> +int h<bq, br, am>::bx(const bl &bs, const bm &) const { bp<int>(bs); return 0; } +template <class bq, class br, class am> +template <class> +int h<bq, br, am>::bp(const bl &) const { bo<int>(); return 0; } +char bt[] = ""; +void +d() +{ + h<int, int> bu; + for (auto bv : bu) + try { + bv.f.bx(bt, 0); + } catch (a::exception) { + } +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-29 Jakub Jelinek <ja...@redhat.com> PR target/88234 * config/rs6000/rs6000.c (rs6000_gimple_fold_builtin): For vec_add and vec_sub builtins, perform PLUS_EXPR or MINUS_EXPR in unsigned_type_for instead of vector integral type where overflow doesn't wrap. * gcc.dg/ubsan/pr88234.c: New test. --- gcc/config/rs6000/rs6000.c (revision 266618) +++ gcc/config/rs6000/rs6000.c (revision 266619) @@ -15371,6 +15371,7 @@ rs6000_gimple_fold_builtin (gimple_stmt_ enum rs6000_builtins fn_code = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl); tree arg0, arg1, lhs, temp; + enum tree_code bcode; gimple *g; size_t uns_fncode = (size_t) fn_code; @@ -15409,10 +15410,32 @@ rs6000_gimple_fold_builtin (gimple_stmt_ case P8V_BUILTIN_VADDUDM: case ALTIVEC_BUILTIN_VADDFP: case VSX_BUILTIN_XVADDDP: + bcode = PLUS_EXPR; + do_binary: arg0 = gimple_call_arg (stmt, 0); arg1 = gimple_call_arg (stmt, 1); lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, PLUS_EXPR, arg0, arg1); + if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (lhs))) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (TREE_TYPE (lhs)))) + { + /* Ensure the binary operation is performed in a type + that wraps if it is integral type. */ + gimple_seq stmts = NULL; + tree type = unsigned_type_for (TREE_TYPE (lhs)); + tree uarg0 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + type, arg0); + tree uarg1 = gimple_build (&stmts, VIEW_CONVERT_EXPR, + type, arg1); + tree res = gimple_build (&stmts, gimple_location (stmt), bcode, + type, uarg0, uarg1); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR, + build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (lhs), res)); + gsi_replace (gsi, g, true); + return true; + } + g = gimple_build_assign (lhs, bcode, arg0, arg1); gimple_set_location (g, gimple_location (stmt)); gsi_replace (gsi, g, true); return true; @@ -15424,13 +15447,8 @@ rs6000_gimple_fold_builtin (gimple_stmt_ case P8V_BUILTIN_VSUBUDM: case ALTIVEC_BUILTIN_VSUBFP: case VSX_BUILTIN_XVSUBDP: - arg0 = gimple_call_arg (stmt, 0); - arg1 = gimple_call_arg (stmt, 1); - lhs = gimple_call_lhs (stmt); - g = gimple_build_assign (lhs, MINUS_EXPR, arg0, arg1); - gimple_set_location (g, gimple_location (stmt)); - gsi_replace (gsi, g, true); - return true; + bcode = MINUS_EXPR; + goto do_binary; case VSX_BUILTIN_XVMULSP: case VSX_BUILTIN_XVMULDP: arg0 = gimple_call_arg (stmt, 0); --- gcc/testsuite/gcc.dg/ubsan/pr88234.c (nonexistent) +++ gcc/testsuite/gcc.dg/ubsan/pr88234.c (revision 266619) @@ -0,0 +1,29 @@ +/* PR target/88234 */ +/* { dg-do run { target { powerpc*-*-* && vmx_hw } } } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-fsanitize=signed-integer-overflow -fno-sanitize-recover=signed-integer-overflow -O2 -maltivec" } */ + +#include <altivec.h> + +__attribute__((noipa)) vector unsigned int +f1 (vector unsigned int x, vector unsigned int y) +{ + return vec_add (x, y); +} + +__attribute__((noipa)) vector unsigned int +f2 (vector unsigned int x, vector unsigned int y) +{ + return vec_sub (x, y); +} + +int +main () +{ + vector unsigned int x = { __INT_MAX__, -__INT_MAX__, __INT_MAX__ - 3, -__INT_MAX__ + 4 }; + vector unsigned int y = { 1, -1, 4, -5 }; + vector unsigned int z = f1 (x, y); + f2 (z, x); + f2 (z, y); + return 0; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-11-30 Jakub Jelinek <ja...@redhat.com> PR debug/85550 * g++.dg/debug/dwarf2/pr85550.C: New test. --- gcc/testsuite/g++.dg/debug/dwarf2/pr85550.C (nonexistent) +++ gcc/testsuite/g++.dg/debug/dwarf2/pr85550.C (revision 266689) @@ -0,0 +1,17 @@ +// PR debug/85550 +// { dg-do link } +// { dg-options "-O2 -g -fdebug-types-section" } + +struct A { + int bar () const { return 0; } +}; +template <int (A::*foo)() const> +struct B { +}; + +B<&A::bar> b; + +int +main () +{ +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-03 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/71109 * gcc.c-torture/compile/pr71109.c: New test. --- gcc/testsuite/gcc.c-torture/compile/pr71109.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr71109.c (revision 266738) @@ -0,0 +1,31 @@ +/* PR tree-optimization/71109 */ + +struct S { int g, h; signed char i; int j; signed char k; int l[4]; } a, c; +struct T { signed char g; } e; +int *b, d; +static void foo (); + +void +bar (void) +{ + while (d) + { + int k; + struct T f[3]; + foo (bar, a); + for (k = 0;; k++) + f[k] = e; + } +} + +static inline void +foo (int x, struct S y, struct T z) +{ + for (z.g = 2; z.g; z.g--) + { + c = a = y; + *b |= 6; + if (y.g) + break; + } +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-04 Jakub Jelinek <ja...@redhat.com> PR c++/88103 * typeck.c (build_class_member_access_expr): If unary_complex_lvalue turned xvalue_p into non-xvalue_p, call move on it. * g++.dg/cpp0x/rv-cond3.C: New test. --- gcc/cp/typeck.c (revision 266771) +++ gcc/cp/typeck.c (revision 266772) @@ -2422,7 +2422,13 @@ build_class_member_access_expr (cp_expr { tree temp = unary_complex_lvalue (ADDR_EXPR, object); if (temp) - object = cp_build_fold_indirect_ref (temp); + { + temp = cp_build_fold_indirect_ref (temp); + if (xvalue_p (object) && !xvalue_p (temp)) + /* Preserve xvalue kind. */ + temp = move (temp); + object = temp; + } } /* In [expr.ref], there is an explicit list of the valid choices for --- gcc/testsuite/g++.dg/cpp0x/rv-cond3.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/rv-cond3.C (revision 266772) @@ -0,0 +1,22 @@ +// PR c++/88103 +// { dg-do compile { target c++11 } } + +struct A { + A (int); + A&& foo () &&; + int i; +}; +void free (A&&); + +void test_xvalue (A a){ + A&& ref = true ? static_cast<A&&> (a) : static_cast<A&&> (a); + free (true ? static_cast<A&&> (a) : static_cast<A&&> (a)); + (true ? static_cast<A&&> (a) : static_cast<A&&> (a)).foo (); + int&& k = (true ? static_cast<A&&> (a) : static_cast<A&&> (a)).i; +} +void test_prvalue (A a){ + A&& ref = true ? static_cast<A&&> (a) : 1; + free (true ? static_cast<A&&> (a) : 1); + (true ? static_cast<A&&> (a) : 1).foo (); + int&& k = (true ? static_cast<A&&> (a) : 1).i; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-04 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/87320 * gcc.dg/pr87320.c: New test. --- gcc/testsuite/gcc.dg/pr87320.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr87320.c (revision 266805) @@ -0,0 +1,28 @@ +/* PR tree-optimization/87320 */ +/* { dg-do run } */ +/* { dg-options "-O3" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +static void __attribute__ ((noinline)) +transpose_vector (unsigned long n) +{ + unsigned long data[2 * n]; + for (unsigned long i = 0; i < 2 * n; i++) + data[i] = 4 * i + 2; + + unsigned long transposed[n]; + for (unsigned long i = 0; i < n; i++) + transposed[i] = data[2 * i]; + + for (unsigned long i = 0; i < n; i++) + if (transposed[i] != 8 * i + 2) + __builtin_abort (); +} + +int +main () +{ + transpose_vector (4); + transpose_vector (120); + return 0; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-05 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/87360 * gimple-loop-jam.c (tree_loop_unroll_and_jam): On failure to analyze data dependencies, don't return false, just continue. * g++.dg/opt/pr87360.C: New test. * gfortran.dg/pr87360.f90: New test. --- gcc/gimple-loop-jam.c (revision 266819) +++ gcc/gimple-loop-jam.c (revision 266820) @@ -455,7 +455,7 @@ tree_loop_unroll_and_jam (void) fprintf (dump_file, "Cannot analyze data dependencies\n"); free_data_refs (datarefs); free_dependence_relations (dependences); - return false; + continue; } if (!datarefs.length ()) continue; --- gcc/testsuite/g++.dg/opt/pr87360.C (nonexistent) +++ gcc/testsuite/g++.dg/opt/pr87360.C (revision 266820) @@ -0,0 +1,27 @@ +// PR tree-optimization/87360 +// { dg-do compile { target size32plus } } +// { dg-options "-O3 -fno-tree-dce --param unroll-jam-min-percent=0" } + +void abort (void); + +void foo (int N) +{ + int i, j; + int x[1000][1000]; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + x[i][j] = i + j + 3; + + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + if (x[i][j] != i + j + 3) + abort (); +} + +int main(void) +{ + foo (1000); + + return 0; +} --- gcc/testsuite/gfortran.dg/pr87360.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr87360.f90 (revision 266820) @@ -0,0 +1,5 @@ +! PR tree-optimization/87360 +! { dg-do compile } +! { dg-options "-fno-tree-dce -O3 --param max-completely-peeled-insns=0" } + +include 'function_optimize_2.f90'
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-06 Jakub Jelinek <ja...@redhat.com> PR target/87598 * config/aarch64/aarch64.c (aarch64_print_address_internal): Don't call output_operand_lossage on VOIDmode CONST_INTs. After output_operand_lossage do return false. * gcc.target/aarch64/asm-5.c: New test. --- gcc/config/aarch64/aarch64.c (revision 266851) +++ gcc/config/aarch64/aarch64.c (revision 266852) @@ -7635,8 +7635,13 @@ aarch64_print_address_internal (FILE *f, unsigned int size; /* Check all addresses are Pmode - including ILP32. */ - if (GET_MODE (x) != Pmode) - output_operand_lossage ("invalid address mode"); + if (GET_MODE (x) != Pmode + && (!CONST_INT_P (x) + || trunc_int_for_mode (INTVAL (x), Pmode) != INTVAL (x))) + { + output_operand_lossage ("invalid address mode"); + return false; + } if (aarch64_classify_address (&addr, x, mode, true, type)) switch (addr.type) --- gcc/testsuite/gcc.target/aarch64/asm-5.c (nonexistent) +++ gcc/testsuite/gcc.target/aarch64/asm-5.c (revision 266852) @@ -0,0 +1,8 @@ +/* PR target/87598 */ +/* { dg-do compile } */ + +void +foo (void) +{ + __asm__ ("# %a0" : : "i" (0)); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-07 Jakub Jelinek <ja...@redhat.com> PR c++/87506 * constexpr.c (adjust_temp_type): Handle EMPTY_CLASS_EXPR. * g++.dg/cpp0x/constexpr-87506.C: New test. --- gcc/cp/constexpr.c (revision 266876) +++ gcc/cp/constexpr.c (revision 266877) @@ -1281,6 +1281,8 @@ adjust_temp_type (tree type, tree temp) /* Avoid wrapping an aggregate value in a NOP_EXPR. */ if (TREE_CODE (temp) == CONSTRUCTOR) return build_constructor (type, CONSTRUCTOR_ELTS (temp)); + if (TREE_CODE (temp) == EMPTY_CLASS_EXPR) + return build0 (EMPTY_CLASS_EXPR, type); gcc_assert (scalarish_type_p (type)); return cp_fold_convert (type, temp); } --- gcc/testsuite/g++.dg/cpp0x/constexpr-87506.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-87506.C (revision 266877) @@ -0,0 +1,12 @@ +// PR c++/87506 +// { dg-do compile { target c++11 } } + +struct A {}; +struct B { constexpr B (const A) {} }; +struct C : B { using B::B; }; + +void +foo () +{ + C c (A{}); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-07 Jakub Jelinek <ja...@redhat.com> PR fortran/88377 * trans-openmp.c (gfc_omp_clause_default_ctor, gfc_omp_clause_copy_ctor, gfc_omp_clause_assign_op, gfc_omp_clause_linear_ctor, gfc_omp_clause_dtor): Only consider GFC_DECL_GET_SCALAR_ALLOCATABLE vars as scalar allocatables if they have pointer type. * gfortran.dg/gomp/pr88377.f90: New test. --- gcc/fortran/trans-openmp.c (revision 266878) +++ gcc/fortran/trans-openmp.c (revision 266879) @@ -460,7 +460,8 @@ gfc_omp_clause_default_ctor (tree clause if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) + || !POINTER_TYPE_P (type))) { if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) { @@ -567,7 +568,8 @@ gfc_omp_clause_copy_ctor (tree clause, t if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) + || !POINTER_TYPE_P (type))) { if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) { @@ -667,7 +669,8 @@ gfc_omp_clause_assign_op (tree clause, t if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) + || !POINTER_TYPE_P (type))) { if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) { @@ -905,7 +908,8 @@ gfc_omp_clause_linear_ctor (tree clause, if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) + || !POINTER_TYPE_P (type))) { gcc_assert (TREE_CODE (type) == ARRAY_TYPE); if (!TYPE_DOMAIN (type) @@ -989,7 +993,8 @@ gfc_omp_clause_dtor (tree clause, tree d if ((! GFC_DESCRIPTOR_TYPE_P (type) || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) - && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))) + && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) + || !POINTER_TYPE_P (type))) { if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) return gfc_walk_alloc_comps (decl, NULL_TREE, --- gcc/testsuite/gfortran.dg/gomp/pr88377.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/gomp/pr88377.f90 (revision 266879) @@ -0,0 +1,15 @@ +! PR fortran/88377 +! { dg-do compile } + +program pr88377 + call s(3) +contains + subroutine s(n) + integer :: n + character(n), allocatable :: x + x = 'abc' + !$omp task + print *, x, (x == 'abc') + !$omp end task + end +end
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-07 Jakub Jelinek <ja...@redhat.com> PR target/85593 * final.c (rest_of_handle_final): Don't call collect_fn_hard_reg_usage for functions with naked attribute. * gcc.target/i386/pr85593.c: New test. --- gcc/final.c (revision 266880) +++ gcc/final.c (revision 266881) @@ -4659,7 +4659,11 @@ rest_of_handle_final (void) final_start_function_1 (&first, asm_out_file, &seen, optimize); final_1 (first, asm_out_file, seen, optimize); if (flag_ipa_ra - && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)) + /* Functions with naked attributes are supported only with basic asm + statements in the body, thus for supported use cases the information + on clobbered registers is not available. */ + && !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))) collect_fn_hard_reg_usage (); final_end_function (); --- gcc/testsuite/gcc.target/i386/pr85593.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr85593.c (revision 266881) @@ -0,0 +1,30 @@ +/* PR target/85593 */ +/* { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */ +/* { dg-options "-O2" } */ + +__attribute__((naked)) void +bar (void) +{ + asm ("xorl %eax, %eax\n\t" + "xorl %edx, %edx\n\t" + "xorl %ecx, %ecx\n\t" + "xorl %esi, %esi\n\t" + "xorl %edi, %edi\n\t" + "xorl %r8d, %r8d\n\t" + "xorl %r9d, %r9d\n\t" + "xorl %r10d, %r10d\n\t" + "xorl %r11d, %r11d\n\t" + "ret"); +} + +int +main () +{ + int a = 42; + asm ("" : "+r" (a)); + bar (); + asm ("" : "+r" (a)); + if (a != 42) + __builtin_abort (); + return 0; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-07 Jakub Jelinek <ja...@redhat.com> PR c++/86669 * call.c (make_temporary_var_for_ref_to_temp): Call pushdecl even for automatic vars. * g++.dg/cpp0x/initlist105.C: New test. * g++.dg/cpp0x/initlist106.C: New test. * g++.dg/other/pr86669.C: New test. --- gcc/cp/call.c (revision 266892) +++ gcc/cp/call.c (revision 266893) @@ -11148,14 +11148,12 @@ make_temporary_var_for_ref_to_temp (tree tree name = mangle_ref_init_variable (decl); DECL_NAME (var) = name; SET_DECL_ASSEMBLER_NAME (var, name); - - var = pushdecl (var); } else /* Create a new cleanup level if necessary. */ maybe_push_cleanup_level (type); - return var; + return pushdecl (var); } /* EXPR is the initializer for a variable DECL of reference or --- gcc/testsuite/g++.dg/cpp0x/initlist105.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist105.C (revision 266893) @@ -0,0 +1,28 @@ +// PR c++/86669 +// { dg-do run { target c++11 } } + +#include <initializer_list> + +struct S { S (); }; +struct T : public S {}; +int cnt; +void foo (int) { cnt++; } + +S::S () +{ + int e = 1, f = 2, g = 3, h = 4; + + for (auto k : { e, f, g, h }) + foo (k); +} + +int +main () +{ + S s; + if (cnt != 4) + __builtin_abort (); + T t; + if (cnt != 8) + __builtin_abort (); +} --- gcc/testsuite/g++.dg/cpp0x/initlist106.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/initlist106.C (revision 266893) @@ -0,0 +1,29 @@ +// PR c++/86669 +// { dg-do run { target c++11 } } + +#include <initializer_list> + +struct A { }; +struct S : virtual public A { S (); }; +struct T : public S, virtual public A {}; +int cnt; +void foo (int) { cnt++; } + +S::S () +{ + int e = 1, f = 2, g = 3, h = 4; + + for (auto k : { e, f, g, h }) + foo (k); +} + +int +main () +{ + S s; + if (cnt != 4) + __builtin_abort (); + T t; + if (cnt != 8) + __builtin_abort (); +} --- gcc/testsuite/g++.dg/other/pr86669.C (nonexistent) +++ gcc/testsuite/g++.dg/other/pr86669.C (revision 266893) @@ -0,0 +1,10 @@ +// PR c++/86669 +// { dg-do compile } + +struct S { S (); }; +struct T : public S {}; + +S::S () +{ + int *p = { (int *) &p }; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-11 Jakub Jelinek <ja...@redhat.com> PR sanitizer/88426 * c-convert.c (convert): Call c_fully_fold before calling ubsan_instrument_float_cast. * c-c++-common/ubsan/float-cast-overflow-11.c: New test. --- gcc/c/c-convert.c (revision 267021) +++ gcc/c/c-convert.c (revision 267022) @@ -115,6 +115,7 @@ convert (tree type, tree expr) && COMPLETE_TYPE_P (type)) { expr = save_expr (expr); + expr = c_fully_fold (expr, false, NULL); tree check = ubsan_instrument_float_cast (loc, type, expr); expr = fold_build1 (FIX_TRUNC_EXPR, type, expr); if (check == NULL_TREE) --- gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-11.c (nonexistent) +++ gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-11.c (revision 267022) @@ -0,0 +1,10 @@ +/* PR sanitizer/88426 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +int +foo (void) +{ + const float v = 0.0f; + return (int) (v < 0.0f ? v : 0.0f); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-12 Jakub Jelinek <ja...@redhat.com> PR fortran/88463 * trans-openmp.c (gfc_omp_predetermined_sharing): Handle TREE_READONLY VAR_DECLs with DECL_EXTERNAL like those with TREE_STATIC. * testsuite/libgomp.fortran/pr88463-1.f90: New test. * testsuite/libgomp.fortran/pr88463-2.f90: New test. --- gcc/fortran/trans-openmp.c (revision 267068) +++ gcc/fortran/trans-openmp.c (revision 267069) @@ -149,7 +149,8 @@ gfc_omp_predetermined_sharing (tree decl variables at all (they can't be redefined), but they can nevertheless appear in parallel/task regions and for default(none) purposes treat them as shared. For vtables likely the same handling is desirable. */ - if (VAR_P (decl) && TREE_READONLY (decl) && TREE_STATIC (decl)) + if (VAR_P (decl) && TREE_READONLY (decl) + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) return OMP_CLAUSE_DEFAULT_SHARED; return OMP_CLAUSE_DEFAULT_UNSPECIFIED; --- libgomp/testsuite/libgomp.fortran/pr88463-1.f90 (nonexistent) +++ libgomp/testsuite/libgomp.fortran/pr88463-1.f90 (revision 267069) @@ -0,0 +1,19 @@ +! PR fortran/88463 +! { dg-do compile { target { ! *-*-* } } } + +module pr88463_1 + integer, parameter :: c = 1 + real, parameter :: d(4) = (/ 2, 3, 4, 5 /) +end module pr88463_1 + +program pr88463 + use pr88463_1 + use pr88463_2 + integer :: i + real :: j(4) + !$omp parallel default(none) private (i, j) + i = a + b(1) + b(4) + c + d(1) + d(4) + j(1:4) = b(1:4) + j(1:4) = d(1:4) + !$omp end parallel +end program pr88463 --- libgomp/testsuite/libgomp.fortran/pr88463-2.f90 (nonexistent) +++ libgomp/testsuite/libgomp.fortran/pr88463-2.f90 (revision 267069) @@ -0,0 +1,9 @@ +! PR fortran/88463 +! { dg-do link } +! { dg-options "-fopenmp" } +! { dg-additional-sources pr88463-1.f90 } + +module pr88463_2 + integer, parameter :: a = 1 + real, parameter :: b(4) = (/ 2., 3., 4., 5. /) +end module pr88463_2
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-13 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/88416 * valtrack.c (cleanup_auto_inc_dec): Handle pre/post-inc/dec/modify even if !AUTO_INC_DEC. * gcc.target/i386/pr88416.c: New test. --- gcc/valtrack.c (revision 267104) +++ gcc/valtrack.c (revision 267105) @@ -56,8 +56,6 @@ static rtx cleanup_auto_inc_dec (rtx src, machine_mode mem_mode ATTRIBUTE_UNUSED) { rtx x = src; - if (!AUTO_INC_DEC) - return copy_rtx (x); const RTX_CODE code = GET_CODE (x); int i; --- gcc/testsuite/gcc.target/i386/pr88416.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr88416.c (revision 267105) @@ -0,0 +1,5 @@ +/* PR rtl-optimization/88416 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fvar-tracking-assignments -fno-forward-propagate --param max-cse-insns=1" } */ + +#include "writeeflags-1.c"
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-13 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/88470 * cfgcleanup.c (outgoing_edges_match): If the function is shrink-wrapped and bb1 ends with a JUMP_INSN with a single fake edge to EXIT, return false. * gcc.target/i386/pr88470.c: New test. --- gcc/cfgcleanup.c (revision 267111) +++ gcc/cfgcleanup.c (revision 267112) @@ -1592,10 +1592,13 @@ outgoing_edges_match (int mode, basic_bl if (crtl->shrink_wrapped && single_succ_p (bb1) && single_succ (bb1) == EXIT_BLOCK_PTR_FOR_FN (cfun) - && !JUMP_P (BB_END (bb1)) + && (!JUMP_P (BB_END (bb1)) + /* Punt if the only successor is a fake edge to exit, the jump + must be some weird one. */ + || (single_succ_edge (bb1)->flags & EDGE_FAKE) != 0) && !(CALL_P (BB_END (bb1)) && SIBLING_CALL_P (BB_END (bb1)))) return false; - + /* If BB1 has only one successor, we may be looking at either an unconditional jump, or a fake edge to exit. */ if (single_succ_p (bb1) --- gcc/testsuite/gcc.target/i386/pr88470.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr88470.c (revision 267112) @@ -0,0 +1,16 @@ +/* PR rtl-optimization/88470 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -maccumulate-outgoing-args -ftrapv -fno-ivopts -fno-reorder-blocks-and-partition" } */ + +void +foo (long x, long *y) +{ + long *a = y - 64, i; + for (i = 0; i < x; i++) + { + long v = y[i]; + *a++ = v; + } + register void **c __asm__ ("di"); + goto **c; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-14 Jakub Jelinek <ja...@redhat.com> PR c++/82294 PR c++/87436 * init.c (build_vec_init): Change num_initialized_elts type from int to HOST_WIDE_INT. Build a RANGE_EXPR if e needs to be repeated more than once. --- gcc/cp/init.c (revision 267141) +++ gcc/cp/init.c (revision 267142) @@ -4104,7 +4104,7 @@ build_vec_init (tree base, tree maxindex tree compound_stmt; int destroy_temps; tree try_block = NULL_TREE; - int num_initialized_elts = 0; + HOST_WIDE_INT num_initialized_elts = 0; bool is_global; tree obase = base; bool xvalue = false; @@ -4539,10 +4539,13 @@ build_vec_init (tree base, tree maxindex if (e) { - int max = tree_to_shwi (maxindex)+1; - for (; num_initialized_elts < max; ++num_initialized_elts) + HOST_WIDE_INT last = tree_to_shwi (maxindex); + if (num_initialized_elts <= last) { tree field = size_int (num_initialized_elts); + if (num_initialized_elts != last) + field = build2 (RANGE_EXPR, sizetype, field, + size_int (last)); CONSTRUCTOR_APPEND_ELT (const_vec, field, e); } }
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-14 Jakub Jelinek <ja...@redhat.com> PR c++/82294 PR c++/87436 * expr.h (categorize_ctor_elements): Add p_unique_nz_elts argument. * expr.c (categorize_ctor_elements_1): Likewise. Compute it like p_nz_elts, except don't multiply it by mult. Adjust recursive call. Fix up COMPLEX_CST handling. (categorize_ctor_elements): Add p_unique_nz_elts argument, initialize it and pass it through to categorize_ctor_elements_1. (mostly_zeros_p, all_zeros_p): Adjust categorize_ctor_elements callers. * gimplify.c (gimplify_init_constructor): Likewise. Don't force ctor into readonly data section if num_unique_nonzero_elements is smaller or equal to 1/8 of num_nonzero_elements and size is >= 64 bytes. * g++.dg/tree-ssa/pr82294.C: New test. * g++.dg/tree-ssa/pr87436.C: New test. --- gcc/expr.c (revision 267142) +++ gcc/expr.c (revision 267143) @@ -5945,10 +5945,11 @@ count_type_elements (const_tree type, bo static bool categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts, + HOST_WIDE_INT *p_unique_nz_elts, HOST_WIDE_INT *p_init_elts, bool *p_complete) { unsigned HOST_WIDE_INT idx; - HOST_WIDE_INT nz_elts, init_elts, num_fields; + HOST_WIDE_INT nz_elts, unique_nz_elts, init_elts, num_fields; tree value, purpose, elt_type; /* Whether CTOR is a valid constant initializer, in accordance with what @@ -5958,6 +5959,7 @@ categorize_ctor_elements_1 (const_tree c bool const_p = const_from_elts_p ? true : TREE_STATIC (ctor); nz_elts = 0; + unique_nz_elts = 0; init_elts = 0; num_fields = 0; elt_type = NULL_TREE; @@ -5982,12 +5984,13 @@ categorize_ctor_elements_1 (const_tree c { case CONSTRUCTOR: { - HOST_WIDE_INT nz = 0, ic = 0; + HOST_WIDE_INT nz = 0, unz = 0, ic = 0; - bool const_elt_p = categorize_ctor_elements_1 (value, &nz, &ic, - p_complete); + bool const_elt_p = categorize_ctor_elements_1 (value, &nz, &unz, + &ic, p_complete); nz_elts += mult * nz; + unique_nz_elts += unz; init_elts += mult * ic; if (const_from_elts_p && const_p) @@ -5999,21 +6002,31 @@ categorize_ctor_elements_1 (const_tree c case REAL_CST: case FIXED_CST: if (!initializer_zerop (value)) - nz_elts += mult; + { + nz_elts += mult; + unique_nz_elts++; + } init_elts += mult; break; case STRING_CST: nz_elts += mult * TREE_STRING_LENGTH (value); + unique_nz_elts += TREE_STRING_LENGTH (value); init_elts += mult * TREE_STRING_LENGTH (value); break; case COMPLEX_CST: if (!initializer_zerop (TREE_REALPART (value))) - nz_elts += mult; + { + nz_elts += mult; + unique_nz_elts++; + } if (!initializer_zerop (TREE_IMAGPART (value))) - nz_elts += mult; - init_elts += mult; + { + nz_elts += mult; + unique_nz_elts++; + } + init_elts += 2 * mult; break; case VECTOR_CST: @@ -6025,7 +6038,10 @@ categorize_ctor_elements_1 (const_tree c { tree v = VECTOR_CST_ELT (value, i); if (!initializer_zerop (v)) - nz_elts += mult; + { + nz_elts += mult; + unique_nz_elts++; + } init_elts += mult; } } @@ -6035,6 +6051,7 @@ categorize_ctor_elements_1 (const_tree c { HOST_WIDE_INT tc = count_type_elements (elt_type, false); nz_elts += mult * tc; + unique_nz_elts += tc; init_elts += mult * tc; if (const_from_elts_p && const_p) @@ -6054,6 +6071,7 @@ categorize_ctor_elements_1 (const_tree c *p_complete = false; *p_nz_elts += nz_elts; + *p_unique_nz_elts += unique_nz_elts; *p_init_elts += init_elts; return const_p; @@ -6062,6 +6080,11 @@ categorize_ctor_elements_1 (const_tree c /* Examine CTOR to discover: * how many scalar fields are set to nonzero values, and place it in *P_NZ_ELTS; + * the same, but counting RANGE_EXPRs as multiplier of 1 instead of + high - low + 1 (this can be useful for callers to determine ctors + that could be cheaply initialized with - perhaps nested - loops + compared to copied from huge read-only data), + and place it in *P_UNIQUE_NZ_ELTS; * how many scalar fields in total are in CTOR, and place it in *P_ELT_COUNT. * whether the constructor is complete -- in the sense that every @@ -6073,13 +6096,16 @@ categorize_ctor_elements_1 (const_tree c bool categorize_ctor_elements (const_tree ctor, HOST_WIDE_INT *p_nz_elts, + HOST_WIDE_INT *p_unique_nz_elts, HOST_WIDE_INT *p_init_elts, bool *p_complete) { *p_nz_elts = 0; + *p_unique_nz_elts = 0; *p_init_elts = 0; *p_complete = true; - return categorize_ctor_elements_1 (ctor, p_nz_elts, p_init_elts, p_complete); + return categorize_ctor_elements_1 (ctor, p_nz_elts, p_unique_nz_elts, + p_init_elts, p_complete); } /* TYPE is initialized by a constructor with NUM_ELTS elements, the last @@ -6110,17 +6136,18 @@ complete_ctor_at_level_p (const_tree typ return count_type_elements (type, true) == num_elts; } -/* Return 1 if EXP contains mostly (3/4) zeros. */ +/* Return 1 if EXP contains mostly (3/4) zeros. */ static int mostly_zeros_p (const_tree exp) { if (TREE_CODE (exp) == CONSTRUCTOR) { - HOST_WIDE_INT nz_elts, init_elts; + HOST_WIDE_INT nz_elts, unz_elts, init_elts; bool complete_p; - categorize_ctor_elements (exp, &nz_elts, &init_elts, &complete_p); + categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts, + &complete_p); return !complete_p || nz_elts < init_elts / 4; } @@ -6134,10 +6161,11 @@ all_zeros_p (const_tree exp) { if (TREE_CODE (exp) == CONSTRUCTOR) { - HOST_WIDE_INT nz_elts, init_elts; + HOST_WIDE_INT nz_elts, unz_elts, init_elts; bool complete_p; - categorize_ctor_elements (exp, &nz_elts, &init_elts, &complete_p); + categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts, + &complete_p); return nz_elts == 0; } --- gcc/expr.h (revision 267142) +++ gcc/expr.h (revision 267143) @@ -309,7 +309,8 @@ extern bool can_move_by_pieces (unsigned extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree); extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *, - HOST_WIDE_INT *, bool *); + HOST_WIDE_INT *, HOST_WIDE_INT *, + bool *); extern void expand_operands (tree, tree, rtx, rtx*, rtx*, enum expand_modifier); --- gcc/gimplify.c (revision 267142) +++ gcc/gimplify.c (revision 267143) @@ -4778,7 +4778,15 @@ gimplify_init_constructor (tree *expr_p, { struct gimplify_init_ctor_preeval_data preeval_data; HOST_WIDE_INT num_ctor_elements, num_nonzero_elements; + HOST_WIDE_INT num_unique_nonzero_elements; bool cleared, complete_p, valid_const_initializer; + /* Use readonly data for initializers of this or smaller size + regardless of the num_nonzero_elements / num_unique_nonzero_elements + ratio. */ + const HOST_WIDE_INT min_unique_size = 64; + /* If num_nonzero_elements / num_unique_nonzero_elements ratio + is smaller than this, use readonly data. */ + const int unique_nonzero_ratio = 8; /* Aggregate types must lower constructors to initialization of individual elements. The exception is that a CONSTRUCTOR node @@ -4795,6 +4803,7 @@ gimplify_init_constructor (tree *expr_p, can only do so if it known to be a valid constant initializer. */ valid_const_initializer = categorize_ctor_elements (ctor, &num_nonzero_elements, + &num_unique_nonzero_elements, &num_ctor_elements, &complete_p); /* If a const aggregate variable is being initialized, then it @@ -4803,7 +4812,15 @@ gimplify_init_constructor (tree *expr_p, && num_nonzero_elements > 1 && TREE_READONLY (object) && VAR_P (object) - && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object))) + && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)) + /* For ctors that have many repeated nonzero elements + represented through RANGE_EXPRs, prefer initializing + those through runtime loops over copies of large amounts + of data from readonly data section. */ + && (num_unique_nonzero_elements + > num_nonzero_elements / unique_nonzero_ratio + || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type) + <= (unsigned HOST_WIDE_INT) min_unique_size))) { if (notify_temp_creation) return GS_ERROR; @@ -4896,6 +4913,13 @@ gimplify_init_constructor (tree *expr_p, is so large as to make individual moves inefficient. */ if (size > 0 && num_nonzero_elements > 1 + /* For ctors that have many repeated nonzero elements + represented through RANGE_EXPRs, prefer initializing + those through runtime loops over copies of large amounts + of data from readonly data section. */ + && (num_unique_nonzero_elements + > num_nonzero_elements / unique_nonzero_ratio + || size <= min_unique_size) && (size < num_nonzero_elements || !can_move_by_pieces (size, align))) { --- gcc/testsuite/g++.dg/tree-ssa/pr82294.C (nonexistent) +++ gcc/testsuite/g++.dg/tree-ssa/pr82294.C (revision 267143) @@ -0,0 +1,13 @@ +// PR c++/82294 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -fdump-tree-gimple" } + +// Verify we don't "optimize" the ctor as copying a 1KB .rodata +// object into the variable. It is better to initialize it through +// a loop. +// { dg-final { scan-tree-dump-not "this->arr = " "gimple" } } + +struct S { int x; explicit constexpr S (); }; +constexpr S::S () : x{7} {} +struct T { S arr[256]; explicit T (); }; +T::T () {} --- gcc/testsuite/g++.dg/tree-ssa/pr87436.C (nonexistent) +++ gcc/testsuite/g++.dg/tree-ssa/pr87436.C (revision 267143) @@ -0,0 +1,25 @@ +// PR c++/87436 +// { dg-do compile { target { c++11 && size32plus } } } +// { dg-options "-O2 -fdump-tree-gimple" } + +// Verify we don't "optimize" the ctor as copying a 384MB .rodata +// object into the variable. It is better to initialize it through +// two nested loops. +// { dg-final { scan-tree-dump-not "this->arr = " "gimple" } } + +struct S { + int a = -1; + short b = 3; + int x = 0; + int y = 1; + int z = 42; + float f = 0.123f; +}; + +struct T { S arr[4096][4096]; }; + +T * +foo () +{ + return new T; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-17 Jakub Jelinek <ja...@redhat.com> PR c++/88410 * cp-gimplify.c (cp_fold) <case ADDR_EXPR>: For offsetof-like folding, call maybe_constant_value on val to see if it is INTEGER_CST. * g++.dg/cpp0x/pr88410.C: New test. --- gcc/cp/cp-gimplify.c (revision 267219) +++ gcc/cp/cp-gimplify.c (revision 267220) @@ -2317,6 +2317,7 @@ cp_fold (tree x) { val = TREE_OPERAND (val, 0); STRIP_NOPS (val); + val = maybe_constant_value (val); if (TREE_CODE (val) == INTEGER_CST) return fold_offsetof (op0, TREE_TYPE (x)); } --- gcc/testsuite/g++.dg/cpp0x/pr88410.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/pr88410.C (revision 267220) @@ -0,0 +1,7 @@ +// PR c++/88410 +// { dg-do compile { target c++11 } } + +typedef __UINTPTR_TYPE__ uintptr_t; +const uintptr_t a = 32; +struct C { int b; int c; }; +uintptr_t d { uintptr_t (&reinterpret_cast<C *>(a)->c) - a };
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-19 Jakub Jelinek <ja...@redhat.com> PR c++/87934 * constexpr.c (cxx_eval_constant_expression) <case CONSTRUCTOR>: Do re-process TREE_CONSTANT CONSTRUCTORs if they aren't reduced constant expressions. * g++.dg/cpp0x/constexpr-87934.C: New test. --- gcc/cp/constexpr.c (revision 267252) +++ gcc/cp/constexpr.c (revision 267253) @@ -4681,7 +4681,7 @@ cxx_eval_constant_expression (const cons break; case CONSTRUCTOR: - if (TREE_CONSTANT (t)) + if (TREE_CONSTANT (t) && reduced_constant_expression_p (t)) { /* Don't re-process a constant CONSTRUCTOR, but do fold it to VECTOR_CST if applicable. */ --- gcc/testsuite/g++.dg/cpp0x/constexpr-87934.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-87934.C (revision 267253) @@ -0,0 +1,9 @@ +// PR c++/87934 +// { dg-do compile { target c++11 } } + +struct Foo +{ + enum { BAR } bar = BAR; +}; + +constexpr Foo foo{};
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-19 Jakub Jelinek <ja...@redhat.com> PR target/88541 * config/i386/vpclmulqdqintrin.h (_mm256_clmulepi64_epi128): Enable for -mavx -mvpclmulqdq rather than just for -mavx512vl -mvpclmulqdq. * gcc.target/i386/avx-vpclmulqdq-1.c: New test. --- gcc/config/i386/vpclmulqdqintrin.h (revision 267253) +++ gcc/config/i386/vpclmulqdqintrin.h (revision 267254) @@ -53,9 +53,9 @@ _mm512_clmulepi64_epi128 (__m512i __A, _ #pragma GCC pop_options #endif /* __DISABLE_VPCLMULQDQF__ */ -#if !defined(__VPCLMULQDQ__) || !defined(__AVX512VL__) +#if !defined(__VPCLMULQDQ__) || !defined(__AVX__) #pragma GCC push_options -#pragma GCC target("vpclmulqdq,avx512vl") +#pragma GCC target("vpclmulqdq,avx") #define __DISABLE_VPCLMULQDQ__ #endif /* __VPCLMULQDQ__ */ @@ -78,6 +78,4 @@ _mm256_clmulepi64_epi128 (__m256i __A, _ #pragma GCC pop_options #endif /* __DISABLE_VPCLMULQDQ__ */ - #endif /* _VPCLMULQDQINTRIN_H_INCLUDED */ - --- gcc/testsuite/gcc.target/i386/avx-vpclmulqdq-1.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/avx-vpclmulqdq-1.c (revision 267254) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx -mvpclmulqdq" } */ + +#include <x86intrin.h> + +__m256i +foo (__m256i x, __m256i y) +{ + return _mm256_clmulepi64_epi128 (x, y, 0); +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-20 Jakub Jelinek <ja...@redhat.com> PR c++/88180 * parser.c (cp_parser_class_specifier_1): If cp_parser_check_type_definition fails, skip default arguments, NSDMIs, etc. like for erroneous template args. * g++.dg/parse/pr88180.C: New test. * g++.dg/pr85039-1.C: Don't expect diagnostics inside of the type definition's NSDMIs. --- gcc/cp/parser.c (revision 267305) +++ gcc/cp/parser.c (revision 267306) @@ -23167,7 +23167,7 @@ cp_parser_class_specifier_1 (cp_parser* cp_ensure_no_oacc_routine (parser); /* Issue an error message if type-definitions are forbidden here. */ - cp_parser_check_type_definition (parser); + bool type_definition_ok_p = cp_parser_check_type_definition (parser); /* Remember that we are defining one more class. */ ++parser->num_classes_being_defined; /* Inside the class, surrounding template-parameter-lists do not @@ -23362,7 +23362,7 @@ cp_parser_class_specifier_1 (cp_parser* cp_default_arg_entry *e; tree save_ccp, save_ccr; - if (any_erroneous_template_args_p (type)) + if (!type_definition_ok_p || any_erroneous_template_args_p (type)) { /* Skip default arguments, NSDMIs, etc, in order to improve error recovery (c++/71169, c++/71832). */ --- gcc/testsuite/g++.dg/pr85039-1.C (revision 267305) +++ gcc/testsuite/g++.dg/pr85039-1.C (revision 267306) @@ -5,9 +5,9 @@ constexpr int a() { __builtin_offsetof(struct { // { dg-error "types may not be defined" } int i; short b { - __builtin_offsetof(struct { // { dg-error "types may not be defined" } + __builtin_offsetof(struct { int j; - struct c { // { dg-error "types may not be defined" } + struct c { void d() { } }; --- gcc/testsuite/g++.dg/parse/pr88180.C (nonexistent) +++ gcc/testsuite/g++.dg/parse/pr88180.C (revision 267306) @@ -0,0 +1,12 @@ +// PR c++/88180 +// { dg-do compile } +// { dg-options "--param ggc-min-heapsize=1024" } + +struct d { + static d *b; +} * d::b(__builtin_offsetof(struct { // { dg-error "types may not be defined" } + int i; + struct a { // { dg-error "types may not be defined" } + int c() { return .1f; } + }; +}, i));
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-21 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/88563 * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Swap innermode and mode arguments to convert_modes. Likewise swap mode and word_mode arguments. Handle both arguments with VOIDmode before convert_modes of one of them. Formatting fixes. * gcc.dg/pr88563.c: New test. --- gcc/expr.c (revision 267325) +++ gcc/expr.c (revision 267326) @@ -8775,8 +8775,8 @@ expand_expr_real_2 (sepops ops, rtx targ != INTEGER_CST check. Handle it. */ if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) { - op0 = convert_modes (innermode, mode, op0, true); - op1 = convert_modes (innermode, mode, op1, false); + op0 = convert_modes (mode, innermode, op0, true); + op1 = convert_modes (mode, innermode, op1, false); return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp)); } @@ -8798,7 +8798,7 @@ expand_expr_real_2 (sepops ops, rtx targ if (TREE_CODE (treeop0) != INTEGER_CST) { if (find_widening_optab_handler (this_optab, mode, innermode) - != CODE_FOR_nothing) + != CODE_FOR_nothing) { expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); @@ -8807,9 +8807,9 @@ expand_expr_real_2 (sepops ops, rtx targ if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) { widen_mult_const: - op0 = convert_modes (innermode, mode, op0, zextend_p); + op0 = convert_modes (mode, innermode, op0, zextend_p); op1 - = convert_modes (innermode, mode, op1, + = convert_modes (mode, innermode, op1, TYPE_UNSIGNED (TREE_TYPE (treeop1))); return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, @@ -8820,21 +8820,19 @@ expand_expr_real_2 (sepops ops, rtx targ return REDUCE_BIT_FIELD (temp); } if (find_widening_optab_handler (other_optab, mode, innermode) - != CODE_FOR_nothing + != CODE_FOR_nothing && innermode == word_mode) { rtx htem, hipart; op0 = expand_normal (treeop0); - if (TREE_CODE (treeop1) == INTEGER_CST) - op1 = convert_modes (word_mode, mode, - expand_normal (treeop1), - TYPE_UNSIGNED (TREE_TYPE (treeop1))); - else - op1 = expand_normal (treeop1); - /* op0 and op1 might still be constant, despite the above + op1 = expand_normal (treeop1); + /* op0 and op1 might be constants, despite the above != INTEGER_CST check. Handle it. */ if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) goto widen_mult_const; + if (TREE_CODE (treeop1) == INTEGER_CST) + op1 = convert_modes (mode, word_mode, op1, + TYPE_UNSIGNED (TREE_TYPE (treeop1))); temp = expand_binop (mode, other_optab, op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); hipart = gen_highpart (word_mode, temp); --- gcc/testsuite/gcc.dg/pr88563.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr88563.c (revision 267326) @@ -0,0 +1,15 @@ +/* PR rtl-optimization/88563 */ +/* { dg-do run { target int128 } } */ +/* { dg-options "-O2 -fno-code-hoisting -fno-tree-ccp -fno-tree-dominator-opts -fno-tree-forwprop -fno-tree-fre -fno-tree-pre -fno-tree-vrp" } */ + +int +main () +{ +#if __SIZEOF_LONG_LONG__ == 8 && __SIZEOF_INT128__ == 16 && __CHAR_BIT__ == 8 + unsigned __int128 a = 5; + __builtin_mul_overflow (0xffffffffffffffffULL, (unsigned long long) a, &a); + if (a != ((unsigned __int128)4 << 64 | 0xfffffffffffffffb)) + __builtin_abort (); +#endif + return 0; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-21 Jakub Jelinek <ja...@redhat.com> PR target/88522 * config/i386/sse.md (*avx512pf_gatherpf<mode>sf_mask, *avx512pf_gatherpf<mode>df_mask, *avx512pf_scatterpf<mode>sf_mask, *avx512pf_scatterpf<mode>df_mask): Use %X5 instead of %5 for -masm=intel. (gatherq_mode): Remove mode iterator. (*avx512f_gathersi<mode>, *avx512f_gathersi<mode>_2): Use X instead of <xtg_mode>. (*avx512f_gatherdi<mode>): Use X instead of <gatherq_mode>. (*avx512f_gatherdi<mode>_2, *avx512f_scattersi<mode>, *avx512f_scatterdi<mode>): Use %X5 for -masm=intel. --- gcc/config/i386/sse.md (revision 267326) +++ gcc/config/i386/sse.md (revision 267327) @@ -17269,9 +17269,11 @@ (define_insn "*avx512pf_gatherpf<mode>sf switch (INTVAL (operands[4])) { case 3: - return "vgatherpf0<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}"; + /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as + gas changed what it requires incompatibly. */ + return "vgatherpf0<ssemodesuffix>ps\t{%5%{%0%}|%X5%{%0%}}"; case 2: - return "vgatherpf1<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}"; + return "vgatherpf1<ssemodesuffix>ps\t{%5%{%0%}|%X5%{%0%}}"; default: gcc_unreachable (); } @@ -17314,9 +17316,11 @@ (define_insn "*avx512pf_gatherpf<mode>df switch (INTVAL (operands[4])) { case 3: - return "vgatherpf0<ssemodesuffix>pd\t{%5%{%0%}|%5%{%0%}}"; + /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as + gas changed what it requires incompatibly. */ + return "vgatherpf0<ssemodesuffix>pd\t{%5%{%0%}|%X5%{%0%}}"; case 2: - return "vgatherpf1<ssemodesuffix>pd\t{%5%{%0%}|%5%{%0%}}"; + return "vgatherpf1<ssemodesuffix>pd\t{%5%{%0%}|%X5%{%0%}}"; default: gcc_unreachable (); } @@ -17360,10 +17364,12 @@ (define_insn "*avx512pf_scatterpf<mode>s { case 3: case 7: - return "vscatterpf0<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}"; + /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as + gas changed what it requires incompatibly. */ + return "vscatterpf0<ssemodesuffix>ps\t{%5%{%0%}|%X5%{%0%}}"; case 2: case 6: - return "vscatterpf1<ssemodesuffix>ps\t{%5%{%0%}|%5%{%0%}}"; + return "vscatterpf1<ssemodesuffix>ps\t{%5%{%0%}|%X5%{%0%}}"; default: gcc_unreachable (); } @@ -17407,10 +17413,12 @@ (define_insn "*avx512pf_scatterpf<mode>d { case 3: case 7: - return "vscatterpf0<ssemodesuffix>pd\t{%5%{%0%}|%5%{%0%}}"; + /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as + gas changed what it requires incompatibly. */ + return "vscatterpf0<ssemodesuffix>pd\t{%5%{%0%}|%X5%{%0%}}"; case 2: case 6: - return "vscatterpf1<ssemodesuffix>pd\t{%5%{%0%}|%5%{%0%}}"; + return "vscatterpf1<ssemodesuffix>pd\t{%5%{%0%}|%X5%{%0%}}"; default: gcc_unreachable (); } @@ -20290,12 +20298,6 @@ (define_insn "*avx2_gatherdi<mode>_4" (set_attr "prefix" "vex") (set_attr "mode" "<sseinsnmode>")]) -;; Memory operand override for -masm=intel of the v*gatherq* patterns. -(define_mode_attr gatherq_mode - [(V4SI "q") (V2DI "x") (V4SF "q") (V2DF "x") - (V8SI "x") (V4DI "t") (V8SF "x") (V4DF "t") - (V16SI "t") (V8DI "g") (V16SF "t") (V8DF "g")]) - (define_expand "<avx512>_gathersi<mode>" [(parallel [(set (match_operand:VI48F 0 "register_operand") (unspec:VI48F @@ -20329,7 +20331,9 @@ (define_insn "*avx512f_gathersi<mode>" UNSPEC_GATHER)) (clobber (match_scratch:<avx512fmaskmode> 2 "=&Yk"))] "TARGET_AVX512F" - "v<sseintprefix>gatherd<ssemodesuffix>\t{%6, %0%{%2%}|%0%{%2%}, %<xtg_mode>6}" +;; %X6 so that we don't emit any *WORD PTR for -masm=intel, as +;; gas changed what it requires incompatibly. + "v<sseintprefix>gatherd<ssemodesuffix>\t{%6, %0%{%2%}|%0%{%2%}, %X6}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) @@ -20348,7 +20352,9 @@ (define_insn "*avx512f_gathersi<mode>_2" UNSPEC_GATHER)) (clobber (match_scratch:<avx512fmaskmode> 1 "=&Yk"))] "TARGET_AVX512F" - "v<sseintprefix>gatherd<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %<xtg_mode>5}" +;; %X5 so that we don't emit any *WORD PTR for -masm=intel, as +;; gas changed what it requires incompatibly. + "v<sseintprefix>gatherd<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %X5}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) @@ -20387,9 +20393,9 @@ (define_insn "*avx512f_gatherdi<mode>" UNSPEC_GATHER)) (clobber (match_scratch:QI 2 "=&Yk"))] "TARGET_AVX512F" -{ - return "v<sseintprefix>gatherq<ssemodesuffix>\t{%6, %1%{%2%}|%1%{%2%}, %<gatherq_mode>6}"; -} +;; %X6 so that we don't emit any *WORD PTR for -masm=intel, as +;; gas changed what it requires incompatibly. + "v<sseintprefix>gatherq<ssemodesuffix>\t{%6, %1%{%2%}|%1%{%2%}, %X6}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) @@ -20409,14 +20415,16 @@ (define_insn "*avx512f_gatherdi<mode>_2" (clobber (match_scratch:QI 1 "=&Yk"))] "TARGET_AVX512F" { + /* %X5 so that we don't emit any *WORD PTR for -masm=intel, as + gas changed what it requires incompatibly. */ if (<MODE>mode != <VEC_GATHER_SRCDI>mode) { if (<MODE_SIZE> != 64) - return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %x0%{%1%}|%x0%{%1%}, %<gatherq_mode>5}"; + return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %x0%{%1%}|%x0%{%1%}, %X5}"; else - return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %t0%{%1%}|%t0%{%1%}, %t5}"; + return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %t0%{%1%}|%t0%{%1%}, %X5}"; } - return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %<gatherq_mode>5}"; + return "v<sseintprefix>gatherq<ssemodesuffix>\t{%5, %0%{%1%}|%0%{%1%}, %X5}"; } [(set_attr "type" "ssemov") (set_attr "prefix" "evex") @@ -20453,7 +20461,9 @@ (define_insn "*avx512f_scattersi<mode>" UNSPEC_SCATTER)) (clobber (match_scratch:<avx512fmaskmode> 1 "=&Yk"))] "TARGET_AVX512F" - "v<sseintprefix>scatterd<ssemodesuffix>\t{%3, %5%{%1%}|%5%{%1%}, %3}" +;; %X5 so that we don't emit any *WORD PTR for -masm=intel, as +;; gas changed what it requires incompatibly. + "v<sseintprefix>scatterd<ssemodesuffix>\t{%3, %5%{%1%}|%X5%{%1%}, %3}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) @@ -20489,11 +20499,9 @@ (define_insn "*avx512f_scatterdi<mode>" UNSPEC_SCATTER)) (clobber (match_scratch:QI 1 "=&Yk"))] "TARGET_AVX512F" -{ - if (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) == 8) - return "v<sseintprefix>scatterq<ssemodesuffix>\t{%3, %5%{%1%}|%5%{%1%}, %3}"; - return "v<sseintprefix>scatterq<ssemodesuffix>\t{%3, %5%{%1%}|%t5%{%1%}, %3}"; -} +;; %X5 so that we don't emit any *WORD PTR for -masm=intel, as +;; gas changed what it requires incompatibly. + "v<sseintprefix>scatterq<ssemodesuffix>\t{%3, %5%{%1%}|%X5%{%1%}, %3}" [(set_attr "type" "ssemov") (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")])
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-12-21 Jakub Jelinek <ja...@redhat.com> PR middle-end/85594 PR middle-end/88553 * omp-expand.c (extract_omp_for_update_vars): Regimplify the condition if needed. (expand_omp_for_generic): Don't clobber t temporary for ordered loops. * gcc.dg/gomp/pr85594.c: New test. * gcc.dg/gomp/pr88553.c: New test. --- gcc/omp-expand.c (revision 267338) +++ gcc/omp-expand.c (revision 267339) @@ -2076,6 +2076,11 @@ extract_omp_for_update_vars (struct omp_ t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t); stmt = gimple_build_cond_empty (t); gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); + if (walk_tree (gimple_cond_lhs_ptr (as_a <gcond *> (stmt)), + expand_omp_regimplify_p, NULL, NULL) + || walk_tree (gimple_cond_rhs_ptr (as_a <gcond *> (stmt)), + expand_omp_regimplify_p, NULL, NULL)) + gimple_regimplify_operands (stmt, &gsi); e = make_edge (bb, body_bb, EDGE_TRUE_VALUE); e->probability = profile_probability::guessed_always ().apply_scale (7, 8); } @@ -3209,20 +3214,21 @@ expand_omp_for_generic (struct omp_regio if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE) { + tree tem; if (fd->collapse > 1) - t = fd->loop.v; + tem = fd->loop.v; else { - t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v), - fd->loops[0].v, fd->loops[0].n1); - t = fold_convert (fd->iter_type, t); + tem = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v), + fd->loops[0].v, fd->loops[0].n1); + tem = fold_convert (fd->iter_type, tem); } tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered], size_zero_node, NULL_TREE, NULL_TREE); - t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, - true, GSI_SAME_STMT); - expand_omp_build_assign (&gsi, aref, t); + tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, + true, GSI_SAME_STMT); + expand_omp_build_assign (&gsi, aref, tem); } t = build2 (fd->loop.cond_code, boolean_type_node, --- gcc/testsuite/gcc.dg/gomp/pr85594.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr85594.c (revision 267339) @@ -0,0 +1,5 @@ +/* PR middle-end/85594 */ +/* { dg-do compile } */ +/* { dg-additional-options "-fwrapv" } */ + +#include "pr81768-2.c" --- gcc/testsuite/gcc.dg/gomp/pr88553.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr88553.c (revision 267339) @@ -0,0 +1,5 @@ +/* PR middle-end/88553 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O1 -ftree-loop-vectorize -fwrapv" } */ + +#include "pr81768-2.c"
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-01-03 Jakub Jelinek <ja...@redhat.com> PR debug/88644 * dwarf2out.c (modified_type_die): If type is equal to sizetype, change it to qualified_type. * gcc.dg/debug/dwarf2/pr88644.c: New test. 2019-01-03 Iain Sandoe <i...@sandoe.co.uk> * gcc.dg/pubtypes-2.c: Adjust expected pubtypes length. * gcc.dg/pubtypes-3.c: Likewise. * gcc.dg/pubtypes-4.c: Likewise. --- gcc/dwarf2out.c (revision 267549) +++ gcc/dwarf2out.c (revision 267550) @@ -13152,6 +13152,8 @@ modified_type_die (tree type, int cv_qua && TYPE_PRECISION (sizetype) == TYPE_PRECISION (size_type_node) && TYPE_UNSIGNED (sizetype) == TYPE_UNSIGNED (size_type_node)) qualified_type = size_type_node; + if (type == sizetype) + type = qualified_type; } /* If we do, then we can just use its DIE, if it exists. */ --- gcc/testsuite/gcc.dg/debug/dwarf2/pr88644.c (nonexistent) +++ gcc/testsuite/gcc.dg/debug/dwarf2/pr88644.c (revision 267550) @@ -0,0 +1,7 @@ +/* PR debug/88644 */ +/* { dg-do compile } */ +/* { dg-options "-gdwarf-4 -dA -gpubnames" } */ + +char array[1]; + +/* { dg-final { scan-assembler-not {\msizetype} } } */ --- gcc/testsuite/gcc.dg/pubtypes-2.c (revision 267549) +++ gcc/testsuite/gcc.dg/pubtypes-2.c (revision 267550) @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x13b+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler "long+\[ \t\]+0x12e+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ --- gcc/testsuite/gcc.dg/pubtypes-3.c (revision 267549) +++ gcc/testsuite/gcc.dg/pubtypes-3.c (revision 267550) @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x13b+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler "long+\[ \t\]+0x12e+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ --- gcc/testsuite/gcc.dg/pubtypes-4.c (revision 267549) +++ gcc/testsuite/gcc.dg/pubtypes-4.c (revision 267550) @@ -2,7 +2,7 @@ /* { dg-options "-O0 -gdwarf-2 -dA" } */ /* { dg-skip-if "Unmatchable assembly" { mmix-*-* } } */ /* { dg-final { scan-assembler "__debug_pubtypes" } } */ -/* { dg-final { scan-assembler "long+\[ \t\]+0x172+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ +/* { dg-final { scan-assembler "long+\[ \t\]+0x165+\[ \t\]+\[#;]+\[ \t\]+Pub Info Length" } } */ /* { dg-final { scan-assembler "used_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler-not "unused_struct\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */ /* { dg-final { scan-assembler "\"list_name_type\\\\0\"+\[ \t\]+\[#;]+\[ \t\]+external name" } } */
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-01-04 Jakub Jelinek <ja...@redhat.com> PR target/88594 * config/i386/i386.c (ix86_expand_divmod_libfunc): Use mode instead of GET_MODE (opN) as modes of the libcall arguments. * gcc.dg/pr88594.c: New test. --- gcc/config/i386/i386.c (revision 267570) +++ gcc/config/i386/i386.c (revision 267571) @@ -51014,9 +51014,7 @@ ix86_expand_divmod_libfunc (rtx libfunc, rtx rem = assign_386_stack_local (mode, SLOT_TEMP); rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL, - mode, - op0, GET_MODE (op0), - op1, GET_MODE (op1), + mode, op0, mode, op1, mode, XEXP (rem, 0), Pmode); *quot_p = quot; *rem_p = rem; --- gcc/testsuite/gcc.dg/pr88594.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr88594.c (revision 267571) @@ -0,0 +1,16 @@ +/* PR target/88594 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fno-tree-forwprop -fno-tree-vrp" } */ + +__int128 +foo (__int128 x, __int128 *y) +{ + int a; + __int128 z, r; + for (a = 0; a < 17; ++a) + ; + z = x / a; + r = x % a; + *y = z; + return r; +}
2019-01-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-01-05 Jakub Jelinek <ja...@redhat.com> PR middle-end/82564 PR target/88620 * expr.c (expand_assignment): For calls returning VLA structures if to_rtx is not a MEM, force it into a stack temporary. * gcc.dg/nested-func-12.c: New test. * gcc.c-torture/compile/pr82564.c: New test. --- gcc/expr.c (revision 267594) +++ gcc/expr.c (revision 267595) @@ -5254,6 +5254,21 @@ expand_assignment (tree to, tree from, b emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true)); } } + /* For calls to functions returning variable length structures, if TO_RTX + is not a MEM, go through a MEM because we must not create temporaries + of the VLA type. */ + else if (!MEM_P (to_rtx) + && TREE_CODE (from) == CALL_EXPR + && COMPLETE_TYPE_P (TREE_TYPE (from)) + && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) != INTEGER_CST) + { + rtx temp = assign_stack_temp (GET_MODE (to_rtx), + GET_MODE_SIZE (GET_MODE (to_rtx))); + result = store_field (temp, bitsize, bitpos, bitregion_start, + bitregion_end, mode1, from, get_alias_set (to), + nontemporal, reversep); + emit_move_insn (to_rtx, temp); + } else { if (MEM_P (to_rtx)) --- gcc/testsuite/gcc.c-torture/compile/pr82564.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr82564.c (revision 267595) @@ -0,0 +1,15 @@ +/* PR middle-end/82564 */ +/* { dg-require-effective-target alloca } */ + +int +main () +{ + int t = 8, i; + typedef struct { char v[t]; } B; + B a, b; + B __attribute__ ((noinline)) f () { return b; } + for (i = 0; i < 8; i++) + b.v[i] = i; + a = f (); + return 0; +} --- gcc/testsuite/gcc.dg/nested-func-12.c (nonexistent) +++ gcc/testsuite/gcc.dg/nested-func-12.c (revision 267595) @@ -0,0 +1,48 @@ +/* PR target/88620 */ +/* { dg-do run } */ +/* { dg-options "-Ofast --param ipa-cp-eval-threshold=0 -fno-guess-branch-probability -fno-inline-small-functions" } */ +/* { dg-require-effective-target alloca } */ + +void +foo (int n) +{ + struct S { int a[n]; }; + + struct S + fn (void) + { + struct S s; + s.a[0] = 42; + return s; + } + + auto struct S + fn2 (void) + { + return fn (); + } + + struct S x; + fn (); + fn2 (); + x = fn (); + + if (x.a[0] != 42) + __builtin_abort (); + + if (fn ().a[0] != 42) + __builtin_abort (); + + __typeof__ (fn ()) *p = &x; + if (p->a[0] != 42) + __builtin_abort (); + + if (fn2 ().a[0] != 42) + __builtin_abort (); +} + +int +main (void) +{ + foo (1); +}