Hi! I've committed following backports to 4.8 branch, after bootstrapping/regtesting on x86_64-linux and i686-linux.
Jakub
2014-11-28 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2014-10-03 Jakub Jelinek <ja...@redhat.com> PR libgomp/61200 * omp-low.c (taskreg_contexts): New variable. (scan_omp_parallel): Push newly created context into taskreg_contexts vector and move record layout code to finish_taskreg_scan. (scan_omp_task): Likewise. (finish_taskreg_scan): New function. (execute_lower_omp): Call finish_taskreg_scan on all taskreg_contexts vector elements and release it. * c-c++-common/gomp/pr61200.c: New test. * testsuite/libgomp.c/pr61200.c: New test. --- gcc/omp-low.c (revision 215834) +++ gcc/omp-low.c (revision 215835) @@ -128,6 +128,7 @@ static splay_tree all_contexts; static int taskreg_nesting_level; struct omp_region *root_omp_region; static bitmap task_shared_vars; +static vec<omp_context *> taskreg_contexts; static void scan_omp (gimple_seq *, omp_context *); static tree scan_omp_1_op (tree *, int *, void *); @@ -1655,6 +1656,7 @@ scan_omp_parallel (gimple_stmt_iterator } ctx = new_omp_context (stmt, outer_ctx); + taskreg_contexts.safe_push (ctx); if (taskreg_nesting_level > 1) ctx->is_nested = true; ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); @@ -1674,11 +1676,6 @@ scan_omp_parallel (gimple_stmt_iterator if (TYPE_FIELDS (ctx->record_type) == NULL) ctx->record_type = ctx->receiver_decl = NULL; - else - { - layout_type (ctx->record_type); - fixup_child_record_type (ctx); - } } /* Scan an OpenMP task directive. */ @@ -1689,7 +1686,6 @@ scan_omp_task (gimple_stmt_iterator *gsi omp_context *ctx; tree name, t; gimple stmt = gsi_stmt (*gsi); - location_t loc = gimple_location (stmt); /* Ignore task directives with empty bodies. */ if (optimize > 0 @@ -1700,6 +1696,7 @@ scan_omp_task (gimple_stmt_iterator *gsi } ctx = new_omp_context (stmt, outer_ctx); + taskreg_contexts.safe_push (ctx); if (taskreg_nesting_level > 1) ctx->is_nested = true; ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); @@ -1737,8 +1734,71 @@ scan_omp_task (gimple_stmt_iterator *gsi t = build_int_cst (long_integer_type_node, 1); gimple_omp_task_set_arg_align (stmt, t); } +} + + +/* If any decls have been made addressable during scan_omp, + adjust their fields if needed, and layout record types + of parallel/task constructs. */ + +static void +finish_taskreg_scan (omp_context *ctx) +{ + if (ctx->record_type == NULL_TREE) + return; + + /* If any task_shared_vars were needed, verify all + OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK} + statements if use_pointer_for_field hasn't changed + because of that. If it did, update field types now. */ + if (task_shared_vars) + { + tree c; + + for (c = gimple_omp_taskreg_clauses (ctx->stmt); + c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED) + { + tree decl = OMP_CLAUSE_DECL (c); + + /* Global variables don't need to be copied, + the receiver side will use them directly. */ + if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) + continue; + if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl)) + || !use_pointer_for_field (decl, ctx)) + continue; + tree field = lookup_field (decl, ctx); + if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE + && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl)) + continue; + TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl)); + TREE_THIS_VOLATILE (field) = 0; + DECL_USER_ALIGN (field) = 0; + DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field)); + if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field)) + TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field); + if (ctx->srecord_type) + { + tree sfield = lookup_sfield (decl, ctx); + TREE_TYPE (sfield) = TREE_TYPE (field); + TREE_THIS_VOLATILE (sfield) = 0; + DECL_USER_ALIGN (sfield) = 0; + DECL_ALIGN (sfield) = DECL_ALIGN (field); + if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield)) + TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield); + } + } + } + + if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL) + { + layout_type (ctx->record_type); + fixup_child_record_type (ctx); + } else { + location_t loc = gimple_location (ctx->stmt); tree *p, vla_fields = NULL_TREE, *q = &vla_fields; /* Move VLA fields to the end. */ p = &TYPE_FIELDS (ctx->record_type); @@ -1758,12 +1818,12 @@ scan_omp_task (gimple_stmt_iterator *gsi fixup_child_record_type (ctx); if (ctx->srecord_type) layout_type (ctx->srecord_type); - t = fold_convert_loc (loc, long_integer_type_node, - TYPE_SIZE_UNIT (ctx->record_type)); - gimple_omp_task_set_arg_size (stmt, t); + tree t = fold_convert_loc (loc, long_integer_type_node, + TYPE_SIZE_UNIT (ctx->record_type)); + gimple_omp_task_set_arg_size (ctx->stmt, t); t = build_int_cst (long_integer_type_node, TYPE_ALIGN_UNIT (ctx->record_type)); - gimple_omp_task_set_arg_align (stmt, t); + gimple_omp_task_set_arg_align (ctx->stmt, t); } } @@ -7112,6 +7172,8 @@ static unsigned int execute_lower_omp (void) { gimple_seq body; + int i; + omp_context *ctx; /* This pass always runs, to provide PROP_gimple_lomp. But there is nothing to do unless -fopenmp is given. */ @@ -7124,6 +7186,9 @@ execute_lower_omp (void) body = gimple_body (current_function_decl); scan_omp (&body, NULL); gcc_assert (taskreg_nesting_level == 0); + FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx) + finish_taskreg_scan (ctx); + taskreg_contexts.release (); if (all_contexts->root) { --- gcc/testsuite/c-c++-common/gomp/pr61200.c (revision 0) +++ gcc/testsuite/c-c++-common/gomp/pr61200.c (revision 215835) @@ -0,0 +1,13 @@ +/* PR libgomp/61200 */ + +int +main () +{ + int var = 1; + #pragma omp parallel + if (var != 1) + __builtin_abort (); + #pragma omp task shared(var) + var = 2; + return 0; +} --- libgomp/testsuite/libgomp.c/pr61200.c (revision 0) +++ libgomp/testsuite/libgomp.c/pr61200.c (revision 215835) @@ -0,0 +1,87 @@ +/* PR libgomp/61200 */ +/* { dg-do run } */ + +#include <omp.h> +#include <stdlib.h> +#include <unistd.h> + +volatile int x; + +void +foo () +{ + int var = 1; + int i; + + for (i = 0; i < 2; i++) + { + if (i == 1) + { + #pragma omp parallel num_threads(2) + if (x) + var++; + else + { + #pragma omp single + sleep (2); + } + } + else + { + #pragma omp task shared(var) + { + sleep (1); + var = 2; + } + } + } + #pragma omp taskwait + if (var != 2) + abort (); +} + +void +bar () +{ + int var = 1; + int i; + + for (i = 0; i < 2; i++) + { + if (i == 0) + { + #pragma omp task shared(var) + { + sleep (1); + var = 2; + } + } + else + { + #pragma omp parallel num_threads(2) + if (x) + var++; + else + { + #pragma omp single + sleep (2); + } + } + } + #pragma omp taskwait + if (var != 2) + abort (); +} + +int +main () +{ + omp_set_nested (1); + #pragma omp parallel num_threads(2) + #pragma omp single + foo (); + #pragma omp parallel num_threads(2) + #pragma omp single + bar (); + return 0; +}
2014-11-28 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2014-10-31 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/63659 * ree.c (update_reg_equal_equiv_notes): New function. (combine_set_extension, transform_ifelse): Use it. * gcc.c-torture/execute/pr63659.c: New test. --- gcc/ree.c (revision 216984) +++ gcc/ree.c (revision 216985) @@ -261,6 +261,50 @@ typedef struct ext_cand static int max_insn_uid; +/* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */ + +static bool +update_reg_equal_equiv_notes (rtx insn, enum machine_mode new_mode, + enum machine_mode old_mode, enum rtx_code code) +{ + rtx *loc = ®_NOTES (insn); + while (*loc) + { + enum reg_note kind = REG_NOTE_KIND (*loc); + if (kind == REG_EQUAL || kind == REG_EQUIV) + { + rtx orig_src = XEXP (*loc, 0); + /* Update equivalency constants. Recall that RTL constants are + sign-extended. */ + if (GET_CODE (orig_src) == CONST_INT + && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode)) + { + if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND) + /* Nothing needed. */; + else + { + /* Zero-extend the negative constant by masking out the + bits outside the source mode. */ + rtx new_const_int + = gen_int_mode (INTVAL (orig_src) + & GET_MODE_MASK (old_mode), + new_mode); + if (!validate_change (insn, &XEXP (*loc, 0), + new_const_int, true)) + return false; + } + loc = &XEXP (*loc, 1); + } + /* Drop all other notes, they assume a wrong mode. */ + else if (!validate_change (insn, loc, XEXP (*loc, 1), true)) + return false; + } + else + loc = &XEXP (*loc, 1); + } + return true; +} + /* Given a insn (CURR_INSN), an extension candidate for removal (CAND) and a pointer to the SET rtx (ORIG_SET) that needs to be modified, this code modifies the SET rtx to a new SET rtx that extends the @@ -282,6 +326,7 @@ static bool combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); + enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); rtx new_set; @@ -296,9 +341,8 @@ combine_set_extension (ext_cand *cand, r { /* Zero-extend the negative constant by masking out the bits outside the source mode. */ - enum machine_mode src_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_const_int - = GEN_INT (INTVAL (orig_src) & GET_MODE_MASK (src_mode)); + = GEN_INT (INTVAL (orig_src) & GET_MODE_MASK (orig_mode)); new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int); } } @@ -336,7 +380,9 @@ combine_set_extension (ext_cand *cand, r /* This change is a part of a group of changes. Hence, validate_change will not try to commit the change. */ - if (validate_change (curr_insn, orig_set, new_set, true)) + if (validate_change (curr_insn, orig_set, new_set, true) + && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode, + cand->code)) { if (dump_file) { @@ -385,7 +431,9 @@ transform_ifelse (ext_cand *cand, rtx de ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2); new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr); - if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)) + if (validate_change (def_insn, &PATTERN (def_insn), new_set, true) + && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg), + cand->code)) { if (dump_file) { --- gcc/testsuite/gcc.c-torture/execute/pr63659.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr63659.c (revision 216985) @@ -0,0 +1,29 @@ +/* PR rtl-optimization/63659 */ + +int a, b, c, *d = &b, g, h, i; +unsigned char e; +char f; + +int +main () +{ + while (a) + { + for (a = 0; a; a++) + for (; c; c++) + ; + if (i) + break; + } + + char j = c, k = -1, l; + l = g = j >> h; + f = l == 0 ? k : k % l; + e = 0 ? 0 : f; + *d = e; + + if (b != 255) + __builtin_abort (); + + return 0; +}
2014-11-28 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2014-11-24 Jakub Jelinek <ja...@redhat.com> PR fortran/63938 * trans-openmp.c (gfc_trans_omp_atomic): Make sure lhsaddr is simple enough for goa_lhs_expr_p. * libgomp.fortran/pr63938-1.f90: New test. * libgomp.fortran/pr63938-2.f90: New test. --- gcc/fortran/trans-openmp.c (revision 218030) +++ gcc/fortran/trans-openmp.c (revision 218031) @@ -1227,6 +1227,18 @@ gfc_trans_omp_atomic (gfc_code *code) } lhsaddr = save_expr (lhsaddr); + if (TREE_CODE (lhsaddr) != SAVE_EXPR + && (TREE_CODE (lhsaddr) != ADDR_EXPR + || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL)) + { + /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize + it even after unsharing function body. */ + tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr), NULL); + DECL_CONTEXT (var) = current_function_decl; + lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, + NULL_TREE, NULL_TREE); + } + rhs = gfc_evaluate_now (rse.expr, &block); if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE) --- libgomp/testsuite/libgomp.fortran/pr63938-1.f90 (revision 0) +++ libgomp/testsuite/libgomp.fortran/pr63938-1.f90 (revision 218031) @@ -0,0 +1,14 @@ +! PR fortran/63938 +! { dg-do run } + +program pr63938_1 + integer :: i, x(1) + x(1) = 0 +!$omp parallel do + do i = 1, 1000 + !$omp atomic + x(1) = x(1) + 1 + end do +!$omp end parallel do + if (x(1) .ne. 1000) call abort +end program pr63938_1 --- libgomp/testsuite/libgomp.fortran/pr63938-2.f90 (revision 0) +++ libgomp/testsuite/libgomp.fortran/pr63938-2.f90 (revision 218031) @@ -0,0 +1,18 @@ +! PR fortran/63938 +! { dg-do run } + +program pr63938_2 + type t + integer :: x + end type + integer :: i + type(t) :: x + x%x = 0 +!$omp parallel do + do i = 1, 1000 + !$omp atomic + x%x = x%x + 1 + end do +!$omp end parallel do + if (x%x .ne. 1000) call abort +end program pr63938_2
2014-11-28 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2014-11-25 Jakub Jelinek <ja...@redhat.com> PR preprocessor/60436 * line-map.c (linemap_line_start): If highest is above 0x60000000 and we are still tracking columns or highest is above 0x70000000, force add_map. --- libcpp/line-map.c (revision 218041) +++ libcpp/line-map.c (revision 218042) @@ -529,10 +529,10 @@ linemap_line_start (struct line_maps *se && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000) || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))) || (max_column_hint <= 80 - && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10)) - { - add_map = true; - } + && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10) + || (highest > 0x60000000 + && (set->max_column_hint || highest > 0x70000000))) + add_map = true; else max_column_hint = set->max_column_hint; if (add_map) @@ -543,7 +543,7 @@ linemap_line_start (struct line_maps *se /* If the column number is ridiculous or we've allocated a huge number of source_locations, give up on column numbers. */ max_column_hint = 0; - if (highest >0x70000000) + if (highest > 0x70000000) return 0; column_bits = 0; }
2014-11-28 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2014-11-27 Jakub Jelinek <ja...@redhat.com> PR middle-end/64067 * expr.c (expand_expr_addr_expr_1) <case COMPOUND_LITERAL_EXPR>: Handle it by returning address of COMPOUND_LITERAL_EXPR_DECL not only if modifier is EXPAND_INITIALIZER, but whenever COMPOUND_LITERAL_EXPR_DECL is non-NULL and TREE_STATIC. * gcc.c-torture/compile/pr64067.c: New test. --- gcc/expr.c (revision 218120) +++ gcc/expr.c (revision 218121) @@ -7677,11 +7677,13 @@ expand_expr_addr_expr_1 (tree exp, rtx t break; case COMPOUND_LITERAL_EXPR: - /* Allow COMPOUND_LITERAL_EXPR in initializers, if e.g. - rtl_for_decl_init is called on DECL_INITIAL with - COMPOUNT_LITERAL_EXPRs in it, they aren't gimplified. */ - if (modifier == EXPAND_INITIALIZER - && COMPOUND_LITERAL_EXPR_DECL (exp)) + /* Allow COMPOUND_LITERAL_EXPR in initializers or coming from + initializers, if e.g. rtl_for_decl_init is called on DECL_INITIAL + with COMPOUND_LITERAL_EXPRs in it, or ARRAY_REF on a const static + array with address of COMPOUND_LITERAL_EXPR in DECL_INITIAL; + the initializers aren't gimplified. */ + if (COMPOUND_LITERAL_EXPR_DECL (exp) + && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp))) return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp), target, tmode, modifier, as); /* FALLTHRU */ --- gcc/testsuite/gcc.c-torture/compile/pr64067.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr64067.c (revision 218121) @@ -0,0 +1,10 @@ +/* PR middle-end/64067 */ + +struct S { int s; }; +int *const v[1] = { &((struct S) { .s = 42 }).s }; + +int * +foo (void) +{ + return v[0]; +}