Enhance fold sibcall pass to fold sibcall targets into jump table by
turning:

foo:
        .cfi_startproc
        cmpl    $4, %edi
        ja      .L1
        movl    %edi, %edi
        jmp     *.L4(,%rdi,8)
        .section        .rodata
.L4:
        .quad   .L8
        .quad   .L7
        .quad   .L6
        .quad   .L5
        .quad   .L3
        .text
.L5:
        jmp     bar3
.L3:
        jmp     bar4
.L8:
        jmp     bar0
.L7:
        jmp     bar1
.L6:
        jmp     bar2
.L1:
        ret
        .cfi_endproc

into:

foo:
        .cfi_startproc
        cmpl    $4, %edi
        ja      .L1
        movl    %edi, %edi
        jmp     *.L4(,%rdi,8)
        .section        .rodata
.L4:
        .quad   bar0
        .quad   bar1
        .quad   bar2
        .quad   bar3
        .quad   bar4
        .text
.L1:
        ret
        .cfi_endproc

After basic block reordering pass, jump tables look like:

(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))

If the jump table entry points to a target basic block with only a direct
sibcall, change the entry to point to the sibcall target and decrement
the target basic block entry label use count.  If the target basic block
isn't kept for JUMP_LABEL of the conditional tailcall, delete it if its
entry label use count is 0.

Update create_trace_edges to skip symbol reference in jump table and
update final_scan_insn_1 to support symbol reference in jump table.

gcc/

        PR target/14721
        * dwarf2cfi.cc (create_trace_edges): Skip symbol reference in
        jump table.
        * final.cc (final_scan_insn_1): Support symbol reference in
        jump table.
        * config/i386/i386-features.cc (jump_table_label_to_basic_block):
        New.
        (fold_sibcall): Fold the sibcall targets into jump table.

gcc/testsuite/

        PR target/14721
        * gcc.target/i386/pr14721-1a.c: New.
        * gcc.target/i386/pr14721-1b.c: Likewise.
        * gcc.target/i386/pr14721-1c.c: Likewise.
        * gcc.target/i386/pr14721-2c.c: Likewise.
        * gcc.target/i386/pr14721-2b.c: Likewise.
        * gcc.target/i386/pr14721-2c.c: Likewise.
        * gcc.target/i386/pr14721-3c.c: Likewise.
        * gcc.target/i386/pr14721-3b.c: Likewise.
        * gcc.target/i386/pr14721-3c.c: Likewise.

Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
---
 gcc/config/i386/i386-features.cc           | 70 +++++++++++++++++++++-
 gcc/dwarf2cfi.cc                           |  7 ++-
 gcc/final.cc                               | 22 ++++++-
 gcc/testsuite/gcc.target/i386/pr14721-1a.c | 54 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-1b.c | 37 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-1c.c | 37 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-2a.c | 58 ++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-2b.c | 41 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-2c.c | 43 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-3a.c | 56 +++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-3b.c | 40 +++++++++++++
 gcc/testsuite/gcc.target/i386/pr14721-3c.c | 39 ++++++++++++
 12 files changed, 499 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-1a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-1b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-1c.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-2a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-2b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-2c.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-3a.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-3b.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr14721-3c.c

diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index bb1e428bb1b..e89c8324f34 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -3328,6 +3328,22 @@ sibcall_only_bb (basic_block bb, bitmap sibcall_bbs)
   return nullptr;
 }
 
+/* Return the sibcall target if the basic block referenced by LABEL only
+   has a direct sibcall.  */
+
+static rtx
+jump_table_label_to_basic_block (rtx label, bitmap sibcall_bbs)
+{
+  label = XEXP (label, 0);
+  basic_block bb = BLOCK_FOR_INSN (label);
+  rtx target = sibcall_only_bb (bb, sibcall_bbs);
+  /* Decrement the label use count if jump table entry will use the
+     sibcall directly.  */
+  if (target)
+    LABEL_NUSES (label) -= 1;
+  return target;
+}
+
 /* Fold direct sibcall.  */
 
 static unsigned int
@@ -3337,11 +3353,13 @@ fold_sibcall (void)
 
   bitmap_obstack_initialize (NULL);
   bitmap jcc_sibcall_bbs = BITMAP_ALLOC (NULL);
+  bitmap table_sibcall_bbs = BITMAP_ALLOC (NULL);
 
   unsigned int todo = 0;
   basic_block bb;
   rtx_insn *insn;
   bool jcc_sibcall = false;
