So far -O0 code could be safely debugged. With 4.3.1 and HEAD if you `break func' in GDB the breakpoint can be missed despite the function got executed. The line number info is wrong and as GCC does not produce prologue-end GDB is using the line number information to skip the prologue.
Version-Release number of selected component (if applicable):
gcc-4.3.1-3.x86_64 (Fedora 9, broken)
Fedora 8 was correct: gcc-4.1.2-33.x86_64
Verified as broken on:
GNU C (GCC) version 4.4.0 20080701 (experimental) (x86_64-unknown-linux-gnu)
compiled by GNU C version 3.4.6 20060404 (Red Hat 3.4.6-9), GMP version 4.2.2, MPFR version 2.3.0-p2.
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Steps to Reproduce:
cat >whilemain.c <<EOH
void func (void)
while (i == 1)
i = 0;
gcc -c -o whilemain.o whilemain.c -Wall -g
new broken gccs:
void func (void)
40047c: 55 push %rbp
40047d: 48 89 e5 mov %rsp,%rbp
400480: eb 0a jmp 40048c <func+0x10>
while (i == 1)
i = 0;
400482: c7 05 fc 03 20 00 00 movl $0x0,0x2003fc(%rip) # 600888 <i>
400489: 00 00 00
gcc-4.1.2-33.x86_64 (Fedora 8):
void func (void)
400468: 55 push %rbp
400469: 48 89 e5 mov %rsp,%rbp
while (i == 1)
40046c: eb 0a jmp 400478 <func+0x10>
i = 0;
40046e: c7 05 fc 03 20 00 00 movl $0x0,0x2003fc(%rip) # 600874 <i>
400475: 00 00 00
I've also observed this problem (as causing a number of GDB testsuite failures).
With both 4.2 and 4.3, the function prologue is followed by a jump,
the loop body, and then the test of the loop condition which the jump
jumps to. The loop body has the correct line number, as does the
condition. With 4.2, the jump has the same line number as the
condition, so that's the line number to which GDB assigns a breakpoint
on the function. With 4.3, the jump insn does not have a line number
and GDB decides to use the line number of the loop body, and the GDB
This is caused by the implicit gotos at the end of basic blocks.
During cfgexpand this can be IMHO fixed by setting curr_location before
emitting the jump, not after it (otherwise e->goto_locus is IMHO useless,
as most likely the following statements will change curr_location before
anything is emitted):
--- gcc/cfgexpand.c.jj 2008-06-06 09:17:07.000000000 +0200
+++ gcc/cfgexpand.c 2008-07-02 10:43:54.000000000 +0200
@@ -1610,9 +1610,9 @@ expand_gimple_basic_block (basic_block b
if (e && e->dest != bb->next_bb)
- emit_jump (label_rtx_for_bb (e->dest));
+ emit_jump (label_rtx_for_bb (e->dest));
e->flags &= ~EDGE_FALLTHRU;
Not sure if expand_gimple_cond_expr should stay as is or be modified as well.
This fixes this problem for the few early RTL passes, but then we go into
cfglayout mode and the JUMP is removed again.
force_nonfallthru_and_redirect then when going out of cfglayout mode recreates
the JUMP again, but completely ignores e->goto_locus:
if (target == EXIT_BLOCK_PTR)
emit_jump_insn_after_noloc (gen_return (), BB_END (jump_block));
rtx label = block_label (target);
emit_jump_insn_after_noloc (gen_jump (label), BB_END (jump_block));
JUMP_LABEL (BB_END (jump_block)) = label;
One problem is that we have just locus for the edges, not BLOCK, so if
force_nonfallthru_and_redirect were to call emit_jump_insn_after_setloc instead,
the question is what BLOCK should be used for it (e.g. pick the block from insn before the jump (if any)? What to do if there is none in the basic block?).
Created attachment 15888 [details]
Unfinished patch which solves the testcase in this PR and a couple of other problems, but still there are plenty of issues.
It adds goto_block field to edges, because sometimes an edge is the only place
that uses certain scope. Consider say:
void bar (int);
void foo (int i)
static int z = 5;
At -O0 -g we really should be able to put breakpoint on goto f1 and see the z
variable. Another testcase I've been playing with is:
bar (int i)
foo (int i, int j)
bar (i + 1);
bar (i + 2);
if (i > 10)
if (i > 40)
foo (0, 1);
foo (11, 1);
foo (21, 0);
foo (41, 0);
Here IMNSHO at -O0 -g one should be able to step through all the gotos, so there should be some instructions with the locations of the gotos. With the attached patch one goto gets a location in the assembly, but the rest don't. One problem
is that already the into_cfglayout pass does some optimizations I wouldn't think are appropriate for -O0, like merging basic blocks. That's e.g. where the
goto_locus of goto f1; is gone. Either we should prevent that kind of optimization if (!optimize) and the edge has goto_locus, or e.g. could insert
a nop insn with goto_locus as INSN_LOCATOR and hope at -O0 nothing later on optimizes that out. Another problem is with the conditional branches. For them
I'm afraid we can't put goto_locus on the conditional jump. If just one
edge has goto_locus and the other does not, at (!optimize) we could possibly
invert the condition and thus let the unconditional jump be the insn that
holds the goto_locus INSN_LOCATOR. But for the case where both edges have
goto_locus, I think we should just insert an extra conditional jump, so that
there are two unconditional jumps, each with its goto_locus.
Subject: Re: [4.3/4.4 Regression] .debug_line first line is behind the first instruction
> One problem
> is that already the into_cfglayout pass does some optimizations I wouldn't
> think are appropriate for -O0, like merging basic blocks. That's e.g. where
Yes, this is long lasting problem. Basically even at -O0 we can
elliminate some of user code completely, while in theory we probably
ought to maintain even stuff like empty statements.
I am not big friend of idea of making edges sort of "abnormal" ie blocks
unmergeable just to preserve debug info. I guess making -O0 to not
elliminate NOP instruction and merge block to insert one when last
instruction of former block is not having same locator is better way
to go given that there are more general problems like this. On tree
level we will likely need something similar (ie empty statements holding
> goto_locus of goto f1; is gone. Either we should prevent that kind of
> optimization if (!optimize) and the edge has goto_locus, or e.g. could insert
> a nop insn with goto_locus as INSN_LOCATOR and hope at -O0 nothing later on
> optimizes that out. Another problem is with the conditional branches. For
> I'm afraid we can't put goto_locus on the conditional jump. If just one
> edge has goto_locus and the other does not, at (!optimize) we could possibly
> invert the condition and thus let the unconditional jump be the insn that
> holds the goto_locus INSN_LOCATOR. But for the case where both edges have
> goto_locus, I think we should just insert an extra conditional jump, so that
> there are two unconditional jumps, each with its goto_locus.
Gimplifier already ought to do COND expr jumping to GOTO expr since I
run into this problem in gcov output. There is code in cfgcleanup
preventing forwarding the edges before gcoving is done. Later we
forward across the forwarder block that is probably optimiztion we need
to disable at O0 if we worry about this (ie forward across forwarder
block only if the forwarders block edge is having no locator or same
locator as the edge we are forwarding).
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
4.3.2 is released, changing milestones to 4.3.3.
Subject: Bug 36690
Date: Tue Oct 7 18:48:40 2008
New Revision: 140948
* 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
(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
(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.
Target Milestone 4.3.3?
But this patch didn't committed to 4.3 branch.