Divide REG_LABEL notes into REG_LABEL_OPERAND and REG_LABEL_TARGET.

* doc/rtl.texi (Insns): Specify when a label_ref makes a jump_insn.
	Similar for what label_refs can go in the JUMP_TARGET field.  Split
	REG_LABEL documentation into REG_LABEL_TARGET and REG_LABEL_OPERAND.
	* reload.c (find_reloads): Generate REG_LABEL_OPERAND, not
	REG_LABEL when replacing an operand with a LABEL_REF for a
	non-jump insn.
	(subst_reloads): When replacing a LABEL_REG with a register,
	instead of generating a REG_LABEL note, assert that there already
	is one or that the label is a known target for the insn.
	* rtlanal.c (computed_jump_p): Instead of looking for a REG_LABEL
	note, check the JUMP_LABEL field.  Remove "else" after return.
	* reorg.c (emit_delay_sequence): Replace case for REG_LABEL with
	cases for REG_LABEL_OPERAND and REG_LABEL_TARGET.
	(fill_slots_from_thread): Handle both REG_LABEL_OPERAND and
	REG_LABEL_TARGET notes, including the JUMP_TARGET field on JUMP_P
	insns.  Iterate over all notes; don't assume there's only one.
	* cse.c (recorded_label_ref): Adjust comment to refer to
	REG_LABEL_OPERAND.
	(cse_extended_basic_block): Do LABEL_REF check for all INSN_P
	insns, not just NONJUMP_INSN_P.
	(check_for_label_ref): For JUMP_P insns, check that the LABEL_REF
	isn't a jump target.
	* jump.c (rebuild_jump_labels): Adjust head comment.
	(init_label_info): Ditto.  Remove REG_LABEL_OPERAND notes only;
	don't reset REG_LABEL_TARGET notes, including the JUMP_LABEL field.
	(mark_all_labels): For JUMP_P insns without a target, check if the
	the target is noted on the previous nonjump insn.
	(mark_jump_label_1): New function, guts from mark_jump_label.
	<case IF_THEN_ELSE>: Handle first operand as a non-target when
	marking jump target labels.
	<case LABEL_REF>: Adjust for whether to generate a
	REG_LABEL_TARGET or a REG_LABEL_OPERAND note.
	For 'E' format rtl, iterate in descending element order.
	(delete_related_insns): Handle both REG_LABEL_TARGET and
	REG_LABEL_OPERAND notes.  For JUMP_P insns with labels with zero
	reference count, delete and fallthrough.  Move finding-next-
	non-deleted insn last in the function.  Look at all INSN_P insns
	for REG_LABEL_OPERAND notes.
	(redirect_jump_2): Assert that OLABEL equals the old JUMP_LABEL of
	JUMP.
	* print-rtl.c (print_rtx): For JUMP_P insns and a non-NULL
	JUMP_LABEL, output the INSN_UID of it.
	* gcse.c: Adjust comments as appropriate to say REG_LABEL_OPERAND
	and/or REG_LABEL_TARGET.
	(add_label_notes): Only add REG_LABEL_OPERAND notes.  Put in line
	with jump.c copy by only adding notes for labels actually
	referenced in the insn.
	* emit-rtl.c (try_split): Don't assume only NONJUMP_INSN_P need
	usage count increment; handle all INSN_P trial insns.
	(emit_copy_of_insn_after): Change to not copy REG_LABEL_OPERAND
	notes.
	* rtl.h (struct rtx_def) <volatil>: Adjust to mention
	REG_LABEL_TARGET and REG_LABEL_OPERAND.
	(LABEL_REF_NONLOCAL_P): Allow REG_LABEL_TARGET and
	REG_LABEL_OPERAND.
	* combine.c (distribute_notes): Adjust for REG_LABEL_TARGET on
	JUMP_P insns and REG_LABEL_OPERAND everywhere.
	* sched-rgn.c (is_cfg_nonregular): Check for REG_LABEL_OPERANDS
	on all INSN_P insns.
	* reg-notes.def (LABEL_TARGET, LABEL_OPERAND): Split from LABEL.
	* cfgrtl.c (delete_insn): Adjust to handle REG_LABEL_TARGET and
	REG_LABEL_OPERAND notes.
	* reload1.c (calculate_needs_all_insns): Adjust comments.
	(set_label_offsets): Adjust to look for REG_LABEL_OPERAND notes.
	* config/alpha/alpha.md (split for load of an address into a
	four-insn sequence on Unicos/Mk): Adjust to use
	REG_LABEL_OPERAND.
	* config/sh/sh.md (sh_reorg, final_prescan_insn): Ditto.

From-SVN: r128287
This commit is contained in:
Hans-Peter Nilsson 2007-09-09 04:41:58 +00:00 committed by Hans-Peter Nilsson
parent 97c954f700
commit cf7c4aa6af
18 changed files with 441 additions and 205 deletions

View File

