Conditional and unconditional branch targets can be either a label or
a symbol.  For conditional jump:

(jump_insn 7 6 14 2 (set (pc)
        (if_then_else (eq (reg:CCZ 17 flags)
                (const_int 0 [0]))
            (label_ref:DI 23)
            (pc))) "x.c":8:5 1458 {jcc}
     (expr_list:REG_DEAD (reg:CCZ 17 flags)
        (int_list:REG_BR_PROB 217325348 (nil)))
...
(code_label 23 20 8 4 4 (nil) [1 uses])
(note 8 23 9 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
(call_insn/j 9 8 10 4 (call (mem:QI (symbol_ref:DI ("bar") [flags 0x41]  
<function_decl 0x7f4cff3c0b00 bar>) [0 bar S1 A8])
        (const_int 0 [0])) "x.c":8:14 discrim 1 1469 {sibcall_di}
     (expr_list:REG_CALL_DECL (symbol_ref:DI ("bar") [flags 0x41]  <function_dec
l 0x7f4cff3c0b00 bar>)
        (nil))
    (nil))

they can be changed to

(jump_insn 7 6 14 2 (set (pc)
        (if_then_else (eq (reg:CCZ 17 flags)
                (const_int 0 [0]))
            ((symbol_ref:DI ("bar") [flags 0x41] <function_decl 0x7fffe99c0c00 
foo>)
            (pc))) "x.c":8:5 1458 {jcc}
     (expr_list:REG_DEAD (reg:CCZ 17 flags)
        (int_list:REG_BR_PROB 217325348 (nil)))

if the call is a sibcall.  For jump table:

(jump_table_data 16 15 17 (addr_vec:DI [
            (label_ref:DI 18)
            (label_ref:DI 22)
            (label_ref:DI 26)
            (label_ref:DI 30)
            (label_ref:DI 34)
        ]))
...
(code_label 30 17 31 4 5 (nil) [1 uses])
(note 31 30 32 4 [bb 4] NOTE_INSN_BASIC_BLOCK)
(call_insn/j 32 31 33 4 (call (mem:QI (symbol_ref:DI ("bar3") [flags 0x41]  
<function_decl 0x7f21be3c0e00 bar3>) [0 bar3 S1 A8])
        (const_int 0 [0])) "j.c":15:13 1469 {sibcall_di}
     (expr_list:REG_CALL_DECL (symbol_ref:DI ("bar3") [flags 0x41]  
<function_decl 0x7f21be3c0e00 bar3>)
        (nil))
    (nil))

They can be changed to

(jump_table_data 16 15 17 (addr_vec:DI [
            (symbol_ref:DI ("bar0") [flags 0x41]  <function_decl 0x7f4f1c5c0b00 
bar0>)
            (symbol_ref:DI ("bar1") [flags 0x41]  <function_decl 0x7f4f1c5c0c00 
bar1>)
            (symbol_ref:DI ("bar2") [flags 0x41]  <function_decl 0x7f4f1c5c0d00 
bar2>)
            (symbol_ref:DI ("bar3") [flags 0x41]  <function_decl 0x7f4f1c5c0e00 
bar3>)
            (symbol_ref:DI ("bar4") [flags 0x41]  <function_decl 0x7f4f1c5c0f00 
bar4>)
        ]))

if bar0/bar1/bar2/bar3/bar4 calls are sibcalls.

Applications similar to

https://quick-bench.com/q/ogkuxaj98UEqLYnRUlWZk-ppAtU

show that folding sibcalls into jump label and jump table has a small but
noticeable decrease in runtime.

Instead of supporting symbol reference in jump label and jump table in
the full RTL optimization pipeline, which requires very invasive changes
to GCC RTL infrastructure, support symbol reference in jump label and
jump table for the pass which turning REG_EH_REGION notes back into
NOTE_INSN_EH_REGION notes and after:

1. Add a set_jump_target method to assign symbol reference to jump label.
2. Add condsibcall_p for conditional sibling call.
3. Add anycall_p to return true for call and conditional sibcall.
4. Replace CALL_P with anycall_p in except.cc, final.cc and function-abi.cc
to support conditional sibcall.
5. Return false for symbol reference in jump table check.
6. Update create_trace_edges and rtx_writer::print_rtx_operand_code_0 to
handle symbol reference in jump label.
7. Add ASM_OUTPUT_ADDR_VEC_SYM_ELT and use it in final_scan_insn_1 to
output symbol reference in jump table.
8. Document limitation of symbol reference support in jump label.

        * dwarf2cfi.c (create_trace_edges): Skip symbol reference in
        jump table and in JUMP_LABEL.  Short-circuit JUMP for the pure
        sibcall.
        * except.cc (sjlj_mark_call_sites): Replace CALL_P with
        anycall_p.
        (finish_eh_generation): Likewise.
        (insn_could_throw_p): Likewise.
        (can_nonlocal_goto): Likewise.
        (set_nothrow_function_flags): Also call condsibcall_p to check
        conditional sibcall.
        * final.cc (final_scan_insn_1): Use ASM_OUTPUT_ADDR_VEC_SYM_ELT
        to output symbol reference in jump table.
        (collect_fn_hard_reg_usage): Replace CALL_P with anycall_p.
        * function-abi.cc (insn_callee_abi): Likewise.
        * jump.cc (condsibcall_p): New.
        * print-rtl.cc (rtx_writer::print_rtx_operand_code_0): Support
        symbol reference in JUMP_LABEL.
        * rtl.h (rtx_jump_insn::set_jump_target): New, with the rtx
        argument.
        * rtl.h (condsibcall_p): New.
        (anycall_p): Likewise.
        * rtlanal.cc (tablejump_p): Return false if JUMP_LABEL is a
        symbol reference.
        * config/i386/i386-expand.cc (ix86_notrack_prefixed_insn_p):
        Likewise.
        * config/i386/i386-protos.h (ix86_output_addr_vec_sym_elt): New.
        * config/i386/i386.cc (ix86_output_addr_vec_sym_elt): Likewise.
        * config/i386/linux-common.h (ASM_OUTPUT_ADDR_VEC_SYM_ELT):
        Likewise.
        * doc/rtl.texi (addr_vec): Also allow symbol reference.
        (JUMP_LABEL): Likewise.
        * doc/tm.texi: Regenerated.
        * doc/tm.texi.in (ASM_OUTPUT_ADDR_VEC_SYM_ELT): New.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/config/i386/i386-expand.cc |  5 ++++-
 gcc/config/i386/i386-protos.h  |  2 ++
 gcc/config/i386/i386.cc        | 18 +++++++++++++++++
 gcc/config/i386/linux-common.h |  6 ++++++
 gcc/doc/rtl.texi               | 24 +++++++++++++----------
 gcc/doc/tm.texi                |  8 ++++++++
 gcc/doc/tm.texi.in             |  8 ++++++++
 gcc/dwarf2cfi.cc               | 20 ++++++++++++++++++-
 gcc/except.cc                  | 11 ++++++-----
 gcc/final.cc                   | 19 +++++++++++++++---
 gcc/function-abi.cc            |  2 +-
 gcc/jump.cc                    | 36 ++++++++++++++++++++++++++++++++++
 gcc/print-rtl.cc               |  2 ++
 gcc/rtl.h                      | 32 ++++++++++++++++++++++++++++++
 gcc/rtlanal.cc                 |  5 ++++-
 15 files changed, 176 insertions(+), 22 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 20914fcbad9..b7eb75ead6e 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -26767,7 +26767,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/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 21994d3d498..95ea19927c0 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -39,6 +39,8 @@ extern void ix86_expand_split_stack_prologue (void);
 extern void ix86_output_addr_vec_elt (FILE *, int);
 extern void ix86_output_addr_diff_elt (FILE *, int, int);
 
+extern void ix86_output_addr_vec_sym_elt (FILE *, rtx);
+
 extern const char *ix86_output_ssemov (rtx_insn *, rtx *);
 
 extern enum calling_abi ix86_cfun_abi (void);
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 33e5e063b99..0aaa8be29e7 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -16161,6 +16161,24 @@ ix86_output_addr_diff_elt (FILE *file, int value, int 
rel)
     asm_fprintf (file, ASM_LONG "%U%s+[.-%s%d]\n",
                 GOT_SYMBOL_NAME, LPREFIX, value);
 }
+
+void
+ix86_output_addr_vec_sym_elt (FILE *file, rtx sym)
+{
+  const char *directive = ASM_LONG;
+
+#ifdef ASM_QUAD
+  if (TARGET_LP64)
+    directive = ASM_QUAD;
+#else
+  gcc_assert (!TARGET_64BIT);
+#endif
+
+  fprintf (file, "%s", directive);
+  assemble_external (SYMBOL_REF_DECL (sym));
+  ASM_OUTPUT_SYMBOL_REF (file, sym);
+  putc ('\n', file);
+}
 
 #define LEA_MAX_STALL (3)
 #define LEA_SEARCH_THRESHOLD (LEA_MAX_STALL << 1)
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index ab45eda17ab..828b6d152df 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -66,3 +66,9 @@ extern void file_end_indicate_exec_stack_and_gnu_property 
(void);
 
 #undef TARGET_ASM_FILE_END
 #define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_gnu_property
+
+/* This is how to output an element of a case-vector with symbol
+   reference that is absolute.  */
+
+#define ASM_OUTPUT_ADDR_VEC_SYM_ELT(FILE, SYM)  \
+  ix86_output_addr_vec_sym_elt ((FILE), (SYM))
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index f606b97389f..227862e7479 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -3460,8 +3460,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
@@ -3781,14 +3782,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/doc/tm.texi b/gcc/doc/tm.texi
index 85e17525683..c7f4bc52042 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -9986,6 +9986,14 @@ fprintf (@var{stream}, "\t.word L%d\n", @var{value})
 @end smallexample
 @end defmac
 
+@defmac ASM_OUTPUT_ADDR_VEC_SYM_ELT (@var{stream}, @var{sym})
+This macro is similar to @code{ASM_OUTPUT_ADDR_VEC_ELT}, except that
+@var{value} is replaced by @var{sym} which is a symbol reference.
+
+You must provide this macro for absolute symbol references in a dispatch
+table.
+@end defmac
+
 @defmac ASM_OUTPUT_CASE_LABEL (@var{stream}, @var{prefix}, @var{num}, 
@var{table})
 Define this if the label before a jump-table needs to be output
 specially.  The first three arguments are the same as for
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 1a9edd0635d..33e1ad1374b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -6513,6 +6513,14 @@ fprintf (@var{stream}, "\t.word L%d\n", @var{value})
 @end smallexample
 @end defmac
 
+@defmac ASM_OUTPUT_ADDR_VEC_SYM_ELT (@var{stream}, @var{sym})
+This macro is similar to @code{ASM_OUTPUT_ADDR_VEC_ELT}, except that
+@var{value} is replaced by @var{sym} which is a symbol reference.
+
+You must provide this macro for absolute symbol references in a dispatch
+table.
+@end defmac
+
 @defmac ASM_OUTPUT_CASE_LABEL (@var{stream}, @var{prefix}, @var{num}, 
@var{table})
 Define this if the label before a jump-table needs to be output
 specially.  The first three arguments are the same as for
diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
index a7c00354ff1..3388a989926 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 98876833ee1..fca1bf06673 100644
--- a/gcc/except.cc
+++ b/gcc/except.cc
@@ -1152,7 +1152,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 ();
@@ -1560,7 +1560,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);
        }
@@ -1756,7 +1756,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));
@@ -1973,7 +1973,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)
@@ -2013,7 +2013,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 0152be59fc8..9349d690ddf 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -2539,8 +2539,21 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int 
optimize_p ATTRIBUTE_UNUSED,
                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))
