This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: flow still deleting important labels
- To: Richard Henderson <rth at cygnus dot com>
- Subject: Re: flow still deleting important labels
- From: Jeffrey A Law <law at upchuck dot cygnus dot com>
- Date: Sun, 04 Apr 1999 01:15:34 -0700
- cc: egcs-bugs at egcs dot cygnus dot com, egcs-patches at egcs dot cygnus dot com
- Reply-To: law at cygnus dot com
In message <19990328165757.A19211@cygnus.com>you write:
> Ok, sanity check me here. I found enough places we were doing
> the wrong thing wrt REG_LABEL I can't believe I'm not skewed.
[ Reordering your message... It's easiest to answer this first :-) ]
> So how did this work before, anyway?
If jump.c ever found a non-jumping insn with a LABEL_REF, it would attach
a REG_LABEL note to the insn.
Then in flow:
/* References to labels in non-jumping insns have
REG_LABEL notes attached to them.
This can happen for computed gotos; we don't care
about them here since the values are also on the
label_value_list and will be marked live if we find
a live computed goto.
This can also happen when we take the address of
a label to pass as an argument to __throw. Note
throw only uses the value to determine what handler
should be called -- ie the label is not used as
a jump target, it just marks regions in the code.
In theory we should be able to ignore the REG_LABEL
notes, but we have to make sure that the label and
associated insns aren't marked dead, so we make
the block in question live and create an edge from
this insn to the label. This is not strictly
correct, but it is close enough for now. */
for (note = REG_NOTES (insn);
note;
note = XEXP (note, 1))
{
if (REG_NOTE_KIND (note) == REG_LABEL)
{
x = XEXP (note, 0);
block_live[BLOCK_NUM (x)] = 1;
mark_label_ref (gen_rtx_LABEL_REF (VOIDmode, x),
insn, 0);
}
}
So that marked the label as reachable. It's an inaccuracy in the cfg that we
decided to "live with" about a year or so ago I suspect. [ It was an
improvement over marking those labels are reachable from every computed jump
if I remember correctly. ]
In the new flow code you only look at the last insn in the basic block to find
out the outgong edges exist for each block. So you never see any REG_LABELs
that may be attached to instructions within the basic block. Thus you never
mark their destination as reachable and you eventually kill it as unreachable.
I believe this is wrong. If you have a reference to a label in a block that
is reachable, then you must consider the block starting with that label also
reachable -- or at least arrange to keep the label for the sake of EH which
may be marking a region of code with it.
I suspect you also need to create a fake edge to that block so that we don't
have blocks in the cfg that can't be reached from the root node -- you'll
confuse gcse, haifa and other global optimizers.
It may be better to make the edge to the target block from the entry block
instead of the block which had the reference. That may (or may not) help
the global optimizers.
I didn't read the code that closely, so I could be wrong. Anyway, I suspect
this is what's causing our labels to go away in the normal -mgas case.
> Basic problem -- expand_builtin_setjmp puts a label in memory.
> The code it generates to do that doesn't contain a REG_LABEL.
> Secondary problems exist in that the REG_LABEL keeps vanishing.
This is the -mno-gas case I presume. In that case labels are not
legitimate constants and thus we call force_const_mem on them to shove
them into memory. That's how they got into the constant pool in the -mno-gas
case.
I believe in the normal -mgas case we do have the appropriate REG_LABEL
notes and we just need to fix flow to not delete a label which is
referenced by a non-jumping insn inside a basic block.
I'm not *that* concerned about the -mno-gas case -- HP's assembler is far
too lame to be useful on PAs.
jeff