@ -1,3 +1,75 @@
2007-09-09 Hans-Peter Nilsson <hp@axis.com>
Divide REG_LABEL notes into REG_LABEL_OPERAND and REG_LABEL_TARGET.
* doc/rtl.texi (Insns): Specify when a label_ref makes a jump_insn.
Similar for what label_refs can go in the JUMP_TARGET field. Split
REG_LABEL documentation into REG_LABEL_TARGET and REG_LABEL_OPERAND.
* reload.c (find_reloads): Generate REG_LABEL_OPERAND, not
REG_LABEL when replacing an operand with a LABEL_REF for a
non-jump insn.
(subst_reloads): When replacing a LABEL_REG with a register,
instead of generating a REG_LABEL note, assert that there already
is one or that the label is a known target for the insn.
* rtlanal.c (computed_jump_p): Instead of looking for a REG_LABEL
note, check the JUMP_LABEL field. Remove "else" after return.
* reorg.c (emit_delay_sequence): Replace case for REG_LABEL with
cases for REG_LABEL_OPERAND and REG_LABEL_TARGET.
(fill_slots_from_thread): Handle both REG_LABEL_OPERAND and
REG_LABEL_TARGET notes, including the JUMP_TARGET field on JUMP_P
insns. Iterate over all notes; don't assume there's only one.
* cse.c (recorded_label_ref): Adjust comment to refer to
REG_LABEL_OPERAND.
(cse_extended_basic_block): Do LABEL_REF check for all INSN_P
insns, not just NONJUMP_INSN_P.
(check_for_label_ref): For JUMP_P insns, check that the LABEL_REF
isn't a jump target.
* jump.c (rebuild_jump_labels): Adjust head comment.
(init_label_info): Ditto. Remove REG_LABEL_OPERAND notes only;
don't reset REG_LABEL_TARGET notes, including the JUMP_LABEL field.
(mark_all_labels): For JUMP_P insns without a target, check if the
the target is noted on the previous nonjump insn.
(mark_jump_label_1): New function, guts from mark_jump_label.
<case IF_THEN_ELSE>: Handle first operand as a non-target when
marking jump target labels.
<case LABEL_REF>: Adjust for whether to generate a
REG_LABEL_TARGET or a REG_LABEL_OPERAND note.
For 'E' format rtl, iterate in descending element order.
(delete_related_insns): Handle both REG_LABEL_TARGET and
REG_LABEL_OPERAND notes. For JUMP_P insns with labels with zero
reference count, delete and fallthrough. Move finding-next-
non-deleted insn last in the function. Look at all INSN_P insns
for REG_LABEL_OPERAND notes.
(redirect_jump_2): Assert that OLABEL equals the old JUMP_LABEL of
JUMP.
* print-rtl.c (print_rtx): For JUMP_P insns and a non-NULL
JUMP_LABEL, output the INSN_UID of it.
* gcse.c: Adjust comments as appropriate to say REG_LABEL_OPERAND
and/or REG_LABEL_TARGET.
(add_label_notes): Only add REG_LABEL_OPERAND notes. Put in line
with jump.c copy by only adding notes for labels actually
referenced in the insn.
* emit-rtl.c (try_split): Don't assume only NONJUMP_INSN_P need
usage count increment; handle all INSN_P trial insns.
(emit_copy_of_insn_after): Change to not copy REG_LABEL_OPERAND
notes.
* rtl.h (struct rtx_def) <volatil>: Adjust to mention
REG_LABEL_TARGET and REG_LABEL_OPERAND.
(LABEL_REF_NONLOCAL_P): Allow REG_LABEL_TARGET and
REG_LABEL_OPERAND.
* combine.c (distribute_notes): Adjust for REG_LABEL_TARGET on
JUMP_P insns and REG_LABEL_OPERAND everywhere.
* sched-rgn.c (is_cfg_nonregular): Check for REG_LABEL_OPERANDS
on all INSN_P insns.
* reg-notes.def (LABEL_TARGET, LABEL_OPERAND): Split from LABEL.
* cfgrtl.c (delete_insn): Adjust to handle REG_LABEL_TARGET and
REG_LABEL_OPERAND notes.
* reload1.c (calculate_needs_all_insns): Adjust comments.
(set_label_offsets): Adjust to look for REG_LABEL_OPERAND notes.
* config/alpha/alpha.md (split for load of an address into a
four-insn sequence on Unicos/Mk): Adjust to use
REG_LABEL_OPERAND.
* config/sh/sh.md (sh_reorg, final_prescan_insn): Ditto.
2007-09-09 Laurynas Biveinis <laurynas.biveinis@gmail.com>
Revert:

View File

@ -138,15 +138,15 @@ delete_insn (rtx insn)
/* If deleting a jump, decrement the use count of the label. Deleting
the label itself should happen in the normal course of block merging. */
if (JUMP_P (insn)
&& JUMP_LABEL (insn)
&& LABEL_P (JUMP_LABEL (insn)))
LABEL_NUSES (JUMP_LABEL (insn))--;
/* Also if deleting an insn that references a label. */
else
if (JUMP_P (insn))
{
while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
if (JUMP_LABEL (insn)
&& LABEL_P (JUMP_LABEL (insn)))
LABEL_NUSES (JUMP_LABEL (insn))--;
/* If there are more targets, remove them too. */
while ((note
= find_reg_note (insn, REG_LABEL_TARGET, NULL_RTX)) != NULL_RTX
&& LABEL_P (XEXP (note, 0)))
{
LABEL_NUSES (XEXP (note, 0))--;
@ -154,6 +154,14 @@ delete_insn (rtx insn)
}
}
/* Also if deleting any insn that references a label as an operand. */
while ((note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX)) != NULL_RTX
&& LABEL_P (XEXP (note, 0)))
{
LABEL_NUSES (XEXP (note, 0))--;
remove_note (insn, note);
}
if (JUMP_P (insn)
&& (GET_CODE (PATTERN (insn)) == ADDR_VEC
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))

View File