+                     {
+#ifdef ASM_OUTPUT_ADDR_VEC_SYM_ELT
+                       ASM_OUTPUT_ADDR_VEC_SYM_ELT (file, l);
+#else
+                       gcc_unreachable ();
+#endif
+                     }
+                   else
+                     {
+                       l = XEXP (l, 0);
+                       ASM_OUTPUT_ADDR_VEC_ELT (file,
+                                                CODE_LABEL_NUMBER (l));
+                     }
 #else
                    gcc_unreachable ();
 #endif
@@ -4627,7 +4640,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 277863ecee3..7b9afc45924 100644
--- a/gcc/function-abi.cc
+++ b/gcc/function-abi.cc
@@ -221,7 +221,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 75158924c8f..cf9f905102d 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 315b027516d..394967eb194 100644
--- a/gcc/print-rtl.cc
+++ b/gcc/print-rtl.cc
@@ -312,6 +312,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 aa0b4c77a39..7bcd236b11b 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -628,6 +628,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
@@ -1914,6 +1915,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.  */
@@ -4295,6 +4302,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 *);
@@ -4756,6 +4764,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 5274a5c59cf..7ee3262a971 100644
--- a/gcc/rtlanal.cc
+++ b/gcc/rtlanal.cc
@@ -3532,7 +3532,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.55.0

Reply via email to