aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/gcc.target')
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr83370.c22
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c28
-rw-r--r--gcc/testsuite/gcc.target/arm/pr83687.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-pr84524.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/i386.exp12
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-1.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-10.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-3.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-4.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-5.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-6.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-7.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-8.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-9.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81481.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82795.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr83330.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84310-2.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84310.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84625.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-10.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-11.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-12.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-13.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-14.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-15.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-16.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-17.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-18.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-19.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-20.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-21.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-22.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-23.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-24.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-25.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-26.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-4.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-5.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-7.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-8.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-9.c21
-rw-r--r--gcc/testsuite/gcc.target/msp430/pr79242.c11
-rw-r--r--gcc/testsuite/gcc.target/nvptx/indirect_call.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3-p8.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3-p9.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-3.c3
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-7-p9-runnable.c169
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p8.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p9.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-1.c39
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-2.c30
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr81572.c13
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83399.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83629.c10
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr83862.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr84154-1.c55
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr84154-2.c58
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr84154-3.c60
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c53
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c26
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c56
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c81
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsxcopy.c4
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c59
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c56
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c42
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c42
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c40
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c49
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c46
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c48
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c44
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c44
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c41
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c78
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c78
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c77
-rw-r--r--gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c78
-rw-r--r--gcc/testsuite/gcc.target/s390/pr84295.c14
134 files changed, 3582 insertions, 119 deletions
diff --git a/gcc/testsuite/gcc.target/aarch64/pr83370.c b/gcc/testsuite/gcc.target/aarch64/pr83370.c
new file mode 100644
index 00000000000..001373c4d39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr83370.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef void (*fun) (void);
+
+void
+f (fun x1)
+{
+ register fun x2 asm ("x16");
+ int arr[5000];
+ int *volatile ptr = arr;
+ asm ("mov %0, %1" : "=r" (x2) : "r" (x1));
+ x2 ();
+}
+
+void g (void) {}
+
+int
+main (void)
+{
+ f (g);
+}
diff --git a/gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c b/gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c
index fe3d78b308c..784714f0e87 100644
--- a/gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c
+++ b/gcc/testsuite/gcc.target/arm/neon-combine-sub-abs-into-vabd.c
@@ -12,31 +12,3 @@ float32x2_t f_sub_abs_to_vabd_32(float32x2_t val1, float32x2_t val2)
return res;
}
/* { dg-final { scan-assembler "vabd\.f32" } }*/
-
-#include <arm_neon.h>
-int8x8_t sub_abs_to_vabd_8(int8x8_t val1, int8x8_t val2)
-{
- int8x8_t sres = vsub_s8(val1, val2);
- int8x8_t res = vabs_s8 (sres);
-
- return res;
-}
-/* { dg-final { scan-assembler "vabd\.s8" } }*/
-
-int16x4_t sub_abs_to_vabd_16(int16x4_t val1, int16x4_t val2)
-{
- int16x4_t sres = vsub_s16(val1, val2);
- int16x4_t res = vabs_s16 (sres);
-
- return res;
-}
-/* { dg-final { scan-assembler "vabd\.s16" } }*/
-
-int32x2_t sub_abs_to_vabd_32(int32x2_t val1, int32x2_t val2)
-{
- int32x2_t sres = vsub_s32(val1, val2);
- int32x2_t res = vabs_s32 (sres);
-
- return res;
-}
-/* { dg-final { scan-assembler "vabd\.s32" } }*/
diff --git a/gcc/testsuite/gcc.target/arm/pr83687.c b/gcc/testsuite/gcc.target/arm/pr83687.c
new file mode 100644
index 00000000000..42754138660
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr83687.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_neon } */
+
+#include <arm_neon.h>
+
+__attribute__ ((noinline)) int8_t
+testFunction1 (int8_t a, int8_t b)
+{
+ volatile int8x16_t sub = vsubq_s8 (vdupq_n_s8 (a), vdupq_n_s8 (b));
+ int8x16_t abs = vabsq_s8 (sub);
+ return vgetq_lane_s8 (abs, 0);
+}
+
+__attribute__ ((noinline)) int8_t
+testFunction2 (int8_t a, int8_t b)
+{
+ int8x16_t sub = vsubq_s8 (vdupq_n_s8 (a), vdupq_n_s8 (b));
+ int8x16_t abs = vabsq_s8 (sub);
+ return vgetq_lane_s8 (abs, 0);
+}
+
+int
+main (void)
+{
+ if (testFunction1 (-100, 100) != testFunction2 (-100, 100))
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-pr84524.c b/gcc/testsuite/gcc.target/i386/avx512bw-pr84524.c
new file mode 100644
index 00000000000..536e81e17db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-pr84524.c
@@ -0,0 +1,14 @@
+/* PR target/84524 */
+/* { dg-do run { target avx512bw } } */
+/* { dg-options "-O3 -mavx512bw" } */
+
+#include "avx512bw-check.h"
+
+#define main() do_main()
+#include "../../gcc.c-torture/execute/pr84524.c"
+
+static void
+avx512bw_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp
index eae253192ad..ec13306b1ed 100644
--- a/gcc/testsuite/gcc.target/i386/i386.exp
+++ b/gcc/testsuite/gcc.target/i386/i386.exp
@@ -241,18 +241,6 @@ proc check_effective_target_rtm { } {
} "-mrtm" ]
}
-# Return 1 if avx512f instructions can be compiled.
-proc check_effective_target_avx512f { } {
- return [check_no_compiler_messages avx512f object {
- typedef long long __v8di __attribute__ ((__vector_size__ (64)));
- __v8di
- mm512_and_epi64 (__v8di __X, __v8di __Y)
- {
- return __builtin_ia32_pandq512_mask (__X, __Y, __X, -1);
- }
- } "-mavx512f" ]
-}
-
# Return 1 if avx512vl instructions can be compiled.
proc check_effective_target_avx512vl { } {
return [check_no_compiler_messages avx512vl object {
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
new file mode 100644
index 00000000000..6e94d2c4865
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c
new file mode 100644
index 00000000000..a0674bd2363
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-10.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk-inline -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
new file mode 100644
index 00000000000..3c467078964
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
new file mode 100644
index 00000000000..2c7fb52b59d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
new file mode 100644
index 00000000000..0d3f895009d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
new file mode 100644
index 00000000000..fb26c005e80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
new file mode 100644
index 00000000000..aa03fbd8446
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 { target x32 } } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
new file mode 100644
index 00000000000..3c72036dbaf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c
new file mode 100644
index 00000000000..7a80a8986e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-8.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c
new file mode 100644
index 00000000000..d4d45c5114d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-9.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mfunction-return=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
new file mode 100644
index 00000000000..7106407b83d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+extern void male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk")));
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c
new file mode 100644
index 00000000000..3a2aeaddbc5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk-extern")))
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c
new file mode 100644
index 00000000000..8e52f032b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk-inline")))
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
new file mode 100644
index 00000000000..27c7e5b029b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk")))
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
new file mode 100644
index 00000000000..89a2bac8403
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+extern int male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk-inline")));
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
new file mode 100644
index 00000000000..3eb83c3779a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk-inline")))
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
new file mode 100644
index 00000000000..0098dd1133d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+extern int male_indirect_jump (long)
+ __attribute__ ((indirect_branch("thunk-extern")));
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
new file mode 100644
index 00000000000..ece8de15a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+__attribute__ ((indirect_branch("thunk-extern")))
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
new file mode 100644
index 00000000000..d53fc887dcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+__attribute__ ((indirect_branch("thunk-extern")))
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
new file mode 100644
index 00000000000..d730d31bda1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+__attribute__ ((indirect_branch("keep")))
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c
new file mode 100644
index 00000000000..bdaa4f6911b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mindirect-branch=keep -mfunction-return=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((indirect_branch("thunk")))
+void
+bar (void)
+{ /* { dg-error "'-mindirect-branch=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
new file mode 100644
index 00000000000..73d16baddc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { ! x32 } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+void (*dispatch) (char *);
+char buf[10];
+
+void
+foo (void)
+{
+ dispatch (buf);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_rax" { target lp64 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
new file mode 100644
index 00000000000..856751ac224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { ! x32 } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+void (*dispatch) (char *);
+char buf[10];
+
+int
+foo (void)
+{
+ dispatch (buf);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_(r|e)ax" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
new file mode 100644
index 00000000000..42312f65588
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+void
+foo (void)
+{
+ bar (buf);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd_rax" { target lp64 } } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
new file mode 100644
index 00000000000..c8ca102c8df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+void bar (char *);
+char buf[10];
+
+int
+foo (void)
+{
+ bar (buf);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" } } */
+/* { dg-final { scan-assembler "bnd call\[ \t\]*__x86_indirect_thunk_bnd_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 1 } } */
+/* { dg-final { scan-assembler "bnd ret" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
new file mode 100644
index 00000000000..c09dd0afd2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
new file mode 100644
index 00000000000..826425a5115
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
new file mode 100644
index 00000000000..385626850a2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
new file mode 100644
index 00000000000..1ae49b137ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
new file mode 100644
index 00000000000..53282390977
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
new file mode 100644
index 00000000000..8ae43482d0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
new file mode 100644
index 00000000000..2b9a33e93dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
new file mode 100644
index 00000000000..869d9040838
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
new file mode 100644
index 00000000000..c5c16ed8bd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
new file mode 100644
index 00000000000..4a63ebed8ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
new file mode 100644
index 00000000000..a395ffca018
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch[256];
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch[offset](offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
new file mode 100644
index 00000000000..21cbfd39582
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+void
+foo (void)
+{
+ bar ();
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
new file mode 100644
index 00000000000..d1300f18dc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+extern void bar (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" { target x32 } } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar@GOT" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
new file mode 100644
index 00000000000..ea009245a58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+void func0 (void);
+void func1 (void);
+void func2 (void);
+void func3 (void);
+void func4 (void);
+void func4 (void);
+void func5 (void);
+
+void
+bar (int i)
+{
+ switch (i)
+ {
+ default:
+ func0 ();
+ break;
+ case 1:
+ func1 ();
+ break;
+ case 2:
+ func2 ();
+ break;
+ case 3:
+ func3 ();
+ break;
+ case 4:
+ func4 ();
+ break;
+ case 5:
+ func5 ();
+ break;
+ }
+}
+
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
new file mode 100644
index 00000000000..7d396a31953
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk\n" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk_bnd\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
new file mode 100644
index 00000000000..e7e616bb271
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
new file mode 100644
index 00000000000..5320e923be2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-register -fno-pic" } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+void
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
+/* { dg-final { scan-assembler-not {\t(pause|pause|nop)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
new file mode 100644
index 00000000000..f0cd9b75be8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=keep -fno-pic" } */
+
+extern void (*func_p) (void);
+
+void
+foo (void)
+{
+ asm("call __x86_indirect_thunk_%V0" : : "a" (func_p));
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_rax" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81481.c b/gcc/testsuite/gcc.target/i386/pr81481.c
new file mode 100644
index 00000000000..a5b936fdacc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr81481.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ssse3 } */
+/* { dg-options "-O2 -fpic -mssse3" } */
+/* { dg-final { scan-assembler-not "pshufb\[ \t\]\\(%esp\\)" } } */
+#include <immintrin.h>
+
+extern const signed char c[31] __attribute__((visibility("hidden")));
+
+__m128i f(__m128i *x, void *v)
+{
+ int i;
+ asm("# %0" : "=r"(i));
+ __m128i t = _mm_loadu_si128((void*)&c[i]);
+ __m128i xx = *x;
+ xx = _mm_shuffle_epi8(xx, t);
+ asm("# %0 %1 %2" : "+x"(xx) : "r"(c), "r"(i));
+ return xx;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr82795.c b/gcc/testsuite/gcc.target/i386/pr82795.c
new file mode 100644
index 00000000000..9e7fec74699
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr82795.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx2" } */
+
+void
+sj (int qh, int rn, int *by)
+{
+ for (;;)
+ if (qh != 0)
+ {
+ int dc;
+
+ for (dc = 0; dc < 17; ++dc)
+ {
+ int nn;
+
+ nn = (rn != 0) ? qh : dc;
+ if (nn != 0)
+ qh = nn;
+ else
+ qh = (qh != 0) ? *by : dc;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr83330.c b/gcc/testsuite/gcc.target/i386/pr83330.c
new file mode 100644
index 00000000000..9040168377a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr83330.c
@@ -0,0 +1,29 @@
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2 -fno-tree-dce -mno-push-args" } */
+
+typedef unsigned long long u64;
+typedef unsigned __int128 u128;
+
+u64 v;
+u64 g;
+
+u64 __attribute__ ((noinline, noclone))
+bar (u128 d, u64 e, u64 f, u64 g, u128 h)
+{
+ (void)d, (void)e, (void)f, (void)g, (void)h;
+ return 0;
+}
+
+static u64
+foo (void)
+{
+ (void)(v - bar (0, 0, 0, 0, 0));
+ return g;
+}
+
+int
+main (void)
+{
+ (void)foo ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr84310-2.c b/gcc/testsuite/gcc.target/i386/pr84310-2.c
new file mode 100644
index 00000000000..dbf5db6ff87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr84310-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -malign-loops=16" } */
+/* { dg-warning "is obsolete" "" { target *-*-* } 0 } */
+
+void
+c (void)
+{
+ for (;;)
+ ;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr84310.c b/gcc/testsuite/gcc.target/i386/pr84310.c
new file mode 100644
index 00000000000..f82327e45f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr84310.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -falign-functions=100000" } */
+/* { dg-error "is not between 0 and 65536" "" { target *-*-* } 0 } */
+
+void
+test_func (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr84625.c b/gcc/testsuite/gcc.target/i386/pr84625.c
new file mode 100644
index 00000000000..600a6f15a9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr84625.c
@@ -0,0 +1,12 @@
+/* PR inline-asm/84625 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef int V __attribute__((vector_size (16)));
+
+void
+foo (void)
+{
+ asm volatile ("# %0" : : "X" ((V) { 1, 2, 3, 4 })); // { dg-error "invalid vector immediate" }
+ asm volatile ("# %0" : : "" ((V) { 2, 3, 4, 5 })); // { dg-error "invalid vector immediate" }
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
new file mode 100644
index 00000000000..7223f67ba5e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
new file mode 100644
index 00000000000..af9023af613
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
new file mode 100644
index 00000000000..ba467c59b36
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
new file mode 100644
index 00000000000..43e57cac2c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
new file mode 100644
index 00000000000..55f156c4376
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+extern void (*bar) (void);
+extern int foo (void) __attribute__ ((function_return("thunk")));
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 3 } } */
+/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 3 } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
new file mode 100644
index 00000000000..1c790436a53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("thunk-inline")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
new file mode 100644
index 00000000000..58aba319cba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("thunk-extern"), indirect_branch("thunk")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-times {\tpause} 1 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
new file mode 100644
index 00000000000..a16cad16aaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk-extern -fno-pic" } */
+
+extern void (*bar) (void);
+
+__attribute__ ((function_return("keep"), indirect_branch("keep")))
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-17.c b/gcc/testsuite/gcc.target/i386/ret-thunk-17.c
new file mode 100644
index 00000000000..0605e2c6542
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-17.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=keep -mcmodel=large" } */
+
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-18.c b/gcc/testsuite/gcc.target/i386/ret-thunk-18.c
new file mode 100644
index 00000000000..307019dc242
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-18.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-19.c b/gcc/testsuite/gcc.target/i386/ret-thunk-19.c
new file mode 100644
index 00000000000..772617f4010
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-19.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+
+__attribute__ ((function_return("thunk")))
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
new file mode 100644
index 00000000000..c6659e3ad09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-20.c b/gcc/testsuite/gcc.target/i386/ret-thunk-20.c
new file mode 100644
index 00000000000..1e9f9bd5a66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-20.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((function_return("thunk-extern")))
+void
+bar (void)
+{ /* { dg-error "'-mfunction-return=thunk-extern' and '-mcmodel=large' are not compatible" } */
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-21.c b/gcc/testsuite/gcc.target/i386/ret-thunk-21.c
new file mode 100644
index 00000000000..eea07f7abe1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-21.c
@@ -0,0 +1,9 @@
+/* { dg-do compile { target { lp64 } } } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -mcmodel=large" } */
+/* { dg-additional-options "-fPIC" { target fpic } } */
+
+__attribute__ ((function_return("thunk-inline")))
+void
+bar (void)
+{
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
new file mode 100644
index 00000000000..89e086de97b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
new file mode 100644
index 00000000000..43f0ccaa854
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {\tpause} } } */
+/* { dg-final { scan-assembler-not {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
new file mode 100644
index 00000000000..8729e35147e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-25.c b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
new file mode 100644
index 00000000000..f73553c9a9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
@@ -0,0 +1,15 @@
+/* PR target/r84530 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -mfunction-return=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+struct s { _Complex unsigned short x; };
+struct s gs = { 100 + 200i };
+struct s __attribute__((noinline)) foo (void) { return gs; }
+
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_bnd_ecx" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
new file mode 100644
index 00000000000..9144e988735
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
@@ -0,0 +1,40 @@
+/* PR target/r84530 */
+/* { dg-do run } */
+/* { dg-options "-Os -mfunction-return=thunk" } */
+
+struct S { int i; };
+__attribute__((const, noinline, noclone))
+struct S foo (int x)
+{
+ struct S s;
+ s.i = x;
+ return s;
+}
+
+int a[2048], b[2048], c[2048], d[2048];
+struct S e[2048];
+
+__attribute__((noinline, noclone)) void
+bar (void)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ {
+ e[i] = foo (i);
+ a[i+2] = a[i] + a[i+1];
+ b[10] = b[10] + i;
+ c[i] = c[2047 - i];
+ d[i] = d[i + 1];
+ }
+}
+
+int
+main ()
+{
+ int i;
+ bar ();
+ for (i = 0; i < 1024; i++)
+ if (e[i].i != i)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
new file mode 100644
index 00000000000..0f7f388f459
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
new file mode 100644
index 00000000000..9ae37e835a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
new file mode 100644
index 00000000000..4bd0d2a27bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+extern void foo (void) __attribute__ ((function_return("thunk")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
new file mode 100644
index 00000000000..053841f6f7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+__attribute__ ((function_return("thunk-inline")))
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {\tpause} } } */
+/* { dg-final { scan-assembler {\tlfence} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
new file mode 100644
index 00000000000..262e6780112
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=keep" } */
+
+__attribute__ ((function_return("thunk-extern")))
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
new file mode 100644
index 00000000000..c1658e96673
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
+
+extern void foo (void) __attribute__ ((function_return("keep")));
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
new file mode 100644
index 00000000000..d2df8b874e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "__x86_indirect_thunk:" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/msp430/pr79242.c b/gcc/testsuite/gcc.target/msp430/pr79242.c
new file mode 100644
index 00000000000..d7ff8d38a3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/pr79242.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { "*-*-*" } { "-mcpu=msp430" "-msmall" } { "" } } */
+/* { dg-options "-mcpu=msp430x" } */
+
+typedef _Complex __int20 C;
+
+C
+foo (C x, C y)
+{
+ return x + y;
+}
diff --git a/gcc/testsuite/gcc.target/nvptx/indirect_call.c b/gcc/testsuite/gcc.target/nvptx/indirect_call.c
new file mode 100644
index 00000000000..39992a7137b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/indirect_call.c
@@ -0,0 +1,19 @@
+/* { dg-options "-O2 -msoft-stack" } */
+/* { dg-do run } */
+
+int
+f1 (int a)
+{
+ return a + 1;
+}
+
+int (*f2)(int) = f1;
+
+int
+main ()
+{
+ if (f2 (100) != 101)
+ __builtin_abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3-p8.c b/gcc/testsuite/gcc.target/powerpc/builtins-3-p8.c
index 90e573d2654..92b8f9a9154 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-3-p8.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3-p8.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-options "-mcpu=power8" } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3-p9.c b/gcc/testsuite/gcc.target/powerpc/builtins-3-p9.c
index e3db2da655c..25a94bca612 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-3-p9.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3-p9.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-options "-mcpu=power9" } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-3.c b/gcc/testsuite/gcc.target/powerpc/builtins-3.c
index bddd0ac91cc..01aa862aaa8 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-3.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-maltivec -mvsx" } */
+/* { dg-options "-O2 -mvsx -mcpu=power6" } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-7-p9-runnable.c b/gcc/testsuite/gcc.target/powerpc/builtins-7-p9-runnable.c
new file mode 100644
index 00000000000..137b46b052a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-7-p9-runnable.c
@@ -0,0 +1,169 @@
+/* { dg-do run { target { powerpc*-*-* && p9vector_hw } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+#include <altivec.h>
+#define TRUE 1
+#define FALSE 0
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#define EXTRACT 0
+
+void abort (void);
+
+int result_wrong_ull (vector unsigned long long vec_expected,
+ vector unsigned long long vec_actual)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ if (vec_expected[i] != vec_actual[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+int result_wrong_uc (vector unsigned char vec_expected,
+ vector unsigned char vec_actual)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ if (vec_expected[i] != vec_actual[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+#ifdef DEBUG
+void print_ull (vector unsigned long long vec_expected,
+ vector unsigned long long vec_actual)
+{
+ int i;
+
+ printf("expected unsigned long long data\n");
+ for (i = 0; i < 2; i++)
+ printf(" %lld,", vec_expected[i]);
+
+ printf("\nactual signed char data\n");
+ for (i = 0; i < 2; i++)
+ printf(" %lld,", vec_actual[i]);
+ printf("\n");
+}
+
+void print_uc (vector unsigned char vec_expected,
+ vector unsigned char vec_actual)
+{
+ int i;
+
+ printf("expected unsigned char data\n");
+ for (i = 0; i < 16; i++)
+ printf(" %d,", vec_expected[i]);
+
+ printf("\nactual unsigned char data\n");
+ for (i = 0; i < 16; i++)
+ printf(" %d,", vec_actual[i]);
+ printf("\n");
+}
+#endif
+
+#if EXTRACT
+vector unsigned long long
+vext (vector unsigned char *vc)
+{
+ return vextract_si_vchar (*vc, 5);
+}
+#endif
+
+int main()
+{
+ vector signed int vsi_arg;
+ vector unsigned char vec_uc_arg, vec_uc_result, vec_uc_expected;
+ vector unsigned long long vec_ull_result, vec_ull_expected;
+ unsigned long long ull_result, ull_expected;
+
+ vec_uc_arg = (vector unsigned char){1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+
+ vsi_arg = (vector signed int){0xA, 0xB, 0xC, 0xD};
+
+ vec_uc_expected = (vector unsigned char){0xC, 0, 0, 0,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+ /* Test vec_insert4b() */
+ /* Insert into char 0 location */
+ vec_uc_result = vec_insert4b (vsi_arg, vec_uc_arg, 0);
+
+ if (result_wrong_uc(vec_uc_expected, vec_uc_result))
+ {
+#ifdef DEBUG
+ printf("Error: vec_insert4b pos 0, result does not match expected result\n");
+ print_uc (vec_uc_expected, vec_uc_result);
+#else
+ abort();
+#endif
+ }
+
+ /* insert into char 4 location */
+ vec_uc_expected = (vector unsigned char){1, 2, 3, 4,
+ 0xC, 0, 0, 0,
+ 9, 10, 11, 12,
+ 13, 14, 15, 16};
+ vec_uc_result = vec_insert4b (vsi_arg, vec_uc_arg, 4);
+
+ if (result_wrong_uc(vec_uc_expected, vec_uc_result))
+ {
+#ifdef DEBUG
+ printf("Error: vec_insert4b pos 4, result does not match expected result\n");
+ print_uc (vec_uc_expected, vec_uc_result);
+#else
+ abort();
+#endif
+ }
+
+ /* Test vec_extract4b() */
+ /* Extract 4b, from char 0 location */
+ vec_uc_arg = (vector unsigned char){10, 0, 0, 0,
+ 20, 0, 0, 0,
+ 30, 0, 0, 0,
+ 40, 0, 0, 0};
+
+ vec_ull_expected = (vector unsigned long long){0, 10};
+ vec_ull_result = vec_extract4b(vec_uc_arg, 0);
+
+ if (result_wrong_ull(vec_ull_expected, vec_ull_result))
+ {
+#ifdef DEBUG
+ printf("Error: vec_extract4b pos 0, result does not match expected result\n");
+ print_ull (vec_ull_expected, vec_ull_result);
+#else
+ abort();
+#endif
+ }
+
+ /* Extract 4b, from char 12 location */
+ vec_uc_arg = (vector unsigned char){10, 0, 0, 0,
+ 20, 0, 0, 0,
+ 30, 0, 0, 0,
+ 40, 0, 0, 0};
+
+ vec_ull_expected = (vector unsigned long long){0, 40};
+ vec_ull_result = vec_extract4b(vec_uc_arg, 12);
+
+ if (result_wrong_ull(vec_ull_expected, vec_ull_result))
+ {
+#ifdef DEBUG
+ printf("Error: vec_extract4b pos 12, result does not match expected result\n");
+ print_ull (vec_ull_expected, vec_ull_result);
+#else
+ abort();
+#endif
+ }
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p8.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p8.c
index a133c5d90fe..b1cf0a78628 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p8.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p8.c
@@ -4,7 +4,9 @@
/* { dg-do compile } */
/* { dg-require-effective-target powerpc_p8vector_ok } */
/* { dg-require-effective-target int128 } */
-/* { dg-options "-maltivec -mvsx -mpower8-vector" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mpower8-vector -mcpu=power8 -O2" } */
/* { dg-additional-options "-maix64" { target powerpc-ibm-aix* } } */
#include "altivec.h"
@@ -21,5 +23,5 @@ test2 (vector unsigned __int128 x, vector unsigned __int128 y)
return vec_mul (x, y);
}
-/* { dg-final { scan-assembler-times "\[ \t\]mulld " 6 } } */
-/* { dg-final { scan-assembler-times "\[ \t\]mulhdu" 2 } } */
+/* { dg-final { scan-assembler-times {\mmulld\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mmulhdu\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p9.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p9.c
index 96c9d019682..657188435d4 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p9.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-mult-int128-p9.c
@@ -2,10 +2,10 @@
inputs produce the right results. */
/* { dg-do compile } */
-/* { dg-require-effective-target powerpc_float128_hw_ok } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-require-effective-target int128 } */
/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-maltivec -mvsx -mcpu=power9 -O2" } */
+/* { dg-options "-mpower9-vector -mcpu=power9 -O2" } */
/* { dg-additional-options "-maix64" { target powerpc-ibm-aix* } } */
#include "altivec.h"
@@ -22,4 +22,5 @@ test2 (vector unsigned __int128 x, vector unsigned __int128 y)
return vec_mul (x, y);
}
-/* { dg-final { scan-assembler-times "\[ \t\]xsmulqp" 2 } } */
+/* { dg-final { scan-assembler-times {\mmulld\M} 4 } } */
+/* { dg-final { scan-assembler-times {\mmulhdu\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c b/gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c
index 71dd0a24ae1..6a7baf31b43 100644
--- a/gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c
+++ b/gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c
@@ -6,7 +6,7 @@
/* { dg-options "-O0 -Wno-deprecated" } */
/* { dg-final { scan-assembler-times "lvsl" 2 } } */
/* { dg-final { scan-assembler-times "lvsr" 2 } } */
-/* { dg-final { scan-assembler-times "lxvd2x" 2 } } */
+/* { dg-final { scan-assembler-times {\mlxvd2x\M|\mlxv\M} 2 } } */
/* { dg-final { scan-assembler-times "vperm" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-1.c b/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-1.c
deleted file mode 100644
index fa1ba754705..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-1.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2" } */
-
-#include <altivec.h>
-
-vector signed char
-vins_v4si (vector int *vi, vector signed char *vc)
-{
- return vec_vinsert4b (*vi, *vc, 1);
-}
-
-vector unsigned char
-vins_di (long di, vector unsigned char *vc)
-{
- return vec_vinsert4b (di, *vc, 2);
-}
-
-vector char
-vins_di2 (long *p_di, vector char *vc)
-{
- return vec_vinsert4b (*p_di, *vc, 3);
-}
-
-vector unsigned char
-vins_di0 (vector unsigned char *vc)
-{
- return vec_vinsert4b (0, *vc, 4);
-}
-
-long
-vext (vector signed char *vc)
-{
- return vec_vextract4b (*vc, 5);
-}
-
-/* { dg-final { scan-assembler "xxextractuw\|vextuw\[lr\]x" } } */
-/* { dg-final { scan-assembler "xxinsertw" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-2.c b/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-2.c
deleted file mode 100644
index 3b5872ebec6..00000000000
--- a/gcc/testsuite/gcc.target/powerpc/p9-vinsert4b-2.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-require-effective-target powerpc_p9vector_ok } */
-/* { dg-options "-mcpu=power9 -O2" } */
-
-#include <altivec.h>
-
-vector signed char
-ins_v4si (vector int vi, vector signed char vc)
-{
- return vec_vinsert4b (vi, vc, 13); /* { dg-error "vec_vinsert4b" } */
-}
-
-vector unsigned char
-ins_di (long di, vector unsigned char vc, long n)
-{
- return vec_vinsert4b (di, vc, n); /* { dg-error "vec_vinsert4b" } */
-}
-
-long
-vext1 (vector signed char vc)
-{
- return vec_vextract4b (vc, 13); /* { dg-error "vec_vextract4b" } */
-}
-
-long
-vextn (vector unsigned char vc, long n)
-{
- return vec_vextract4b (vc, n); /* { dg-error "vec_vextract4b" } */
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr81572.c b/gcc/testsuite/gcc.target/powerpc/pr81572.c
new file mode 100644
index 00000000000..de00c187d62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr81572.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target powerpc64*-*-* } } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler-not "xxlor" } } */
+
+#include <altivec.h>
+
+typedef __vector unsigned char nvec_t;
+
+long testz_and(nvec_t a, nvec_t b)
+{
+ nvec_t c = vec_andc(a, b);
+ return vec_all_eq(a, c);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83399.c b/gcc/testsuite/gcc.target/powerpc/pr83399.c
new file mode 100644
index 00000000000..96d9b382184
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83399.c
@@ -0,0 +1,15 @@
+/* PR target/83399 */
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O1 -mabi=elfv2 -mlittle -mvsx" } */
+
+typedef __attribute__((altivec(vector__))) int v4si_t;
+int
+foo (void)
+{
+ v4si_t a, u, v, y;
+ u = __builtin_altivec_lvx (32, ((void *) &a) - 32);
+ v = __builtin_altivec_lvx (64, ((void *) &a) - 32);
+ y = u + v;
+ return y[0];
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83629.c b/gcc/testsuite/gcc.target/powerpc/pr83629.c
new file mode 100644
index 00000000000..ae00e145952
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83629.c
@@ -0,0 +1,10 @@
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -fPIC -frename-registers --param=sched-autopref-queue-depth=0 -mcpu=603" } */
+
+extern void bar (void *);
+
+void
+foo (void)
+{
+ bar ("");
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr83862.c b/gcc/testsuite/gcc.target/powerpc/pr83862.c
new file mode 100644
index 00000000000..ac97e6aa5b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr83862.c
@@ -0,0 +1,34 @@
+/* PR target/83862.c */
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mpower9-vector -O2 -mfloat128" } */
+
+/* On little endian systems, optimizing signbit of IEEE 128-bit values from
+ memory could abort if the memory address was indexed (reg+reg). The
+ optimization is only on 64-bit machines with direct move.
+
+ Compile with -g -O2 -mabi=ieeelongdouble -Wno-psabi. */
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+int sbr (TYPE a) { return __builtin_signbit (a); }
+int sbm (TYPE *a) { return __builtin_signbit (*a); }
+int sbo (TYPE *a) { return __builtin_signbit (a[4]); }
+int sbi (TYPE *a, unsigned long n) { return __builtin_signbit (a[n]); }
+void sbs (int *p, TYPE a) { *p = __builtin_signbit (a); }
+
+/* On big endian systems, this will generate 2 LDs and 1 LDX, while on
+ little endian systems, this will generate 3 LDs and an ADD. */
+
+/* { dg-final { scan-assembler-times {\mldx?\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mmfvsrd\M} 2 } } */
+/* { dg-final { scan-assembler-times {\msrdi\M} 5 } } */
+/* { dg-final { scan-assembler-not {\mmfvsrld\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvx?\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvw4x\M} } } */
+/* { dg-final { scan-assembler-not {\mstxvd2x\M} } } */
+/* { dg-final { scan-assembler-not {\mstvx\M} } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr84154-1.c b/gcc/testsuite/gcc.target/powerpc/pr84154-1.c
new file mode 100644
index 00000000000..c7c61be0def
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr84154-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mpower8-vector -O2" } */
+
+/* PR target/84154. Make sure conversion to char/short does not generate a
+ store and a load on ISA 2.07 and newer systems. */
+
+unsigned char
+double_to_uc (double x)
+{
+ return x;
+}
+
+signed char
+double_to_sc (double x)
+{
+ return x;
+}
+
+unsigned short
+double_to_us (double x)
+{
+ return x;
+}
+
+short
+double_to_ss (double x)
+{
+ return x;
+}
+
+unsigned int
+double_to_ui (double x)
+{
+ return x;
+}
+
+int
+double_to_si (double x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times {\mextsb\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mextsh\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mfctiwuz\M|\mxscvdpuxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mfctiwz\M|\mxscvdpsxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mmfvsrwz\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mrlwinm\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlbz\M} } } */
+/* { dg-final { scan-assembler-not {\mlhz\M} } } */
+/* { dg-final { scan-assembler-not {\mlha\M} } } */
+/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr84154-2.c b/gcc/testsuite/gcc.target/powerpc/pr84154-2.c
new file mode 100644
index 00000000000..619777ce8dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr84154-2.c
@@ -0,0 +1,58 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2" } */
+
+/* PR target/84154. Make sure on ISA 2.07 (power8) that we store the result of
+ a conversion to char/short using an offsettable address does not generate
+ direct moves for storing 32-bit integers, but does do a direct move for
+ 8/16-bit integers. */
+
+void
+double_to_uc (double x, unsigned char *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_sc (double x, signed char *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_us (double x, unsigned short *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_ss (double x, short *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_ui (double x, unsigned int *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_si (double x, int *p)
+{
+ p[3] = x;
+}
+
+/* { dg-final { scan-assembler-times {\mfctiwuz\M|\mxscvdpuxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mfctiwz\M|\mxscvdpsxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mmfvsrwz\M} 4 } } */
+/* { dg-final { scan-assembler-times {\mstfiwx\M|\mstxsiwx\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstb\M} 2 } } */
+/* { dg-final { scan-assembler-times {\msth\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlbz\M} } } */
+/* { dg-final { scan-assembler-not {\mlhz\M} } } */
+/* { dg-final { scan-assembler-not {\mlha\M} } } */
+/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr84154-3.c b/gcc/testsuite/gcc.target/powerpc/pr84154-3.c
new file mode 100644
index 00000000000..0361e2f1b51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr84154-3.c
@@ -0,0 +1,60 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+/* PR target/84154. Make sure on ISA 3.0 we store the result of a conversion
+ to char/short using an offsettable address does not generate direct moves
+ for storing 8/16/32-bit integers. */
+
+void
+double_to_uc (double x, unsigned char *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_sc (double x, signed char *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_us (double x, unsigned short *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_ss (double x, short *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_ui (double x, unsigned int *p)
+{
+ p[3] = x;
+}
+
+void
+double_to_si (double x, int *p)
+{
+ p[3] = x;
+}
+
+/* { dg-final { scan-assembler-times {\maddi\M} 6 } } */
+/* { dg-final { scan-assembler-times {\mfctiwuz\M|\mxscvdpuxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mfctiwz\M|\mxscvdpsxws\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mstfiwx\M|\mstxsiwx\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstxsibx\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstxsihx\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlbz\M} } } */
+/* { dg-final { scan-assembler-not {\mlhz\M} } } */
+/* { dg-final { scan-assembler-not {\mlha\M} } } */
+/* { dg-final { scan-assembler-not {\mmfvsrwz\M} } } */
+/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mstw\M} } } */
+/* { dg-final { scan-assembler-not {\mstb\M} } } */
+/* { dg-final { scan-assembler-not {\msth\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
new file mode 100644
index 00000000000..16ccfe471f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of indirect calls. */
+
+extern int (*f)();
+
+int bar ()
+{
+ return (*f) ();
+}
+
+/* { dg-final { scan-assembler "crset 2" } } */
+
+/* The AIX and ELFv2 ABIs don't allow a sibcall here. */
+/* { dg-final { scan-assembler "beqctrl-" { target { lp64 || { powerpc*-*-aix* } } } } } */
+
+/* The other ABIs do allow a sibcall. */
+/* { dg-final { scan-assembler "beqctr-" { target { ilp32 && !powerpc*-*-aix* } } } } */
+/* { dg-final { scan-assembler {b \$} { target { ilp32 && !powerpc*-*-aix* } } } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c
new file mode 100644
index 00000000000..d3d040fbbf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-2.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of computed goto. */
+
+int bar (int);
+int baz (int);
+int spaz (int);
+
+int foo (int x)
+{
+ static void *labptr[] = { &&lab0, &&lab1, &&lab2 };
+
+ if (x < 0 || x > 2)
+ return -1;
+
+ goto *labptr[x];
+
+ lab0:
+ return bar (x);
+
+ lab1:
+ return baz (x) + 1;
+
+ lab2:
+ return spaz (x) / 2;
+}
+
+/* The following assumes CR7 as the first chosen volatile. */
+
+/* { dg-final { scan-assembler "crset 30" } } */
+/* { dg-final { scan-assembler "beqctr- 7" } } */
+/* { dg-final { scan-assembler {b \$} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c
new file mode 100644
index 00000000000..c338e30d01a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-3.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of jump tables. */
+
+void bar (void);
+
+int foo (int x)
+{
+ int a;
+
+ switch (x)
+ {
+ default:
+ a = -1;
+ break;
+ case 0:
+ a = x * x;
+ break;
+ case 1:
+ a = x + 1;
+ break;
+ case 2:
+ a = x + x;
+ break;
+ case 3:
+ a = x << 3;
+ break;
+ case 4:
+ a = x >> 1;
+ break;
+ case 5:
+ a = x;
+ break;
+ case 6:
+ a = 0;
+ break;
+ case 7:
+ a = x * x + x;
+ break;
+ }
+
+ bar();
+
+ return a;
+}
+
+/* The following assumes CR7 as the first chosen volatile. */
+
+/* { dg-final { scan-assembler "crset 30" } } */
+/* { dg-final { scan-assembler "beqctr- 7" } } */
+/* { dg-final { scan-assembler {b \$} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c
new file mode 100644
index 00000000000..b55de13af93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-4.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of indirect calls for ELFv2. */
+
+int (*f)();
+
+int __attribute__((noinline)) bar ()
+{
+ return (*f) ();
+}
+
+int g ()
+{
+ return 26;
+}
+
+int main ()
+{
+ f = &g;
+ if (bar () != 26)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c
new file mode 100644
index 00000000000..fd04ffd56c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-5.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps -Wno-pedantic" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of computed goto. */
+
+int __attribute__((noinline)) bar (int i)
+{
+ return 1960 + i;
+}
+
+int __attribute__((noinline)) baz (int i)
+{
+ return i * i;
+}
+
+int __attribute__((noinline)) spaz (int i)
+{
+ return i + 1;
+}
+
+int foo (int x)
+{
+ static void *labptr[] = { &&lab0, &&lab1, &&lab2 };
+
+ if (x < 0 || x > 2)
+ return -1;
+
+ goto *labptr[x];
+
+ lab0:
+ return bar (x);
+
+ lab1:
+ return baz (x) + 1;
+
+ lab2:
+ return spaz (x) / 2;
+}
+
+int main ()
+{
+ if (foo (0) != 1960)
+ __builtin_abort ();
+
+ if (foo (1) != 2)
+ __builtin_abort ();
+
+ if (foo (2) != 1)
+ __builtin_abort ();
+
+ if (foo (3) != -1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c
new file mode 100644
index 00000000000..1468a4ee20d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-6.c
@@ -0,0 +1,81 @@
+/* { dg-do run } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of jump tables. */
+
+void __attribute__((noinline)) bar ()
+{
+}
+
+int foo (int x)
+{
+ int a;
+
+ switch (x)
+ {
+ default:
+ a = -1;
+ break;
+ case 0:
+ a = x * x + 3;
+ break;
+ case 1:
+ a = x + 1;
+ break;
+ case 2:
+ a = x + x;
+ break;
+ case 3:
+ a = x << 3;
+ break;
+ case 4:
+ a = x >> 1;
+ break;
+ case 5:
+ a = x;
+ break;
+ case 6:
+ a = 0;
+ break;
+ case 7:
+ a = x * x + x;
+ break;
+ }
+
+ bar();
+
+ return a;
+}
+
+int main ()
+{
+ if (foo (0) != 3)
+ __builtin_abort ();
+
+ if (foo (1) != 2)
+ __builtin_abort ();
+
+ if (foo (2) != 4)
+ __builtin_abort ();
+
+ if (foo (3) != 24)
+ __builtin_abort ();
+
+ if (foo (4) != 2)
+ __builtin_abort ();
+
+ if (foo (5) != 5)
+ __builtin_abort ();
+
+ if (foo (6) != 0)
+ __builtin_abort ();
+
+ if (foo (7) != 56)
+ __builtin_abort ();
+
+ if (foo (8) != -1)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
new file mode 100644
index 00000000000..e7d81d40ff0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
+/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
+
+/* Test for deliberate misprediction of indirect calls. */
+
+extern int (*f)();
+
+int bar ()
+{
+ return (*f) () * 53;
+}
+
+/* { dg-final { scan-assembler "crset 2" } } */
+/* { dg-final { scan-assembler "beqctrl-" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c
new file mode 100644
index 00000000000..23494b695a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/swaps-p8-46.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target { powerpc64le-*-* } } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2 " } */
+
+typedef __attribute__ ((__aligned__ (8))) unsigned long long __m64;
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+/* PR84033. Extracted from xmmintrin.h but with a pointer param to
+ allow swaps to happen when not inline. */
+int __attribute__ ((__noinline__))
+_mm_movemask_ps (__m128 *__A)
+{
+ __vector __m64 result;
+ static const __vector unsigned int perm_mask =
+ {
+ 0x00204060, 0x80808080, 0x80808080, 0x80808080
+ };
+
+ result = (__vector __m64)
+ __builtin_vec_vbpermq ((__vector unsigned char) (*__A),
+ (__vector unsigned char) perm_mask);
+ return result[1];
+}
+
+int
+main (void)
+{
+ union { unsigned int i[4]; __m128 m; } x
+ = { 0x80000000, 0x80000000, 0x7fffffff, 0x7fffffff };
+ if (_mm_movemask_ps (&x.m) != 3)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
index fbe3c67e7e5..2060046eaf2 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsxcopy.c
@@ -1,8 +1,8 @@
/* { dg-do compile { target { powerpc64*-*-* } } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O1 -mvsx" } */
-/* { dg-final { scan-assembler "lxvd2x" } } */
-/* { dg-final { scan-assembler "stxvd2x" } } */
+/* { dg-final { scan-assembler {\mlxvd2x\M|\mlxv\M} } } */
+/* { dg-final { scan-assembler {\mstxvd2x\M|\mstxv\M} } } */
/* { dg-final { scan-assembler-not "xxpermdi" } } */
typedef float vecf __attribute__ ((vector_size (16)));
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c
new file mode 100644
index 00000000000..db9336d51dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-attr.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int __attribute__((indirect_branch_call("thunk")))
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c
new file mode 100644
index 00000000000..c02b45a2cc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-nothunk.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-call=thunk-extern -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c
new file mode 100644
index 00000000000..b5f13eb0793
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z10.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-call=thunk -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c
new file mode 100644
index 00000000000..486495b97ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-function-pointer-z900.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-call=thunk -mindirect-branch-table" } */
+
+int gl;
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ gl = a + 40;
+}
+
+int __attribute__((noinline,noclone))
+foo_value (int a)
+{
+ return a + 40;
+}
+
+void* __attribute__((noinline,noclone))
+get_fptr (int a)
+{
+ switch (a)
+ {
+ case 0: return &foo; break;
+ case 1: return &foo_value; break;
+ default: __builtin_abort ();
+ }
+}
+
+void (*f) (int);
+int (*g) (int);
+
+int
+main ()
+{
+ int res;
+
+ f = get_fptr(0);
+ f (2);
+ if (gl != 42)
+ __builtin_abort ();
+
+ g = get_fptr(1);
+ if (g (2) != 42)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 2 x main
+/* { dg-final { scan-assembler-times "brasl\t%r\[0-9\]*,__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c
new file mode 100644
index 00000000000..c62ddf56b8a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-attr.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void __attribute__((indirect_branch_jump("thunk")))
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int main() {
+ bar(code);
+ return 0;
+}
+
+/* 2x bar */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c
new file mode 100644
index 00000000000..63d64c15941
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-attr.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void __attribute__((indirect_branch_jump("thunk-inline")))
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c
new file mode 100644
index 00000000000..28d7837e2a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z10.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c
new file mode 100644
index 00000000000..3c0c0072539
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-inline-z900.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* The two gotos in bar get merged. */
+/* { dg-final { scan-assembler-times "\tex\t" 1 } } */
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c
new file mode 100644
index 00000000000..05c8bb8c12d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-nothunk.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk-extern -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c
new file mode 100644
index 00000000000..71c86fdfebc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z10.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2x bar */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c
new file mode 100644
index 00000000000..89ad799c7a6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-indirect-jump-z900.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* { dg-require-effective-target label_values } */
+
+/* This is a copy of the gcc.c-torture/execute/20040302-1.c
+ testcase. */
+
+int code[]={0,0,0,0,1};
+
+void
+foo(int x) {
+ volatile int b;
+ b = 0xffffffff;
+}
+
+void
+bar(int *pc) {
+ static const void *l[] = {&&lab0, &&end};
+
+ foo(0);
+ goto *l[*pc];
+ lab0:
+ foo(0);
+ pc++;
+ goto *l[*pc];
+ end:
+ return;
+}
+
+int
+main() {
+ bar(code);
+ return 0;
+}
+
+/* 2 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c b/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c
new file mode 100644
index 00000000000..4bf88cf78c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-attr-all.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return("thunk"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c b/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c
new file mode 100644
index 00000000000..8b32bfe5172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-attr-neg.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return("keep"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int __attribute__((function_return("keep")))
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "jg\t__s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c
new file mode 100644
index 00000000000..39cab8bd89e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-attr.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((function_return_mem("thunk"),noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c
new file mode 100644
index 00000000000..f99f152305c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-nothunk.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk-extern -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 3 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c
new file mode 100644
index 00000000000..177fc32c24b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z10.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* With -march=z10 -mzarch the shrink wrapped returns use compare and
+ swap relative to jump to the exit block instead of making use of
+ the conditional return pattern.
+ FIXME: Use compare and branch register for that!!!! */
+
+/* 2 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 3 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c
new file mode 100644
index 00000000000..0b318115a8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-mem-z900.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-mem=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x foo, 1 x main
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+
+/* 1 x foo, conditional return, shrink wrapped
+/* { dg-final { scan-assembler "jge\t__s390_indirect_jump" } } */
+
+/* 1 x foo, conditional return, shrink wrapped
+/* { dg-final { scan-assembler "jgle\t__s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c
new file mode 100644
index 00000000000..ebfc9ff0ebb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-attr.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((function_return_reg("thunk"),noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c
new file mode 100644
index 00000000000..82833f7e0d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-mixed.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+/* We have to generate different thunks for indirect branches
+ depending on whether the code is compiled for pre z10 machines or
+ later. This testcase makes sure this works within the same compile
+ unit. */
+
+int __attribute__((noinline,noclone,target("arch=z10")))
+bar (int a)
+{
+ return a + 2;
+}
+
+int __attribute__((noinline,noclone,target("arch=z9-ec")))
+foo (int a)
+{
+ return a + 3;
+}
+
+int
+main ()
+{
+ if (bar (42) != 44)
+ __builtin_abort ();
+
+ if (foo (42) != 45)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar, 1 x foo */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 2 } } */
+/* 1 x foo */
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump_r1use" 1 } } */
+
+/* { dg-final { scan-assembler-times "ex\t" 1 } } */
+/* { dg-final { scan-assembler-times "exrl\t" 1 } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c
new file mode 100644
index 00000000000..4ea14e379f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-nothunk.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10 --save-temps -mfunction-return-reg=thunk-extern -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+
+/* No thunks due to thunk-extern. */
+/* { dg-final { scan-assembler-not "exrl" } } */
+/* { dg-final { scan-assembler-not ".globl __s390_indirect_jump" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c
new file mode 100644
index 00000000000..42c3e7435fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z10.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "exrl" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c
new file mode 100644
index 00000000000..3f4efa57e71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-return-reg-z900.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+int gl = 0;
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ return a + 2;
+}
+
+void __attribute__((noinline,noclone))
+foo (int a)
+{
+ int i;
+
+ if (a == 42)
+ return;
+
+ for (i = 0; i < a; i++)
+ gl += bar (i);
+}
+
+int
+main ()
+{
+ foo (3);
+ if (gl != 9)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c
new file mode 100644
index 00000000000..8dfd7e4c786
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z10.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c
new file mode 100644
index 00000000000..46d2c54bcff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-inline-z900.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 -mzarch --save-temps -mindirect-branch-jump=thunk-inline -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "\tex\t" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c
new file mode 100644
index 00000000000..9dfe391f337
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z10.c
@@ -0,0 +1,77 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z10 -mzarch --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "exrl" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c
new file mode 100644
index 00000000000..f1439a8b120
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nobp-table-jump-z900.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -march=z900 -mzarch --save-temps -mindirect-branch-jump=thunk -mindirect-branch-table" } */
+
+/* case-values-threshold will be set to 20 by the back-end when jump
+ thunk are requested. */
+
+int __attribute__((noinline,noclone)) foo1 (void) { return 1; }
+int __attribute__((noinline,noclone)) foo2 (void) { return 2; }
+int __attribute__((noinline,noclone)) foo3 (void) { return 3; }
+int __attribute__((noinline,noclone)) foo4 (void) { return 4; }
+int __attribute__((noinline,noclone)) foo5 (void) { return 5; }
+int __attribute__((noinline,noclone)) foo6 (void) { return 6; }
+int __attribute__((noinline,noclone)) foo7 (void) { return 7; }
+int __attribute__((noinline,noclone)) foo8 (void) { return 8; }
+int __attribute__((noinline,noclone)) foo9 (void) { return 9; }
+int __attribute__((noinline,noclone)) foo10 (void) { return 10; }
+int __attribute__((noinline,noclone)) foo11 (void) { return 11; }
+int __attribute__((noinline,noclone)) foo12 (void) { return 12; }
+int __attribute__((noinline,noclone)) foo13 (void) { return 13; }
+int __attribute__((noinline,noclone)) foo14 (void) { return 14; }
+int __attribute__((noinline,noclone)) foo15 (void) { return 15; }
+int __attribute__((noinline,noclone)) foo16 (void) { return 16; }
+int __attribute__((noinline,noclone)) foo17 (void) { return 17; }
+int __attribute__((noinline,noclone)) foo18 (void) { return 18; }
+int __attribute__((noinline,noclone)) foo19 (void) { return 19; }
+int __attribute__((noinline,noclone)) foo20 (void) { return 20; }
+
+
+int __attribute__((noinline,noclone))
+bar (int a)
+{
+ int ret = 0;
+
+ switch (a)
+ {
+ case 1: ret = foo1 (); break;
+ case 2: ret = foo2 (); break;
+ case 3: ret = foo3 (); break;
+ case 4: ret = foo4 (); break;
+ case 5: ret = foo5 (); break;
+ case 6: ret = foo6 (); break;
+ case 7: ret = foo7 (); break;
+ case 8: ret = foo8 (); break;
+ case 9: ret = foo9 (); break;
+ case 10: ret = foo10 (); break;
+ case 11: ret = foo11 (); break;
+ case 12: ret = foo12 (); break;
+ case 13: ret = foo13 (); break;
+ case 14: ret = foo14 (); break;
+ case 15: ret = foo15 (); break;
+ case 16: ret = foo16 (); break;
+ case 17: ret = foo17 (); break;
+ case 18: ret = foo18 (); break;
+ case 19: ret = foo19 (); break;
+ case 20: ret = foo20 (); break;
+ default:
+ __builtin_abort ();
+ }
+
+ return ret;
+}
+
+int
+main ()
+{
+ if (bar (3) != 3)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* 1 x bar
+/* { dg-final { scan-assembler-times "ex\t" 1 } } */
+
+/* { dg-final { scan-assembler "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_fromreg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_frommem" } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr84295.c b/gcc/testsuite/gcc.target/s390/pr84295.c
new file mode 100644
index 00000000000..4da43c3cded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr84295.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z900 -fgnu89-inline --save-temps -mfunction-return-reg=thunk -mindirect-branch-table" } */
+
+extern void foo (void);
+extern __inline void foo (void) {}
+void foo (void) {}
+
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */
+/* { dg-final { scan-assembler "ex\t" } } */
+
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */