re PR middle-end/29609 (Even with -O0 -g gcc optimizes a goto away and I cannot debug)

PR debug/29609
	PR debug/36690
	PR debug/37616
	* basic-block.h (struct edge_def): Add goto_block field.
	* cfglayout.c (fixup_reorder_chain): Ensure that there is at least
	one insn with locus corresponding to edge's goto_locus if !optimize.
	* profile.c (branch_prob): Copy edge's goto_block.
	* cfgrtl.c (force_nonfallthru_and_redirect): Use goto_locus for
	emitted jumps.
	(cfg_layout_merge_blocks): Emit a nop with edge's goto_locus
	locator in between the merged basic blocks if !optimize and needed.
	* cfgexpand.c (expand_gimple_cond): Convert goto_block and
	goto_locus into RTL locator.  For unconditional jump use that
	locator for the jump insn.
	(expand_gimple_cond): Convert goto_block and goto_locus into
	RTL locator for all remaining edges.  For unconditional jump
	use that locator for the jump insn.
	* cfgcleanup.c (try_forward_edges): Avoid the optimization if
	there is more than one edge or insn locator along the forwarding
	edges and !optimize.  If there is just one, set e->goto_locus.
	* tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Set also
	edge's goto_block.
	(move_block_to_fn): Adjust edge's goto_block.

	* gcc.dg/debug/pr29609-1.c: New test.
	* gcc.dg/debug/pr29609-2.c: New test.
	* gcc.dg/debug/pr36690-1.c: New test.
	* gcc.dg/debug/pr36690-2.c: New test.
	* gcc.dg/debug/pr36690-3.c: New test.
	* gcc.dg/debug/pr37616.c: New test.
	* gcc.dg/debug/dwarf2/pr29609-1.c: New test.
	* gcc.dg/debug/dwarf2/pr29609-2.c: New test.
	* gcc.dg/debug/dwarf2/pr36690-1.c: New test.
	* gcc.dg/debug/dwarf2/pr36690-2.c: New test.
	* gcc.dg/debug/dwarf2/pr36690-3.c: New test.
	* gcc.dg/debug/dwarf2/pr37616.c: New test.

From-SVN: r140948
This commit is contained in:
Jakub Jelinek 2008-10-07 20:48:40 +02:00 committed by Jakub Jelinek
parent aee857a2f4
commit 7241571ec8
21 changed files with 679 additions and 23 deletions

View File

@ -1,3 +1,29 @@
2008-10-07 Jakub Jelinek <jakub@redhat.com>
PR debug/29609
PR debug/36690
PR debug/37616
* basic-block.h (struct edge_def): Add goto_block field.
* cfglayout.c (fixup_reorder_chain): Ensure that there is at least
one insn with locus corresponding to edge's goto_locus if !optimize.
* profile.c (branch_prob): Copy edge's goto_block.
* cfgrtl.c (force_nonfallthru_and_redirect): Use goto_locus for
emitted jumps.
(cfg_layout_merge_blocks): Emit a nop with edge's goto_locus
locator in between the merged basic blocks if !optimize and needed.
* cfgexpand.c (expand_gimple_cond): Convert goto_block and
goto_locus into RTL locator. For unconditional jump use that
locator for the jump insn.
(expand_gimple_cond): Convert goto_block and goto_locus into
RTL locator for all remaining edges. For unconditional jump
use that locator for the jump insn.
* cfgcleanup.c (try_forward_edges): Avoid the optimization if
there is more than one edge or insn locator along the forwarding
edges and !optimize. If there is just one, set e->goto_locus.
* tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Set also
edge's goto_block.
(move_block_to_fn): Adjust edge's goto_block.
2008-10-07 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/37731

View File

@ -129,7 +129,8 @@ struct edge_def GTY(())
/* Auxiliary info specific to a pass. */
PTR GTY ((skip (""))) aux;
/* Location of any goto implicit in the edge, during tree-ssa. */
/* Location of any goto implicit in the edge and associated BLOCK. */
tree goto_block;
location_t goto_locus;
/* The index number corresponding to this edge in the edge vector

View File

@ -429,7 +429,7 @@ try_forward_edges (int mode, basic_block b)
for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
{
basic_block target, first;
int counter;
int counter, goto_locus;
bool threaded = false;
int nthreaded_edges = 0;
bool may_thread = first_pass | df_get_bb_dirty (b);
@ -447,6 +447,7 @@ try_forward_edges (int mode, basic_block b)
target = first = e->dest;
counter = NUM_FIXED_BLOCKS;
goto_locus = e->goto_locus;
/* If we are partitioning hot/cold basic_blocks, we don't want to mess
up jumps that cross between hot/cold sections.
@ -476,6 +477,27 @@ try_forward_edges (int mode, basic_block b)
new_target = single_succ (target);
if (target == new_target)
counter = n_basic_blocks;
else if (!optimize)
{
/* When not optimizing, ensure that edges or forwarder
blocks with different locus are not optimized out. */
int locus = single_succ_edge (target)->goto_locus;
if (locus && goto_locus && locus != goto_locus)
counter = n_basic_blocks;
else if (locus)
goto_locus = locus;
if (INSN_P (BB_END (target)))
{
locus = INSN_LOCATOR (BB_END (target));
if (locus && goto_locus && locus != goto_locus)
counter = n_basic_blocks;
else if (locus)
goto_locus = locus;
}
}
}
/* Allow to thread only over one edge at time to simplify updating
@ -539,6 +561,8 @@ try_forward_edges (int mode, basic_block b)
int edge_frequency;
int n = 0;
e->goto_locus = goto_locus;
/* Don't force if target is exit block. */
if (threaded && target != EXIT_BLOCK_PTR)
{

View File

@ -1666,7 +1666,12 @@ expand_gimple_cond (basic_block bb, gimple stmt)
add_reg_br_prob_note (last, true_edge->probability);
maybe_dump_rtl_for_gimple_stmt (stmt, last);
if (true_edge->goto_locus)
set_curr_insn_source_location (true_edge->goto_locus);
{
set_curr_insn_source_location (true_edge->goto_locus);
set_curr_insn_block (true_edge->goto_block);
true_edge->goto_locus = curr_insn_locator ();
}
true_edge->goto_block = NULL;
false_edge->flags |= EDGE_FALLTHRU;
ggc_free (pred);
return NULL;
@ -1677,7 +1682,12 @@ expand_gimple_cond (basic_block bb, gimple stmt)
add_reg_br_prob_note (last, false_edge->probability);
maybe_dump_rtl_for_gimple_stmt (stmt, last);
if (false_edge->goto_locus)
set_curr_insn_source_location (false_edge->goto_locus);
{
set_curr_insn_source_location (false_edge->goto_locus);
set_curr_insn_block (false_edge->goto_block);
false_edge->goto_locus = curr_insn_locator ();
}
false_edge->goto_block = NULL;
true_edge->flags |= EDGE_FALLTHRU;
ggc_free (pred);
return NULL;
@ -1686,6 +1696,13 @@ expand_gimple_cond (basic_block bb, gimple stmt)
jumpif (pred, label_rtx_for_bb (true_edge->dest));
add_reg_br_prob_note (last, true_edge->probability);
last = get_last_insn ();
if (false_edge->goto_locus)
{
set_curr_insn_source_location (false_edge->goto_locus);
set_curr_insn_block (false_edge->goto_block);
false_edge->goto_locus = curr_insn_locator ();
}
false_edge->goto_block = NULL;
emit_jump (label_rtx_for_bb (false_edge->dest));
BB_END (bb) = last;
@ -1708,9 +1725,6 @@ expand_gimple_cond (basic_block bb, gimple stmt)
maybe_dump_rtl_for_gimple_stmt (stmt, last2);
if (false_edge->goto_locus)
set_curr_insn_source_location (false_edge->goto_locus);
ggc_free (pred);
return new_bb;
}
@ -1962,19 +1976,21 @@ expand_gimple_basic_block (basic_block bb)
}
}
/* Expand implicit goto. */
/* Expand implicit goto and convert goto_locus. */
FOR_EACH_EDGE (e, ei, bb->succs)
{
if (e->flags & EDGE_FALLTHRU)
break;
}
if (e && e->dest != bb->next_bb)
{
emit_jump (label_rtx_for_bb (e->dest));
if (e->goto_locus)
set_curr_insn_source_location (e->goto_locus);
e->flags &= ~EDGE_FALLTHRU;
if (e->goto_locus && e->goto_block)
{
set_curr_insn_source_location (e->goto_locus);
set_curr_insn_block (e->goto_block);
e->goto_locus = curr_insn_locator ();
}
e->goto_block = NULL;
if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb)
{
emit_jump (label_rtx_for_bb (e->dest));
e->flags &= ~EDGE_FALLTHRU;
}
}
do_pending_stack_adjust ();

View File

@ -887,6 +887,46 @@ fixup_reorder_chain (void)
if (e && !can_fallthru (e->src, e->dest))
force_nonfallthru (e);
}
/* Ensure goto_locus from edges has some instructions with that locus
in RTL. */
if (!optimize)
FOR_EACH_BB (bb)
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
{
basic_block nb;
if (simplejump_p (BB_END (e->src)))
{
if (INSN_LOCATOR (BB_END (e->src)) == (int) e->goto_locus)
continue;
if (INSN_LOCATOR (BB_END (e->src)) == 0)
{
INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
continue;
}
}
if (e->dest != EXIT_BLOCK_PTR)
{
insn = BB_HEAD (e->dest);
if (!INSN_P (insn))
insn = next_insn (insn);
if (insn && INSN_P (insn)
&& INSN_LOCATOR (insn) == (int) e->goto_locus)
continue;
}
nb = split_edge (e);
if (!INSN_P (BB_END (nb)))
BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
nb);
INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
}
}
}
/* Perform sanity checks on the insn chain.

View File

@ -1009,6 +1009,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
rtx note;
edge new_edge;
int abnormal_edge_flags = 0;
int loc;
/* In the case the last instruction is conditional jump to the next
instruction, first redirect the jump itself and then continue
@ -1127,11 +1128,15 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
else
jump_block = e->src;
if (e->goto_locus && e->goto_block == NULL)
loc = e->goto_locus;
else
loc = 0;
e->flags &= ~EDGE_FALLTHRU;
if (target == EXIT_BLOCK_PTR)
{
#ifdef HAVE_return
emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
emit_jump_insn_after_setloc (gen_return (), BB_END (jump_block), loc);
#else
gcc_unreachable ();
#endif
@ -1139,7 +1144,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target)
else
{
rtx label = block_label (target);
emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
emit_jump_insn_after_setloc (gen_jump (label), BB_END (jump_block), loc);
JUMP_LABEL (BB_END (jump_block)) = label;
LABEL_NUSES (label)++;
}
@ -2606,6 +2611,32 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
try_redirect_by_replacing_jump (EDGE_SUCC (a, 0), b, true);
gcc_assert (!JUMP_P (BB_END (a)));
/* When not optimizing and the edge is the only place in RTL which holds
some unique locus, emit a nop with that locus in between. */
if (!optimize && EDGE_SUCC (a, 0)->goto_locus)
{
rtx insn = BB_END (a);
int goto_locus = EDGE_SUCC (a, 0)->goto_locus;
if (NOTE_P (insn))
insn = prev_nonnote_insn (insn);
if (insn && INSN_P (insn) && INSN_LOCATOR (insn) == goto_locus)
goto_locus = 0;
else
{
insn = BB_HEAD (b);
if (!INSN_P (insn))
insn = next_insn (insn);
if (insn && INSN_P (insn) && INSN_LOCATOR (insn) == goto_locus)
goto_locus = 0;
}
if (goto_locus)
{
BB_END (a) = emit_insn_after_noloc (gen_nop (), BB_END (a), a);
INSN_LOCATOR (BB_END (a)) = goto_locus;
}
}
/* Possible line number notes should appear in between. */
if (b->il.rtl->header)
{

View File

@ -960,10 +960,12 @@ branch_prob (void)
&& (LOCATION_FILE (e->goto_locus)
!= LOCATION_FILE (gimple_location (last))
|| (LOCATION_LINE (e->goto_locus)
!= LOCATION_LINE (gimple_location (last)))))
!= LOCATION_LINE (gimple_location (last)))))
{
basic_block new_bb = split_edge (e);
single_succ_edge (new_bb)->goto_locus = e->goto_locus;
edge ne = single_succ_edge (new_bb);
ne->goto_locus = e->goto_locus;
ne->goto_block = e->goto_block;
}
if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
&& e->dest != EXIT_BLOCK_PTR)

View File

@ -1,3 +1,21 @@
2008-10-07 Jakub Jelinek <jakub@redhat.com>
PR debug/29609
PR debug/36690
PR debug/37616
* gcc.dg/debug/pr29609-1.c: New test.
* gcc.dg/debug/pr29609-2.c: New test.
* gcc.dg/debug/pr36690-1.c: New test.
* gcc.dg/debug/pr36690-2.c: New test.
* gcc.dg/debug/pr36690-3.c: New test.
* gcc.dg/debug/pr37616.c: New test.
* gcc.dg/debug/dwarf2/pr29609-1.c: New test.
* gcc.dg/debug/dwarf2/pr29609-2.c: New test.
* gcc.dg/debug/dwarf2/pr36690-1.c: New test.
* gcc.dg/debug/dwarf2/pr36690-2.c: New test.
* gcc.dg/debug/dwarf2/pr36690-3.c: New test.
* gcc.dg/debug/dwarf2/pr37616.c: New test.
2008-10-07 H.J. Lu <hongjiu.lu@intel.com>
PR middle-end/37731

View File

@ -0,0 +1,32 @@
/* PR debug/29609 */
/* Verify that breakpoint on the break is hit. */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
void abort (void);
int
foo (void)
{
int a, i;
for (i = 1; i <= 10; i++)
{
if (i < 3)
a = 1;
else
break;
a = 5;
}
return a;
}
int
main (void)
{
if (foo () != 5)
abort ();
return 0;
}
/* { dg-final { scan-assembler "pr29609-1.c:18" } } */

View File

@ -0,0 +1,53 @@
/* PR debug/29609 */
/* Verify that breakpoint on both goto failure; stmts is hit. */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
extern void abort (void);
int x;
int
foo (void)
{
return 0 ^ x;
}
int
bar (void)
{
return 1 ^ x;
}
int
baz (void)
{
int c;
if (!foo ())
goto failure;
if (!bar ())
goto failure;
return 0;
failure:
return 1;
}
int
main (void)
{
if (baz () != 1)
abort ();
x = 1;
if (baz () != 1)
abort ();
x = 2;
if (baz () != 0)
abort ();
return 0;
}
/* { dg-final { scan-assembler "pr29609-2.c:27" } } */
/* { dg-final { scan-assembler "pr29609-2.c:30" } } */

View File

@ -0,0 +1,22 @@
/* PR debug/36690 */
/* Verify that break func is hit. */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
int i;
void
func (void)
{
while (i == 1)
i = 0;
}
int
main (void)
{
func ();
return 0;
}
/* { dg-final { scan-assembler "pr36690-1.c:11" } } */

View File

@ -0,0 +1,39 @@
/* PR debug/36690 */
/* Verify that breakpoint can be put on goto f1, it is hit and
varz at that spot is defined and contains 5. Nowhere else
in the function should be varz in the scope. */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
int cnt;
void
bar (int i)
{
cnt += i;
}
void
foo (int i)
{
if (!i)
bar (0);
else
{
static int varz = 5;
goto f1;
}
bar (1);
f1:
bar (2);
}
int
main (void)
{
foo (0);
foo (1);
return 0;
}
/* { dg-final { scan-assembler "pr36690-2.c:24" } } */

View File

@ -0,0 +1,53 @@
/* PR debug/36690 */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
int cnt;
void
bar (int i)
{
cnt += i;
}
void
foo (int i, int j)
{
if (j)
{
bar (i + 1);
goto f1;
}
bar (i + 2);
goto f2;
f1:
if (i > 10)
goto f3;
f2:
if (i > 40)
goto f4;
else
goto f5;
f3:
bar (i);
f4:
bar (i);
f5:
bar (i);
}
int
main (void)
{
foo (0, 1);
foo (11, 1);
foo (21, 0);
foo (41, 0);
return 0;
}
/* { dg-final { scan-assembler "pr36690-3.c:19" } } */
/* { dg-final { scan-assembler "pr36690-3.c:22" } } */
/* { dg-final { scan-assembler "pr36690-3.c:25" } } */
/* { dg-final { scan-assembler "pr36690-3.c:28" } } */
/* { dg-final { scan-assembler "pr36690-3.c:30" } } */

View File

@ -0,0 +1,41 @@
/* PR debug/37616 */
/* Test that one can put breakpoints onto continue, exitlab and break
and actually see program reaching those breakpoints. */
/* { dg-do compile } */
/* { dg-options "-O0 -gdwarf-2 -dA" } */
extern void abort (void);
int
foo (int parm)
{
int varj, varm;
for (varj = 0; varj < 10; varj++)
{
if (varj == 5)
continue;
if (varj == 7 && !parm)
goto exitlab;
if (varj == 9)
break;
varm = varj;
}
exitlab:
return varm;
}
int
main (void)
{
if (foo (0) != 6)
abort ();
if (foo (1) != 8)
abort ();
return 0;
}
/* { dg-final { scan-assembler "pr37616.c:17" } } */
/* { dg-final { scan-assembler "pr37616.c:19" } } */
/* { dg-final { scan-assembler "pr37616.c:21" } } */

View File

@ -0,0 +1,33 @@
/* PR debug/29609 */
/* Verify that breakpoint on the break is hit.
This version of the test just checks that it can be compiled, linked
and executed, further testing is done in corresponding gcc.dg/dwarf2/
test and hopefully in gdb testsuite. */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
extern void abort (void);
int
foo (void)
{
int a, i;
for (i = 1; i <= 10; i++)
{
if (i < 3)
a = 1;
else
break;
a = 5;
}
return a;
}
int
main (void)
{
if (foo () != 5)
abort ();
return 0;
}

View File

@ -0,0 +1,53 @@
/* PR debug/29609 */
/* Verify that breakpoint on both goto failure; stmts is hit.
This version of the test just checks that it can be compiled, linked
and executed, further testing is done in corresponding gcc.dg/dwarf2/
test and hopefully in gdb testsuite. */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
extern void abort (void);
int x;
int
foo (void)
{
return 0 ^ x;
}
int
bar (void)
{
return 1 ^ x;
}
int
baz (void)
{
int c;
if (!foo ())
goto failure;
if (!bar ())
goto failure;
return 0;
failure:
return 1;
}
int
main (void)
{
if (baz () != 1)
abort ();
x = 1;
if (baz () != 1)
abort ();
x = 2;
if (baz () != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,23 @@
/* PR debug/36690 */
/* Verify that break func is hit.
This version of the test just checks that it can be compiled, linked
and executed, further testing is done in corresponding gcc.dg/dwarf2/
test and hopefully in gdb testsuite. */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
int i;
void
func (void)
{
while (i == 1)
i = 0;
}
int
main (void)
{
func ();
return 0;
}

View File

@ -0,0 +1,40 @@
/* PR debug/36690 */
/* Verify that breakpoint can be put on goto f1, it is hit and
varz at that spot is defined and contains 5. Nowhere else
in the function should be varz in the scope.
This version of the test just checks that it can be compiled, linked
and executed, further testing is done in corresponding gcc.dg/dwarf2/
test and hopefully in gdb testsuite. */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
int cnt;
void
bar (int i)
{
cnt += i;
}
void
foo (int i)
{
if (!i)
bar (0);
else
{
static int varz = 5;
goto f1;
}
bar (1);
f1:
bar (2);
}
int
main (void)
{
foo (0);
foo (1);
return 0;
}

View File

@ -0,0 +1,47 @@
/* PR debug/36690 */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
int cnt;
void
bar (int i)
{
cnt += i;
}
void
foo (int i, int j)
{
if (j)
{
bar (i + 1);
goto f1;
}
bar (i + 2);
goto f2;
f1:
if (i > 10)
goto f3;
f2:
if (i > 40)
goto f4;
else
goto f5;
f3:
bar (i);
f4:
bar (i);
f5:
bar (i);
}
int
main (void)
{
foo (0, 1);
foo (11, 1);
foo (21, 0);
foo (41, 0);
return 0;
}

View File

@ -0,0 +1,40 @@
/* PR debug/37616 */
/* Test that one can put breakpoints onto continue, exitlab and break
and actually see program reaching those breakpoints.
This version of the test just checks that it can be compiled, linked
and executed, further testing is done in corresponding gcc.dg/dwarf2/
test and hopefully in gdb testsuite. */
/* { dg-do run } */
/* { dg-options "-O0 -g -dA" } */
extern void abort (void);
int
foo (int parm)
{
int varj, varm;
for (varj = 0; varj < 10; varj++)
{
if (varj == 5)
continue;
if (varj == 7 && !parm)
goto exitlab;
if (varj == 9)
break;
varm = varj;
}
exitlab:
return varm;
}
int
main (void)
{
if (foo (0) != 6)
abort ();
if (foo (1) != 8)
abort ();
return 0;
}

View File

@ -658,9 +658,13 @@ make_cond_expr_edges (basic_block bb)
e = make_edge (bb, then_bb, EDGE_TRUE_VALUE);
e->goto_locus = gimple_location (then_stmt);
e->goto_block = gimple_block (then_stmt);
e = make_edge (bb, else_bb, EDGE_FALSE_VALUE);
if (e)
e->goto_locus = gimple_location (else_stmt);
{
e->goto_locus = gimple_location (else_stmt);
e->goto_block = gimple_block (else_stmt);
}
/* We do not need the labels anymore. */
gimple_cond_set_true_label (entry, NULL_TREE);
@ -849,6 +853,7 @@ make_goto_expr_edges (basic_block bb)
tree dest = gimple_goto_dest (goto_t);
edge e = make_edge (bb, label_to_block (dest), EDGE_FALLTHRU);
e->goto_locus = gimple_location (goto_t);
e->goto_block = gimple_block (goto_t);
gsi_remove (&last, true);
return;
}
@ -5743,6 +5748,23 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
update_stmt (stmt);
pop_cfun ();
}
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->goto_locus)
{
tree block = e->goto_block;
if (d->orig_block == NULL_TREE
|| block == d->orig_block)
e->goto_block = d->new_block;
#ifdef ENABLE_CHECKING
else if (block != d->new_block)
{
while (block && block != d->orig_block)
block = BLOCK_SUPERCONTEXT (block);
gcc_assert (block);
}
#endif
}
}
/* Examine the statements in BB (which is in SRC_CFUN); find and return