Hi! I've backported 13 commits of mine and one from Richard. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to gcc-6-branch.
Jakub
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-06-30 Jakub Jelinek <ja...@redhat.com> PR target/81225 * config/i386/sse.md (vec_extract_lo_<mode><mask_name>): For V8FI, V16FI and VI8F_256 iterators, use <store_mask_predicate> instead of nonimmediate_operand and <store_mask_constraint> instead of m for the input operand. For V8FI iterator, always split if input is a MEM. For V16FI and V8SF_256 iterators, don't test if both operands are MEM if <mask_applied>. For VI4F_256 iterator, use <store_mask_predicate> instead of register_operand and <store_mask_constraint> instead of v for the input operand. Make sure both operands aren't MEMs for if not <mask_applied>. * gcc.target/i386/pr81225.c: New test. --- gcc/config/i386/sse.md (revision 250284) +++ gcc/config/i386/sse.md (revision 250285) @@ -7230,12 +7230,13 @@ (define_insn "vec_extract_lo_<mode>_mask (define_insn "vec_extract_lo_<mode><mask_name>" [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=<store_mask_constraint>,v") (vec_select:<ssehalfvecmode> - (match_operand:V8FI 1 "nonimmediate_operand" "v,m") + (match_operand:V8FI 1 "<store_mask_predicate>" "v,<store_mask_constraint>") (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)])))] - "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "TARGET_AVX512F + && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))" { - if (<mask_applied> || !TARGET_AVX512VL) + if (<mask_applied> || (!TARGET_AVX512VL && !MEM_P (operands[1]))) return "vextract<shuffletype>64x4\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}"; else return "#"; @@ -7374,14 +7375,15 @@ (define_expand "avx_vextractf128<mode>" (define_insn "vec_extract_lo_<mode><mask_name>" [(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=v,m") (vec_select:<ssehalfvecmode> - (match_operand:V16FI 1 "nonimmediate_operand" "vm,v") + (match_operand:V16FI 1 "<store_mask_predicate>" + "<store_mask_constraint>,v") (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3) (const_int 4) (const_int 5) (const_int 6) (const_int 7)])))] "TARGET_AVX512F && <mask_mode512bit_condition> - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))" { if (<mask_applied>) return "vextract<shuffletype>32x8\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}"; @@ -7413,11 +7415,12 @@ (define_split (define_insn "vec_extract_lo_<mode><mask_name>" [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=v,m") (vec_select:<ssehalfvecmode> - (match_operand:VI8F_256 1 "nonimmediate_operand" "vm,v") + (match_operand:VI8F_256 1 "<store_mask_predicate>" + "<store_mask_constraint>,v") (parallel [(const_int 0) (const_int 1)])))] "TARGET_AVX && <mask_avx512vl_condition> && <mask_avx512dq_condition> - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))" { if (<mask_applied>) return "vextract<shuffletype>64x2\t{$0x0, %1, %0%{%3%}|%0%{%3%}, %1, 0x0}"; @@ -7493,12 +7496,16 @@ (define_split (define_insn "vec_extract_lo_<mode><mask_name>" - [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" "=<store_mask_constraint>") + [(set (match_operand:<ssehalfvecmode> 0 "<store_mask_predicate>" + "=<store_mask_constraint>,v") (vec_select:<ssehalfvecmode> - (match_operand:VI4F_256 1 "register_operand" "v") + (match_operand:VI4F_256 1 "<store_mask_predicate>" + "v,<store_mask_constraint>") (parallel [(const_int 0) (const_int 1) (const_int 2) (const_int 3)])))] - "TARGET_AVX && <mask_avx512vl_condition> && <mask_avx512dq_condition>" + "TARGET_AVX + && <mask_avx512vl_condition> && <mask_avx512dq_condition> + && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))" { if (<mask_applied>) return "vextract<shuffletype>32x4\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}"; --- gcc/testsuite/gcc.target/i386/pr81225.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr81225.c (revision 250285) @@ -0,0 +1,14 @@ +/* PR target/81225 */ +/* { dg-do compile } */ +/* { dg-options "-mavx512ifma -O3 -ffloat-store" } */ + +long a[24]; +float b[4], c[24]; +int d; + +void +foo () +{ + for (d = 0; d < 24; d++) + c[d] = (float) d ? : b[a[d]]; +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> PR libquadmath/65757 * math/roundq.c: Cherry-pick upstream glibc 2015-04-28 change. --- libquadmath/math/roundq.c (revision 250378) +++ libquadmath/math/roundq.c (revision 250379) @@ -1,5 +1,5 @@ /* Round __float128 to integer away from zero. - Copyright (C) 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1997-2017 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drep...@cygnus.com>, 1997 and Jakub Jelinek <j...@ultra.linux.cz>, 1999. @@ -32,7 +32,7 @@ roundq (__float128 x) GET_FLT128_WORDS64 (i0, i1, x); j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; - if (j0 < 31) + if (j0 < 48) { if (j0 < 0) {
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-08-08 Richard Biener <rguent...@suse.de> PR middle-end/81766 * function.c (thread_prologue_and_epilogue_insns): Restore behavior of always calling find_many_sub_basic_blocks on the inserted prologue. * gcc.target/i386/pr81766.c: New testcase. 2017-08-02 Jakub Jelinek <ja...@redhat.com> PR middle-end/79499 * function.c (thread_prologue_and_epilogue_insns): Determine blocks for find_many_sub_basic_blocks bitmap by looking up BLOCK_FOR_INSN of first NONDEBUG_INSN_P in each of the split_prologue_seq and prologue_seq sequences - if any. * gcc.dg/pr79499.c: New test. --- gcc/function.c (revision 250814) +++ gcc/function.c (revision 250958) @@ -6068,13 +6068,19 @@ thread_prologue_and_epilogue_insns (void try_shrink_wrapping (&entry_edge, &bb_flags, prologue_seq); + rtx_insn *split_prologue_insn = split_prologue_seq; if (split_prologue_seq != NULL_RTX) { + while (split_prologue_insn && !NONDEBUG_INSN_P (split_prologue_insn)) + split_prologue_insn = NEXT_INSN (split_prologue_insn); insert_insn_on_edge (split_prologue_seq, orig_entry_edge); inserted = true; } + rtx_insn *prologue_insn = prologue_seq; if (prologue_seq != NULL_RTX) { + while (prologue_insn && !NONDEBUG_INSN_P (prologue_insn)) + prologue_insn = NEXT_INSN (prologue_insn); insert_insn_on_edge (prologue_seq, entry_edge); inserted = true; } @@ -6215,8 +6221,19 @@ epilogue_done: commit_edge_insertions (); /* Look for basic blocks within the prologue insns. */ + if (split_prologue_insn + && BLOCK_FOR_INSN (split_prologue_insn) == NULL) + split_prologue_insn = NULL; + if (prologue_insn + && BLOCK_FOR_INSN (prologue_insn) == NULL) + prologue_insn = NULL; blocks = sbitmap_alloc (last_basic_block_for_fn (cfun)); bitmap_clear (blocks); + if (split_prologue_insn) + bitmap_set_bit (blocks, + BLOCK_FOR_INSN (split_prologue_insn)->index); + if (prologue_insn) + bitmap_set_bit (blocks, BLOCK_FOR_INSN (prologue_insn)->index); bitmap_set_bit (blocks, entry_edge->dest->index); bitmap_set_bit (blocks, orig_entry_edge->dest->index); find_many_sub_basic_blocks (blocks); --- gcc/testsuite/gcc.dg/pr79499.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr79499.c (revision 250815) @@ -0,0 +1,13 @@ +/* PR middle-end/79499 */ +/* { dg-do compile { target split_stack } } */ +/* { dg-options "-O2 -fsplit-stack -fno-omit-frame-pointer" } */ + +struct S { struct S *a, *b; }; + +void +foo (struct S *x) +{ + do + x->b = x->a; + while (x = x->a); +} --- gcc/testsuite/gcc.target/i386/pr81766.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr81766.c (revision 250958) @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -fPIE -mcmodel=large" } */ + +int main() { return 0; }
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-07-27 Jakub Jelinek <ja...@redhat.com> PR c/45784 * c-omp.c (c_finish_omp_for): If the condition is wrapped in rhs of COMPOUND_EXPR(s), skip them and readd their lhs into new COMPOUND_EXPRs around the rhs of the comparison. * testsuite/libgomp.c/pr45784.c: New test. * testsuite/libgomp.c++/pr45784.C: New test. --- gcc/c-family/c-omp.c (revision 251847) +++ gcc/c-family/c-omp.c (revision 251848) @@ -531,6 +531,12 @@ c_finish_omp_for (location_t locus, enum { bool cond_ok = false; + /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with + evaluation of the vla VAR_DECL. We need to readd + them to the non-decl operand. See PR45784. */ + while (TREE_CODE (cond) == COMPOUND_EXPR) + cond = TREE_OPERAND (cond, 1); + if (EXPR_HAS_LOCATION (cond)) elocus = EXPR_LOCATION (cond); @@ -605,6 +611,21 @@ c_finish_omp_for (location_t locus, enum else if (code != CILK_SIMD && code != CILK_FOR) cond_ok = false; } + + if (cond_ok && TREE_VEC_ELT (condv, i) != cond) + { + tree ce = NULL_TREE, *pce = &ce; + tree type = TREE_TYPE (TREE_OPERAND (cond, 1)); + for (tree c = TREE_VEC_ELT (condv, i); c != cond; + c = TREE_OPERAND (c, 1)) + { + *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0), + TREE_OPERAND (cond, 1)); + pce = &TREE_OPERAND (*pce, 1); + } + TREE_OPERAND (cond, 1) = ce; + TREE_VEC_ELT (condv, i) = cond; + } } if (!cond_ok) --- libgomp/testsuite/libgomp.c/pr45784.c (nonexistent) +++ libgomp/testsuite/libgomp.c/pr45784.c (revision 251848) @@ -0,0 +1,41 @@ +/* PR c/45784 */ +/* { dg-do run } */ + +void +foo (int n) +{ + char *p, vla[2 * n]; + int i; + #pragma omp parallel for + for (p = vla; p < vla + (sizeof (vla) / sizeof (vla[0])); p++) + *p = ' '; + #pragma omp parallel for + for (i = 0; i < 2 * n; i++) + if (vla[i] != ' ') + __builtin_abort (); +} + +void +bar (int n) +{ + char *p, vla1[n], vla2[n * 2], vla3[n * 3], vla4[n * 4]; + int i; + __builtin_memset (vla4, ' ', n * 4); + #pragma omp parallel for + for (p = vla4 + sizeof (vla1); p < vla4 + sizeof (vla3) - sizeof (vla2) + sizeof (vla1); p += sizeof (vla4) / sizeof (vla4)) + p[0] = '!'; + #pragma omp parallel for + for (i = 0; i < n * 4; i++) + if (vla4[i] != ((i >= n && i < 2 * n) ? '!' : ' ')) + __builtin_abort (); +} + +int +main () +{ + volatile int n; + n = 128; + foo (n); + bar (n); + return 0; +} --- libgomp/testsuite/libgomp.c++/pr45784.C (nonexistent) +++ libgomp/testsuite/libgomp.c++/pr45784.C (revision 251848) @@ -0,0 +1,5 @@ +// PR c/45784 +// { dg-do run } + +#include "../libgomp.c/pr45784.c" +
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-08-03 Jakub Jelinek <ja...@redhat.com> PR middle-end/81052 * omp-low.c (diagnose_sb_0): Handle flag_openmp_simd like flag_openmp. (pass_diagnose_omp_blocks::gate): Enable also for flag_openmp_simd. * c-c++-common/pr81052.c: New test. --- gcc/omp-low.c (revision 251848) +++ gcc/omp-low.c (revision 251849) @@ -9089,7 +9089,7 @@ diagnose_sb_0 (gimple_stmt_iterator *gsi } if (kind == NULL) { - gcc_checking_assert (flag_openmp); + gcc_checking_assert (flag_openmp || flag_openmp_simd); kind = "OpenMP"; } @@ -9349,7 +9349,7 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - return flag_cilkplus || flag_openacc || flag_openmp; + return flag_cilkplus || flag_openacc || flag_openmp || flag_openmp_simd; } virtual unsigned int execute (function *) { --- gcc/testsuite/c-c++-common/pr81052.c (nonexistent) +++ gcc/testsuite/c-c++-common/pr81052.c (revision 251849) @@ -0,0 +1,28 @@ +/* PR middle-end/81052 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp-simd -O2" } */ + +int +foo (int x, int y) +{ + int i; +#pragma omp simd + for (i = x; i < y; ++i) + return 0; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + return 1; +} + +#ifdef __cplusplus +template <typename T> +T +bar (T x, T y) +{ + T i; +#pragma omp simd + for (i = x; i < y; ++i) + return 0; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c++ } } */ + return 1; +} + +int x = bar (1, 7); +#endif
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-08-03 Jakub Jelinek <ja...@redhat.com> PR target/81621 * bb-reorder.c (pass_partition_blocks::execute): Return TODO_df_finish after setting changeable df flags. * gcc.dg/pr81621.c: New test. --- gcc/bb-reorder.c (revision 251850) +++ gcc/bb-reorder.c (revision 251851) @@ -2881,7 +2881,8 @@ pass_partition_blocks::execute (function crossing_edges = find_rarely_executed_basic_blocks_and_crossing_edges (); if (!crossing_edges.exists ()) - return 0; + /* Make sure to process deferred rescans and clear changeable df flags. */ + return TODO_df_finish; crtl->has_bb_partition = true; @@ -2947,7 +2948,8 @@ pass_partition_blocks::execute (function df_analyze (); } - return 0; + /* Make sure to process deferred rescans and clear changeable df flags. */ + return TODO_df_finish; } } // anon namespace --- gcc/testsuite/gcc.dg/pr81621.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr81621.c (revision 251851) @@ -0,0 +1,5 @@ +/* PR target/81621 */ +/* { dg-do compile { target freorder } } */ +/* { dg-options "-Og -fno-split-wide-types -freorder-blocks-and-partition" } */ + +#include "graphite/scop-10.c"
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-08-09 Jakub Jelinek <ja...@redhat.com> PR c/81687 * omp-low.c (omp_copy_decl): Don't remap FORCED_LABEL or DECL_NONLOCAL LABEL_DECLs. * tree-cfg.c (move_stmt_op): Don't adjust DECL_CONTEXT of FORCED_LABEL or DECL_NONLOCAL labels. (move_stmt_r) <case GIMPLE_LABEL>: Adjust DECL_CONTEXT of FORCED_LABEL or DECL_NONLOCAL labels here. * testsuite/libgomp.c/pr81687-1.c: New test. * testsuite/libgomp.c/pr81687-2.c: New test. --- gcc/omp-low.c (revision 251852) +++ gcc/omp-low.c (revision 251853) @@ -800,6 +800,8 @@ omp_copy_decl (tree var, copy_body_data if (TREE_CODE (var) == LABEL_DECL) { + if (FORCED_LABEL (var) || DECL_NONLOCAL (var)) + return var; new_var = create_artificial_label (DECL_SOURCE_LOCATION (var)); DECL_CONTEXT (new_var) = current_function_decl; insert_decl_map (&ctx->cb, var, new_var); --- gcc/tree-cfg.c (revision 251852) +++ gcc/tree-cfg.c (revision 251853) @@ -6667,7 +6667,15 @@ move_stmt_op (tree *tp, int *walk_subtre *tp = t = out->to; } - DECL_CONTEXT (t) = p->to_context; + /* For FORCED_LABELs we can end up with references from other + functions if some SESE regions are outlined. It is UB to + jump in between them, but they could be used just for printing + addresses etc. In that case, DECL_CONTEXT on the label should + be the function containing the glabel stmt with that LABEL_DECL, + rather than whatever function a reference to the label was seen + last time. */ + if (!FORCED_LABEL (t) && !DECL_NONLOCAL (t)) + DECL_CONTEXT (t) = p->to_context; } else if (p->remap_decls_p) { @@ -6785,6 +6793,21 @@ move_stmt_r (gimple_stmt_iterator *gsi_p case GIMPLE_OMP_RETURN: case GIMPLE_OMP_CONTINUE: break; + + case GIMPLE_LABEL: + { + /* For FORCED_LABEL, move_stmt_op doesn't adjust DECL_CONTEXT, + so that such labels can be referenced from other regions. + Make sure to update it when seeing a GIMPLE_LABEL though, + that is the owner of the label. */ + walk_gimple_op (stmt, move_stmt_op, wi); + *handled_ops_p = true; + tree label = gimple_label_label (as_a <glabel *> (stmt)); + if (FORCED_LABEL (label) || DECL_NONLOCAL (label)) + DECL_CONTEXT (label) = p->to_context; + } + break; + default: if (is_gimple_omp (stmt)) { --- libgomp/testsuite/libgomp.c/pr81687-1.c (nonexistent) +++ libgomp/testsuite/libgomp.c/pr81687-1.c (revision 251853) @@ -0,0 +1,23 @@ +/* PR c/81687 */ +/* { dg-do link } */ +/* { dg-additional-options "-O2" } */ + +extern int printf (const char *, ...); + +int +main () +{ + #pragma omp parallel + { + lab1: + printf ("lab1=%p\n", (void *)(&&lab1)); + } + lab2: + #pragma omp parallel + { + lab3: + printf ("lab2=%p\n", (void *)(&&lab2)); + } + printf ("lab3=%p\n", (void *)(&&lab3)); + return 0; +} --- libgomp/testsuite/libgomp.c/pr81687-2.c (nonexistent) +++ libgomp/testsuite/libgomp.c/pr81687-2.c (revision 251853) @@ -0,0 +1,27 @@ +/* PR c/81687 */ +/* { dg-do link } */ +/* { dg-additional-options "-O2" } */ + +int +main () +{ + __label__ lab4, lab5, lab6; + volatile int l = 0; + int m = l; + void foo (int x) { if (x == 1) goto lab4; } + void bar (int x) { if (x == 2) goto lab5; } + void baz (int x) { if (x == 3) goto lab6; } + #pragma omp parallel + { + foo (m + 1); + lab4:; + } + #pragma omp task + { + bar (m + 2); + lab5:; + } + baz (m + 3); + lab6:; + return 0; +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-04 Jakub Jelinek <ja...@redhat.com> * lra-remat.c (reg_overlap_for_remat_p): Fix a pasto. --- gcc/lra-remat.c (revision 251854) +++ gcc/lra-remat.c (revision 251855) @@ -684,7 +684,7 @@ reg_overlap_for_remat_p (lra_insn_reg *r if (regno2 >= FIRST_PSEUDO_REGISTER && reg_renumber[regno2] >= 0) regno2 = reg_renumber[regno2]; - if (regno >= FIRST_PSEUDO_REGISTER) + if (regno2 >= FIRST_PSEUDO_REGISTER) nregs2 = 1; else nregs2 = hard_regno_nregs[regno2][reg->biggest_mode];
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-05 Jakub Jelinek <ja...@redhat.com> PR middle-end/81768 * omp-low.c (expand_omp_simd): Force second operands of COND_EXPR into gimple val before gimplification fo the COND_EXPR. * gcc.dg/gomp/pr81768-1.c: New test. --- gcc/omp-low.c (revision 251855) +++ gcc/omp-low.c (revision 251856) @@ -4725,24 +4725,28 @@ expand_omp_simd (struct omp_region *regi tree itype2 = TREE_TYPE (fd->loops[i - 1].v); if (POINTER_TYPE_P (itype2)) itype2 = signed_type_for (itype2); + t = fold_convert (itype2, fd->loops[i - 1].step); + t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, + GSI_SAME_STMT); t = build3 (COND_EXPR, itype2, build2 (fd->loops[i].cond_code, boolean_type_node, fd->loops[i].v, fold_convert (itype, fd->loops[i].n2)), - build_int_cst (itype2, 0), - fold_convert (itype2, fd->loops[i - 1].step)); + build_int_cst (itype2, 0), t); if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v))) t = fold_build_pointer_plus (fd->loops[i - 1].v, t); else t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t); expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t); + t = fold_convert (itype, fd->loops[i].n1); + t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, + GSI_SAME_STMT); t = build3 (COND_EXPR, itype, build2 (fd->loops[i].cond_code, boolean_type_node, fd->loops[i].v, fold_convert (itype, fd->loops[i].n2)), - fd->loops[i].v, - fold_convert (itype, fd->loops[i].n1)); + fd->loops[i].v, t); expand_omp_build_assign (&gsi, fd->loops[i].v, t); } } --- gcc/testsuite/gcc.dg/gomp/pr81768-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr81768-1.c (revision 251856) @@ -0,0 +1,15 @@ +/* PR middle-end/81768 */ +/* { dg-do compile } */ + +float b[10][15][10]; + +void +foo (void) +{ + float *i; +#pragma omp target parallel for simd schedule(static, 32) collapse(3) + for (i = &b[0][0][0]; i < &b[0][0][10]; i++) + for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10) + for (float *k = &b[0][0][10]; k > &b[0][0][0]; --k) + b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1] -= 3.5; +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-05 Jakub Jelinek <ja...@redhat.com> PR middle-end/81768 * omp-low.c (lower_omp_for): Recompute tree invariant if gimple_omp_for_initial/final is ADDR_EXPR. * gcc.dg/gomp/pr81768-2.c: New test. --- gcc/omp-low.c (revision 251856) +++ gcc/omp-low.c (revision 251857) @@ -6927,10 +6927,14 @@ lower_omp_for (gimple_stmt_iterator *gsi rhs_p = gimple_omp_for_initial_ptr (stmt, i); if (!is_gimple_min_invariant (*rhs_p)) *rhs_p = get_formal_tmp_var (*rhs_p, &body); + else if (TREE_CODE (*rhs_p) == ADDR_EXPR) + recompute_tree_invariant_for_addr_expr (*rhs_p); rhs_p = gimple_omp_for_final_ptr (stmt, i); if (!is_gimple_min_invariant (*rhs_p)) *rhs_p = get_formal_tmp_var (*rhs_p, &body); + else if (TREE_CODE (*rhs_p) == ADDR_EXPR) + recompute_tree_invariant_for_addr_expr (*rhs_p); rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1); if (!is_gimple_min_invariant (*rhs_p)) --- gcc/testsuite/gcc.dg/gomp/pr81768-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/gomp/pr81768-2.c (revision 251857) @@ -0,0 +1,15 @@ +/* PR middle-end/81768 */ +/* { dg-do compile } */ + +float b[10][15][10]; + +void +foo (void) +{ + float *i; +#pragma omp target parallel for schedule(static, 32) collapse(3) + for (i = &b[0][0][0]; i < &b[0][0][10]; i++) + for (float *j = &b[0][15][0]; j > &b[0][0][0]; j -= 10) + for (float *k = &b[0][0][10]; k > &b[0][0][0]; --k) + b[i - &b[0][0][0]][(j - &b[0][0][0]) / 10 - 1][(k - &b[0][0][0]) - 1] -= 3.5; +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-12 Jakub Jelinek <ja...@redhat.com> PR target/82112 * c-common.c (sync_resolve_size): Instead of c_dialect_cxx () assertion check that in the condition. (get_atomic_generic_size): Likewise. Before testing if parameter has pointer type, if it has array type, call for C++ default_conversion to perform array-to-pointer conversion. * c-c++-common/pr82112.c: New test. * gcc.dg/pr82112.c: New test. --- gcc/c-family/c-common.c (revision 252802) +++ gcc/c-family/c-common.c (revision 252803) @@ -6576,10 +6576,9 @@ sync_resolve_size (tree function, vec<tr } argtype = type = TREE_TYPE ((*params)[0]); - if (TREE_CODE (type) == ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ()) { /* Force array-to-pointer decay for C++. */ - gcc_assert (c_dialect_cxx()); (*params)[0] = default_conversion ((*params)[0]); type = TREE_TYPE ((*params)[0]); } @@ -6741,10 +6740,9 @@ get_atomic_generic_size (location_t loc, /* Get type of first parameter, and determine its size. */ type_0 = TREE_TYPE ((*params)[0]); - if (TREE_CODE (type_0) == ARRAY_TYPE) + if (TREE_CODE (type_0) == ARRAY_TYPE && c_dialect_cxx ()) { /* Force array-to-pointer decay for C++. */ - gcc_assert (c_dialect_cxx()); (*params)[0] = default_conversion ((*params)[0]); type_0 = TREE_TYPE ((*params)[0]); } @@ -6783,6 +6781,12 @@ get_atomic_generic_size (location_t loc, /* __atomic_compare_exchange has a bool in the 4th position, skip it. */ if (n_param == 6 && x == 3) continue; + if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ()) + { + /* Force array-to-pointer decay for C++. */ + (*params)[x] = default_conversion ((*params)[x]); + type = TREE_TYPE ((*params)[x]); + } if (!POINTER_TYPE_P (type)) { error_at (loc, "argument %d of %qE must be a pointer type", x + 1, --- gcc/testsuite/gcc.dg/pr82112.c (nonexistent) +++ gcc/testsuite/gcc.dg/pr82112.c (revision 252803) @@ -0,0 +1,21 @@ +/* PR target/82112 */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu90" } */ + +struct S { int a[10]; } bar (void); +int b, c; + +void +foo (void) +{ + __atomic_load (bar ().a, &b, __ATOMIC_ACQUIRE); /* { dg-error "argument 1 of .__atomic_load. must be a non-void pointer type" } */ + __atomic_load (&b, bar ().a, __ATOMIC_ACQUIRE); /* { dg-error "argument 2 of .__atomic_load. must be a pointer type" } */ + __atomic_store (bar ().a, &b, __ATOMIC_SEQ_CST); /* { dg-error "argument 1 of .__atomic_store. must be a non-void pointer type" } */ + __atomic_store (&b, bar ().a, __ATOMIC_SEQ_CST); /* { dg-error "argument 2 of .__atomic_store. must be a pointer type" } */ + __atomic_exchange (bar ().a, &b, &c, __ATOMIC_RELAXED); /* { dg-error "argument 1 of .__atomic_exchange. must be a non-void pointer type" } */ + __atomic_exchange (&b, bar ().a, &c, __ATOMIC_RELAXED); /* { dg-error "argument 2 of .__atomic_exchange. must be a pointer type" } */ + __atomic_exchange (&b, &c, bar ().a, __ATOMIC_RELAXED); /* { dg-error "argument 3 of .__atomic_exchange. must be a pointer type" } */ + __atomic_compare_exchange (bar ().a, &b, &c, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED); /* { dg-error "argument 1 of .__atomic_compare_exchange. must be a non-void pointer type" } */ + __atomic_compare_exchange (&b, bar ().a, &c, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED); /* { dg-error "argument 2 of .__atomic_compare_exchange. must be a pointer type" } */ + __atomic_compare_exchange (&b, &c, bar ().a, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED); /* { dg-error "argument 3 of .__atomic_compare_exchange. must be a pointer type" } */ +} --- gcc/testsuite/c-c++-common/pr82112.c (nonexistent) +++ gcc/testsuite/c-c++-common/pr82112.c (revision 252803) @@ -0,0 +1,13 @@ +/* PR target/82112 */ +/* { dg-do compile } */ + +int c[10], d[10], e[10], f[10], g[10], h[10], i[10], j[10], k[10], l[10]; + +void +foo (void) +{ + __atomic_load (c, d, __ATOMIC_ACQUIRE); + __atomic_store (e, f, __ATOMIC_SEQ_CST); + __atomic_exchange (g, h, i, __ATOMIC_RELAXED); + __atomic_compare_exchange (j, k, l, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED); +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-12 Jakub Jelinek <ja...@redhat.com> PR target/82112 * gcc.target/powerpc/pr82112.c: New test. * g++.dg/ext/altivec-18.C: New test. --- gcc/testsuite/gcc.target/powerpc/pr82112.c (nonexistent) +++ gcc/testsuite/gcc.target/powerpc/pr82112.c (revision 252804) @@ -0,0 +1,16 @@ +/* PR target/82112 */ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-maltivec -std=gnu90" } */ + +#include <altivec.h> + +struct __attribute__((aligned (16))) S { unsigned char c[64]; } bar (void); +vector unsigned char v; + +void +foo (void) +{ + vec_ld (0, bar ().c); /* { dg-error "invalid parameter combination for AltiVec intrinsic" } */ + vec_st (v, 0, bar ().c); /* { dg-error "invalid parameter combination for AltiVec intrinsic" } */ +} --- gcc/testsuite/g++.dg/ext/altivec-18.C (nonexistent) +++ gcc/testsuite/g++.dg/ext/altivec-18.C (revision 252804) @@ -0,0 +1,14 @@ +// PR target/82112 +// { dg-do compile { target powerpc*-*-* } } +// { dg-require-effective-target powerpc_altivec_ok } +// { dg-options "-maltivec" } + +#include <altivec.h> + +__attribute__((aligned (16))) extern const unsigned char c[16]; + +void +foo (void) +{ + vec_ld (0, c); +}
2017-09-15 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-09-14 Jakub Jelinek <ja...@redhat.com> PR c++/81314 * cp-gimplify.c (omp_var_to_track): Look through references. (omp_cxx_notice_variable): Likewise. * testsuite/libgomp.c++/pr81314.C: New test. --- gcc/cp/cp-gimplify.c (revision 252805) +++ gcc/cp/cp-gimplify.c (revision 252806) @@ -924,6 +924,8 @@ omp_var_to_track (tree decl) tree type = TREE_TYPE (decl); if (is_invisiref_parm (decl)) type = TREE_TYPE (type); + else if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); if (type == error_mark_node || !CLASS_TYPE_P (type)) @@ -976,6 +978,8 @@ omp_cxx_notice_variable (struct cp_gener tree type = TREE_TYPE (decl); if (is_invisiref_parm (decl)) type = TREE_TYPE (type); + else if (TREE_CODE (type) == REFERENCE_TYPE) + type = TREE_TYPE (type); while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); get_copy_ctor (type, tf_none); --- libgomp/testsuite/libgomp.c++/pr81314.C (nonexistent) +++ libgomp/testsuite/libgomp.c++/pr81314.C (revision 252806) @@ -0,0 +1,38 @@ +// PR c++/81314 +// { dg-do link } + +template <int N> +struct S { + S () { s = 0; } + S (const S &x) { s = x.s; } + ~S () {} + int s; +}; + +void +foo (S<2> &x) +{ + #pragma omp taskloop + for (int i = 0; i < 100; ++i) + x.s++; +} + +void +bar (S<3> &x) +{ + #pragma omp task + x.s++; +} + +int +main () +{ + S<2> s; + S<3> t; + #pragma omp parallel + #pragma omp master + { + foo (s); + bar (t); + } +}