Hi! I've committed these backports to 4.5 branch after bootstrapping/regtesting them on x86_64-linux and i686-linux.
Jakub
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-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-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; +}
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) @@ -989,6 +989,45 @@ 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); +#ifdef ENABLE_CHECKING + gcc_assert (!gsi_end_p (gsi)); +#endif + first = gsi_stmt (gsi); + if (is_gimple_debug (first)) + { + gsi_next_nondebug (&gsi); +#ifdef ENABLE_CHECKING + gcc_assert (!gsi_end_p (gsi)); +#endif + 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); +}