@ -12408,7 +12408,8 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
}
break;
case REG_LABEL:
case REG_LABEL_TARGET:
case REG_LABEL_OPERAND:
/* This can show up in several ways -- either directly in the
pattern, or hidden off in the constant pool with (or without?)
a REG_EQUAL note. */
@ -12431,34 +12432,33 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
place = i2;
}
/* Don't attach REG_LABEL note to a JUMP_INSN. Add
a JUMP_LABEL instead or decrement LABEL_NUSES. */
if (place && JUMP_P (place))
/* For REG_LABEL_TARGET on a JUMP_P, we prefer to put the note
as a JUMP_LABEL or decrement LABEL_NUSES if it's already
there. */
if (place && JUMP_P (place)
&& REG_NOTE_KIND (note) == REG_LABEL_TARGET
&& (JUMP_LABEL (place) == NULL
|| JUMP_LABEL (place) == XEXP (note, 0)))
{
rtx label = JUMP_LABEL (place);
if (!label)
JUMP_LABEL (place) = XEXP (note, 0);
else
{
gcc_assert (label == XEXP (note, 0));
if (LABEL_P (label))
LABEL_NUSES (label)--;
}
place = 0;
else if (LABEL_P (label))
LABEL_NUSES (label)--;
}
if (place2 && JUMP_P (place2))
if (place2 && JUMP_P (place2)
&& REG_NOTE_KIND (note) == REG_LABEL_TARGET
&& (JUMP_LABEL (place2) == NULL
|| JUMP_LABEL (place2) == XEXP (note, 0)))
{
rtx label = JUMP_LABEL (place2);
if (!label)
JUMP_LABEL (place2) = XEXP (note, 0);
else
{
gcc_assert (label == XEXP (note, 0));
if (LABEL_P (label))
LABEL_NUSES (label)--;
}
else if (LABEL_P (label))
LABEL_NUSES (label)--;
place2 = 0;
}
break;

View File

@ -5375,9 +5375,9 @@
;; Split the load of an address into a four-insn sequence on Unicos/Mk.
;; Always generate a REG_EQUAL note for the last instruction to facilitate
;; optimizations. If the symbolic operand is a label_ref, generate REG_LABEL
;; notes and update LABEL_NUSES because this is not done automatically.
;; Labels may be incorrectly deleted if we don't do this.
;; optimizations. If the symbolic operand is a label_ref, generate
;; REG_LABEL_OPERAND notes and update LABEL_NUSES because this is not done
;; automatically. Labels may be incorrectly deleted if we don't do this.
;;
;; Describing what the individual instructions do correctly is too complicated
;; so use UNSPECs for each of the three parts of an address.
@ -5401,11 +5401,11 @@
rtx label;
label = XEXP (operands[1], 0);
REG_NOTES (insn1) = gen_rtx_EXPR_LIST (REG_LABEL, label,
REG_NOTES (insn1) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (insn1));
REG_NOTES (insn2) = gen_rtx_EXPR_LIST (REG_LABEL, label,
REG_NOTES (insn2) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (insn2));
REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_LABEL, label,
REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (insn3));
LABEL_NUSES (label) += 3;
}

View File