+  bool table_sibcall = false;
 
   FOR_EACH_BB_FN (bb, cfun)
     {
@@ -3350,10 +3368,11 @@ fold_sibcall (void)
          if (!JUMP_P (insn))
            continue;
 
+         rtx label = JUMP_LABEL (insn);
+         rtx sibcall_target;
+
          if (INSN_CODE (insn) == CODE_FOR_jcc)
            {
-             rtx label = JUMP_LABEL (insn);
-             rtx sibcall_target;
              edge branch_edge = BRANCH_EDGE (bb);
              basic_block branch_bb = branch_edge->dest;
              sibcall_target = sibcall_only_bb (branch_bb,
@@ -3373,6 +3392,33 @@ fold_sibcall (void)
                  jcc_sibcall = true;
                }
            }
+         else if (label && !ANY_RETURN_P (label))
+           {
+             /* Check if it is a jump table with addresses.  */
+             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)
+               continue;
+
+             rtx body = PATTERN (table);
+             unsigned int len = XVECLEN (body, 0);
+             for (unsigned int i = 0; i < len; i++)
+               {
+                 rtx elt = XVECEXP (body, 0, i);
+                 sibcall_target
+                   = jump_table_label_to_basic_block (elt,
+                                                      table_sibcall_bbs);
+                 /* Fold the sibcall target by changing the jump table
+                    entry to the sibcall target. */
+                 if (sibcall_target)
+                   {
+                     XVECEXP (body, 0, i) = sibcall_target;
+                     table_sibcall = true;
+                   }
+               }
+           }
        }
     }
 
@@ -3440,6 +3486,26 @@ fold_sibcall (void)
        }
     }
 
+  if (table_sibcall)
+    {
+      bitmap_iterator bi;
+      unsigned id;
+      EXECUTE_IF_SET_IN_BITMAP (table_sibcall_bbs, 0, id, bi)
+       {
+         /* Check if this basic block should be kept for JUMP_LABEL of
+            the conditional tailcall.  */
+         if (jcc_sibcall_bbs && bitmap_bit_p (jcc_sibcall_bbs, id))
+           continue;
+         bb = BASIC_BLOCK_FOR_FN (cfun, id);
+         insn = BB_HEAD (bb);
+         gcc_assert (LABEL_P (insn));
+         /* Delete the basic block if its entry label is unused now.  */
+         if (LABEL_NUSES (insn) == 0)
+           delete_basic_block (bb);
+       }
+    }
+
+  BITMAP_FREE (table_sibcall_bbs);
   BITMAP_FREE (jcc_sibcall_bbs);
   bitmap_obstack_release (NULL);
 
diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
index a5353d39e7e..e80b2061453 100644
--- a/gcc/dwarf2cfi.cc
+++ b/gcc/dwarf2cfi.cc
@@ -2657,7 +2657,12 @@ 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);
+             /* Skip symbol reference.  */
+             if (SYMBOL_REF_P (l))
+               continue;
+             l = XEXP (l, 0);
+             rtx_insn *lab = as_a <rtx_insn *> (l);
              maybe_record_trace_start (lab, insn);
            }
 
diff --git a/gcc/final.cc b/gcc/final.cc
index 5fb44433fb8..602bfb09005 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -2528,13 +2528,31 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int 
optimize_p ATTRIBUTE_UNUSED,
              }
 #else
            vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
+           const char *asm_op = integer_asm_op (POINTER_SIZE_UNITS, true);
+           gcc_assert (asm_op != NULL);
            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))
