Hi! I've backported these patches from trunk to 4.6 branch, bootstrapped/regtested them on x86_64-linux and i686-linux and committed. Sorry for the delay.
Jakub
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2011-12-15 Jakub Jelinek <ja...@redhat.com> PR debug/51517 * tree-ssa-coalesce.c (coalesce_ssa_name): For !optimize, test !DECL_IGNORED_P instead of !DECL_ARTIFICIAL. * trans-decl.c (gfc_get_symbol_decl): Don't set DECL_INITAL on span. (gfc_trans_deferred_vars): Instead add its runtime initialization here. --- gcc/tree-ssa-coalesce.c (revision 182361) +++ gcc/tree-ssa-coalesce.c (revision 182362) @@ -1373,7 +1373,7 @@ coalesce_ssa_name (void) if (a && SSA_NAME_VAR (a) - && !DECL_ARTIFICIAL (SSA_NAME_VAR (a)) + && !DECL_IGNORED_P (SSA_NAME_VAR (a)) && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a))) { tree *slot = (tree *) htab_find_slot (ssa_name_hash, a, INSERT); --- gcc/fortran/trans-decl.c (revision 182361) +++ gcc/fortran/trans-decl.c (revision 182362) @@ -1352,7 +1352,6 @@ gfc_get_symbol_decl (gfc_symbol * sym) gfc_finish_var_decl (span, sym); TREE_STATIC (span) = TREE_STATIC (decl); DECL_ARTIFICIAL (span) = 1; - DECL_INITIAL (span) = build_int_cst (gfc_array_index_type, 0); GFC_DECL_SPAN (decl) = span; GFC_TYPE_ARRAY_SPAN (TREE_TYPE (decl)) = span; @@ -3394,6 +3393,17 @@ gfc_trans_deferred_vars (gfc_symbol * pr if (sym->assoc) continue; + if (sym->attr.subref_array_pointer + && GFC_DECL_SPAN (sym->backend_decl) + && !TREE_STATIC (GFC_DECL_SPAN (sym->backend_decl))) + { + gfc_init_block (&tmpblock); + gfc_add_modify (&tmpblock, GFC_DECL_SPAN (sym->backend_decl), + build_int_cst (gfc_array_index_type, 0)); + gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock), + NULL_TREE); + } + if (sym->attr.dimension) { /* Assumed-size Cray pointees need to be treated as AS_EXPLICIT. */
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2011-12-15 Jakub Jelinek <ja...@redhat.com> PR c/51360 * c-parser.c (c_parser_omp_clause_num_threads, c_parser_omp_clause_schedule): Call mark_exp_read. * semantics.c (finish_omp_clauses): For OMP_CLAUSE_NUM_THREADS_EXPR and OMP_CLAUSE_SCHEDULE_CHUNK_EXPR call mark_rvalue_use. * gcc.dg/gomp/pr51360.c: New test. * g++.dg/gomp/pr51360.C: New test. * g++.dg/gomp/pr51360-2.C: New test. --- gcc/cp/semantics.c (revision 182380) +++ gcc/cp/semantics.c (revision 182381) @@ -4087,6 +4087,8 @@ finish_omp_clauses (tree clauses) error ("num_threads expression must be integral"); remove = true; } + else + OMP_CLAUSE_NUM_THREADS_EXPR (c) = mark_rvalue_use (t); break; case OMP_CLAUSE_SCHEDULE: @@ -4101,6 +4103,8 @@ finish_omp_clauses (tree clauses) error ("schedule chunk size expression must be integral"); remove = true; } + else + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = mark_rvalue_use (t); break; case OMP_CLAUSE_NOWAIT: --- gcc/c-parser.c (revision 182380) +++ gcc/c-parser.c (revision 182381) @@ -9011,6 +9011,7 @@ c_parser_omp_clause_num_threads (c_parse { location_t expr_loc = c_parser_peek_token (parser)->location; tree c, t = c_parser_expression (parser).value; + mark_exp_read (t); t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -9218,6 +9219,7 @@ c_parser_omp_clause_schedule (c_parser * here = c_parser_peek_token (parser)->location; t = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (t); t = c_fully_fold (t, false, NULL); if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) --- gcc/testsuite/g++.dg/gomp/pr51360.C (revision 0) +++ gcc/testsuite/g++.dg/gomp/pr51360.C (revision 182381) @@ -0,0 +1,28 @@ +// PR c/51360 +// { dg-do compile } +// { dg-options "-Wunused -W -fopenmp" } + +template <typename T> +void +foo (T a, T b, T c) +{ + T m, n, o, i; + m = 6; + n = 1; + o = 5; + a = 6; + b = 1; + c = 5; + #pragma omp parallel for num_threads (m) if (n) schedule (static, o) + for (i = 0; i < 10; i++) + ; + #pragma omp parallel for num_threads (a) if (b) schedule (static, c) + for (i = 0; i < 10; i++) + ; +} + +void +bar () +{ + foo (0, 0, 0); +} --- gcc/testsuite/gcc.dg/gomp/pr51360.c (revision 0) +++ gcc/testsuite/gcc.dg/gomp/pr51360.c (revision 182381) @@ -0,0 +1,21 @@ +/* PR c/51360 */ +/* { dg-do compile } */ +/* { dg-options "-Wunused -W -fopenmp" } */ + +void +foo (int a, int b, int c) +{ + int m, n, o, i; + m = 6; + n = 1; + o = 5; + a = 6; + b = 1; + c = 5; + #pragma omp parallel for num_threads (m) if (n) schedule (static, o) + for (i = 0; i < 10; i++) + ; + #pragma omp parallel for num_threads (a) if (b) schedule (static, c) + for (i = 0; i < 10; i++) + ; +} --- gcc/testsuite/g++.dg/gomp/pr51360-2.C (revision 0) +++ gcc/testsuite/g++.dg/gomp/pr51360-2.C (revision 182381) @@ -0,0 +1,21 @@ +/* PR c/51360 */ +/* { dg-do compile } */ +/* { dg-options "-Wunused -W -fopenmp" } */ + +void +foo (int a, int b, int c) +{ + int m, n, o, i; + m = 6; + n = 1; + o = 5; + a = 6; + b = 1; + c = 5; + #pragma omp parallel for num_threads (m) if (n) schedule (static, o) + for (i = 0; i < 10; i++) + ; + #pragma omp parallel for num_threads (a) if (b) schedule (static, c) + for (i = 0; i < 10; i++) + ; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-26 Jakub Jelinek <ja...@redhat.com> * make-relative-prefix.c (make_relative_prefix_1): Avoid warning about using preprocessor directives inside of macro arguments. 2012-01-02 Jakub Jelinek <ja...@redhat.com> * make-relative-prefix.c (make_relative_prefix_1): Avoid stack overflow if PATH contains just a single entry and HOST_EXECUTABLE_SUFFIX needs to be used. PR driver/48306 * make-relative-prefix.c: Include sys/stat.h. (make_relative_prefix_1): If access succeeds, check also stat if nstore is a regular file. --- libiberty/make-relative-prefix.c (revision 182819) +++ libiberty/make-relative-prefix.c (revision 183561) @@ -58,6 +58,9 @@ #ifdef HAVE_UNISTD_H #include <unistd.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #include <string.h> @@ -245,10 +248,15 @@ { char *startp, *endp, *nstore; size_t prefixlen = strlen (temp) + 1; + size_t len; if (prefixlen < 2) prefixlen = 2; - nstore = (char *) alloca (prefixlen + strlen (progname) + 1); + len = prefixlen + strlen (progname) + 1; +#ifdef HAVE_HOST_EXECUTABLE_SUFFIX + len += strlen (HOST_EXECUTABLE_SUFFIX); +#endif + nstore = (char *) alloca (len); startp = endp = temp; while (1) @@ -263,7 +271,7 @@ } else { - strncpy (nstore, startp, endp - startp); + memcpy (nstore, startp, endp - startp); if (! IS_DIR_SEPARATOR (endp[-1])) { nstore[endp - startp] = DIR_SEPARATOR; @@ -279,8 +287,14 @@ #endif ) { - progname = nstore; - break; +#if defined (HAVE_SYS_STAT_H) && defined (S_ISREG) + struct stat st; + if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode)) +#endif + { + progname = nstore; + break; + } } if (*endp == 0)
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-03 Jakub Jelinek <ja...@redhat.com> PR c++/51669 * semantics.c (finish_omp_clauses): Call fold_build_cleanup_point_expr on OMP_CLAUSE_{IF,NUM_THREADS,SCHEDULE_CHUNK}_EXPR. * g++.dg/gomp/pr51669.C: New test. --- gcc/cp/semantics.c (revision 182827) +++ gcc/cp/semantics.c (revision 182828) @@ -3804,6 +3804,8 @@ finish_omp_clauses (tree clauses) t = maybe_convert_cond (t); if (t == error_mark_node) remove = true; + else if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); OMP_CLAUSE_IF_EXPR (c) = t; break; @@ -3818,7 +3820,12 @@ finish_omp_clauses (tree clauses) remove = true; } else - OMP_CLAUSE_NUM_THREADS_EXPR (c) = mark_rvalue_use (t); + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; + } break; case OMP_CLAUSE_SCHEDULE: @@ -3834,7 +3841,12 @@ finish_omp_clauses (tree clauses) remove = true; } else - OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = mark_rvalue_use (t); + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; + } break; case OMP_CLAUSE_NOWAIT: --- gcc/testsuite/g++.dg/gomp/pr51669.C (revision 0) +++ gcc/testsuite/g++.dg/gomp/pr51669.C (revision 182828) @@ -0,0 +1,32 @@ +// PR c++/51669 +// { dg-do compile } +// { dg-options "-fopenmp" } + +template <typename T> const T & min (const T &, const T &); + +void +f1 () +{ +#pragma omp parallel num_threads (min (4, 5)) + ; +} + +struct A { A (); ~A (); }; +int foo (const A &); + +void +f2 () +{ + int i; +#pragma omp parallel if (foo (A ())) num_threads (foo (A ())) + ; +#pragma omp task if (foo (A ())) + ; +#pragma omp for schedule (static, foo (A ())) + for (i = 0; i < 10; i++) + ; +#pragma omp parallel for schedule (static, foo (A ())) \ + if (foo (A ())) num_threads (foo (A ())) + for (i = 0; i < 10; i++) + ; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-04 Jakub Jelinek <ja...@redhat.com> PR debug/51695 * dwarf2out.c (output_loc_list): For now drop >= 64KB expressions in .debug_loc on the floor. * gcc.dg/pr51695.c: New test. --- gcc/dwarf2out.c (revision 182885) +++ gcc/dwarf2out.c (revision 182886) @@ -11164,6 +11164,13 @@ output_loc_list (dw_loc_list_ref list_he /* Don't output an entry that starts and ends at the same address. */ if (strcmp (curr->begin, curr->end) == 0) continue; + size = size_of_locs (curr->expr); + /* If the expression is too large, drop it on the floor. We could + perhaps put it into DW_TAG_dwarf_procedure and refer to that + in the expression, but >= 64KB expressions for a single value + in a single range are unlikely very useful. */ + if (size > 0xffff) + continue; if (!have_multiple_function_sections) { dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, @@ -11182,7 +11189,6 @@ output_loc_list (dw_loc_list_ref list_he "Location list end address (%s)", list_head->ll_symbol); } - size = size_of_locs (curr->expr); /* Output the block length for this list of location operations. */ gcc_assert (size <= 0xffff); --- gcc/testsuite/gcc.dg/pr51695.c (revision 0) +++ gcc/testsuite/gcc.dg/pr51695.c (revision 182886) @@ -0,0 +1,52 @@ +/* PR debug/51695 */ +/* { dg-do compile { target { int32plus } } } */ +/* { dg-options "-O2 -g" } */ + +typedef struct +{ + struct { unsigned int t1, t2, t3, t4, t5, t6; } t; + int p; + struct { double X, Y, Z; } r; +} T; +typedef struct { T *h; } S; + +static unsigned int v = 0x12345678; + +int +foo (void) +{ + v = (v & 0x80000000) ? ((v << 1) ^ 0xa398655d) : (v << 1); + return 0; +} + +double +bar (void) +{ + unsigned int o; + v = (v & 0x80000000) ? ((v << 1) ^ 0xa398655d) : (v << 1); + o = v & 0xffff; + return (double) o / 32768.0; +} + +int +baz (void) +{ + foo (); + return 0; +} + +void +test (S *x) +{ + T *t = x->h; + t->t.t1 = foo (); + t->t.t2 = foo (); + t->t.t3 = foo (); + t->t.t4 = foo (); + t->t.t5 = foo (); + t->t.t6 = foo (); + t->p = baz (); + t->r.X = bar (); + t->r.Y = bar (); + t->r.Z = bar (); +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-05 Jakub Jelinek <ja...@redhat.com> PR middle-end/44777 * profile.c (branch_prob): Split bbs that have exit edge and need a fake entry edge too. * gcc.dg/tree-prof/pr44777.c: New test. --- gcc/profile.c (revision 182919) +++ gcc/profile.c (revision 182920) @@ -1040,6 +1040,41 @@ branch_prob (void) fprintf (dump_file, "Adding fake entry edge to bb %i\n", bb->index); make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE); + /* Avoid bbs that have both fake entry edge and also some + exit edge. One of those edges wouldn't be added to the + spanning tree, but we can't instrument any of them. */ + if (have_exit_edge || need_exit_edge) + { + gimple_stmt_iterator gsi; + gimple first; + tree fndecl; + + gsi = gsi_after_labels (bb); + gcc_checking_assert (!gsi_end_p (gsi)); + first = gsi_stmt (gsi); + if (is_gimple_debug (first)) + { + gsi_next_nondebug (&gsi); + gcc_checking_assert (!gsi_end_p (gsi)); + first = gsi_stmt (gsi); + } + /* Don't split the bbs containing __builtin_setjmp_receiver + or __builtin_setjmp_dispatcher calls. These are very + special and don't expect anything to be inserted before + them. */ + if (!is_gimple_call (first) + || (fndecl = gimple_call_fndecl (first)) == NULL + || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL + || (DECL_FUNCTION_CODE (fndecl) != BUILT_IN_SETJMP_RECEIVER + && (DECL_FUNCTION_CODE (fndecl) + != BUILT_IN_SETJMP_DISPATCHER))) + { + if (dump_file) + fprintf (dump_file, "Splitting bb %i after labels\n", + bb->index); + split_block_after_labels (bb); + } + } } } --- gcc/testsuite/gcc.dg/tree-prof/pr44777.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-prof/pr44777.c (revision 182920) @@ -0,0 +1,43 @@ +/* PR middle-end/44777 */ +/* { dg-options "-O0" } */ +/* A variant of gcc.c-torture/execute/comp-goto-2.c. */ + +extern void abort (void); +extern void exit (int); + +#ifdef STACK_SIZE +#define DEPTH ((STACK_SIZE) / 512 + 1) +#else +#define DEPTH 1000 +#endif + +#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES) +int +x (int a) +{ + __label__ xlab; + void y (int a) + { + void *x = &&llab; + if (a==-1) + goto *x; + if (a==0) + goto xlab; + llab: + y (a-1); + } + y (a); + xlab:; + return a; +} +#endif + +int +main () +{ +#if ! defined (NO_LABEL_VALUES) && !defined (NO_TRAMPOLINES) + if (x (DEPTH) != DEPTH) + abort (); +#endif + exit (0); +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-05 Jakub Jelinek <ja...@redhat.com> PR middle-end/51768 * stmt.c (check_unique_operand_names): Don't ICE during error reporting if i is from labels chain. * c-c++-common/pr51768.c: New test. --- gcc/stmt.c (revision 182920) +++ gcc/stmt.c (revision 182921) @@ -1253,11 +1253,11 @@ check_operand_nalternatives (tree output static bool check_unique_operand_names (tree outputs, tree inputs, tree labels) { - tree i, j; + tree i, j, i_name = NULL_TREE; for (i = outputs; i ; i = TREE_CHAIN (i)) { - tree i_name = TREE_PURPOSE (TREE_PURPOSE (i)); + i_name = TREE_PURPOSE (TREE_PURPOSE (i)); if (! i_name) continue; @@ -1268,7 +1268,7 @@ check_unique_operand_names (tree outputs for (i = inputs; i ; i = TREE_CHAIN (i)) { - tree i_name = TREE_PURPOSE (TREE_PURPOSE (i)); + i_name = TREE_PURPOSE (TREE_PURPOSE (i)); if (! i_name) continue; @@ -1282,7 +1282,7 @@ check_unique_operand_names (tree outputs for (i = labels; i ; i = TREE_CHAIN (i)) { - tree i_name = TREE_PURPOSE (i); + i_name = TREE_PURPOSE (i); if (! i_name) continue; @@ -1297,8 +1297,7 @@ check_unique_operand_names (tree outputs return true; failure: - error ("duplicate asm operand name %qs", - TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i)))); + error ("duplicate asm operand name %qs", TREE_STRING_POINTER (i_name)); return false; } --- gcc/testsuite/c-c++-common/pr51768.c (revision 0) +++ gcc/testsuite/c-c++-common/pr51768.c (revision 182921) @@ -0,0 +1,25 @@ +/* PR middle-end/51768 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ + asm goto ("" : : : : lab, lab, lab2, lab); /* { dg-error "duplicate asm operand name" } */ +lab:; +lab2:; +} + +void +bar (void) +{ + asm goto ("" : : [lab] "i" (0) : : lab); /* { dg-error "duplicate asm operand name" } */ +lab:; +} + +void +baz (void) +{ + int x; + asm ("" : [lab] "=r" (x) : [lab] "r" (x)); /* { dg-error "duplicate asm operand name" } */ +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-05 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/51767 * cfgrtl.c (force_nonfallthru_and_redirect): Force addition of jump_block and add an extra edge for degenerated asm gotos. * gcc.c-torture/compile/pr51767.c: New test. --- gcc/cfgrtl.c (revision 182921) +++ gcc/cfgrtl.c (revision 182922) @@ -1129,6 +1129,7 @@ force_nonfallthru_and_redirect (edge e, rtx note; edge new_edge; int abnormal_edge_flags = 0; + bool asm_goto_edge = false; int loc; /* In the case the last instruction is conditional jump to the next @@ -1208,8 +1209,28 @@ force_nonfallthru_and_redirect (edge e, } } - if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags) + /* If e->src ends with asm goto, see if any of the ASM_OPERANDS_LABELs + don't point to target label. */ + if (JUMP_P (BB_END (e->src)) + && target != EXIT_BLOCK_PTR + && e->dest == target + && (e->flags & EDGE_FALLTHRU) + && (note = extract_asm_operands (PATTERN (BB_END (e->src))))) { + int i, n = ASM_OPERANDS_LABEL_LENGTH (note); + + for (i = 0; i < n; ++i) + if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (target)) + { + asm_goto_edge = true; + break; + } + } + + if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge) + { + gcov_type count = e->count; + int probability = e->probability; /* Create the new structures. */ /* If the old block ended with a tablejump, skip its table @@ -1220,7 +1241,7 @@ force_nonfallthru_and_redirect (edge e, note = NEXT_INSN (note); jump_block = create_basic_block (note, NULL, e->src); - jump_block->count = e->count; + jump_block->count = count; jump_block->frequency = EDGE_FREQUENCY (e); jump_block->loop_depth = target->loop_depth; @@ -1236,13 +1257,27 @@ force_nonfallthru_and_redirect (edge e, /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); - new_edge->probability = e->probability; - new_edge->count = e->count; + new_edge->probability = probability; + new_edge->count = count; /* Redirect old edge. */ redirect_edge_pred (e, jump_block); e->probability = REG_BR_PROB_BASE; + /* If asm goto has any label refs to target's label, + add also edge from asm goto bb to target. */ + if (asm_goto_edge) + { + new_edge->probability /= 2; + new_edge->count /= 2; + jump_block->count /= 2; + jump_block->frequency /= 2; + new_edge = make_edge (new_edge->src, target, + e->flags & ~EDGE_FALLTHRU); + new_edge->probability = probability - probability / 2; + new_edge->count = count - count / 2; + } + new_bb = jump_block; } else --- gcc/testsuite/gcc.c-torture/compile/pr51767.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr51767.c (revision 182922) @@ -0,0 +1,23 @@ +/* PR rtl-optimization/51767 */ + +extern void fn1 (void), fn2 (void); + +static inline __attribute__((always_inline)) int +foo (int *x, long y) +{ + asm goto ("" : : "r" (x), "r" (y) : "memory" : lab); + return 0; +lab: + return 1; +} + +void +bar (int *x) +{ + if (foo (x, 23)) + fn1 (); + else + fn2 (); + + foo (x, 2); +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-19 Jakub Jelinek <ja...@redhat.com> PR libmudflap/40778 * tree-mudflap.c (mf_artificial): New function. (execute_mudflap_function_ops, execute_mudflap_function_decls, mx_register_decls, mudflap_enqueue_decl): Use it. * testsuite/libmudflap.c/fail68-frag.c: New test. --- gcc/tree-mudflap.c (revision 183306) +++ gcc/tree-mudflap.c (revision 183307) @@ -69,6 +69,13 @@ static tree mx_xfn_xform_decls (gimple_s static gimple_seq mx_register_decls (tree, gimple_seq, location_t); static unsigned int execute_mudflap_function_decls (void); +/* Return true if DECL is artificial stub that shouldn't be instrumented by + mf. We should instrument clones of non-artificial functions. */ +static inline bool +mf_artificial (const_tree decl) +{ + return DECL_ARTIFICIAL (DECL_ORIGIN (decl)); +} /* ------------------------------------------------------------------------ */ /* Some generally helpful functions for mudflap instrumentation. */ @@ -412,8 +419,8 @@ execute_mudflap_function_ops (void) /* Don't instrument functions such as the synthetic constructor built during mudflap_finish_file. */ - if (mf_marked_p (current_function_decl) || - DECL_ARTIFICIAL (current_function_decl)) + if (mf_marked_p (current_function_decl) + || mf_artificial (current_function_decl)) return 0; push_gimplify_context (&gctx); @@ -994,8 +1001,8 @@ execute_mudflap_function_decls (void) /* Don't instrument functions such as the synthetic constructor built during mudflap_finish_file. */ - if (mf_marked_p (current_function_decl) || - DECL_ARTIFICIAL (current_function_decl)) + if (mf_marked_p (current_function_decl) + || mf_artificial (current_function_decl)) return 0; push_gimplify_context (&gctx); @@ -1078,7 +1085,7 @@ mx_register_decls (tree decl, gimple_seq /* Add the __mf_register call at the current appending point. */ if (gsi_end_p (initially_stmts)) { - if (!DECL_ARTIFICIAL (decl)) + if (!mf_artificial (decl)) warning (OPT_Wmudflap, "mudflap cannot track %qE in stub function", DECL_NAME (decl)); @@ -1249,7 +1256,7 @@ mudflap_enqueue_decl (tree obj) during mudflap_finish_file (). That would confuse the user, since the text would refer to variables that don't show up in the user's source code. */ - if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj)) + if (DECL_P (obj) && DECL_EXTERNAL (obj) && mf_artificial (obj)) return; VEC_safe_push (tree, gc, deferred_static_decls, obj); --- libmudflap/testsuite/libmudflap.c/fail68-frag.c (revision 0) +++ libmudflap/testsuite/libmudflap.c/fail68-frag.c (revision 183307) @@ -0,0 +1,27 @@ +/* PR libmudflap/40778 */ + +char p[32]; +static int j; + +__attribute__((noinline)) +static void foo (int i) +{ + if (j++ == 0) + p[i + 4] = 12; + else + p[i - 4] = 13; +} + +int +main () +{ + foo (30); + foo (30); + foo (30); + return 0; +} + +/* { dg-output "mudflap violation 1.*" } */ +/* { dg-output "Nearby object 1.*" } */ +/* { dg-output "mudflap object.*name.*p" } */ +/* { dg-do run { xfail *-*-* } } */
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-01-28 Jakub Jelinek <ja...@redhat.com> PR target/52006 * config/arm/arm.md (pic_add_dot_plus_eight peephole2): Use arm_general_register_operand predicate for operand 2 instead of register_operand. * gcc.target/arm/pr52006.c: New test. --- gcc/config/arm/arm.md (revision 183660) +++ gcc/config/arm/arm.md (revision 183661) @@ -5719,7 +5719,8 @@ (define_peephole2 (const_int 8) (match_operand 1 "" "")] UNSPEC_PIC_BASE)) - (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))] + (set (match_operand:SI 2 "arm_general_register_operand" "") + (mem:SI (match_dup 0)))] "TARGET_ARM && peep2_reg_dead_p (2, operands[0])" [(set (match_dup 2) (mem:SI (unspec:SI [(match_dup 3) --- gcc/testsuite/gcc.target/arm/pr52006.c (revision 0) +++ gcc/testsuite/gcc.target/arm/pr52006.c (revision 183661) @@ -0,0 +1,19 @@ +/* PR target/52006 */ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mfloat-abi=hard -O2 -fPIC" } */ + +unsigned long a; +static int b; + +void +foo (void) +{ + asm volatile ("" : "=r" (b)); +} + +void +bar (float f) +{ + if (f < b / 100.0) + a = 1; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-02-02 Jakub Jelinek <ja...@redhat.com> PR middle-end/48071 * diagnostic.c (diagnostic_finish): Remove trailing newlines. --- gcc/diagnostic.c (revision 183846) +++ gcc/diagnostic.c (revision 183847) @@ -133,12 +133,12 @@ diagnostic_finish (diagnostic_context *c /* -Werror was given. */ if (context->warning_as_error_requested) pp_verbatim (context->printer, - _("%s: all warnings being treated as errors\n"), + _("%s: all warnings being treated as errors"), progname); /* At least one -Werror= was given. */ else pp_verbatim (context->printer, - _("%s: some warnings being treated as errors\n"), + _("%s: some warnings being treated as errors"), progname); pp_flush (context->printer); }
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-02-06 Jakub Jelinek <ja...@redhat.com> PR target/52129 * calls.c (mem_overlaps_already_clobbered_arg_p): If val is CONST_INT_P, subtract resp. add crtl->args.pretend_args_size to it. * gcc.c-torture/execute/pr52129.c: New test. --- gcc/calls.c (revision 183932) +++ gcc/calls.c (revision 183933) @@ -1808,6 +1808,11 @@ mem_overlaps_already_clobbered_arg_p (rt return true; else i = INTVAL (val); +#ifdef STACK_GROWS_DOWNWARD + i -= crtl->args.pretend_args_size; +#else + i += crtl->args.pretend_args_size; +#endif #ifdef ARGS_GROW_DOWNWARD i = -i - size; --- gcc/testsuite/gcc.c-torture/execute/pr52129.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/pr52129.c (revision 183933) @@ -0,0 +1,28 @@ +/* PR target/52129 */ + +extern void abort (void); +struct S { void *p; unsigned int q; }; +struct T { char a[64]; char b[64]; } t; + +__attribute__((noinline, noclone)) int +foo (void *x, struct S s, void *y, void *z) +{ + if (x != &t.a[2] || s.p != &t.b[5] || s.q != 27 || y != &t.a[17] || z != &t.b[17]) + abort (); + return 29; +} + +__attribute__((noinline, noclone)) int +bar (void *x, void *y, void *z, struct S s, int t, struct T *u) +{ + return foo (x, s, &u->a[t], &u->b[t]); +} + +int +main () +{ + struct S s = { &t.b[5], 27 }; + if (bar (&t.a[2], (void *) 0, (void *) 0, s, 17, &t) != 29) + abort (); + return 0; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-02-07 Jakub Jelinek <ja...@redhat.com> PR middle-end/52074 * expr.c (expand_expr_addr_expr_1): For CONSTANT_CLASS_P or CONST_DECL if modifier < EXPAND_SUM call force_operand on the result. * gcc.c-torture/compile/pr52074.c: New test. --- gcc/expr.c (revision 183955) +++ gcc/expr.c (revision 183956) @@ -7414,7 +7414,12 @@ expand_expr_addr_expr_1 (tree exp, rtx t generating ADDR_EXPR of something that isn't an LVALUE. The only exception here is STRING_CST. */ if (CONSTANT_CLASS_P (exp)) - return XEXP (expand_expr_constant (exp, 0, modifier), 0); + { + result = XEXP (expand_expr_constant (exp, 0, modifier), 0); + if (modifier < EXPAND_SUM) + result = force_operand (result, target); + return result; + } /* Everything must be something allowed by is_gimple_addressable. */ switch (TREE_CODE (exp)) @@ -7433,7 +7438,11 @@ expand_expr_addr_expr_1 (tree exp, rtx t case CONST_DECL: /* Expand the initializer like constants above. */ - return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0); + result = XEXP (expand_expr_constant (DECL_INITIAL (exp), + 0, modifier), 0); + if (modifier < EXPAND_SUM) + result = force_operand (result, target); + return result; case REALPART_EXPR: /* The real part of the complex number is always first, therefore --- gcc/testsuite/gcc.c-torture/compile/pr52074.c (revision 0) +++ gcc/testsuite/gcc.c-torture/compile/pr52074.c (revision 183956) @@ -0,0 +1,10 @@ +/* PR middle-end/52074 */ + +struct S { const char *d, *e; } __attribute__((packed)); + +void +foo (const char **p, struct S *q) +{ + *p = "abcdef"; + q->d = "ghijk"; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-02-07 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/52060 * combine.c (try_combine): Add i0src_copy and i0src_copy2 variables, copy i1src to i1src_copy whenever added_sets_2 && i1_feeds_i2_n already before i1dest -> i1src substitution in newpat, copy i0src to i0src_copy and/or i0src_copy2 when needed. * gcc.dg/torture/pr52060.c: New test. --- gcc/combine.c (revision 183971) +++ gcc/combine.c (revision 183972) @@ -2558,8 +2558,8 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx rtx i3dest_killed = 0; /* SET_DEST and SET_SRC of I2, I1 and I0. */ rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; - /* Copy of SET_SRC of I1, if needed. */ - rtx i1src_copy = 0; + /* Copy of SET_SRC of I1 and I0, if needed. */ + rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0; /* Set if I2DEST was reused as a scratch register. */ bool i2scratch = false; /* The PATTERNs of I0, I1, and I2, or a copy of them in certain cases. */ @@ -3171,6 +3171,11 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx n_occurrences = 0; subst_low_luid = DF_INSN_LUID (i1); + /* If the following substitution will modify I1SRC, make a copy of it + for the case where it is substituted for I1DEST in I2PAT later. */ + if (added_sets_2 && i1_feeds_i2_n) + i1src_copy = copy_rtx (i1src); + /* If I0 feeds into I1 and I0DEST is in I0SRC, we need to make a unique copy of I1SRC each time we substitute it, in order to avoid creating self-referential RTL when we will be substituting I0SRC for I0DEST @@ -3198,10 +3203,14 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx return 0; } - /* If the following substitution will modify I1SRC, make a copy of it - for the case where it is substituted for I1DEST in I2PAT later. */ - if (i0_feeds_i1_n && added_sets_2 && i1_feeds_i2_n) - i1src_copy = copy_rtx (i1src); + /* If the following substitution will modify I0SRC, make a copy of it + for the case where it is substituted for I0DEST in I1PAT later. */ + if (added_sets_1 && i0_feeds_i1_n) + i0src_copy = copy_rtx (i0src); + /* And a copy for I0DEST in I2PAT substitution. */ + if (added_sets_2 && ((i0_feeds_i1_n && i1_feeds_i2_n) + || (i0_feeds_i2_n))) + i0src_copy2 = copy_rtx (i0src); n_occurrences = 0; subst_low_luid = DF_INSN_LUID (i0); @@ -3267,7 +3276,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx { rtx t = i1pat; if (i0_feeds_i1_n) - t = subst (t, i0dest, i0src, 0, 0); + t = subst (t, i0dest, i0src_copy ? i0src_copy : i0src, 0, 0); XVECEXP (newpat, 0, --total_sets) = t; } @@ -3278,7 +3287,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx t = subst (t, i1dest, i1src_copy ? i1src_copy : i1src, 0, i0_feeds_i1_n && i0dest_in_i0src); if ((i0_feeds_i1_n && i1_feeds_i2_n) || i0_feeds_i2_n) - t = subst (t, i0dest, i0src, 0, 0); + t = subst (t, i0dest, i0src_copy2 ? i0src_copy2 : i0src, 0, 0); XVECEXP (newpat, 0, --total_sets) = t; } --- gcc/testsuite/gcc.dg/torture/pr52060.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr52060.c (revision 183972) @@ -0,0 +1,57 @@ +/* PR rtl-optimization/52060 */ +/* { dg-do run { target int32plus } } */ + +extern void abort (void); +union U { float f; unsigned int i; }; + +static inline __attribute__((always_inline)) unsigned int +foo (float x) +{ + union U u; + unsigned int a, b, c; + int d; + int e; + u.f = x; + d = ((unsigned) u.i >> 23) & 0xFF; + c = d < 126 ? 0 : ~0; + e = 127 + 30 - d; + a = (u.i << 8) | 0x80000000U; + b = a & ((1 << e) - 1); + a = a >> e; + c &= (b | (a & 2)) ? ~0 : ~1; + a = ((a + 1U) >> 1) & c; + return a; +} + +__attribute__((noinline)) unsigned int +bar (float x) +{ + unsigned int a, b, c; + static const unsigned int d[128] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7 + }; + a = foo (1048575.0f * x); + c = d[a >> 13]; + b = (c << 13) | ((a >> (7 - c)) & 0x1fff); + return b; +} + +int +main () +{ + union U u; + u.f = 1048575.0f; + if (sizeof (u.i) == sizeof (u.f) + && u.i == 0x497ffff0U + && bar (1.0f) != 65535) + abort (); + return 0; +}
2012-02-09 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2012-02-08 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/52139 * cfgrtl.c (cfg_layout_merge_blocks): If BB_END is a BARRIER after emit_insn_after_noloc, move BB_END to the last non-BARRIER insn before it. * gcc.dg/pr52139.c: New test. --- gcc/cfgrtl.c (revision 184004) +++ gcc/cfgrtl.c (revision 184005) @@ -2871,6 +2871,11 @@ cfg_layout_merge_blocks (basic_block a, rtx first = BB_END (a), last; last = emit_insn_after_noloc (b->il.rtl->header, BB_END (a), a); + /* The above might add a BARRIER as BB_END, but as barriers + aren't valid parts of a bb, remove_insn doesn't update + BB_END if it is a barrier. So adjust BB_END here. */ + while (BB_END (a) != first && BARRIER_P (BB_END (a))) + BB_END (a) = PREV_INSN (BB_END (a)); delete_insn_chain (NEXT_INSN (first), last, false); b->il.rtl->header = NULL; } --- gcc/testsuite/gcc.dg/pr52139.c (revision 0) +++ gcc/testsuite/gcc.dg/pr52139.c (revision 184005) @@ -0,0 +1,49 @@ +/* PR rtl-optimization/52139 */ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-dominator-opts -fno-tree-fre" } */ +/* { dg-options "-O -fno-tree-dominator-opts -fno-tree-fre -fpic" { target fpic } } */ + +void *p; + +void +foo (int a) +{ + switch (a) + { + case 0: + a0: + case 1: + a1: + p = &&a1; + case 2: + a2: + p = &&a2; + case 3: + a3: + p = &&a3; + case 4: + a4: + p = &&a4; + case 5: + a5: + p = &&a5; + case 6: + a6: + p = &&a6; + case 7: + a7: + p = &&a7; + case 8: + a8: + p = &&a8; + case 9: + a9: + p = &&a9; + case 10: + a10: + p = &&a10; + default: + p = &&a0; + } + goto *p; +}