@ -4716,8 +4716,8 @@ sh_reorg (void)
mdep_reorg_phase = SH_INSERT_USES_LABELS;
if (TARGET_RELAX)
{
/* Remove all REG_LABEL notes. We want to use them for our own
purposes. This works because none of the remaining passes
/* Remove all REG_LABEL_OPERAND notes. We want to use them for our
own purposes. This works because none of the remaining passes
need to look at them.
??? But it may break in the future. We should use a machine
@ -4728,7 +4728,8 @@ sh_reorg (void)
{
rtx note;
while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0)
while ((note = find_reg_note (insn, REG_LABEL_OPERAND,
NULL_RTX)) != 0)
remove_note (insn, note);
}
}
@ -4879,16 +4880,16 @@ sh_reorg (void)
continue;
}
/* Create a code label, and put it in a REG_LABEL note on
the insn which sets the register, and on each call insn
which uses the register. In final_prescan_insn we look
for the REG_LABEL notes, and output the appropriate label
/* Create a code label, and put it in a REG_LABEL_OPERAND note
on the insn which sets the register, and on each call insn
which uses the register. In final_prescan_insn we look for
the REG_LABEL_OPERAND notes, and output the appropriate label
or pseudo-op. */
label = gen_label_rtx ();
REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL, label,
REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (link));
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (insn));
if (rescan)
{
@ -4904,7 +4905,8 @@ sh_reorg (void)
|| ((reg2 = sfunc_uses_reg (scan))
&& REGNO (reg2) == REGNO (reg))))
REG_NOTES (scan)
= gen_rtx_INSN_LIST (REG_LABEL, label, REG_NOTES (scan));
= gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label,
REG_NOTES (scan));
}
while (scan != dies);
}
@ -5405,7 +5407,7 @@ final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
{
rtx note;
note = find_reg_note (insn, REG_LABEL, NULL_RTX);
note = find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX);
if (note)
{
rtx pattern;

View File

@ -353,8 +353,9 @@ static HARD_REG_SET hard_regs_in_table;
static int cse_jumps_altered;
/* Nonzero if we put a LABEL_REF into the hash table for an INSN without a
REG_LABEL, we have to rerun jump after CSE to put in the note. */
/* Nonzero if we put a LABEL_REF into the hash table for an INSN
without a REG_LABEL_OPERAND, we have to rerun jump after CSE to put
in the note. */
static int recorded_label_ref;
/* canon_hash stores 1 in do_not_record
@ -6091,7 +6092,7 @@ cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
/* If we haven't already found an insn where we added a LABEL_REF,
check this one. */
if (NONJUMP_INSN_P (insn) && ! recorded_label_ref
if (INSN_P (insn) && ! recorded_label_ref
&& for_each_rtx (&PATTERN (insn), check_for_label_ref,
(void *) insn))
recorded_label_ref = 1;
@ -6277,23 +6278,26 @@ cse_main (rtx f ATTRIBUTE_UNUSED, int nregs)
return cse_jumps_altered || recorded_label_ref;
}
/* Called via for_each_rtx to see if an insn is using a LABEL_REF for which
there isn't a REG_LABEL note. Return one if so. DATA is the insn. */
/* Called via for_each_rtx to see if an insn is using a LABEL_REF for
which there isn't a REG_LABEL_OPERAND note.
Return one if so. DATA is the insn. */
static int
check_for_label_ref (rtx *rtl, void *data)
{
rtx insn = (rtx) data;
/* If this insn uses a LABEL_REF and there isn't a REG_LABEL note for it,
we must rerun jump since it needs to place the note. If this is a
LABEL_REF for a CODE_LABEL that isn't in the insn chain, don't do this
since no REG_LABEL will be added. */
/* If this insn uses a LABEL_REF and there isn't a REG_LABEL_OPERAND
note for it, we must rerun jump since it needs to place the note. If
this is a LABEL_REF for a CODE_LABEL that isn't in the insn chain,
don't do this since no REG_LABEL_OPERAND will be added. */
return (GET_CODE (*rtl) == LABEL_REF
&& ! LABEL_REF_NONLOCAL_P (*rtl)
&& (!JUMP_P (insn)
|| !label_is_jump_target_p (XEXP (*rtl, 0), insn))
&& LABEL_P (XEXP (*rtl, 0))
&& INSN_UID (XEXP (*rtl, 0)) != 0
&& ! find_reg_note (insn, REG_LABEL, XEXP (*rtl, 0)));
&& ! find_reg_note (insn, REG_LABEL_OPERAND, XEXP (*rtl, 0)));
}
/* Count the number of times registers are used (not set) in X.

View File

@ -3201,9 +3201,10 @@ mandatory ones listed above. These four are described in a table below.
@findex jump_insn
@item jump_insn
The expression code @code{jump_insn} is used for instructions that may
jump (or, more generally, may contain @code{label_ref} expressions). If
there is an instruction to return from the current function, it is
recorded as a @code{jump_insn}.
jump (or, more generally, may contain @code{label_ref} expressions to
which @code{pc} can be set in that instruction). If there is an
instruction to return from the current function, it is recorded as a
@code{jump_insn}.
@findex JUMP_LABEL
@code{jump_insn} insns have the same extra fields as @code{insn} insns,
@ -3213,9 +3214,11 @@ accessed in the same way and in addition contain a field
For simple conditional and unconditional jumps, this field contains
the @code{code_label} to which this insn will (possibly conditionally)
branch. In a more complex jump, @code{JUMP_LABEL} records one of the
labels that the insn refers to; the only way to find the others is to
scan the entire body of the insn. In an @code{addr_vec},
@code{JUMP_LABEL} is @code{NULL_RTX}.
labels that the insn refers to; other jump target labels are recorded
as @code{REG_LABEL_TARGET} notes. The exception is @code{addr_vec}
and @code{addr_diff_vec}, where @code{JUMP_LABEL} is @code{NULL_RTX}
and the only way to find the labels is to scan the entire body of the
insn.
Return insns count as jumps, but since they do not refer to any
labels, their @code{JUMP_LABEL} is @code{NULL_RTX}.
@ -3531,14 +3534,25 @@ note giving the expression being computed. This block is encapsulated
with @code{REG_LIBCALL} and @code{REG_RETVAL} notes on the first and
last insns, respectively.
@findex REG_LABEL
@item REG_LABEL
@findex REG_LABEL_OPERAND
@item REG_LABEL_OPERAND
This insn uses @var{op}, a @code{code_label} or a @code{note} of type
@code{NOTE_INSN_DELETED_LABEL}, but is not a
@code{jump_insn}, or it is a @code{jump_insn} that required the label to
be held in a register. The presence of this note allows jump
optimization to be aware that @var{op} is, in fact, being used, and flow
optimization to build an accurate flow graph.
@code{NOTE_INSN_DELETED_LABEL}, but is not a @code{jump_insn}, or it
is a @code{jump_insn} that refers to the operand as an ordinary
operand. The label may still eventually be a jump target, but if so
in an indirect jump in a subsequent insn. The presence of this note
allows jump optimization to be aware that @var{op} is, in fact, being
used, and flow optimization to build an accurate flow graph.
@findex REG_LABEL_TARGET
@item REG_LABEL_TARGET
This insn is a @code{jump_insn} but not a @code{addr_vec} or
@code{addr_diff_vec}. It uses @var{op}, a @code{code_label} as a
direct or indirect jump target. Its purpose is similar to that of
@code{REG_LABEL_OPERAND}. This note is only present if the insn has
multiple targets; the last label in the insn (in the highest numbered
insn-field) goes into the @code{JUMP_LABEL} field and does not have a
@code{REG_LABEL_TARGET} note. @xref{Insns, JUMP_LABEL}.
@findex REG_CROSSING_JUMP
@item REG_CROSSING_JUMP

View File

@ -3355,11 +3355,12 @@ try_split (rtx pat, rtx trial, int last)
/* If there are LABELS inside the split insns increment the
usage count so we don't delete the label. */
if (NONJUMP_INSN_P (trial))
if (INSN_P (trial))
{
insn = insn_last;
while (insn != NULL_RTX)
{
/* JUMP_P insns have already been "marked" above. */
if (NONJUMP_INSN_P (insn))
mark_label_nuses (PATTERN (insn));
@ -5529,10 +5530,11 @@ emit_copy_of_insn_after (rtx insn, rtx after)
which may be duplicated by the basic block reordering code. */
RTX_FRAME_RELATED_P (new) = RTX_FRAME_RELATED_P (insn);
/* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
make them. */
/* Copy all REG_NOTES except REG_LABEL_OPERAND since mark_jump_label
will make them. REG_LABEL_TARGETs are created there too, but are
supposed to be sticky, so we copy them. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) != REG_LABEL)
if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
{
if (GET_CODE (link) == EXPR_LIST)
REG_NOTES (new)

View File

@ -4584,14 +4584,15 @@ one_pre_gcse_pass (int pass)
return changed;
}
/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN.
If notes are added to an insn which references a CODE_LABEL, the
LABEL_NUSES count is incremented. We have to add REG_LABEL notes,
because the following loop optimization pass requires them. */
/* If X contains any LABEL_REF's, add REG_LABEL_OPERAND notes for them
to INSN. If such notes are added to an insn which references a
CODE_LABEL, the LABEL_NUSES count is incremented. We have to add
that note, because the following loop optimization pass requires
them. */
/* ??? If there was a jump optimization pass after gcse and before loop,
then we would not need to do this here, because jump would add the
necessary REG_LABEL notes. */
necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes. */
static void
add_label_notes (rtx x, rtx insn)
@ -4608,10 +4609,18 @@ add_label_notes (rtx x, rtx insn)
We no longer ignore such label references (see LABEL_REF handling in
mark_jump_label for additional information). */
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0),
REG_NOTES (insn));
if (LABEL_P (XEXP (x, 0)))
LABEL_NUSES (XEXP (x, 0))++;
if (reg_mentioned_p (XEXP (x, 0), insn))
{
/* There's no reason for current users to emit jump-insns
with such a LABEL_REF, so we don't have to handle
REG_LABEL_TARGET notes. */
gcc_assert (!JUMP_P (insn));
REG_NOTES (insn)
= gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0),
REG_NOTES (insn));
if (LABEL_P (XEXP (x, 0)))
LABEL_NUSES (XEXP (x, 0))++;
}
return;
}

