Andi
>> > > > > * doc/rtl.texi (addr_vec): Also allow symbol reference.
>> > > > > (JUMP_LABEL): Likewise.
>> > > > >
>> > > > > Signed-off-by: H.J. Lu <[email protected]>
>> > >
>> > > PING^2.
>> > >
>> > > > > ---
>> > > > > gcc/config/i386/i386-expand.cc | 5 ++++-
>> > > > > gcc/doc/rtl.texi | 24 +++++++++++++----------
>> > > > > gcc/dwarf2cfi.cc | 20 ++++++++++++++++++-
>> > > > > gcc/except.cc | 11 ++++++-----
>> > > > > gcc/final.cc | 26 +++++++++++++++++++++---
>> > > > > gcc/function-abi.cc | 2 +-
>> > > > > gcc/jump.cc | 36
++++++++++++++++++++++++++++++++++
>> > > > > gcc/print-rtl.cc | 2 ++
>> > > > > gcc/rtl.h | 32 ++++++++++++++++++++++++++++++
>> > > > > gcc/rtlanal.cc | 5 ++++-
>> > > > > 10 files changed, 141 insertions(+), 22 deletions(-)
>> > > > >
>> > > > > diff --git a/gcc/config/i386/i386-expand.cc
b/gcc/config/i386/i386-expand.cc
>> > > > > index 7f0fdb6fa9e..0d0802692d1 100644
>> > > > > --- a/gcc/config/i386/i386-expand.cc
>> > > > > +++ b/gcc/config/i386/i386-expand.cc
>> > > > > @@ -25501,7 +25501,10 @@ ix86_notrack_prefixed_insn_p (rtx_insn
*insn)
>> > > > > if (JUMP_P (insn) && !flag_cet_switch)
>> > > > > {
>> > > > > rtx target = JUMP_LABEL (insn);
>> > > > > - if (target == NULL_RTX || ANY_RETURN_P (target))
>> > > > > + if (target == NULL_RTX
>> > > > > + || ANY_RETURN_P (target)
>> > > > > + /* Also check for conditional sibcall. */
>> > > > > + || SYMBOL_REF_P (target))
>> > > > > return false;
>> > > > >
>> > > > > /* Check the jump is a switch table. */
>> > > > > diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
>> > > > > index 089bb1c4ede..0976c9c82dd 100644
>> > > > > --- a/gcc/doc/rtl.texi
>> > > > > +++ b/gcc/doc/rtl.texi
>> > > > > @@ -3459,8 +3459,9 @@ insn, inside a @code{parallel}, or inside an
expression.
>> > > > > @findex addr_vec
>> > > > > @item (addr_vec:@var{m} [@var{lr0} @var{lr1} @dots{}])
>> > > > > Represents a table of jump addresses. The vector elements
@var{lr0},
>> > > > > -etc., are @code{label_ref} expressions. The mode @var{m} specifies
>> > > > > -how much space is given to each address; normally @var{m} would be
>> > > > > +etc., are @code{label_ref} or @code{symbol_ref} expressions. The
mode
>> > > > > +@var{m} specifies how much space is given to each address; normally
>> > > > > +@var{m} would be
>> > > > > @code{Pmode}.
>> > > > >
>> > > > > @findex addr_diff_vec
>> > > > > @@ -3780,14 +3781,17 @@ instruction to return from the current
function, it is recorded as a
>> > > > > accessed in the same way and in addition contain a field
>> > > > > @code{JUMP_LABEL} which is defined once jump optimization has
completed.
>> > > > >
>> > > > > -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; 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.
>> > > > > +For unconditional jumps, this field contains the @code{code_label}
to
>> > > > > +which this insn will branch. For simple conditional jumps, this
field
>> > > > > +contains the @code{code_label} or @code{symbol_ref} to which this
insn
>> > > > > +will branch possibly conditionally. @code{symbol_ref} should only
be
>> > > > > +generated immediately before the pass which turning REG_EH_REGION
notes
>> > > > > +back into NOTE_INSN_EH_REGION notes. In a more complex jump,
>> > > > > +@code{JUMP_LABEL} records one of the 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 their @code{JUMP_LABEL} is
@code{RETURN}
>> > > > > or @code{SIMPLE_RETURN}.
>> > > > > diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
>> > > > > index a5353d39e7e..d8f25123284 100644
>> > > > > --- a/gcc/dwarf2cfi.cc
>> > > > > +++ b/gcc/dwarf2cfi.cc
>> > > > > @@ -2646,6 +2646,8 @@ create_trace_edges (rtx_insn *insn)
>> > > > > if (JUMP_P (insn))
>> > > > > {
>> > > > > rtx_jump_table_data *table;
>> > > > > + bool sibcall_p = false;
>> > > > > + bool label_p = false;
>> > > > >
>> > > > > if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
>> > > > > return;
>> > > > > @@ -2657,8 +2659,17 @@ create_trace_edges (rtx_insn *insn)
>> > > > > n = GET_NUM_ELEM (vec);
>> > > > > for (i = 0; i < n; ++i)
>> > > > > {
>> > > > > - rtx_insn *lab = as_a <rtx_insn *> (XEXP (RTVEC_ELT
(vec, i), 0));
>> > > > > + rtx l = RTVEC_ELT (vec, i);
>> > > > > + if (SYMBOL_REF_P (l))
>> > > > > + {
>> > > > > + /* A symbol reference must be a sibcall. Skip it.
*/
>> > > > > + sibcall_p = true;
>> > > > > + continue;
>> > > > > + }
>> > > > > + l = XEXP (l, 0);
>> > > > > + rtx_insn *lab = as_a <rtx_insn *> (l);
>> > > > > maybe_record_trace_start (lab, insn);
>> > > > > + label_p = true;
>> > > > > }
>> > > > >
>> > > > > /* Handle casesi dispatch insns. */
>> > > > > @@ -2687,12 +2698,19 @@ create_trace_edges (rtx_insn *insn)
>> > > > > maybe_record_trace_start (lab, insn);
>> > > > > }
>> > > > > }
>> > > > > + /* A symbol reference must be a sibcall. */
>> > > > > + else if (SYMBOL_REF_P (JUMP_LABEL (insn)))
>> > > > > + sibcall_p = true;
>> > > > > else
>> > > > > {
>> > > > > rtx_insn *lab = JUMP_LABEL_AS_INSN (insn);
>> > > > > gcc_assert (lab != NULL);
>> > > > > maybe_record_trace_start (lab, insn);
>> > > > > }
>> > > > > +
>> > > > > + /* Check for the pure sibcall. */
>> > > > > + if (sibcall_p && !label_p)
>> > > > > + return;
>> > > > > }
>> > > > > else if (CALL_P (insn))
>> > > > > {
>> > > > > diff --git a/gcc/except.cc b/gcc/except.cc
>> > > > > index 0fe1e093489..2f37e4652b9 100644
>> > > > > --- a/gcc/except.cc
>> > > > > +++ b/gcc/except.cc
>> > > > > @@ -1154,7 +1154,7 @@ sjlj_mark_call_sites (void)
>> > > > >
>> > > > > /* Don't separate a call from it's argument loads. */
>> > > > > before = insn;
>> > > > > - if (CALL_P (insn))
>> > > > > + if (anycall_p (insn))
>> > > > > before = find_first_parameter_load (insn, NULL);
>> > > > >
>> > > > > start_sequence ();
>> > > > > @@ -1567,7 +1567,7 @@ finish_eh_generation (void)
>> > > > > gcc_assert (BB_HEAD (e->dest) == label_rtx
(lp->post_landing_pad));
>> > > > >
>> > > > > redirect_edge_succ (e, BLOCK_FOR_INSN (lp->landing_pad));
>> > > > > - e->flags |= (CALL_P (BB_END (bb))
>> > > > > + e->flags |= (anycall_p (BB_END (bb))
>> > > > > ? EDGE_ABNORMAL | EDGE_ABNORMAL_CALL
>> > > > > : EDGE_ABNORMAL);
>> > > > > }
>> > > > > @@ -1763,7 +1763,7 @@ insn_could_throw_p (const_rtx insn)
>> > > > > {
>> > > > > if (!flag_exceptions)
>> > > > > return false;
>> > > > > - if (CALL_P (insn))
>> > > > > + if (anycall_p (insn))
>> > > > > return true;
>> > > > > if (INSN_P (insn) && cfun->can_throw_non_call_exceptions)
>> > > > > return may_trap_p (PATTERN (insn));
>> > > > > @@ -1980,7 +1980,7 @@ insn_nothrow_p (const_rtx insn)
>> > > > > bool
>> > > > > can_nonlocal_goto (const rtx_insn *insn)
>> > > > > {
>> > > > > - if (nonlocal_goto_handler_labels && CALL_P (insn))
>> > > > > + if (nonlocal_goto_handler_labels && anycall_p (insn))
>> > > > > {
>> > > > > rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
>> > > > > if (!note || INTVAL (XEXP (note, 0)) != INT_MIN)
>> > > > > @@ -2020,7 +2020,8 @@ set_nothrow_function_flags (void)
>> > > > > {
>> > > > > crtl->nothrow = 0;
>> > > > >
>> > > > > - if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
>> > > > > + if ((!CALL_P (insn) || !SIBLING_CALL_P (insn))
>> > > > > + && !condsibcall_p (insn))
>> > > > > {
>> > > > > crtl->all_throwers_are_sibcalls = 0;
>> > > > > return 0;
>> > > > > diff --git a/gcc/final.cc b/gcc/final.cc
>> > > > > index 12c6eb0ac09..bff6bf3fd86 100644
>> > > > > --- a/gcc/final.cc
>> > > > > +++ b/gcc/final.cc
>> > > > > @@ -2524,13 +2524,33 @@ final_scan_insn_1 (rtx_insn *insn, FILE
*file, int optimize_p ATTRIBUTE_UNUSED,
>> > > > > }
>> > > > > #else
>> > > > > vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
>> > > > > +#ifdef ASM_OUTPUT_ADDR_VEC_ELT
>> > > > > + const char *asm_op = integer_asm_op (POINTER_SIZE_UNITS,
true);
>> > > > > +#endif
>> > > > > for (idx = 0; idx < vlen; idx++)
>> > > > > {
>> > > > > if (GET_CODE (body) == ADDR_VEC)
>> > > > > {
>> > > > > #ifdef ASM_OUTPUT_ADDR_VEC_ELT
>> > > > > - ASM_OUTPUT_ADDR_VEC_ELT
>> > > > > - (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body,
0, idx), 0)));
>> > > > > + rtx l = XVECEXP (body, 0, idx);
>> > > > > + if (SYMBOL_REF_P (l))
>> > > > > + {
>> > > > > + gcc_assert (asm_op != NULL);
>> > > > > + fprintf (file, "%s", asm_op);
>> > > > > + assemble_external (SYMBOL_REF_DECL (l));
>> > > > > +#ifdef ASM_OUTPUT_SYMBOL_REF
>> > > > > + ASM_OUTPUT_SYMBOL_REF (file, l);
>> > > > > +#else
>> > > > > + assemble_name (file, XSTR (l, 0));
>> > > > > +#endif
>> > > > > + putc ('\n', file);
>> > > > > + }
>> > > > > + else
>> > > > > + {
>> > > > > + l = XEXP (l, 0);
>> > > > > + ASM_OUTPUT_ADDR_VEC_ELT
>> > > > > + (file, CODE_LABEL_NUMBER (l));
>> > > > > + }
>> > > > > #else
>> > > > > gcc_unreachable ();
>> > > > > #endif
>> > > > > @@ -4604,7 +4624,7 @@ collect_fn_hard_reg_usage (void)
>> > > > > if (!NONDEBUG_INSN_P (insn))
>> > > > > continue;
>> > > > >
>> > > > > - if (CALL_P (insn)
>> > > > > + if (anycall_p (insn)
>> > > > > && !self_recursive_call_p (insn))
>> > > > > function_used_regs
>> > > > > |= insn_callee_abi (insn).full_and_partial_reg_clobbers ();
>> > > > > diff --git a/gcc/function-abi.cc b/gcc/function-abi.cc
>> > > > > index d500657b49e..3cabe67af73 100644
>> > > > > --- a/gcc/function-abi.cc
>> > > > > +++ b/gcc/function-abi.cc
>> > > > > @@ -218,7 +218,7 @@ fndecl_abi (const_tree fndecl)
>> > > > > function_abi
>> > > > > insn_callee_abi (const rtx_insn *insn)
>> > > > > {
>> > > > > - gcc_assert (insn && CALL_P (insn));
>> > > > > + gcc_assert (insn && anycall_p (insn));
>> > > > >
>> > > > > if (flag_ipa_ra)
>> > > > > if (tree fndecl = get_call_fndecl (insn))
>> > > > > diff --git a/gcc/jump.cc b/gcc/jump.cc
>> > > > > index 02df75ab08e..b7768a8b53f 100644
>> > > > > --- a/gcc/jump.cc
>> > > > > +++ b/gcc/jump.cc
>> > > > > @@ -1011,6 +1011,42 @@ jump_to_label_p (const rtx_insn *insn)
>> > > > > return (JUMP_P (insn)
>> > > > > && JUMP_LABEL (insn) != NULL && !ANY_RETURN_P (JUMP_LABEL
(insn)));
>> > > > > }
>> > > > > +
>> > > > > +/* Return true if INSN has a conditional sibling call. */
>> > > > > +
>> > > > > +bool
>> > > > > +condsibcall_p (const rtx_insn *insn)
>> > > > > +{
>> > > > > + if (!JUMP_P (insn))
>> > > > > + return false;
>> > > > > +
>> > > > > + rtx label = JUMP_LABEL (insn);
>> > > > > + if (label == nullptr || ANY_RETURN_P (label))
>> > > > > + return false;
>> > > > > +
>> > > > > + /* Check the direct conditional sibling call. */
>> > > > > + if (SYMBOL_REF_P (label))
>> > > > > + return true;
>> > > > > +
>> > > > > + /* Check jump table with the indirect conditional sibling call.
*/
>> > > > > + rtx_insn *target = as_a<rtx_insn *> (label);
>> > > > > + rtx_insn *table = next_insn (target);
>> > > > > + if (!table
>> > > > > + || !JUMP_TABLE_DATA_P (table)
>> > > > > + || GET_CODE (PATTERN (table)) != ADDR_VEC)
>> > > > > + return false;
>> > > > > +
>> > > > > + rtx body = PATTERN (table);
>> > > > > + unsigned int len = XVECLEN (body, 0);
>> > > > > + for (unsigned int i = 0; i < len; i++)
>> > > > > + {
>> > > > > + rtx target = XVECEXP (body, 0, i);
>> > > > > + if (SYMBOL_REF_P (target))
>> > > > > + return true;
>> > > > > + }
>> > > > > +
>> > > > > + return false;
>> > > > > +}
>> > > > >
>> > > > > /* 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
>> > > > > diff --git a/gcc/print-rtl.cc b/gcc/print-rtl.cc
>> > > > > index 033f7e7aab0..3ed7130ee1c 100644
>> > > > > --- a/gcc/print-rtl.cc
>> > > > > +++ b/gcc/print-rtl.cc
>> > > > > @@ -308,6 +308,8 @@ rtx_writer::print_rtx_operand_code_0 (const_rtx
in_rtx ATTRIBUTE_UNUSED,
>> > > > > fprintf (m_outfile, "return");
>> > > > > else if (GET_CODE (JUMP_LABEL (in_rtx)) == SIMPLE_RETURN)
>> > > > > fprintf (m_outfile, "simple_return");
>> > > > > + else if (SYMBOL_REF_P (JUMP_LABEL (in_rtx)))
>> > > > > + print_rtx_operand_code_0 (JUMP_LABEL (in_rtx), idx);
>> > > > > else
>> > > > > fprintf (m_outfile, "%d", INSN_UID (JUMP_LABEL (in_rtx)));
>> > > > > }
>> > > > > diff --git a/gcc/rtl.h b/gcc/rtl.h
>> > > > > index cc25aed1f49..0d665b74c7a 100644
>> > > > > --- a/gcc/rtl.h
>> > > > > +++ b/gcc/rtl.h
>> > > > > @@ -625,6 +625,7 @@ public:
>> > > > > /* Set jump target. */
>> > > > >
>> > > > > inline void set_jump_target (rtx_code_label *);
>> > > > > + inline void set_jump_target (rtx);
>> > > > > };
>> > > > >
>> > > > > struct GTY(()) rtx_call_insn : public rtx_insn
>> > > > > @@ -1895,6 +1896,12 @@ inline void rtx_jump_insn::set_jump_target
(rtx_code_label *target)
>> > > > > JUMP_LABEL (this) = target;
>> > > > > }
>> > > > >
>> > > > > +inline void rtx_jump_insn::set_jump_target (rtx target)
>> > > > > +{
>> > > > > + gcc_assert (SYMBOL_REF_P (target) || LABEL_P (target));
>> > > > > + JUMP_LABEL (this) = target;
>> > > > > +}
>> > > > > +
>> > > > > /* Once basic blocks are found, each CODE_LABEL starts a chain that
>> > > > > goes through all the LABEL_REFs that jump to that label. The
chain
>> > > > > eventually winds up at the CODE_LABEL: it is circular. */
>> > > > > @@ -4175,6 +4182,7 @@ extern bool jump_to_label_p (const rtx_insn *);
>> > > > > extern bool condjump_p (const rtx_insn *);
>> > > > > extern bool any_condjump_p (const rtx_insn *);
>> > > > > extern bool any_uncondjump_p (const rtx_insn *);
>> > > > > +extern bool condsibcall_p (const rtx_insn *);
>> > > > > extern rtx pc_set (const rtx_insn *);
>> > > > > extern rtx condjump_label (const rtx_insn *);
>> > > > > extern bool simplejump_p (const rtx_insn *);
>> > > > > @@ -4635,6 +4643,30 @@ word_register_operation_p (const_rtx x)
>> > > > > }
>> > > > > }
>> > > > >
>> > > > > +/* Return true if INSN is a conditional sibcall. */
>> > > > > +
>> > > > > +inline bool
>> > > > > +condsibcall_p (const_rtx insn)
>> > > > > +{
>> > > > > + return condsibcall_p (as_a <const rtx_insn *> (insn));
>> > > > > +}
>> > > > > +
>> > > > > +/* Return true if INSN is a call or a conditional sibcall. */
>> > > > > +
>> > > > > +inline bool
>> > > > > +anycall_p (const rtx_insn *insn)
>> > > > > +{
>> > > > > + return CALL_P (insn) || condsibcall_p (insn);
>> > > > > +}
>> > > > > +
>> > > > > +/* Return true if INSN is a call or a conditional sibcall. */
>> > > > > +
>> > > > > +inline bool
>> > > > > +anycall_p (const_rtx insn)
>> > > > > +{
>> > > > > + return CALL_P (insn) || condsibcall_p (insn);
>> > > > > +}
>> > > > > +
>> > > > > /* Holds an rtx comparison to simplify passing many parameters
pertaining to a
>> > > > > single comparison. */
>> > > > >
>> > > > > diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
>> > > > > index 86a5e473308..915a5d4634d 100644
>> > > > > --- a/gcc/rtlanal.cc
>> > > > > +++ b/gcc/rtlanal.cc
>> > > > > @@ -3539,7 +3539,10 @@ tablejump_p (const rtx_insn *insn, rtx_insn
**labelp,
>> > > > > return false;
>> > > > >
>> > > > > rtx target = JUMP_LABEL (insn);
>> > > > > - if (target == NULL_RTX || ANY_RETURN_P (target))
>> > > > > + if (target == NULL_RTX
>> > > > > + || ANY_RETURN_P (target)
>> > > > > + /* Also check for conditional sibcall. */
>> > > > > + || SYMBOL_REF_P (target))
>> > > > > return false;
>> > > > >
>> > > > > rtx_insn *label = as_a<rtx_insn *> (target);
>> > > > > --
>> > > > > 2.49.0
>> > > > >
>> > > >
>> > > >
>> > > > --
>> > > > H.J.
>> > >
>> > >
>> >
>> > PING.
>> >
>>
>> PING^4.
>>
>
> PING^5.