+                     {
+                       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
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-1a.c 
b/gcc/testsuite/gcc.target/i386/pr14721-1a.c
new file mode 100644
index 00000000000..0ebd16554b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-1a.c
@@ -0,0 +1,54 @@
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    %edi, %edi
+**     jmp     \*.L4\(,%rdi,8\)
+**     .section        .rodata
+**...
+**.L4:
+**     .quad   bar0
+**     .quad   bar1
+**     .quad   bar2
+**     .quad   bar3
+**     .quad   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+extern void bar0 (void);
+extern void bar1 (void);
+extern void bar2 (void);
+extern void bar3 (void);
+extern void bar4 (void);
+
+void
+foo (int i)
+{
+  switch (i)
+    {
+    case 0: bar0 (); break;
+    case 1: bar1 (); break;
+    case 2: bar2 (); break;
+    case 3: bar3 (); break;
+    case 4: bar4 (); break;
+    }
+}
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar1" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar2" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-1b.c 
b/gcc/testsuite/gcc.target/i386/pr14721-1b.c
new file mode 100644
index 00000000000..d194a332221
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-1b.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     movl    4\(%esp\), %eax
+**     cmpl    \$4, %eax
+**     ja      .L1
+**     jmp     \*.L4\(,%eax,4\)
+**     .section        .rodata
+**...
+**.L4:
+**     .long   bar0
+**     .long   bar1
+**     .long   bar2
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-1a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar1" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar2" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-1c.c 
b/gcc/testsuite/gcc.target/i386/pr14721-1c.c
new file mode 100644
index 00000000000..1a9b137d5a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-1c.c
@@ -0,0 +1,37 @@
+/* { dg-do compile { target { *-*-linux* && maybe_x32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt -mx32" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    .L4\(,%edi,4\), %eax
+**     jmp     \*%rax
+**     .section        .rodata
+**...
+**.L4:
+**     .long   bar0
+**     .long   bar1
+**     .long   bar2
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-1a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar1" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar2" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-2a.c 
b/gcc/testsuite/gcc.target/i386/pr14721-2a.c
new file mode 100644
index 00000000000..a5a0d6c147a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-2a.c
@@ -0,0 +1,58 @@
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    %edi, %edi
+**     jmp     \*.L4\(,%rdi,8\)
+**     .section        .rodata
+**...
+**.L4:
+**     .quad   bar0
+**     .quad   .L7
+**     .quad   .L6
+**     .quad   bar3
+**     .quad   bar4
+**...
+**     .text
+**...
+**.L7:
+**     jmp     \*bar1\(%rip\)
+**...
+**.L6:
+**     jmp     \*bar2\(%rip\)
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+extern void bar0 (void);
+extern void (*bar1) (void);
+extern void (*bar2) (void);
+extern void bar3 (void);
+extern void bar4 (void);
+
+void
+foo (int i)
+{
+  switch (i)
+    {
+    case 0: bar0 (); break;
+    case 1: bar1 (); break;
+    case 2: bar2 (); break;
+    case 3: bar3 (); break;
+    case 4: bar4 (); break;
+    }
+}
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-2b.c 
b/gcc/testsuite/gcc.target/i386/pr14721-2b.c
new file mode 100644
index 00000000000..9edc23a063d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-2b.c
@@ -0,0 +1,41 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     movl    4\(%esp\), %eax
+**     cmpl    \$4, %eax
+**     ja      .L1
+**     jmp     \*.L4\(,%eax,4\)
+**     .section        .rodata
+**...
+**.L4:
+**     .long   bar0
+**     .long   .L7
+**     .long   .L6
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L7:
+**     jmp     \*bar1
+**...
+**.L6:
+**     jmp     \*bar2
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-2a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-2c.c 
b/gcc/testsuite/gcc.target/i386/pr14721-2c.c
new file mode 100644
index 00000000000..c0d8d7b23cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-2c.c
@@ -0,0 +1,43 @@
+/* { dg-do compile { target { *-*-linux* && maybe_x32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt -mx32" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    .L4\(,%edi,4\), %eax
+**     jmp     \*%rax
+**     .section        .rodata
+**...
+**.L4:
+**     .long   bar0
+**     .long   .L7
+**     .long   .L6
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L7:
+**     movl    bar1\(%rip\), %eax
+**     jmp     \*%rax
+**...
+**.L6:
+**     movl    bar2\(%rip\), %eax
+**     jmp     \*%rax
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-2a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-3a.c 
b/gcc/testsuite/gcc.target/i386/pr14721-3a.c
new file mode 100644
index 00000000000..78e073723eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-3a.c
@@ -0,0 +1,56 @@
+/* { dg-do compile { target { *-*-linux* && lp64 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     testl   %esi, %esi
+**     jne     bar0
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    %edi, %edi
+**     jmp     \*.L5\(,%rdi,8\)
+**     .section        .rodata
+**...
+**.L5:
+**     .quad   bar0
+**     .quad   bar1
+**     .quad   bar2
+**     .quad   bar3
+**     .quad   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+extern void bar0 (void);
+extern void bar1 (void);
+extern void bar2 (void);
+extern void bar3 (void);
+extern void bar4 (void);
+
+void
+foo (int i, int j)
+{
+  if (j)
+    {
+      bar0 ();
+      return;
+    }
+
+  switch (i)
+    {
+    case 0: bar0 (); break;
+    case 1: bar1 (); break;
+    case 2: bar2 (); break;
+    case 3: bar3 (); break;
+    case 4: bar4 (); break;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-3b.c 
b/gcc/testsuite/gcc.target/i386/pr14721-3b.c
new file mode 100644
index 00000000000..3870e963e4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-3b.c
@@ -0,0 +1,40 @@
+/* { dg-do compile { target { *-*-linux* && ia32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     movl    8\(%esp\), %edx
+**     movl    4\(%esp\), %eax
+**     testl   %edx, %edx
+**     jne     bar0
+**     cmpl    \$4, %eax
+**     ja      .L1
+**     jmp     \*.L5\(,%eax,4\)
+**     .section        .rodata
+**...
+**.L5:
+**     .long   bar0
+**     .long   bar1
+**     .long   bar2
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-3a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar1" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar2" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr14721-3c.c 
b/gcc/testsuite/gcc.target/i386/pr14721-3c.c
new file mode 100644
index 00000000000..fa763099bd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr14721-3c.c
@@ -0,0 +1,39 @@
+/* { dg-do compile { target { *-*-linux* && maybe_x32 } } } */
+/* { dg-options "-O2 -fno-pic -fplt -mx32" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
+/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.}  
} } */
+
+/*
+**foo:
+**.LFB0:
+**     .cfi_startproc
+**     testl   %esi, %esi
+**     jne     bar0
+**     cmpl    \$4, %edi
+**     ja      .L1
+**     movl    .L5\(,%edi,4\), %eax
+**     jmp     \*%rax
+**     .section        .rodata
+**...
+**.L5:
+**     .long   bar0
+**     .long   bar1
+**     .long   bar2
+**     .long   bar3
+**     .long   bar4
+**...
+**     .text
+**...
+**.L1:
+**     ret
+**     .cfi_endproc
+**...
+*/
+
+#include "pr14721-3a.c"
+
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar0" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar1" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar2" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar3" } } */
+/* { dg-final { scan-assembler-not "jmp\[\\t \]*bar4" } } */
-- 
2.48.1

Reply via email to