View File

@ -67,13 +67,15 @@ along with GCC; see the file COPYING3. If not see
static void init_label_info (rtx);
static void mark_all_labels (rtx);
static void mark_jump_label_1 (rtx, rtx, bool, bool);
static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
static int invert_exp_1 (rtx, rtx);
static int returnjump_p_1 (rtx *, void *);
/* Alternate entry into the jump optimizer. This entry point only rebuilds
the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping
instructions. */
/* This function rebuilds the JUMP_LABEL field and REG_LABEL_TARGET
notes in jumping insns and REG_LABEL_OPERAND notes in non-jumping
instructions and jumping insns that have labels as operands
(e.g. cbranchsi4). */
void
rebuild_jump_labels (rtx f)
{
@ -138,31 +140,43 @@ struct tree_opt_pass pass_cleanup_barriers =
};
/* Initialize LABEL_NUSES and JUMP_LABEL fields. Delete any REG_LABEL
notes whose labels don't occur in the insn any more. Returns the
largest INSN_UID found. */
/* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
for remaining targets for JUMP_P. Delete any REG_LABEL_OPERAND
notes whose labels don't occur in the insn any more. */
static void
init_label_info (rtx f)
{
rtx insn;
for (insn = f; insn; insn = NEXT_INSN (insn))
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
else if (JUMP_P (insn))
JUMP_LABEL (insn) = 0;
else if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx note, next;
{
if (LABEL_P (insn))
LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
for (note = REG_NOTES (insn); note; note = next)
{
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_LABEL
&& ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
remove_note (insn, note);
}
}
/* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
sticky and not reset here; that way we won't lose association
with a label when e.g. the source for a target register
disappears out of reach for targets that may use jump-target
registers. Jump transformations are supposed to transform
any REG_LABEL_TARGET notes. The target label reference in a
branch may disappear from the branch (and from the
instruction before it) for other reasons, like register
allocation. */
if (INSN_P (insn))
{
rtx note, next;
for (note = REG_NOTES (insn); note; note = next)
{
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
&& ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
remove_note (insn, note);
}
}
}
}
/* Mark the label each jump jumps to.
@ -172,34 +186,69 @@ static void
mark_all_labels (rtx f)
{
rtx insn;
rtx prev_nonjump_insn = NULL;
for (insn = f; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
{
mark_jump_label (PATTERN (insn), insn, 0);
if (! INSN_DELETED_P (insn) && JUMP_P (insn))
{
/* When we know the LABEL_REF contained in a REG used in
an indirect jump, we'll have a REG_LABEL note so that
flow can tell where it's going. */
if (JUMP_LABEL (insn) == 0)
{
rtx label_note = find_reg_note (insn, REG_LABEL, NULL_RTX);
if (label_note)
{
/* But a LABEL_REF around the REG_LABEL note, so
that we can canonicalize it. */
rtx label_ref = gen_rtx_LABEL_REF (Pmode,
XEXP (label_note, 0));
mark_jump_label (label_ref, insn, 0);
XEXP (label_note, 0) = XEXP (label_ref, 0);
JUMP_LABEL (insn) = XEXP (label_note, 0);
/* If the previous non-jump insn sets something to a label,
something that this jump insn uses, make that label the primary
target of this insn if we don't yet have any. That previous
insn must be a single_set and not refer to more than one label.
The jump insn must not refer to other labels as jump targets
and must be a plain (set (pc) ...), maybe in a parallel, and
may refer to the item being set only directly or as one of the
arms in an IF_THEN_ELSE. */
if (! INSN_DELETED_P (insn)
&& JUMP_P (insn)
&& JUMP_LABEL (insn) == NULL)
{
rtx label_note = NULL;
rtx pc = pc_set (insn);
rtx pc_src = pc != NULL ? SET_SRC (pc) : NULL;
if (prev_nonjump_insn != NULL)
label_note
= find_reg_note (prev_nonjump_insn, REG_LABEL_OPERAND, NULL);
if (label_note != NULL && pc_src != NULL)
{
rtx label_set = single_set (prev_nonjump_insn);
rtx label_dest
= label_set != NULL ? SET_DEST (label_set) : NULL;
if (label_set != NULL
/* The source must be the direct LABEL_REF, not a
PLUS, UNSPEC, IF_THEN_ELSE etc. */
&& GET_CODE (SET_SRC (label_set)) == LABEL_REF
&& (rtx_equal_p (label_dest, pc_src)
|| (GET_CODE (pc_src) == IF_THEN_ELSE
&& (rtx_equal_p (label_dest, XEXP (pc_src, 1))
|| rtx_equal_p (label_dest,
XEXP (pc_src, 2))))))
{
/* The CODE_LABEL referred to in the note must be the
CODE_LABEL in the LABEL_REF of the "set". We can
conveniently use it for the marker function, which
requires a LABEL_REF wrapping. */
gcc_assert (XEXP (label_note, 0)
== XEXP (SET_SRC (label_set), 0));
mark_jump_label_1 (label_set, insn, false, true);
gcc_assert (JUMP_LABEL (insn)
== XEXP (SET_SRC (label_set), 0));
}
}
}
else if (! INSN_DELETED_P (insn))
prev_nonjump_insn = insn;
}
else if (LABEL_P (insn))
prev_nonjump_insn = NULL;
/* If we are in cfglayout mode, there may be non-insns between the
basic blocks. If those non-insns represent tablejump data, they
contain label references that we must record. */
@ -904,12 +953,14 @@ sets_cc0_p (const_rtx x)
}
#endif
/* Find all CODE_LABELs referred to in X, and increment their use counts.
If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced
in INSN, then store one of them in JUMP_LABEL (INSN).
If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL
referenced in INSN, add a REG_LABEL note containing that label to INSN.
Also, when there are consecutive labels, canonicalize on the last of them.
/* Find all CODE_LABELs referred to in X, and increment their use
counts. If INSN is a JUMP_INSN and there is at least one
CODE_LABEL referenced in INSN as a jump target, then store the last
one in JUMP_LABEL (INSN). For a tablejump, this must be the label
for the ADDR_VEC. Store any other jump targets as REG_LABEL_TARGET
notes. If INSN is an INSN or a CALL_INSN or non-target operands of
a JUMP_INSN, and there is at least one CODE_LABEL referenced in
INSN, add a REG_LABEL_OPERAND note containing that label to INSN.
Note that two labels separated by a loop-beginning note
must be kept distinct if we have not yet done loop-optimization,
@ -919,6 +970,19 @@ sets_cc0_p (const_rtx x)
void
mark_jump_label (rtx x, rtx insn, int in_mem)
{
mark_jump_label_1 (x, insn, in_mem != 0,
(insn != NULL && x == PATTERN (insn) && JUMP_P (insn)));
}
/* Worker function for mark_jump_label. IN_MEM is TRUE when X occurrs
within a (MEM ...). IS_TARGET is TRUE when X is to be treated as a
jump-target; when the JUMP_LABEL field of INSN should be set or a
REG_LABEL_TARGET note should be added, not a REG_LABEL_OPERAND
note. */
static void
mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
{
RTX_CODE code = GET_CODE (x);
int i;
@ -936,7 +1000,7 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
return;
case MEM:
in_mem = 1;
in_mem = true;
break;
case SEQUENCE:
@ -951,9 +1015,19 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
/* If this is a constant-pool reference, see if it is a label. */
if (CONSTANT_POOL_ADDRESS_P (x))
mark_jump_label (get_pool_constant (x), insn, in_mem);
mark_jump_label_1 (get_pool_constant (x), insn, in_mem, is_target);
break;
/* Handle operands in the condition of an if-then-else as for a
non-jump insn. */
case IF_THEN_ELSE:
if (!is_target)
break;
mark_jump_label_1 (XEXP (x, 0), insn, in_mem, false);
mark_jump_label_1 (XEXP (x, 1), insn, in_mem, true);
mark_jump_label_1 (XEXP (x, 2), insn, in_mem, true);
return;
case LABEL_REF:
{
rtx label = XEXP (x, 0);
@ -976,17 +1050,21 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
if (insn)
{
if (JUMP_P (insn))
if (is_target
&& (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == label))
JUMP_LABEL (insn) = label;
else
{
/* Add a REG_LABEL note for LABEL unless there already
is one. All uses of a label, except for labels
that are the targets of jumps, must have a
REG_LABEL note. */
if (! find_reg_note (insn, REG_LABEL, label))
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
REG_NOTES (insn));
enum reg_note kind
= is_target ? REG_LABEL_TARGET : REG_LABEL_OPERAND;
/* Add a REG_LABEL_OPERAND or REG_LABEL_TARGET note
for LABEL unless there already is one. All uses of
a label, except for the primary target of a jump,
must have such a note. */
if (! find_reg_note (insn, kind, label))
REG_NOTES (insn)
= gen_rtx_INSN_LIST (kind, label, REG_NOTES (insn));
}
}
return;
@ -1001,7 +1079,8 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
for (i = 0; i < XVECLEN (x, eltnum); i++)
mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, in_mem);
mark_jump_label_1 (XVECEXP (x, eltnum, i), NULL_RTX, in_mem,
is_target);
}
return;
@ -1010,15 +1089,21 @@ mark_jump_label (rtx x, rtx insn, int in_mem)
}
fmt = GET_RTX_FORMAT (code);
/* The primary target of a tablejump is the label of the ADDR_VEC,
which is canonically mentioned *last* in the insn. To get it
marked as JUMP_LABEL, we iterate over items in reverse order. */
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
mark_jump_label (XEXP (x, i), insn, in_mem);
mark_jump_label_1 (XEXP (x, i), insn, in_mem, is_target);
else if (fmt[i] == 'E')
{
int j;
for (j = 0; j < XVECLEN (x, i); j++)
mark_jump_label (XVECEXP (x, i, j), insn, in_mem);
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
mark_jump_label_1 (XVECEXP (x, i, j), insn, in_mem,
is_target);
}
}
}
@ -1062,20 +1147,10 @@ delete_related_insns (rtx insn)
rtx lab = JUMP_LABEL (insn), lab_next;
if (LABEL_NUSES (lab) == 0)
{
/* This can delete NEXT or PREV,
either directly if NEXT is JUMP_LABEL (INSN),
or indirectly through more levels of jumps. */
delete_related_insns (lab);
/* I feel a little doubtful about this loop,
but I see no clean and sure alternative way
to find the first insn after INSN that is not now deleted.
I hope this works. */
while (next && INSN_DELETED_P (next))
next = NEXT_INSN (next);
return next;
}
/* This can delete NEXT or PREV,
either directly if NEXT is JUMP_LABEL (INSN),
or indirectly through more levels of jumps. */
delete_related_insns (lab);
else if (tablejump_p (insn, NULL, &lab_next))
{
/* If we're deleting the tablejump, delete the dispatch table.
@ -1104,10 +1179,12 @@ delete_related_insns (rtx insn)
return next;
}
/* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note. */
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
/* Likewise for any JUMP_P / INSN / CALL_INSN with a
REG_LABEL_OPERAND or REG_LABEL_TARGET note. */
if (INSN_P (insn))
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_LABEL
if ((REG_NOTE_KIND (note) == REG_LABEL_OPERAND
|| REG_NOTE_KIND (note) == REG_LABEL_TARGET)
/* This could also be a NOTE_INSN_DELETED_LABEL note. */
&& LABEL_P (XEXP (note, 0)))
if (LABEL_NUSES (XEXP (note, 0)) == 0)
@ -1151,6 +1228,12 @@ delete_related_insns (rtx insn)
}
}
/* I feel a little doubtful about this loop,
but I see no clean and sure alternative way
to find the first insn after INSN that is not now deleted.
I hope this works. */
while (next && INSN_DELETED_P (next))
next = NEXT_INSN (next);
return next;
}
@ -1307,6 +1390,8 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused,
{
rtx note;
gcc_assert (JUMP_LABEL (jump) == olabel);
/* Negative DELETE_UNUSED used to be used to signalize behavior on
moving FUNCTION_END note. Just sanity check that no user still worry
about this. */

View File

@ -335,6 +335,9 @@ print_rtx (const_rtx in_rtx)
break;
}
}
else if (i == 9 && JUMP_P (in_rtx) && XEXP (in_rtx, i) != NULL)
/* Output the JUMP_LABEL reference. */
fprintf (outfile, "\n -> %d", INSN_UID (XEXP (in_rtx, i)));
break;
case 'e':

