diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-05 20:20:57 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-05 20:20:57 +0000 |
commit | d7ff3ab6455d3c222ff98a4d30e0e86d115564bf (patch) | |
tree | 990059fd6e94d825094e7d8bc0afd68533edad28 /gcc | |
parent | 1aed71d6a8edf6d77849059d17daf851bc646cca (diff) | |
download | gcc-d7ff3ab6455d3c222ff98a4d30e0e86d115564bf.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182922 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cfgrtl.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr51767.c | 23 |
4 files changed, 71 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2e59648f2fa..1bd3bb26295 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2012-01-05 Jakub Jelinek <jakub@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. + PR middle-end/51768 * stmt.c (check_unique_operand_names): Don't ICE during error reporting if i is from labels chain. diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 4b1d8350de5..635955b7990 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1,7 +1,7 @@ /* Control flow graph manipulation code for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011, 2012 Free Software Foundation, Inc. This file is part of GCC. @@ -1129,6 +1129,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label) 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, basic_block target, rtx jump_label) } } - 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, basic_block target, rtx jump_label) 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, basic_block target, rtx jump_label) /* 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5341574befe..8db8b22655a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2012-01-05 Jakub Jelinek <jakub@redhat.com> + PR rtl-optimization/51767 + * gcc.c-torture/compile/pr51767.c: New test. + PR middle-end/51768 * c-c++-common/pr51768.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/compile/pr51767.c b/gcc/testsuite/gcc.c-torture/compile/pr51767.c new file mode 100644 index 00000000000..62a192d660d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr51767.c @@ -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); +} |