Hi! I've committed following backports of my trunk commits to gcc-5-branch after bootstrapping/regtesting them on x86_64-linux and i686-linux.
Jakub
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2015-12-03 Jakub Jelinek <ja...@redhat.com> PR preprocessor/57580 * c-ppoutput.c (print): Change printed field to bool. Move src_file last for smaller padding. (init_pp_output): Set print.printed to false instead of 0. (scan_translation_unit): Fix up formatting. Set print.printed to true after printing something other than newline. (scan_translation_unit_trad): Set print.printed to true instead of 1. (maybe_print_line_1): Set print.printed to false instead of 0. (print_line_1): Likewise. (do_line_change): Set print.printed to true instead of 1. (cb_define, dump_queued_macros, cb_include, cb_def_pragma, dump_macro): Set print.printed to false after printing newline. * c-c++-common/cpp/pr57580.c: New test. * c-c++-common/gomp/pr57580.c: New test. --- gcc/c-family/c-ppoutput.c (revision 231212) +++ gcc/c-family/c-ppoutput.c (revision 231213) @@ -31,11 +31,11 @@ static struct const cpp_token *prev; /* Previous token. */ const cpp_token *source; /* Source token for spacing. */ int src_line; /* Line number currently being written. */ - unsigned char printed; /* Nonzero if something output at line. */ + bool printed; /* True if something output at line. */ bool first_time; /* pp_file_change hasn't been called yet. */ - const char *src_file; /* Current source file. */ bool prev_was_system_token; /* True if the previous token was a system token.*/ + const char *src_file; /* Current source file. */ } print; /* Defined and undefined macros being queued for output with -dU at @@ -153,7 +153,7 @@ init_pp_output (FILE *out_stream) /* Initialize the print structure. */ print.src_line = 1; - print.printed = 0; + print.printed = false; print.prev = 0; print.outf = out_stream; print.first_time = 1; @@ -206,12 +206,16 @@ scan_translation_unit (cpp_reader *pfile { line_marker_emitted = do_line_change (pfile, token, loc, false); putc (' ', print.outf); + print.printed = true; } else if (print.source->flags & PREV_WHITE || (print.prev && cpp_avoid_paste (pfile, print.prev, token)) || (print.prev == NULL && token->type == CPP_HASH)) - putc (' ', print.outf); + { + putc (' ', print.outf); + print.printed = true; + } } else if (token->flags & PREV_WHITE) { @@ -222,6 +226,7 @@ scan_translation_unit (cpp_reader *pfile && !in_pragma) line_marker_emitted = do_line_change (pfile, token, loc, false); putc (' ', print.outf); + print.printed = true; } avoid_paste = false; @@ -239,7 +244,7 @@ scan_translation_unit (cpp_reader *pfile fprintf (print.outf, "%s %s", space, name); else fprintf (print.outf, "%s", name); - print.printed = 1; + print.printed = true; in_pragma = true; } else if (token->type == CPP_PRAGMA_EOL) @@ -250,23 +255,23 @@ scan_translation_unit (cpp_reader *pfile else { if (cpp_get_options (parse_in)->debug) - linemap_dump_location (line_table, token->src_loc, - print.outf); + linemap_dump_location (line_table, token->src_loc, print.outf); if (do_line_adjustments && !in_pragma && !line_marker_emitted - && print.prev_was_system_token != !!in_system_header_at(loc) + && print.prev_was_system_token != !!in_system_header_at (loc) && !is_location_from_builtin_token (loc)) /* The system-ness of this token is different from the one of the previous token. Let's emit a line change to mark the new system-ness before we emit the token. */ { do_line_change (pfile, token, loc, false); - print.prev_was_system_token = !!in_system_header_at(loc); + print.prev_was_system_token = !!in_system_header_at (loc); } cpp_output_token (token, print.outf); line_marker_emitted = false; + print.printed = true; } /* CPP_COMMENT tokens and raw-string literal tokens can @@ -316,7 +321,7 @@ scan_translation_unit_trad (cpp_reader * size_t len = pfile->out.cur - pfile->out.base; maybe_print_line (pfile->out.first_line); fwrite (pfile->out.base, 1, len, print.outf); - print.printed = 1; + print.printed = true; if (!CPP_OPTION (pfile, discard_comments)) account_for_newlines (pfile->out.base, len); } @@ -339,7 +344,7 @@ maybe_print_line_1 (source_location src_ { putc ('\n', stream); print.src_line++; - print.printed = 0; + print.printed = false; } if (!flag_no_line_commands @@ -385,7 +390,7 @@ print_line_1 (source_location src_loc, c /* End any previous line of text. */ if (print.printed) putc ('\n', stream); - print.printed = 0; + print.printed = false; if (!flag_no_line_commands) { @@ -460,7 +465,7 @@ do_line_change (cpp_reader *pfile, const if (!CPP_OPTION (pfile, traditional)) { int spaces = LOCATION_COLUMN (src_loc) - 2; - print.printed = 1; + print.printed = true; while (-- spaces >= 0) putc (' ', print.outf); @@ -503,6 +508,7 @@ cb_define (cpp_reader *pfile, source_loc fputs ((const char *) NODE_NAME (node), print.outf); putc ('\n', print.outf); + print.printed = false; linemap_resolve_location (line_table, line, LRK_MACRO_DEFINITION_LOCATION, &map); @@ -554,7 +560,7 @@ dump_queued_macros (cpp_reader *pfile AT { putc ('\n', print.outf); print.src_line++; - print.printed = 0; + print.printed = false; } for (q = define_queue; q;) @@ -563,6 +569,7 @@ dump_queued_macros (cpp_reader *pfile AT fputs ("#define ", print.outf); fputs (q->macro, print.outf); putc ('\n', print.outf); + print.printed = false; print.src_line++; oq = q; q = q->next; @@ -606,6 +613,7 @@ cb_include (cpp_reader *pfile ATTRIBUTE_ } putc ('\n', print.outf); + print.printed = false; print.src_line++; } @@ -671,6 +679,7 @@ cb_def_pragma (cpp_reader *pfile, source maybe_print_line (line); fputs ("#pragma ", print.outf); cpp_output_line (pfile, print.outf); + print.printed = false; print.src_line++; } @@ -684,6 +693,7 @@ dump_macro (cpp_reader *pfile, cpp_hashn fputs ((const char *) cpp_macro_definition (pfile, node), print.outf); putc ('\n', print.outf); + print.printed = false; print.src_line++; } --- gcc/testsuite/c-c++-common/cpp/pr57580.c (revision 0) +++ gcc/testsuite/c-c++-common/cpp/pr57580.c (revision 231213) @@ -0,0 +1,9 @@ +/* PR preprocessor/57580 */ +/* { dg-do compile } */ +/* { dg-options "-save-temps" } */ + +#define MSG \ + _Pragma("message(\"message0\")") \ + _Pragma("message(\"message1\")") +MSG /* { dg-message "message0" } */ +/* { dg-message "message1" "" { target *-*-* } 8 } */ --- gcc/testsuite/c-c++-common/gomp/pr57580.c (revision 0) +++ gcc/testsuite/c-c++-common/gomp/pr57580.c (revision 231213) @@ -0,0 +1,36 @@ +/* PR preprocessor/57580 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -save-temps -fdump-tree-gimple" } */ + +#define PS \ + _Pragma("omp parallel num_threads(2)") \ + { \ + _Pragma("omp single") \ + { \ + ret = 0; \ + } \ + } + +int +main () +{ + int ret; + _Pragma("omp parallel num_threads(3)") + { + _Pragma("omp single") + { + ret = 0; + } + } + _Pragma("omp parallel num_threads(4)") { _Pragma("omp single") { ret = 0; } } + { _Pragma("omp parallel num_threads(5)") { _Pragma("omp single") { ret = 0; } } } + PS + PS + return ret; +} + +/* { dg-final { scan-tree-dump-times "#pragma omp parallel\[^\n\r]*num_threads\\(2\\)" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp parallel\[^\n\r]*num_threads\\(3\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp parallel\[^\n\r]*num_threads\\(4\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp parallel\[^\n\r]*num_threads\\(5\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "#pragma omp single" 5 "gimple" } } */
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2015-12-22 Jakub Jelinek <ja...@redhat.com> PR c++/67376 * fold-const.c (size_low_cst): Removed. (fold_comparison): For POINTER_PLUS_EXPR where base is ADDR_EXPR call get_inner_reference and handle INDIRECT_REF base of it. Use offset_int for computation of the bitpos. (fold_binary_loc) <case EQ_EXPR, NE_EXPR>: Formatting fixes for X +- Y CMP X and C - X CMP X folding. Add X CMP X +- Y and X CMP C - X folding. * g++.dg/cpp0x/constexpr-67376.C: New test. --- gcc/fold-const.c (revision 231908) +++ gcc/fold-const.c (revision 231909) @@ -8731,20 +8731,6 @@ pointer_may_wrap_p (tree base, tree offs return total.to_uhwi () > (unsigned HOST_WIDE_INT) size; } -/* Return the HOST_WIDE_INT least significant bits of T, a sizetype - kind INTEGER_CST. This makes sure to properly sign-extend the - constant. */ - -static HOST_WIDE_INT -size_low_cst (const_tree t) -{ - HOST_WIDE_INT w = TREE_INT_CST_ELT (t, 0); - int prec = TYPE_PRECISION (TREE_TYPE (t)); - if (prec < HOST_BITS_PER_WIDE_INT) - return sext_hwi (w, prec); - return w; -} - /* Subroutine of fold_binary. This routine performs all of the transformations that are common to the equality/inequality operators (EQ_EXPR and NE_EXPR) and the ordering operators @@ -8889,18 +8875,29 @@ fold_comparison (location_t loc, enum tr STRIP_SIGN_NOPS (base0); if (TREE_CODE (base0) == ADDR_EXPR) { - base0 = TREE_OPERAND (base0, 0); - indirect_base0 = true; + base0 + = get_inner_reference (TREE_OPERAND (base0, 0), + &bitsize, &bitpos0, &offset0, &mode, + &unsignedp, &volatilep, false); + if (TREE_CODE (base0) == INDIRECT_REF) + base0 = TREE_OPERAND (base0, 0); + else + indirect_base0 = true; } - offset0 = TREE_OPERAND (arg0, 1); - if (tree_fits_shwi_p (offset0)) - { - HOST_WIDE_INT off = size_low_cst (offset0); - if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) - * BITS_PER_UNIT) - / BITS_PER_UNIT == (HOST_WIDE_INT) off) + if (offset0 == NULL_TREE || integer_zerop (offset0)) + offset0 = TREE_OPERAND (arg0, 1); + else + offset0 = size_binop (PLUS_EXPR, offset0, + TREE_OPERAND (arg0, 1)); + if (TREE_CODE (offset0) == INTEGER_CST) + { + offset_int tem = wi::sext (wi::to_offset (offset0), + TYPE_PRECISION (sizetype)); + tem = wi::lshift (tem, LOG2_BITS_PER_UNIT); + tem += bitpos0; + if (wi::fits_shwi_p (tem)) { - bitpos0 = off * BITS_PER_UNIT; + bitpos0 = tem.to_shwi (); offset0 = NULL_TREE; } } @@ -8923,18 +8920,29 @@ fold_comparison (location_t loc, enum tr STRIP_SIGN_NOPS (base1); if (TREE_CODE (base1) == ADDR_EXPR) { - base1 = TREE_OPERAND (base1, 0); - indirect_base1 = true; + base1 + = get_inner_reference (TREE_OPERAND (base1, 0), + &bitsize, &bitpos1, &offset1, &mode, + &unsignedp, &volatilep, false); + if (TREE_CODE (base1) == INDIRECT_REF) + base1 = TREE_OPERAND (base1, 0); + else + indirect_base1 = true; } - offset1 = TREE_OPERAND (arg1, 1); - if (tree_fits_shwi_p (offset1)) + if (offset1 == NULL_TREE || integer_zerop (offset1)) + offset1 = TREE_OPERAND (arg1, 1); + else + offset1 = size_binop (PLUS_EXPR, offset1, + TREE_OPERAND (arg1, 1)); + if (TREE_CODE (offset1) == INTEGER_CST) { - HOST_WIDE_INT off = size_low_cst (offset1); - if ((HOST_WIDE_INT) (((unsigned HOST_WIDE_INT) off) - * BITS_PER_UNIT) - / BITS_PER_UNIT == (HOST_WIDE_INT) off) + offset_int tem = wi::sext (wi::to_offset (offset1), + TYPE_PRECISION (sizetype)); + tem = wi::lshift (tem, LOG2_BITS_PER_UNIT); + tem += bitpos1; + if (wi::fits_shwi_p (tem)) { - bitpos1 = off * BITS_PER_UNIT; + bitpos1 = tem.to_shwi (); offset1 = NULL_TREE; } } @@ -12375,12 +12383,27 @@ fold_binary_loc (location_t loc, || POINTER_TYPE_P (TREE_TYPE (arg0)))) { tree val = TREE_OPERAND (arg0, 1); - return omit_two_operands_loc (loc, type, - fold_build2_loc (loc, code, type, - val, - build_int_cst (TREE_TYPE (val), - 0)), - TREE_OPERAND (arg0, 0), arg1); + val = fold_build2_loc (loc, code, type, val, + build_int_cst (TREE_TYPE (val), 0)); + return omit_two_operands_loc (loc, type, val, + TREE_OPERAND (arg0, 0), arg1); + } + + /* Transform comparisons of the form X CMP X +- Y to Y CMP 0. */ + if ((TREE_CODE (arg1) == PLUS_EXPR + || TREE_CODE (arg1) == POINTER_PLUS_EXPR + || TREE_CODE (arg1) == MINUS_EXPR) + && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, + 0)), + arg0, 0) + && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + || POINTER_TYPE_P (TREE_TYPE (arg1)))) + { + tree val = TREE_OPERAND (arg1, 1); + val = fold_build2_loc (loc, code, type, val, + build_int_cst (TREE_TYPE (val), 0)); + return omit_two_operands_loc (loc, type, val, + TREE_OPERAND (arg1, 0), arg0); } /* Transform comparisons of the form C - X CMP X if C % 2 == 1. */ @@ -12390,12 +12413,22 @@ fold_binary_loc (location_t loc, 1)), arg1, 0) && wi::extract_uhwi (TREE_OPERAND (arg0, 0), 0, 1) == 1) - { - return omit_two_operands_loc (loc, type, - code == NE_EXPR - ? boolean_true_node : boolean_false_node, - TREE_OPERAND (arg0, 1), arg1); - } + return omit_two_operands_loc (loc, type, + code == NE_EXPR + ? boolean_true_node : boolean_false_node, + TREE_OPERAND (arg0, 1), arg1); + + /* Transform comparisons of the form X CMP C - X if C % 2 == 1. */ + if (TREE_CODE (arg1) == MINUS_EXPR + && TREE_CODE (TREE_OPERAND (arg1, 0)) == INTEGER_CST + && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, + 1)), + arg0, 0) + && wi::extract_uhwi (TREE_OPERAND (arg1, 0), 0, 1) == 1) + return omit_two_operands_loc (loc, type, + code == NE_EXPR + ? boolean_true_node : boolean_false_node, + TREE_OPERAND (arg1, 1), arg0); /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */ if (TREE_CODE (arg0) == ABS_EXPR --- gcc/testsuite/g++.dg/cpp0x/constexpr-67376.C (revision 0) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-67376.C (revision 231909) @@ -0,0 +1,17 @@ +// PR c++/67376 +// { dg-do compile { target c++11 } } + +struct A { int e[2]; }; +constexpr A a { { 0, 1 } }; +static_assert (a.e + 1 != a.e, ""); +static_assert (a.e != a.e + 1, ""); +static_assert (a.e + 2 != a.e, ""); +static_assert (a.e != a.e + 2, ""); +static_assert (a.e + 1 > a.e, ""); +static_assert (a.e < a.e + 1, ""); +static_assert (a.e + 2 > a.e, ""); +static_assert (a.e < a.e + 2, ""); +static_assert (a.e + 1 >= a.e, ""); +static_assert (a.e <= a.e + 1, ""); +static_assert (a.e + 2 >= a.e, ""); +static_assert (a.e <= a.e + 2, "");
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-01 Jakub Jelinek <ja...@redhat.com> PR target/69015 * ifcvt.c (find_cond_trap): Give up if returnjump_p (jump). * gcc.dg/pr69015.c: New test. --- gcc/ifcvt.c (revision 232019) +++ gcc/ifcvt.c (revision 232020) @@ -4526,8 +4526,11 @@ find_cond_trap (basic_block test_bb, edg return FALSE; /* If the conditional jump is more than just a conditional jump, then - we can not do if-conversion on this block. */ - if (! onlyjump_p (jump)) + we can not do if-conversion on this block. Give up for returnjump_p, + changing a conditional return followed by unconditional trap for + conditional trap followed by unconditional return is likely not + beneficial and harder to handle. */ + if (! onlyjump_p (jump) || returnjump_p (jump)) return FALSE; /* We must be comparing objects whose modes imply the size. */ --- gcc/testsuite/gcc.dg/pr69015.c (revision 0) +++ gcc/testsuite/gcc.dg/pr69015.c (revision 232020) @@ -0,0 +1,10 @@ +/* PR target/69015 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-if-conversion" } */ + +void +foo (int c) +{ + if (c) + __builtin_trap (); +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-01 Jakub Jelinek <ja...@redhat.com> PR sanitizer/69055 * ubsan.c (ubsan_instrument_float_cast): Call initialize_sanitizer_builtins. * gfortran.dg/pr69055.f90: New test. --- gcc/ubsan.c (revision 232023) +++ gcc/ubsan.c (revision 232024) @@ -1611,6 +1611,7 @@ ubsan_instrument_float_cast (location_t fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { + initialize_sanitizer_builtins (); /* Create the __ubsan_handle_float_cast_overflow fn call. */ tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0, NULL, ubsan_type_descriptor (expr_type), --- gcc/testsuite/gfortran.dg/pr69055.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/pr69055.f90 (revision 232024) @@ -0,0 +1,10 @@ +! { dg-do compile } +! { dg-options "-fsanitize=float-cast-overflow" } + +subroutine pr69055 + implicit none + integer :: n + real(8) :: b + b = huge(1.0D0) + n = b +end subroutine pr69055
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-07 Jakub Jelinek <ja...@redhat.com> PR middle-end/68960 * gimple-expr.c (copy_var_decl): If var has DECL_USER_ALIGN set, copy it and DECL_ALIGN too. * testsuite/libgomp.c/pr68960.c: New test. --- gcc/gimple-expr.c (revision 232121) +++ gcc/gimple-expr.c (revision 232122) @@ -375,6 +375,11 @@ copy_var_decl (tree var, tree name, tree TREE_USED (copy) = 1; DECL_SEEN_IN_BIND_EXPR_P (copy) = 1; DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var); + if (DECL_USER_ALIGN (var)) + { + DECL_ALIGN (copy) = DECL_ALIGN (var); + DECL_USER_ALIGN (copy) = 1; + } return copy; } --- libgomp/testsuite/libgomp.c/pr68960.c (revision 0) +++ libgomp/testsuite/libgomp.c/pr68960.c (revision 232122) @@ -0,0 +1,25 @@ +/* PR middle-end/68960 */ +/* { dg-do run } */ + +int +main () +{ + int temp[257] __attribute__ ((aligned (256))) = { 0 }; + #pragma omp parallel private (temp) num_threads (2) + { + int *p = &temp[0]; + asm volatile ("" : "+g" (p)); + if (((__UINTPTR_TYPE__) p) & 255) + __builtin_abort (); + } + #pragma omp parallel num_threads (2) + #pragma omp single + #pragma omp task firstprivate (temp) + { + int *p = &temp[0]; + asm volatile ("" : "+g" (p)); + if (((__UINTPTR_TYPE__) p) & 255) + __builtin_abort (); + } + return 0; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-08 Jakub Jelinek <ja...@redhat.com> PR fortran/69128 * trans.h (OMPWS_SCALARIZER_BODY): Define. (OMPWS_NOWAIT): Renumber. * trans-stmt.c (gfc_trans_where_3): Only set OMPWS_SCALARIZER_WS if OMPWS_SCALARIZER_BODY is not set already, and set also OMPWS_SCALARIZER_BODY until the final loop creation. * trans-expr.c (gfc_trans_assignment_1): Likewise. * trans-openmp.c (gfc_trans_omp_workshare): Also clear OMPWS_SCALARIZER_BODY. * trans-array.c (gfc_trans_scalarized_loop_end): Don't create OMP_FOR if OMPWS_SCALARIZER_BODY is set. * gfortran.dg/gomp/pr69128.f90: New test. --- gcc/fortran/trans.h (revision 232150) +++ gcc/fortran/trans.h (revision 232151) @@ -1039,7 +1039,9 @@ extern const char gfc_msg_wrong_return[] construct is not workshared. */ #define OMPWS_SCALARIZER_WS 4 /* Set if scalarizer should attempt to create parallel loops. */ -#define OMPWS_NOWAIT 8 /* Use NOWAIT on OMP_FOR. */ +#define OMPWS_SCALARIZER_BODY 8 /* Set if handling body of potential + parallel loop. */ +#define OMPWS_NOWAIT 16 /* Use NOWAIT on OMP_FOR. */ extern int ompws_flags; #endif /* GFC_TRANS_H */ --- gcc/fortran/trans-stmt.c (revision 232150) +++ gcc/fortran/trans-stmt.c (revision 232151) @@ -5057,10 +5057,15 @@ gfc_trans_where_3 (gfc_code * cblock, gf gfc_loopinfo loop; gfc_ss *edss = 0; gfc_ss *esss = 0; + bool maybe_workshare = false; /* Allow the scalarizer to workshare simple where loops. */ - if (ompws_flags & OMPWS_WORKSHARE_FLAG) - ompws_flags |= OMPWS_SCALARIZER_WS; + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY)) + == OMPWS_WORKSHARE_FLAG) + { + maybe_workshare = true; + ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY; + } cond = cblock->expr1; tdst = cblock->next->expr1; @@ -5160,6 +5165,8 @@ gfc_trans_where_3 (gfc_code * cblock, gf gfc_add_expr_to_block (&body, tmp); gfc_add_block_to_block (&body, &cse.post); + if (maybe_workshare) + ompws_flags &= ~OMPWS_SCALARIZER_BODY; gfc_trans_scalarizing_loops (&loop, &body); gfc_add_block_to_block (&block, &loop.pre); gfc_add_block_to_block (&block, &loop.post); --- gcc/fortran/trans-expr.c (revision 232150) +++ gcc/fortran/trans-expr.c (revision 232151) @@ -9160,6 +9160,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1 bool scalar_to_array; tree string_length; int n; + bool maybe_workshare = false; /* Assignment of the form lhs = rhs. */ gfc_start_block (&block); @@ -9234,8 +9235,13 @@ gfc_trans_assignment_1 (gfc_expr * expr1 } /* Allow the scalarizer to workshare array assignments. */ - if ((ompws_flags & OMPWS_WORKSHARE_FLAG) && loop.temp_ss == NULL) - ompws_flags |= OMPWS_SCALARIZER_WS; + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY)) + == OMPWS_WORKSHARE_FLAG + && loop.temp_ss == NULL) + { + maybe_workshare = true; + ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY; + } /* Start the scalarized loop body. */ gfc_start_scalarized_body (&loop, &body); @@ -9384,6 +9390,9 @@ gfc_trans_assignment_1 (gfc_expr * expr1 gfc_add_expr_to_block (&loop.code[expr1->rank - 1], tmp); } + if (maybe_workshare) + ompws_flags &= ~OMPWS_SCALARIZER_BODY; + /* Generate the copying loops. */ gfc_trans_scalarizing_loops (&loop, &body); --- gcc/fortran/trans-openmp.c (revision 232150) +++ gcc/fortran/trans-openmp.c (revision 232151) @@ -4297,7 +4297,7 @@ gfc_trans_omp_workshare (gfc_code *code, /* By default, every gfc_code is a single unit of work. */ ompws_flags |= OMPWS_CURR_SINGLEUNIT; - ompws_flags &= ~OMPWS_SCALARIZER_WS; + ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY); switch (code->op) { --- gcc/fortran/trans-array.c (revision 232150) +++ gcc/fortran/trans-array.c (revision 232151) @@ -3601,7 +3601,8 @@ gfc_trans_scalarized_loop_end (gfc_loopi tree init; tree incr; - if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)) + if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS + | OMPWS_SCALARIZER_BODY)) == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS) && n == loop->dimen - 1) { --- gcc/testsuite/gfortran.dg/gomp/pr69128.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/gomp/pr69128.f90 (revision 232151) @@ -0,0 +1,23 @@ +! PR fortran/69128 +! { dg-do compile } + +program test + implicit none + interface + subroutine use(b, c) + real, allocatable :: b(:), c(:) + end subroutine + end interface + real, allocatable :: a(:,:), b(:), c(:) + integer :: dim1, dim2, i,j + dim1=10000 + dim2=500 + allocate(a(dim1,dim2),b(dim1),c(dim1)) + call random_number(a) + +!$omp parallel workshare + b(:) = maxval(a(:,:), dim=2) + c(:) = sum(a(:,:), dim=2) +!$omp end parallel workshare + call use(b, c) +end program
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-11 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69214 * tree-vrp.c (simplify_cond_using_ranges): Don't propagate innerop into a comparison if SSA_NAME_OCCURS_IN_ABNORMAL_PHI. Formatting fix. * gcc.c-torture/compile/pr69214.c: New test. --- gcc/tree-vrp.c (revision 232234) +++ gcc/tree-vrp.c (revision 232235) @@ -9534,7 +9534,8 @@ simplify_cond_using_ranges (gcond *stmt) innerop = gimple_assign_rhs1 (def_stmt); if (TREE_CODE (innerop) == SSA_NAME - && !POINTER_TYPE_P (TREE_TYPE (innerop))) + && !POINTER_TYPE_P (TREE_TYPE (innerop)) + && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)) { value_range_t *vr = get_value_range (innerop); @@ -9565,8 +9566,8 @@ simplify_cond_using_ranges (gcond *stmt) else location = gimple_location (stmt); warning_at (location, OPT_Wstrict_overflow, - "assuming signed overflow does not occur when " - "simplifying conditional"); + "assuming signed overflow does not occur when " + "simplifying conditional"); } tree newconst = fold_convert (TREE_TYPE (innerop), op1); --- gcc/testsuite/gcc.c-torture/compile/pr69214.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr69214.c (revision 232235) @@ -0,0 +1,17 @@ +/* PR tree-optimization/69214 */ + +extern void bar (void); +extern int __setjmp (char *); + +void +foo (char *p) +{ + int d = 0; + bar (); + if (__setjmp (p)) + return; + long a = d; + d = 8; + if (!a) + bar (); +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-14 Jakub Jelinek <ja...@redhat.com> PR target/68269 * combine.c (expand_field_assignment): Punt if compute_mode is unsupported scalar mode. --- gcc/combine.c (revision 232365) +++ gcc/combine.c (revision 232366) @@ -7247,6 +7247,10 @@ expand_field_assignment (const_rtx x) if (len >= HOST_BITS_PER_WIDE_INT) break; + /* Don't try to compute in too wide unsupported modes. */ + if (!targetm.scalar_mode_supported_p (compute_mode)) + break; + /* Now compute the equivalent expression. Make a copy of INNER for the SET_DEST in case it is a MEM into which we will substitute; we don't want shared RTL in that case. */
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-19 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/68955 PR rtl-optimization/64557 * dse.c (record_store, check_mem_read_rtx): Don't call get_addr here. Fix up formatting. * alias.c (get_addr): Handle VALUE +/- CONST_SCALAR_INT_P. * gcc.dg/torture/pr68955.c: New test. --- gcc/dse.c (revision 232553) +++ gcc/dse.c (revision 232554) @@ -1571,14 +1571,9 @@ record_store (rtx body, bb_info_t bb_inf mem_addr = base->val_rtx; else { - group_info_t group - = rtx_group_vec[group_id]; + group_info_t group = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } - /* get_addr can only handle VALUE but cannot handle expr like: - VALUE + OFFSET, so call get_addr to get original addr for - mem_addr before plus_constant. */ - mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } @@ -2188,14 +2183,9 @@ check_mem_read_rtx (rtx *loc, bb_info_t mem_addr = base->val_rtx; else { - group_info_t group - = rtx_group_vec[group_id]; + group_info_t group = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } - /* get_addr can only handle VALUE but cannot handle expr like: - VALUE + OFFSET, so call get_addr to get original addr for - mem_addr before plus_constant. */ - mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } --- gcc/alias.c (revision 232553) +++ gcc/alias.c (revision 232554) @@ -2193,8 +2193,8 @@ refs_newer_value_p (const_rtx expr, rtx } /* Convert the address X into something we can use. This is done by returning - it unchanged unless it is a value; in the latter case we call cselib to get - a more useful rtx. */ + it unchanged unless it is a VALUE or VALUE +/- constant; for VALUE + we call cselib to get a more useful rtx. */ rtx get_addr (rtx x) @@ -2203,7 +2203,23 @@ get_addr (rtx x) struct elt_loc_list *l; if (GET_CODE (x) != VALUE) - return x; + { + if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS) + && GET_CODE (XEXP (x, 0)) == VALUE + && CONST_SCALAR_INT_P (XEXP (x, 1))) + { + rtx op0 = get_addr (XEXP (x, 0)); + if (op0 != XEXP (x, 0)) + { + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT) + return plus_constant (GET_MODE (x), op0, INTVAL (XEXP (x, 1))); + return simplify_gen_binary (GET_CODE (x), GET_MODE (x), + op0, XEXP (x, 1)); + } + } + return x; + } v = CSELIB_VAL_PTR (x); if (v) { --- gcc/testsuite/gcc.dg/torture/pr68955.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr68955.c (revision 232554) @@ -0,0 +1,41 @@ +/* PR rtl-optimization/68955 */ +/* { dg-do run } */ +/* { dg-output "ONE1ONE" } */ + +int a, b, c, d, g, m; +int i[7][7][5] = { { { 5 } }, { { 5 } }, + { { 5 }, { 5 }, { 5 }, { 5 }, { 5 }, { -1 } } }; +static int j = 11; +short e, f, h, k, l; + +static void +foo () +{ + for (; e < 5; e++) + for (h = 3; h; h--) + { + for (g = 1; g < 6; g++) + { + m = c == 0 ? b : b / c; + i[e][1][e] = i[1][1][1] | (m & l) && f; + } + for (k = 0; k < 6; k++) + { + for (d = 0; d < 6; d++) + i[1][e][h] = i[h][k][e] >= l; + i[e + 2][h + 3][e] = 6 & l; + i[2][1][2] = a; + for (; j < 5;) + for (;;) + ; + } + } +} + +int +main () +{ + foo (); + __builtin_printf ("ONE%dONE\n", i[1][0][2]); + return 0; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-19 Jakub Jelinek <ja...@redhat.com> PR debug/65779 * shrink-wrap.c: Include valtrack.h. (move_insn_for_shrink_wrap): Add DEBUG argument. If MAY_HAVE_DEBUG_INSNS, call dead_debug_add on DEBUG_INSNs in between insn and where it will be moved to. Call dead_debug_insert_temp. (prepare_shrink_wrap): Adjust caller. Call dead_debug_local_init first and dead_debug_local_finish at the end. For uses and defs bitmap, handle all regs in between REGNO and END_REGNO, not just the first one. * gcc.dg/pr65779.c: New test. --- gcc/shrink-wrap.c (revision 232557) +++ gcc/shrink-wrap.c (revision 232558) @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. #include "shrink-wrap.h" #include "regcprop.h" #include "rtl-iter.h" +#include "valtrack.h" /* Return true if INSN requires the stack frame to be set up. @@ -149,7 +150,8 @@ static bool move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, const HARD_REG_SET uses, const HARD_REG_SET defs, - bool *split_p) + bool *split_p, + struct dead_debug_local *debug) { rtx set, src, dest; bitmap live_out, live_in, bb_uses, bb_defs; @@ -158,6 +160,8 @@ move_insn_for_shrink_wrap (basic_block b unsigned int end_sregno = FIRST_PSEUDO_REGISTER; basic_block next_block; edge live_edge; + rtx_insn *dinsn; + df_ref def; /* Look for a simple register assignment. We don't use single_set here because we can't deal with any CLOBBERs, USEs, or REG_UNUSED secondary @@ -302,6 +306,20 @@ move_insn_for_shrink_wrap (basic_block b move it as far as we can. */ do { + if (MAY_HAVE_DEBUG_INSNS) + { + FOR_BB_INSNS_REVERSE (bb, dinsn) + if (DEBUG_INSN_P (dinsn)) + { + df_ref use; + FOR_EACH_INSN_USE (use, dinsn) + if (refers_to_regno_p (dregno, end_dregno, + DF_REF_REG (use), (rtx *) NULL)) + dead_debug_add (debug, use, DF_REF_REGNO (use)); + } + else if (dinsn == insn) + break; + } live_out = df_get_live_out (bb); live_in = df_get_live_in (next_block); bb = next_block; @@ -384,6 +402,12 @@ move_insn_for_shrink_wrap (basic_block b SET_REGNO_REG_SET (bb_uses, i); } + /* Insert debug temps for dead REGs used in subsequent debug insns. */ + if (debug->used && !bitmap_empty_p (debug->used)) + FOR_EACH_INSN_DEF (def, insn) + dead_debug_insert_temp (debug, DF_REF_REGNO (def), insn, + DEBUG_TEMP_BEFORE_WITH_VALUE); + emit_insn_after (PATTERN (insn), bb_note (bb)); delete_insn (insn); return true; @@ -404,6 +428,8 @@ prepare_shrink_wrap (basic_block entry_b HARD_REG_SET uses, defs; df_ref def, use; bool split_p = false; + unsigned int i; + struct dead_debug_local debug; if (JUMP_P (BB_END (entry_block))) { @@ -414,19 +440,22 @@ prepare_shrink_wrap (basic_block entry_b copyprop_hardreg_forward_bb_without_debug_insn (entry_block); } + dead_debug_local_init (&debug, NULL, NULL); CLEAR_HARD_REG_SET (uses); CLEAR_HARD_REG_SET (defs); + FOR_BB_INSNS_REVERSE_SAFE (entry_block, insn, curr) if (NONDEBUG_INSN_P (insn) && !move_insn_for_shrink_wrap (entry_block, insn, uses, defs, - &split_p)) + &split_p, &debug)) { /* Add all defined registers to DEFs. */ FOR_EACH_INSN_DEF (def, insn) { x = DF_REF_REG (def); if (REG_P (x) && HARD_REGISTER_P (x)) - SET_HARD_REG_BIT (defs, REGNO (x)); + for (i = REGNO (x); i < END_REGNO (x); i++) + SET_HARD_REG_BIT (defs, i); } /* Add all used registers to USESs. */ @@ -434,9 +463,12 @@ prepare_shrink_wrap (basic_block entry_b { x = DF_REF_REG (use); if (REG_P (x) && HARD_REGISTER_P (x)) - SET_HARD_REG_BIT (uses, REGNO (x)); + for (i = REGNO (x); i < END_REGNO (x); i++) + SET_HARD_REG_BIT (uses, i); } } + + dead_debug_local_finish (&debug, NULL); } /* Return whether basic block PRO can get the prologue. It can not if it --- gcc/testsuite/gcc.dg/pr65779.c (revision 0) +++ gcc/testsuite/gcc.dg/pr65779.c (revision 232558) @@ -0,0 +1,42 @@ +/* PR debug/65779 */ +/* { dg-do assemble } */ +/* { dg-options "-O2 -fcompare-debug" } */ + +unsigned long +foo (unsigned long x, unsigned char *y, unsigned int z) +{ + unsigned long a = x & 0xffff; + unsigned long b = (x >> 16) & 0xffff; + int k; + if (y == 0) return 1L; + while (z > 0) + { + k = z < 5552 ? z : 5552; + z -= k; + while (k >= 16) + { + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + a += *y++; b += a; + k -= 16; + } + if (k != 0) + do { a += *y++; b += a; } while (--k); + a %= 65521L; + b %= 65521L; + } + return (b << 16) | a; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-21 Jakub Jelinek <ja...@redhat.com> PR middle-end/67653 * gimplify.c (gimplify_asm_expr): Warn if it is too late to attempt to mark memory input operand addressable and call prepare_gimple_addressable in that case. Don't adjust input_location for diagnostics, use error_at instead. * c-c++-common/pr67653.c: New test. * gcc.dg/torture/pr29119.c: Add dg-warning. --- gcc/gimplify.c (revision 232639) +++ gcc/gimplify.c (revision 232640) @@ -5305,12 +5305,38 @@ gimplify_asm_expr (tree *expr_p, gimple_ TREE_VALUE (link) = error_mark_node; tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p, is_gimple_lvalue, fb_lvalue | fb_mayfail); + if (tret != GS_ERROR) + { + /* Unlike output operands, memory inputs are not guaranteed + to be lvalues by the FE, and while the expressions are + marked addressable there, if it is e.g. a statement + expression, temporaries in it might not end up being + addressable. They might be already used in the IL and thus + it is too late to make them addressable now though. */ + tree x = TREE_VALUE (link); + while (handled_component_p (x)) + x = TREE_OPERAND (x, 0); + if (TREE_CODE (x) == MEM_REF + && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR) + x = TREE_OPERAND (TREE_OPERAND (x, 0), 0); + if ((TREE_CODE (x) == VAR_DECL + || TREE_CODE (x) == PARM_DECL + || TREE_CODE (x) == RESULT_DECL) + && !TREE_ADDRESSABLE (x) + && is_gimple_reg (x)) + { + warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), + input_location), 0, + "memory input %d is not directly addressable", + i); + prepare_gimple_addressable (&TREE_VALUE (link), pre_p); + } + } mark_addressable (TREE_VALUE (link)); if (tret == GS_ERROR) { - if (EXPR_HAS_LOCATION (TREE_VALUE (link))) - input_location = EXPR_LOCATION (TREE_VALUE (link)); - error ("memory input %d is not directly addressable", i); + error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location), + "memory input %d is not directly addressable", i); ret = tret; } } --- gcc/testsuite/gcc.dg/torture/pr29119.c (revision 232639) +++ gcc/testsuite/gcc.dg/torture/pr29119.c (revision 232640) @@ -2,6 +2,5 @@ void ldt_add_entry(void) { - __asm__ ("" :: "m"(({unsigned __v; __v;}))); + __asm__ ("" :: "m"(({unsigned __v; __v;}))); /* { dg-warning "memory input 0 is not directly addressable" } */ } - --- gcc/testsuite/c-c++-common/pr67653.c (revision 0) +++ gcc/testsuite/c-c++-common/pr67653.c (revision 232640) @@ -0,0 +1,8 @@ +/* PR middle-end/67653 */ +/* { dg-do compile } */ + +void +foo (void) +{ + __asm__ ("" : : "m" (({ static int a; a; }))); /* { dg-warning "memory input 0 is not directly addressable" } */ +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-21 Stefan Sørensen <stefan.soren...@spectralink.com> Jakub Jelinek <ja...@redhat.com> PR target/69187 PR target/65624 * config/arm/arm-builtins.c (arm_expand_neon_builtin): Increase args array size by one to avoid buffer overflow. * gcc.target/arm/pr69187.c: New test. --- gcc/config/arm/arm-builtins.c (revision 232667) +++ gcc/config/arm/arm-builtins.c (revision 232668) @@ -2246,7 +2246,7 @@ arm_expand_neon_builtin (int fcode, tree neon_builtin_datum *d = &neon_builtin_data[fcode - ARM_BUILTIN_NEON_PATTERN_START]; enum insn_code icode = d->code; - builtin_arg args[SIMD_MAX_BUILTIN_ARGS]; + builtin_arg args[SIMD_MAX_BUILTIN_ARGS + 1]; int num_args = insn_data[d->code].n_operands; int is_void = 0; int k; --- gcc/testsuite/gcc.target/arm/pr69187.c (revision 0) +++ gcc/testsuite/gcc.target/arm/pr69187.c (revision 232668) @@ -0,0 +1,19 @@ +/* PR target/69187 */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon } */ +/* { dg-options "-O0" } */ +/* { dg-add-options arm_neon } */ + +#include <arm_neon.h> + +int32x4_t +foo (void) +{ + int32x4_t vector_int32x4; + int16x4_t vector3_int16x4; + int16x4_t vector4_int16x4; + static int32_t buffer_int32x4[32]; + + vector_int32x4 = vld1q_s32(buffer_int32x4); + return vqdmlsl_lane_s16(vector_int32x4, vector3_int16x4, vector4_int16x4, 0); +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-22 Jakub Jelinek <ja...@redhat.com> PR target/69432 * config/i386/i386.c: Include dojump.h. (expand_small_movmem_or_setmem, expand_set_or_movmem_prologue_epilogue_by_misaligned_moves): Spelling fixes. (ix86_expand_set_or_movmem): Call do_pending_stack_adjust () early if dynamic_check != -1. * g++.dg/opt/pr69432.C: New test. --- gcc/config/i386/i386.c (revision 232753) +++ gcc/config/i386/i386.c (revision 232754) @@ -115,6 +115,7 @@ along with GCC; see the file COPYING3. #include "tree-iterator.h" #include "tree-chkp.h" #include "rtl-chkp.h" +#include "dojump.h" static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); @@ -24376,7 +24377,7 @@ expand_small_movmem_or_setmem (rtx destm if (DYNAMIC_CHECK) Round COUNT down to multiple of SIZE << optional caller supplied zero size guard is here >> - << optional caller suppplied dynamic check is here >> + << optional caller supplied dynamic check is here >> << caller supplied main copy loop is here >> } done_label: @@ -24550,8 +24551,8 @@ expand_set_or_movmem_prologue_epilogue_b else *min_size = 0; - /* Our loops always round down the bock size, but for dispatch to library - we need precise value. */ + /* Our loops always round down the block size, but for dispatch to + library we need precise value. */ if (dynamic_check) *count = expand_simple_binop (GET_MODE (*count), AND, *count, GEN_INT (-size), *count, 1, OPTAB_DIRECT); @@ -25129,6 +25130,13 @@ ix86_expand_set_or_movmem (rtx dst, rtx size_needed = GET_MODE_SIZE (move_mode) * unroll_factor; epilogue_size_needed = size_needed; + /* If we are going to call any library calls conditionally, make sure any + pending stack adjustment happen before the first conditional branch, + otherwise they will be emitted before the library call only and won't + happen from the other branches. */ + if (dynamic_check != -1) + do_pending_stack_adjust (); + desired_align = decide_alignment (align, alg, expected_size, move_mode); if (!TARGET_ALIGN_STRINGOPS || noalign) align = desired_align; --- gcc/testsuite/g++.dg/opt/pr69432.C (revision 0) +++ gcc/testsuite/g++.dg/opt/pr69432.C (revision 232754) @@ -0,0 +1,62 @@ +// PR target/69432 +// { dg-do compile } +// { dg-options "-O3" } +// { dg-additional-options "-minline-stringops-dynamically" { target i?86-*-* x86_64-*-* } } + +template <typename S, typename T, typename U> +void +f1 (S x, T y, U z) +{ + for (; y; --y, ++x) + *x = z; +} + +template <typename S, typename T, typename U> +void f2 (S x, T y, U z) +{ + f1 (x, y, z); +} + +struct A {}; +struct B { static char f3 (A, unsigned); }; + +template <typename S, typename U> +void f4 (S, U); + +struct C +{ + template <typename S, typename T, typename U> + static S f5 (S x, T y, U z) { f2 (x, y, z); } +}; + +template <typename S, typename T, typename U> +void f6 (S x, T y, U z) { C::f5 (x, y, z); } + +template <typename S, typename T, typename U, typename V> +void f7 (S x, T y, U z, V) { f6 (x, y, z); } + +struct E +{ + struct D : A { char e; D (A); }; + A f; + E (int x) : g(f) { f8 (x); } + ~E (); + D g; + void f9 (int x) { x ? B::f3 (g, x) : char (); } + void f8 (int x) { f9 (x); } +}; + +struct F : E +{ + F (int x) : E(x) { f10 (x); f4 (this, 0); } + char h; + void f10 (int x) { f7 (&g.e, x, h, 0); } +}; + +long a; + +void +test () +{ + F b(a); +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-27 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69399 * wide-int.h (wi::lrshift): For larger precisions, only use fast path if shift is known to be < HOST_BITS_PER_WIDE_INT. * gcc.dg/torture/pr69399.c: New test. --- gcc/wide-int.h (revision 232868) +++ gcc/wide-int.h (revision 232869) @@ -2909,7 +2909,9 @@ wi::lrshift (const T1 &x, const T2 &y) For variable-precision integers like wide_int, handle HWI and sub-HWI integers inline. */ if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT) - ? xi.len == 1 && xi.val[0] >= 0 + ? (shift < HOST_BITS_PER_WIDE_INT + && xi.len == 1 + && xi.val[0] >= 0) : xi.precision <= HOST_BITS_PER_WIDE_INT) { val[0] = xi.to_uhwi () >> shift; --- gcc/testsuite/gcc.dg/torture/pr69399.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr69399.c (revision 232869) @@ -0,0 +1,18 @@ +/* { dg-do run { target int128 } } */ + +static unsigned __attribute__((noinline, noclone)) +foo (unsigned long long u) +{ + unsigned __int128 v = u | 0xffffff81U; + v >>= 64; + return v; +} + +int +main () +{ + unsigned x = foo (27); + if (x != 0) + __builtin_abort (); + return 0; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-28 Jakub Jelinek <ja...@redhat.com> PR pch/68176 * files.c (_cpp_find_file): Set file->implicit_preinclude even if included from file->implicit_preinclude header. --- libcpp/files.c (revision 232955) +++ libcpp/files.c (revision 232956) @@ -522,7 +522,10 @@ _cpp_find_file (cpp_reader *pfile, const return entry->u.file; file = make_cpp_file (pfile, start_dir, fname); - file->implicit_preinclude = implicit_preinclude; + file->implicit_preinclude + = (implicit_preinclude + || (pfile->buffer + && pfile->buffer->file->implicit_preinclude)); /* Try each path in the include chain. */ for (; !fake ;)
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-01-30 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69546 * wide-int.cc (wi::divmod_internal): For unsigned division where both operands fit into uhwi, if o1 is 1 and o0 has msb set, if divident_prec is larger than bits per hwi, clear another quotient word and return 2 instead of 1. Similarly for remainder with msb in HWI set, if dividend_prec is larger than bits per hwi. * gcc.dg/torture/pr69546.c: New test. --- gcc/wide-int.cc (revision 233011) +++ gcc/wide-int.cc (revision 233012) @@ -1788,15 +1788,32 @@ wi::divmod_internal (HOST_WIDE_INT *quot { unsigned HOST_WIDE_INT o0 = dividend.to_uhwi (); unsigned HOST_WIDE_INT o1 = divisor.to_uhwi (); + unsigned int quotient_len = 1; if (quotient) - quotient[0] = o0 / o1; + { + quotient[0] = o0 / o1; + if (o1 == 1 + && (HOST_WIDE_INT) o0 < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + quotient[1] = 0; + quotient_len = 2; + } + } if (remainder) { remainder[0] = o0 % o1; - *remainder_len = 1; + if ((HOST_WIDE_INT) remainder[0] < 0 + && dividend_prec > HOST_BITS_PER_WIDE_INT) + { + remainder[1] = 0; + *remainder_len = 2; + } + else + *remainder_len = 1; } - return 1; + return quotient_len; } /* Make the divisor and dividend positive and remember what we --- gcc/testsuite/gcc.dg/torture/pr69546-1.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr69546-1.c (revision 233012) @@ -0,0 +1,26 @@ +/* PR tree-optimization/69546 */ +/* { dg-do run { target int128 } } */ + +unsigned __int128 __attribute__ ((noinline, noclone)) +foo (unsigned long long x) +{ + unsigned __int128 y = ~0ULL; + x >>= 63; + return y / (x | 1); +} + +unsigned __int128 __attribute__ ((noinline, noclone)) +bar (unsigned long long x) +{ + unsigned __int128 y = ~33ULL; + x >>= 63; + return y / (x | 1); +} + +int +main () +{ + if (foo (1) != ~0ULL || bar (17) != ~33ULL) + __builtin_abort (); + return 0; +} --- gcc/testsuite/gcc.dg/torture/pr69546-2.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr69546-2.c (revision 233012) @@ -0,0 +1,18 @@ +/* PR tree-optimization/69546 */ +/* { dg-do run { target int128 } } */ + +unsigned __int128 +foo (void) +{ + unsigned __int128 a = 0xfffffffffffffffeULL; + unsigned __int128 b = 0xffffffffffffffffULL; + return a % b; +} + +int +main () +{ + if (foo () != 0xfffffffffffffffeULL) + __builtin_abort (); + return 0; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-02-04 Jakub Jelinek <ja...@redhat.com> PR c/69669 * c-decl.c (finish_enum): When honoring mode attribute, make sure to use proper TYPE_MIN_VALUE and TYPE_MAX_VALUE. * c-c++-common/pr69669.c: New test. --- gcc/c/c-decl.c (revision 233153) +++ gcc/c/c-decl.c (revision 233154) @@ -8019,7 +8019,22 @@ finish_enum (tree enumtype, tree values, precision = MAX (tree_int_cst_min_precision (minnode, sign), tree_int_cst_min_precision (maxnode, sign)); - if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node)) + /* If the precision of the type was specified with an attribute and it + was too small, give an error. Otherwise, use it. */ + if (TYPE_PRECISION (enumtype)) + { + if (precision > TYPE_PRECISION (enumtype)) + { + TYPE_PRECISION (enumtype) = 0; + error ("specified mode too small for enumeral values"); + } + else + precision = TYPE_PRECISION (enumtype); + } + + if (TYPE_PACKED (enumtype) + || precision > TYPE_PRECISION (integer_type_node) + || TYPE_PRECISION (enumtype)) { tem = c_common_type_for_size (precision, sign == UNSIGNED ? 1 : 0); if (tem == NULL) @@ -8035,16 +8050,7 @@ finish_enum (tree enumtype, tree values, TYPE_MAX_VALUE (enumtype) = TYPE_MAX_VALUE (tem); TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (tem); TYPE_SIZE (enumtype) = 0; - - /* If the precision of the type was specific with an attribute and it - was too small, give an error. Otherwise, use it. */ - if (TYPE_PRECISION (enumtype)) - { - if (precision > TYPE_PRECISION (enumtype)) - error ("specified mode too small for enumeral values"); - } - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); + TYPE_PRECISION (enumtype) = TYPE_PRECISION (tem); layout_type (enumtype); --- gcc/testsuite/c-c++-common/pr69669.c (revision 0) +++ gcc/testsuite/c-c++-common/pr69669.c (revision 233154) @@ -0,0 +1,10 @@ +/* PR c/69669 */ +/* { dg-do compile } */ + +enum __attribute__((mode(QI))) E { F = 1 }; + +void +foo (enum E *x, int y) +{ + *x = (enum E) y; +}
2016-02-10 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2016-02-08 Jakub Jelinek <ja...@redhat.com> PR c++/59627 * parser.c (cp_parser_omp_declare_reduction): Set assembler name of the DECL_OMP_DECLARE_REDUCTION_P decls. * g++.dg/gomp/pr59627.C: New test. --- gcc/cp/parser.c (revision 233224) +++ gcc/cp/parser.c (revision 233225) @@ -36080,6 +36080,7 @@ cp_parser_omp_declare_reduction (cp_pars DECL_DECLARED_INLINE_P (fndecl) = 1; DECL_IGNORED_P (fndecl) = 1; DECL_OMP_DECLARE_REDUCTION_P (fndecl) = 1; + SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier ("<udr>")); DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gnu_inline"), NULL_TREE, DECL_ATTRIBUTES (fndecl)); --- gcc/testsuite/g++.dg/gomp/pr59627.C (revision 0) +++ gcc/testsuite/g++.dg/gomp/pr59627.C (revision 233225) @@ -0,0 +1,14 @@ +// PR c++/59627 +// { dg-do compile { target lto } } +// { dg-options "-fopenmp -flto" } + +struct A { A () : i (0) {} int i; }; + +void +foo () +{ + A a; + #pragma omp declare reduction (+: A: omp_out.i += omp_in.i) + #pragma omp parallel reduction (+: a) + ; +}