View File

@ -91,10 +91,16 @@ REG_NOTE (UNUSED)
REG_NOTE (CC_SETTER)
REG_NOTE (CC_USER)
/* Points to a CODE_LABEL. Used by non-JUMP_INSNs to say that the
CODE_LABEL contained in the REG_LABEL note is used by the insn.
This note is an INSN_LIST. */
REG_NOTE (LABEL)
/* Points to a CODE_LABEL. Used by JUMP_INSNs to say that the CODE_LABEL
contained in the REG_LABEL_TARGET note is a possible jump target of
this insn. This note is an INSN_LIST. */
REG_NOTE (LABEL_TARGET)
/* Points to a CODE_LABEL. Used by any insn to say that the CODE_LABEL
contained in the REG_LABEL_OPERAND note is used by the insn, but as an
operand, not as a jump target (though it may indirectly be a jump
target for a later jump insn). This note is an INSN_LIST. */
REG_NOTE (LABEL_OPERAND)
/* REG_DEP_OUTPUT and REG_DEP_ANTI are used in scheduler dependencies lists
to represent write-after-write and write-after-read dependencies

View File

@ -4103,13 +4103,18 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
*recog_data.operand_loc[i] = substitution;
/* If we're replacing an operand with a LABEL_REF, we need
to make sure that there's a REG_LABEL note attached to
/* If we're replacing an operand with a LABEL_REF, we need to
make sure that there's a REG_LABEL_OPERAND note attached to
this instruction. */
if (!JUMP_P (insn)
&& GET_CODE (substitution) == LABEL_REF
&& !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
if (GET_CODE (substitution) == LABEL_REF
&& !find_reg_note (insn, REG_LABEL_OPERAND,
XEXP (substitution, 0))
/* For a JUMP_P, if it was a branch target it must have
already been recorded as such. */
&& (!JUMP_P (insn)
|| !label_is_jump_target_p (XEXP (substitution, 0),
insn)))
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND,
XEXP (substitution, 0),
REG_NOTES (insn));
}
@ -6123,17 +6128,15 @@ subst_reloads (rtx insn)
}
#endif /* DEBUG_RELOAD */
/* If we're replacing a LABEL_REF with a register, add a
REG_LABEL note to indicate to flow which label this
/* If we're replacing a LABEL_REF with a register, there must
already be an indication (to e.g. flow) which label this
register refers to. */
if (GET_CODE (*r->where) == LABEL_REF
&& JUMP_P (insn))
{
REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
XEXP (*r->where, 0),
REG_NOTES (insn));
JUMP_LABEL (insn) = XEXP (*r->where, 0);
}
gcc_assert (GET_CODE (*r->where) != LABEL_REF
|| !JUMP_P (insn)
|| find_reg_note (insn,
REG_LABEL_OPERAND,
XEXP (*r->where, 0))
|| label_is_jump_target_p (XEXP (*r->where, 0), insn));
/* Encapsulate RELOADREG so its machine mode matches what
used to be there. Note that gen_lowpart_common will

View File

@ -1539,8 +1539,8 @@ calculate_needs_all_insns (int global)
chain->need_operand_change = 0;
/* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
include REG_LABEL), we need to see what effects this has on the
known offsets at labels. */
include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
what effects this has on the known offsets at labels. */
if (LABEL_P (insn) || JUMP_P (insn)
|| (INSN_P (insn) && REG_NOTES (insn) != 0))
@ -2295,10 +2295,11 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
case INSN:
case CALL_INSN:
/* Any labels mentioned in REG_LABEL notes can be branched to indirectly
and hence must have all eliminations at their initial offsets. */
/* Any labels mentioned in REG_LABEL_OPERAND notes can be branched
to indirectly and hence must have all eliminations at their
initial offsets. */
for (tem = REG_NOTES (x); tem; tem = XEXP (tem, 1))
if (REG_NOTE_KIND (tem) == REG_LABEL)
if (REG_NOTE_KIND (tem) == REG_LABEL_OPERAND)
set_label_offsets (XEXP (tem, 0), insn, 1);
return;
@ -8049,7 +8050,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
{
tem = emit_insn (gen_move_insn (out, in));
/* IN may contain a LABEL_REF, if so add a REG_LABEL note. */
/* IN may contain a LABEL_REF, if so add a REG_LABEL_OPERAND note. */
mark_jump_label (in, tem, 0);
}

View File

@ -541,7 +541,8 @@ emit_delay_sequence (rtx insn, rtx list, int length)
remove_note (tem, note);
break;
case REG_LABEL:
case REG_LABEL_OPERAND:
case REG_LABEL_TARGET:
/* Keep the label reference count up to date. */
if (LABEL_P (XEXP (note, 0)))
LABEL_NUSES (XEXP (note, 0)) ++;
@ -2736,14 +2737,40 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
/* We are moving this insn, not deleting it. We must
temporarily increment the use count on any referenced
label lest it be deleted by delete_related_insns. */
note = find_reg_note (trial, REG_LABEL, 0);
/* REG_LABEL could be NOTE_INSN_DELETED_LABEL too. */
if (note && LABEL_P (XEXP (note, 0)))
for (note = REG_NOTES (trial);
note != NULL;
note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
|| REG_NOTE_KIND (note) == REG_LABEL_TARGET)
{
/* REG_LABEL_OPERAND could be
NOTE_INSN_DELETED_LABEL too. */
if (LABEL_P (XEXP (note, 0)))
LABEL_NUSES (XEXP (note, 0))++;
else
gcc_assert (REG_NOTE_KIND (note)
== REG_LABEL_OPERAND);
}
if (JUMP_P (trial) && JUMP_LABEL (trial))
LABEL_NUSES (XEXP (note, 0))++;
delete_related_insns (trial);
if (note && LABEL_P (XEXP (note, 0)))
for (note = REG_NOTES (trial);
note != NULL;
note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
|| REG_NOTE_KIND (note) == REG_LABEL_TARGET)
{
/* REG_LABEL_OPERAND could be
NOTE_INSN_DELETED_LABEL too. */
if (LABEL_P (XEXP (note, 0)))
LABEL_NUSES (XEXP (note, 0))--;
else
gcc_assert (REG_NOTE_KIND (note)
== REG_LABEL_OPERAND);
}
if (JUMP_P (trial) && JUMP_LABEL (trial))
LABEL_NUSES (XEXP (note, 0))--;
}
else

View File

@ -265,7 +265,8 @@ struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
1 in a REG expression if corresponds to a variable declared by the user,
0 for an internally generated temporary.
1 in a SUBREG with a negative value.
1 in a LABEL_REF or in a REG_LABEL note for a non-local label.
1 in a LABEL_REF, REG_LABEL_TARGET or REG_LABEL_OPERAND note for a
non-local label.
In a SYMBOL_REF, this flag is used for machine-specific purposes. */
unsigned int volatil : 1;
/* 1 in a MEM referring to a field of an aggregate.
@ -1224,10 +1225,11 @@ do { \
MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
/* 1 if RTX is a label_ref for a nonlocal label. */
/* Likewise in an expr_list for a reg_label note. */
/* Likewise in an expr_list for a REG_LABEL_OPERAND or
REG_LABEL_TARGET note. */
#define LABEL_REF_NONLOCAL_P(RTX) \
(RTL_FLAG_CHECK2("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF, \
REG_LABEL)->volatil)
(RTL_FLAG_CHECK3("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF, \
REG_LABEL_OPERAND, REG_LABEL_TARGET)->volatil)
/* 1 if RTX is a code_label that should always be considered to be needed. */
#define LABEL_PRESERVE_P(RTX) \

View File

@ -2703,9 +2703,11 @@ computed_jump_p (const_rtx insn)
{
rtx pat = PATTERN (insn);
if (find_reg_note (insn, REG_LABEL, NULL_RTX))
/* If we have a JUMP_LABEL set, we're not a computed jump. */
if (JUMP_LABEL (insn) != NULL)
return 0;
else if (GET_CODE (pat) == PARALLEL)
if (GET_CODE (pat) == PARALLEL)
{
int len = XVECLEN (pat, 0);
int has_use_labelref = 0;

View File

@ -315,24 +315,20 @@ is_cfg_nonregular (void)
if (current_function_has_exception_handlers ())
return 1;
/* If we have non-jumping insns which refer to labels, then we consider
the cfg not well structured. */
/* If we have insns which refer to labels as non-jumped-to operands,
then we consider the cfg not well structured. */
FOR_EACH_BB (b)
FOR_BB_INSNS (b, insn)
{
/* Check for labels referred by non-jump insns. */
if (NONJUMP_INSN_P (insn) || CALL_P (insn))
{
rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
if (note
&& ! (JUMP_P (NEXT_INSN (insn))
&& find_reg_note (NEXT_INSN (insn), REG_LABEL,
XEXP (note, 0))))
return 1;
}
/* Check for labels referred to but (at least not directly) as
jump targets. */
if (INSN_P (insn)
&& find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
return 1;
/* If this function has a computed jump, then we consider the cfg
not well structured. */
else if (JUMP_P (insn) && computed_jump_p (insn))
if (JUMP_P (insn) && computed_jump_p (insn))
return 1;
}