* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
@ 2018-01-14 13:07 Alex Vong
2018-01-15 14:29 ` Alex Vong
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Alex Vong @ 2018-01-14 13:07 UTC (permalink / raw)
To: 30111
[-- Attachment #1: Type: text/plain, Size: 345 bytes --]
Hello,
This patch adds the repoline patches (totally 17 of them) taken from the
'retpoline-20180107' branch at
``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
Last time it builds fine on my laptop. I am now re-building since I add
some comments on the patches. I will reply asap if anything goes wrong
with the re-build.
[-- Attachment #2: 0001-gnu-gcc-7-Apply-the-retpoline-mitigation-technique.patch --]
[-- Type: text/x-diff, Size: 301145 bytes --]
From 5be54f7ebe9b0ab6dc65ea974584be0850604b14 Mon Sep 17 00:00:00 2001
From: Alex Vong <alexvong1995@gmail.com>
Date: Sun, 14 Jan 2018 20:12:19 +0800
Subject: [PATCH] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
This is part of Spectre (branch target injection) [CVE-2017-5715]
mitigation. Suggested by Mark H Weaver <mhw@netris.org>.
* gnu/local.mk (dist_patch_DATA): Add them.
* gnu/packages/gcc.scm (gcc@7): Use them.
* gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch,
gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch,
gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch,
gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch,
gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch,
gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch,
gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch,
gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch,
gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch,
gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch,
gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch,
gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch,
gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch,
gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch,
gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch,
gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch,
gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch:
New files.
---
gnu/local.mk | 19 +-
gnu/packages/gcc.scm | 20 +-
...-Add-indirect_branch-attribute-with-tests.patch | 475 +++++++++++
...tion-return-and-function_return-attribute.patch | 740 ++++++++++++++++
...tion-return-keep-to-indirect-branch-tests.patch | 421 ++++++++++
.../gcc-retpoline-Add-mindirect-branch-loop.patch | 233 ++++++
...e-Add-mindirect-branch-register-and-tests.patch | 403 +++++++++
...tpoline-Add-mindirect-branch-thunk-extern.patch | 263 ++++++
...tpoline-Add-mindirect-branch-thunk-inline.patch | 310 +++++++
.../gcc-retpoline-Add-mindirect-branch-thunk.patch | 729 ++++++++++++++++
...irect-branch-register-to-indirect-branch-.patch | 554 ++++++++++++
...or-mindirect-branch-thunk-fcheck-pointer-.patch | 134 +++
...Disable-red-zone-with-local-indirect-jump.patch | 147 ++++
...ks-to-__x86_indirect_thunk_rax-etc.-to-re.patch | 926 +++++++++++++++++++++
...ndirect_thunk.reg-for-indirect-branch-via.patch | 623 ++++++++++++++
...line-i386-Add-V-register-operand-modifier.patch | 76 ++
...se-reference-of-struct-ix86_frame-to-avoi.patch | 69 ++
...ove-struct-ix86_frame-to-machine_function.patch | 249 ++++++
...ference-of-struct-ix86_frame-to-avoid-cop.patch | 85 ++
19 files changed, 6474 insertions(+), 2 deletions(-)
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
diff --git a/gnu/local.mk b/gnu/local.mk
index 6af8bfc4b..122e8ef0c 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -9,7 +9,7 @@
# Copyright © 2016 Adonay "adfeno" Felipe Nogueira <https://libreplanet.org/wiki/User:Adfeno> <adfeno@openmailbox.org>
# Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
-# Copyright © 2016, 2017 Alex Vong <alexvong1995@gmail.com>
+# Copyright © 2016, 2017, 2018 Alex Vong <alexvong1995@gmail.com>
# Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 2016, 2017 Jan Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
@@ -652,6 +652,23 @@ dist_patch_DATA = \
%D%/packages/patches/gcc-asan-powerpc-missing-include.patch \
%D%/packages/patches/gcc-cross-environment-variables.patch \
%D%/packages/patches/gcc-libvtv-runpath.patch \
+ %D%/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch \
+ %D%/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch \
+ %D%/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch \
+ %D%/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch \
+ %D%/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch \
+ %D%/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch \
+ %D%/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch \
+ %D%/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch \
+ %D%/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch \
+ %D%/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch \
%D%/packages/patches/gcc-strmov-store-file-names.patch \
%D%/packages/patches/gcc-4-compile-with-gcc-5.patch \
%D%/packages/patches/gcc-4.6-gnu-inline.patch \
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index ad8992289..6b913aff9 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -5,6 +5,7 @@
;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2015, 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Carlos Sánchez de La Lama <csanchezdll@gmail.com>
+;;; Copyright © 2018 ALex Vong <alexvong1995@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -427,7 +428,24 @@ Go. It also includes runtime support libraries for these languages.")
(base32
"16j7i0888j2f1yp9l0nhji6cq65dy6y4nwy8868a8njbzzwavxqw"))
(patches (search-patches "gcc-strmov-store-file-names.patch"
- "gcc-5.0-libvtv-runpath.patch"))))
+ "gcc-5.0-libvtv-runpath.patch"
+ "gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch"
+ "gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch"
+ "gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch"
+ "gcc-retpoline-Add-mindirect-branch-thunk.patch"
+ "gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch"
+ "gcc-retpoline-Add-mindirect-branch-thunk-inline.patch"
+ "gcc-retpoline-Add-mindirect-branch-thunk-extern.patch"
+ "gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch"
+ "gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch"
+ "gcc-retpoline-Add-mindirect-branch-loop.patch"
+ "gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch"
+ "gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch"
+ "gcc-retpoline-Add-mindirect-branch-register-and-tests.patch"
+ "gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch"
+ "gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch"
+ "gcc-retpoline-i386-Add-V-register-operand-modifier.patch"
+ "gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch"))))
(description
"GCC is the GNU Compiler Collection. It provides compiler front-ends
for several languages, including C, C++, Objective-C, Fortran, Ada, and Go.
diff --git a/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
new file mode 100644
index 000000000..5129a8273
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
@@ -0,0 +1,475 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From e9794727bb0384be6d27ad1edaefc71c23cc0d86 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 28 Nov 2017 06:10:39 -0800
+Subject: [PATCH 08/17] Add indirect_branch attribute with tests
+
+__attribute__ ((indirect_branch("thunk")))
+__attribute__ ((indirect_branch("thunk-inline")))
+__attribute__ ((indirect_branch("thunk-extern")))
+__attribute__ ((indirect_branch("keep")))
+---
+ gcc/config/i386/i386-opts.h | 1 +
+ gcc/config/i386/i386.c | 74 ++++++++++++++++++++--
+ gcc/config/i386/i386.h | 3 +
+ .../gcc.target/i386/indirect-thunk-attr-1.c | 22 +++++++
+ .../gcc.target/i386/indirect-thunk-attr-2.c | 20 ++++++
+ .../gcc.target/i386/indirect-thunk-attr-3.c | 21 ++++++
+ .../gcc.target/i386/indirect-thunk-attr-4.c | 20 ++++++
+ .../gcc.target/i386/indirect-thunk-attr-5.c | 22 +++++++
+ .../gcc.target/i386/indirect-thunk-attr-6.c | 21 ++++++
+ .../gcc.target/i386/indirect-thunk-attr-7.c | 44 +++++++++++++
+ .../gcc.target/i386/indirect-thunk-attr-8.c | 41 ++++++++++++
+ 11 files changed, 283 insertions(+), 6 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index f8d80ba7ec6..9e56d7f2d12 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -100,6 +100,7 @@ enum stack_protector_guard {
+ };
+
+ enum indirect_branch {
++ indirect_branch_unset = 0,
+ indirect_branch_keep,
+ indirect_branch_thunk,
+ indirect_branch_thunk_inline,
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index ac542f79846..5e66af08066 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -7137,6 +7137,37 @@ ix86_set_func_type (tree fndecl)
+ }
+ }
+
++/* Set the indirect_branch_type field from the function FNDECL. */
++
++static void
++ix86_set_indirect_branch_type (tree fndecl)
++{
++ if (cfun->machine->indirect_branch_type == indirect_branch_unset)
++ {
++ tree attr = lookup_attribute ("indirect_branch",
++ DECL_ATTRIBUTES (fndecl));
++ if (attr != NULL)
++ {
++ tree args = TREE_VALUE (attr);
++ if (args == NULL)
++ gcc_unreachable ();
++ tree cst = TREE_VALUE (args);
++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_keep;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk_inline;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk_extern;
++ else
++ gcc_unreachable ();
++ }
++ else
++ cfun->machine->indirect_branch_type = ix86_indirect_branch;
++ }
++}
++
+ /* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+@@ -7152,7 +7183,10 @@ ix86_set_current_function (tree fndecl)
+ one is extern inline and one isn't. Call ix86_set_func_type
+ to set the func_type field. */
+ if (fndecl != NULL_TREE)
+- ix86_set_func_type (fndecl);
++ {
++ ix86_set_func_type (fndecl);
++ ix86_set_indirect_branch_type (fndecl);
++ }
+ return;
+ }
+
+@@ -7172,6 +7206,7 @@ ix86_set_current_function (tree fndecl)
+ }
+
+ ix86_set_func_type (fndecl);
++ ix86_set_indirect_branch_type (fndecl);
+
+ tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (new_tree == NULL_TREE)
+@@ -28605,9 +28640,11 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ char push_buf[64];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+
+- if (ix86_indirect_branch != indirect_branch_thunk_inline)
++ if (cfun->machine->indirect_branch_type
++ != indirect_branch_thunk_inline)
+ {
+- bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
++ bool need_thunk
++ = cfun->machine->indirect_branch_type == indirect_branch_thunk;
+ if (need_bnd_p)
+ indirect_thunk_bnd_needed |= need_thunk;
+ else
+@@ -28716,7 +28753,7 @@ const char *
+ ix86_output_indirect_jmp (rtx call_op)
+ {
+ if (ix86_red_zone_size == 0
+- && ix86_indirect_branch != indirect_branch_keep)
++ && cfun->machine->indirect_branch_type != indirect_branch_keep)
+ {
+ ix86_output_indirect_branch (call_op, "%0", true);
+ return "";
+@@ -28733,7 +28770,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ bool direct_p = constant_call_address_operand (call_op, VOIDmode);
+ bool output_indirect_p
+ = (!TARGET_SEH
+- && ix86_indirect_branch != indirect_branch_keep);
++ && cfun->machine->indirect_branch_type != indirect_branch_keep);
+ bool seh_nop_p = false;
+ const char *xasm;
+
+@@ -41749,7 +41786,7 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int,
+ }
+
+ static tree
+-ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
++ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
+ bool *no_add_attrs)
+ {
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+@@ -41758,6 +41795,29 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
+ name);
+ *no_add_attrs = true;
+ }
++
++ if (is_attribute_p ("indirect_branch", name))
++ {
++ tree cst = TREE_VALUE (args);
++ if (TREE_CODE (cst) != STRING_CST)
++ {
++ warning (OPT_Wattributes,
++ "%qE attribute requires a string constant argument",
++ name);
++ *no_add_attrs = true;
++ }
++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
++ {
++ warning (OPT_Wattributes,
++ "argument to %qE attribute is not "
++ "(keep|thunk|thunk-inline|thunk-extern)", name);
++ *no_add_attrs = true;
++ }
++ }
++
+ return NULL_TREE;
+ }
+
+@@ -46052,6 +46112,8 @@ static const struct attribute_spec ix86_attribute_table[] =
+ ix86_handle_interrupt_attribute, false },
+ { "no_caller_saved_registers", 0, 0, false, true, true,
+ ix86_handle_no_caller_saved_registers_attribute, false },
++ { "indirect_branch", 1, 1, true, false, false,
++ ix86_handle_fndecl_attribute, false },
+
+ /* End element. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 7d9f9020fb3..a9c199a107c 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2604,6 +2604,9 @@ struct GTY(()) machine_function {
+ /* Function type. */
+ ENUM_BITFIELD(function_type) func_type : 2;
+
++ /* How to generate indirec branch. */
++ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
++
+ /* If true, the current function is a function specified with
+ the "interrupt" or "no_caller_saved_registers" attribute. */
+ BOOL_BITFIELD no_caller_saved_registers : 1;
+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..26550fad4c8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler {\tlfence} } } */
+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..f57bb2a92d6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { 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..a3668a6586c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..a9c4a137dd4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..9582e0c5824
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+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..66442cacfe8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+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..2a19b54cd2e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+new file mode 100644
+index 00000000000..9f6d12d74a1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+@@ -0,0 +1,41 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
new file mode 100644
index 000000000..0845de4b2
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
@@ -0,0 +1,740 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 29d5a3f23c18c96944dd3230a41380a6edcd25fd Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 5 Dec 2017 13:29:06 -0800
+Subject: [PATCH 11/17] Add -mfunction-return= and function_return attribute
+
+Add -mfunction-return= and function_return attribute tests
+
+-mfunction-return=thunk
+ Convert function return instruction to PC-relative call thunk.
+-mfunction-return=thunk-inline
+ Convert function return instruction to PC-relative call thunk with
+ thunk inlined.
+-mfunction-return=thunk-extern
+ Convert function return instruction to PC-relative call to external
+ thunk.
+
+Add function_return attribute to function declaration
+
+__attribute__ ((function_return("thunk")))
+__attribute__ ((function_return("thunk-inline")))
+__attribute__ ((function_return("thunk-extern")))
+__attribute__ ((function_return("keep")))
+---
+ gcc/config/i386/i386-protos.h | 1 +
+ gcc/config/i386/i386.c | 146 +++++++++++++++++++++++++--
+ gcc/config/i386/i386.h | 3 +
+ gcc/config/i386/i386.md | 9 +-
+ gcc/config/i386/i386.opt | 6 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 12 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 22 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 22 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 21 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 21 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 21 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 21 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 18 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 12 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 12 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 12 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 14 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 13 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 13 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 14 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 23 +++++
+ 21 files changed, 421 insertions(+), 15 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-16.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-8.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+
+diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
+index b746429f420..213663811de 100644
+--- a/gcc/config/i386/i386-protos.h
++++ b/gcc/config/i386/i386-protos.h
+@@ -316,6 +316,7 @@ extern enum attr_cpu ix86_schedule;
+
+ extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+ extern const char * ix86_output_indirect_jmp (rtx call_op);
++extern const char * ix86_output_function_return (bool long_p);
+ extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ enum machine_mode mode);
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index be1ff4752a9..7ae3523095c 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -7166,6 +7166,31 @@ ix86_set_indirect_branch_type (tree fndecl)
+ else
+ cfun->machine->indirect_branch_type = ix86_indirect_branch;
+ }
++
++ if (cfun->machine->function_return_type == indirect_branch_unset)
++ {
++ tree attr = lookup_attribute ("function_return",
++ DECL_ATTRIBUTES (fndecl));
++ if (attr != NULL)
++ {
++ tree args = TREE_VALUE (attr);
++ if (args == NULL)
++ gcc_unreachable ();
++ tree cst = TREE_VALUE (args);
++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
++ cfun->machine->function_return_type = indirect_branch_keep;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk_inline;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk_extern;
++ else
++ gcc_unreachable ();
++ }
++ else
++ cfun->machine->function_return_type = ix86_function_return;
++ }
+ }
+
+ /* Establish appropriate back-end context for processing the function
+@@ -11958,8 +11983,12 @@ static int indirect_thunks_bnd_used;
+ /* Fills in the label name that should be used for the indirect thunk. */
+
+ static void
+-indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
++indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
++ bool ret_p)
+ {
++ if (regno >= 0 && ret_p)
++ gcc_unreachable ();
++
+ if (USE_HIDDEN_LINKONCE)
+ {
+ const char *bnd = need_bnd_p ? "_bnd" : "";
+@@ -11974,7 +12003,10 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
+ bnd, reg_prefix, reg_names[regno]);
+ }
+ else
+- sprintf (name, "__x86.indirect_thunk%s", bnd);
++ {
++ const char *ret = ret_p ? "return" : "indirect";
++ sprintf (name, "__x86.%s_thunk%s", ret, bnd);
++ }
+ }
+ else
+ {
+@@ -11987,10 +12019,20 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
+ }
+ else
+ {
+- if (need_bnd_p)
+- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ if (ret_p)
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
++ }
+ else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ }
+ }
+ }
+ }
+@@ -12071,7 +12113,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+ tree decl;
+
+ /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
+- indirect_thunk_name (name, regno, need_bnd_p);
++ indirect_thunk_name (name, regno, need_bnd_p, false);
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (name),
+ build_function_type_list (void_type_node, NULL_TREE));
+@@ -12114,6 +12156,35 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ }
+
++ if (regno < 0)
++ {
++ /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
++ char alias[32];
++
++ indirect_thunk_name (alias, regno, need_bnd_p, true);
++ ASM_OUTPUT_DEF (asm_out_file, alias, name);
++#if TARGET_MACHO
++ if (TARGET_MACHO)
++ {
++ fputs ("\t.weak_definition\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ fputs ("\n\t.private_extern\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ }
++#else
++ if (USE_HIDDEN_LINKONCE)
++ {
++ fputs ("\t.globl\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ fputs ("\t.hidden\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ }
++#endif
++ }
++
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ allocate_struct_function (decl, false);
+@@ -28736,7 +28807,7 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ indirect_thunk_needed = true;
+ }
+ }
+- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
+ thunk_name = thunk_name_buf;
+ }
+ else
+@@ -28860,6 +28931,43 @@ ix86_output_indirect_jmp (rtx call_op)
+ return "%!jmp\t%A0";
+ }
+
++const char *
++ix86_output_function_return (bool long_p)
++{
++ if (cfun->machine->function_return_type != indirect_branch_keep)
++ {
++ char thunk_name[32];
++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++
++ if (cfun->machine->function_return_type
++ != indirect_branch_thunk_inline)
++ {
++ bool need_thunk = (cfun->machine->function_return_type
++ == indirect_branch_thunk);
++ indirect_thunk_name (thunk_name, -1, need_bnd_p, true);
++ if (need_bnd_p)
++ {
++ indirect_thunk_bnd_needed |= need_thunk;
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ }
++ else
++ {
++ indirect_thunk_needed |= need_thunk;
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ }
++ else
++ output_indirect_thunk (need_bnd_p, -1);
++
++ return "";
++ }
++
++ if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
++ return "%!ret";
++
++ return "rep%; ret";
++}
++
+ /* Output the assembly for a call instruction. */
+
+ const char *
+@@ -41916,6 +42024,28 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
+ }
+ }
+
++ if (is_attribute_p ("function_return", name))
++ {
++ tree cst = TREE_VALUE (args);
++ if (TREE_CODE (cst) != STRING_CST)
++ {
++ warning (OPT_Wattributes,
++ "%qE attribute requires a string constant argument",
++ name);
++ *no_add_attrs = true;
++ }
++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
++ {
++ warning (OPT_Wattributes,
++ "argument to %qE attribute is not "
++ "(keep|thunk|thunk-inline|thunk-extern)", name);
++ *no_add_attrs = true;
++ }
++ }
++
+ return NULL_TREE;
+ }
+
+@@ -46212,6 +46342,8 @@ static const struct attribute_spec ix86_attribute_table[] =
+ ix86_handle_no_caller_saved_registers_attribute, false },
+ { "indirect_branch", 1, 1, true, false, false,
+ ix86_handle_fndecl_attribute, false },
++ { "function_return", 1, 1, true, false, false,
++ ix86_handle_fndecl_attribute, false },
+
+ /* End element. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index a9c199a107c..f248f3ba2f5 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2607,6 +2607,9 @@ struct GTY(()) machine_function {
+ /* How to generate indirec branch. */
+ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
+
++ /* How to generate function return. */
++ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
++
+ /* If true, the current function is a function specified with
+ the "interrupt" or "no_caller_saved_registers" attribute. */
+ BOOL_BITFIELD no_caller_saved_registers : 1;
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index 01b7b2039e6..00a9afef225 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -12288,7 +12288,7 @@
+ (define_insn "simple_return_internal"
+ [(simple_return)]
+ "reload_completed"
+- "%!ret"
++ "* return ix86_output_function_return (false);"
+ [(set_attr "length" "1")
+ (set_attr "atom_unit" "jeu")
+ (set_attr "length_immediate" "0")
+@@ -12310,12 +12310,7 @@
+ [(simple_return)
+ (unspec [(const_int 0)] UNSPEC_REP)]
+ "reload_completed"
+-{
+- if (ix86_bnd_prefixed_insn_p (insn))
+- return "%!ret";
+-
+- return "rep%; ret";
+-}
++ "* return ix86_output_function_return (true);"
+ [(set_attr "length" "2")
+ (set_attr "atom_unit" "jeu")
+ (set_attr "length_immediate" "0")
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index bc81e6bea86..fc2c81c3fb5 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -932,9 +932,13 @@ mindirect-branch=
+ Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
+ Update indirect call and jump.
+
++mfunction-return=
++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
++Update function return.
++
+ Enum
+ Name(indirect_branch) Type(enum indirect_branch)
+-Known indirect branch choices (for use with the -mindirect-branch= option):
++Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
+
+ EnumValue
+ Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
+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..406956f48e5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+@@ -0,0 +1,12 @@
++/* { 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 {\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..aecea4224f9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\tlfence} 2 } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..3bacfb54dfd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..851115ac507
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..7acb6fa5eae
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\tlfence} 2 } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { 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" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..bf340fac7c6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..735f8648c96
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..cf3920563e0
+--- /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 {\tlfence} } } */
++/* { 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-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+new file mode 100644
+index 00000000000..190947cc2ca
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+@@ -0,0 +1,12 @@
++/* { 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 {\tlfence} } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
+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..d71de3ac520
+--- /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 {\tlfence} } } */
++/* { 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..68c22122f0d
+--- /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 {\tlfence} } } */
++/* { 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..28c576e2267
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
+@@ -0,0 +1,14 @@
++/* { 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 {\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..10ad40b9c26
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+@@ -0,0 +1,13 @@
++/* { 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 {\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..7ac0beaa73e
+--- /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 {\tlfence} } } */
++/* { 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..777ab7c8088
+--- /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 {\tlfence} } } */
++/* { 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..569e5f47973
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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-not "__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-times {\tlfence} 1 { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
new file mode 100644
index 000000000..ac900bab0
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
@@ -0,0 +1,421 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From def2b5d75fd6234984ec969f4586fcb8c516a3b9 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 6 Dec 2017 09:58:42 -0800
+Subject: [PATCH 12/17] Add -mfunction-return=keep to indirect branch tests
+
+---
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ 33 files changed, 33 insertions(+), 33 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index 785e593405f..318db1e7f5c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index b69075e6483..f2700dd36cf 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index df8109baf55..46685d9a674 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index 8f3b9f4d8a5..8f701775cea 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+index 1a9bb0e431e..f88ac31d07a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+index bc7d20ec6ad..d745116d321 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index f0e1cfe1893..969cb8c6ddc 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index 8b88449e625..12a61c3bbc7 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index c69f7bf4f60..a06907933a2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+index c845099a83e..7f56725e6b6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index f636f3422fd..fd4ab1dbaa0 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 5f1d6a78041..1ffbf3b1181 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 56c92da9812..1559072919a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index cfb6f5b234b..1717e7bb436 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+index 9f6d12d74a1..af1bb125a22 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+index a5b1d38e061..20903b0f79d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+ void (*dispatch) (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+index a42add209e2..aef4bd144f4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+ void (*dispatch) (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+index 265e010a0fe..2cc0343f828 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+ void bar (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+index 1c01bcb7fc6..91560fef661 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+ void bar (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index f1fa0a11922..dc6bd10af4c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index d6e078d594b..955aa256529 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 3bbe2646955..1537239416f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index 596fac599f6..c82e53068fe 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+index ad54aaeac4c..23548d85f78 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+index a8e75254cfe..56c2fe92f25 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+index ab367951c45..e12b88593fe 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 09b8ad7d879..87b5429702f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+index 1f873758fbe..a496a41a918 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+index b24af1da963..6fe5ce71abf 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+index 1a86608f727..65cd997a33f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+index f4890fe97b2..7321d015c02 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+index 81b09e73ab8..6ec2e5621ab 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+index 01d45782185..a3d1a13cded 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
new file mode 100644
index 000000000..ab715f46a
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
@@ -0,0 +1,233 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From d667049b53e3d45de057fba2f1ed0e3f268201c1 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Thu, 16 Nov 2017 14:46:20 -0800
+Subject: [PATCH 10/17] Add -mindirect-branch-loop=
+
+Add -mindirect-branch-loop= tests.
+---
+ gcc/config/i386/i386-opts.h | 6 ++++++
+ gcc/config/i386/i386.c | 19 +++++++++++++++++--
+ gcc/config/i386/i386.opt | 16 ++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 19 +++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 19 +++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 19 +++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 19 +++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 19 +++++++++++++++++++
+ 8 files changed, 134 insertions(+), 2 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index 9e56d7f2d12..b7b8fd280a3 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -107,4 +107,10 @@ enum indirect_branch {
+ indirect_branch_thunk_extern
+ };
+
++enum indirect_branch_loop {
++ indirect_branch_loop_lfence,
++ indirect_branch_loop_pause,
++ indirect_branch_loop_nop
++};
++
+ #endif
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 590729b3f87..be1ff4752a9 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -12016,8 +12016,23 @@ output_indirect_thunk (bool need_bnd_p, int regno)
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
+
+- /* lfence . */
+- fprintf (asm_out_file, "\tlfence\n");
++ switch (ix86_indirect_branch_loop)
++ {
++ case indirect_branch_loop_lfence:
++ /* lfence. */
++ fprintf (asm_out_file, "\tlfence\n");
++ break;
++ case indirect_branch_loop_pause:
++ /* pause. */
++ fprintf (asm_out_file, "\tpause\n");
++ break;
++ case indirect_branch_loop_nop:
++ /* nop. */
++ fprintf (asm_out_file, "\tnop\n");
++ break;
++ default:
++ gcc_unreachable ();
++ }
+
+ /* Jump. */
+ fputs ("\tjmp\t", asm_out_file);
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 4a932e11bf6..bc81e6bea86 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -947,3 +947,19 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+
+ EnumValue
+ Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
++
++mindirect-branch-loop=
++Target Report RejectNegative Joined Enum(indirect_branch_loop) Var(ix86_indirect_branch_loop) Undocumented Init(indirect_branch_loop_lfence)
++
++Enum
++Name(indirect_branch_loop) Type(enum indirect_branch_loop)
++Known looop choices (for use with the -mindirect-branch-loop= option):
++
++EnumValue
++Enum(indirect_branch_loop) String(lfence) Value(indirect_branch_loop_lfence)
++
++EnumValue
++Enum(indirect_branch_loop) String(pause) Value(indirect_branch_loop_pause)
++
++EnumValue
++Enum(indirect_branch_loop) String(nop) Value(indirect_branch_loop_nop)
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+new file mode 100644
+index 00000000000..f0e8f4949c8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
++
++typedef void (*dispatch_t)(long offset);
++
++dispatch_t dispatch;
++
++void
++male_indirect_jump (long offset)
++{
++ dispatch(offset);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+new file mode 100644
+index 00000000000..a577ac2568a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=nop -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tnop} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+new file mode 100644
+index 00000000000..c8dcb9639c4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
++
++typedef void (*dispatch_t)(long offset);
++
++dispatch_t dispatch;
++
++void
++male_indirect_jump (long offset)
++{
++ dispatch(offset);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+new file mode 100644
+index 00000000000..8569dfc92c3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
++
++typedef void (*dispatch_t)(long offset);
++
++dispatch_t dispatch;
++
++void
++male_indirect_jump (long offset)
++{
++ dispatch(offset);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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-not "__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+new file mode 100644
+index 00000000000..bcf19c9ede1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
++
++typedef void (*dispatch_t)(long offset);
++
++dispatch_t dispatch;
++
++void
++male_indirect_jump (long offset)
++{
++ dispatch(offset);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler-not {\t(lfence|pause|nop)} } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
new file mode 100644
index 000000000..de9e373fd
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
@@ -0,0 +1,403 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From fb8875abab630962dbcb08c822b1b960fa5a51d4 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 19 Jul 2017 19:23:02 -0700
+Subject: [PATCH 13/17] Add -mindirect-branch-register and tests
+
+Add -mindirect-branch-register to force indirect branch via register.
+This is implemented by disabling patterns of indirect branch via memory,
+similar to TARGET_X32. With -mindirect-branch-register:
+
+void (*func) (void);
+
+void
+bar (void)
+{
+ func ();
+}
+
+is compiled into:
+
+ movq func(%rip), %rax
+ jmp __x86.indirect_thunk.ax
+
+__x86.indirect_thunk.ax:
+ call .LIND3
+.LIND2:
+ lfence
+ jmp .LIND2
+.LIND3:
+ mov %rax, (%rsp)
+ ret
+
+and
+
+void (*func) (void);
+
+int
+bar (void)
+{
+ func ();
+ return 0;
+}
+
+is compiled into:
+
+ subq $8, %rsp
+ movq func(%rip), %rax
+ call __x86.indirect_thunk.ax
+ xorl %eax, %eax
+ addq $8, %rsp
+ ret
+
+ * config/i386/constraints.md (Bs): Disallow memory operand for
+ -mindirect-branch-register.
+ (Bw): Likewise.
+ * config/i386/predicates.md (indirect_branch_operand): Likewise.
+ (GOT_memory_operand): Likewise.
+ (call_insn_operand): Likewise.
+ (sibcall_insn_operand): Likewise.
+ (GOT32_symbol_operand): Likewise.
+ * config/i386/i386.md (indirect_jump): Call convert_memory_address
+ for -mindirect-branch-register.
+ (tablejump): Likewise.
+ (*sibcall_memory): Likewise.
+ (*sibcall_value_memory): Likewise.
+ Disallow peepholes of indirect call and jump via memory for
+ -mindirect-branch-register.
+ (*call_pop): Replace m with Bw.
+ (*call_value_pop): Likewise.
+ (*sibcall_pop_memory): Replace m with Bs.
+---
+ gcc/config/i386/constraints.md | 12 +++++---
+ gcc/config/i386/i386.md | 34 ++++++++++++++--------
+ gcc/config/i386/i386.opt | 4 +++
+ gcc/config/i386/predicates.md | 21 ++++++++-----
+ .../gcc.target/i386/indirect-thunk-register-1.c | 22 ++++++++++++++
+ .../gcc.target/i386/indirect-thunk-register-2.c | 20 +++++++++++++
+ .../gcc.target/i386/indirect-thunk-register-3.c | 19 ++++++++++++
+ 7 files changed, 109 insertions(+), 23 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+
+diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
+index 38d604fdace..697caf704dd 100644
+--- a/gcc/config/i386/constraints.md
++++ b/gcc/config/i386/constraints.md
+@@ -198,16 +198,20 @@
+
+ (define_constraint "Bs"
+ "@internal Sibcall memory operand."
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "sibcall_memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand"))))
+
+ (define_constraint "Bw"
+ "@internal Call memory operand."
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand"))))
+
+ (define_constraint "Bz"
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index 00a9afef225..473fa5c089b 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -11608,7 +11608,7 @@
+ [(set (pc) (match_operand 0 "indirect_branch_operand"))]
+ ""
+ {
+- if (TARGET_X32)
++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
+ })
+
+@@ -11657,7 +11657,7 @@
+ OPTAB_DIRECT);
+ }
+
+- if (TARGET_X32)
++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
+ })
+
+@@ -11844,7 +11844,7 @@
+ [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
+ (match_operand 1))
+ (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
+- "!TARGET_X32"
++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
+ "* return ix86_output_call_insn (insn, operands[0]);"
+ [(set_attr "type" "call")])
+
+@@ -11853,7 +11853,9 @@
+ (match_operand:W 1 "memory_operand"))
+ (call (mem:QI (match_dup 0))
+ (match_operand 3))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (1))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
+ [(parallel [(call (mem:QI (match_dup 1))
+@@ -11866,7 +11868,9 @@
+ (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (2))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+@@ -11888,7 +11892,7 @@
+ })
+
+ (define_insn "*call_pop"
+- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
++ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
+ (match_operand 1))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+@@ -11908,7 +11912,7 @@
+ [(set_attr "type" "call")])
+
+ (define_insn "*sibcall_pop_memory"
+- [(call (mem:QI (match_operand:SI 0 "memory_operand" "m"))
++ [(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
+ (match_operand 1))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+@@ -11962,7 +11966,9 @@
+ [(set (match_operand:W 0 "register_operand")
+ (match_operand:W 1 "memory_operand"))
+ (set (pc) (match_dup 0))]
+- "!TARGET_X32 && peep2_reg_dead_p (2, operands[0])"
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && peep2_reg_dead_p (2, operands[0])"
+ [(set (pc) (match_dup 1))])
+
+ ;; Call subroutine, returning value in operand 0
+@@ -12043,7 +12049,7 @@
+ (call (mem:QI (match_operand:W 1 "memory_operand" "m"))
+ (match_operand 2)))
+ (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
+- "!TARGET_X32"
++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
+ "* return ix86_output_call_insn (insn, operands[1]);"
+ [(set_attr "type" "callv")])
+
+@@ -12053,7 +12059,9 @@
+ (set (match_operand 2)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3)))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (1))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
+ [(parallel [(set (match_dup 2)
+@@ -12068,7 +12076,9 @@
+ (set (match_operand 2)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3)))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (2))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+@@ -12093,7 +12103,7 @@
+
+ (define_insn "*call_value_pop"
+ [(set (match_operand 0)
+- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
++ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
+ (match_operand 2)))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index fc2c81c3fb5..802245f4efe 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -952,6 +952,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+ EnumValue
+ Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+
++mindirect-branch-register
++Target Report Var(ix86_indirect_branch_thunk_register) Init(0)
++Force indirect call and jump via register.
++
+ mindirect-branch-loop=
+ Target Report RejectNegative Joined Enum(indirect_branch_loop) Var(ix86_indirect_branch_loop) Undocumented Init(indirect_branch_loop_lfence)
+
+diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
+index 8f250a2e720..fc4933e4533 100644
+--- a/gcc/config/i386/predicates.md
++++ b/gcc/config/i386/predicates.md
+@@ -635,7 +635,8 @@
+ ;; Test for a valid operand for indirect branch.
+ (define_predicate "indirect_branch_operand"
+ (ior (match_operand 0 "register_operand")
+- (and (not (match_test "TARGET_X32"))
++ (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))))
+
+ ;; Return true if OP is a memory operands that can be used in sibcalls.
+@@ -664,7 +665,8 @@
+
+ ;; Return true if OP is a GOT memory operand.
+ (define_predicate "GOT_memory_operand"
+- (match_operand 0 "memory_operand")
++ (and (match_test "!ix86_indirect_branch_thunk_register")
++ (match_operand 0 "memory_operand"))
+ {
+ op = XEXP (op, 0);
+ return (GET_CODE (op) == CONST
+@@ -678,9 +680,11 @@
+ (ior (match_test "constant_call_address_operand
+ (op, mode == VOIDmode ? mode : Pmode)")
+ (match_operand 0 "call_register_no_elim_operand")
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand")))))
+
+ ;; Similarly, but for tail calls, in which we cannot allow memory references.
+@@ -688,14 +692,17 @@
+ (ior (match_test "constant_call_address_operand
+ (op, mode == VOIDmode ? mode : Pmode)")
+ (match_operand 0 "register_no_elim_operand")
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "sibcall_memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand")))))
+
+ ;; Return true if OP is a 32-bit GOT symbol operand.
+ (define_predicate "GOT32_symbol_operand"
+- (match_test "GET_CODE (op) == CONST
++ (match_test "!ix86_indirect_branch_thunk_register
++ && GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC
+ && XINT (XEXP (op, 0), 1) == UNSPEC_GOT"))
+
+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..ef493a05bbf
+--- /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 {\tlfence} } } */
++/* { 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..89fc8e6e6c4
+--- /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 {\tlfence} } } */
++/* { 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..31af7ac05b8
+--- /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(lfence|pause|nop)} } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
new file mode 100644
index 000000000..18b2dfaea
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
@@ -0,0 +1,263 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 4032162fb6d36e20091885d0558f91daaa0080d3 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 27 Nov 2017 08:38:41 -0800
+Subject: [PATCH 07/17] Add -mindirect-branch=thunk-extern
+
+Add -mindirect-branch=thunk-extern tests
+---
+ gcc/config/i386/i386-opts.h | 3 +-
+ gcc/config/i386/i386.opt | 3 ++
+ .../gcc.target/i386/indirect-thunk-extern-1.c | 19 ++++++++++
+ .../gcc.target/i386/indirect-thunk-extern-2.c | 19 ++++++++++
+ .../gcc.target/i386/indirect-thunk-extern-3.c | 20 ++++++++++
+ .../gcc.target/i386/indirect-thunk-extern-4.c | 20 ++++++++++
+ .../gcc.target/i386/indirect-thunk-extern-5.c | 16 ++++++++
+ .../gcc.target/i386/indirect-thunk-extern-6.c | 17 +++++++++
+ .../gcc.target/i386/indirect-thunk-extern-7.c | 43 ++++++++++++++++++++++
+ 9 files changed, 159 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index f301890575a..f8d80ba7ec6 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -102,7 +102,8 @@ enum stack_protector_guard {
+ enum indirect_branch {
+ indirect_branch_keep,
+ indirect_branch_thunk,
+- indirect_branch_thunk_inline
++ indirect_branch_thunk_inline,
++ indirect_branch_thunk_extern
+ };
+
+ #endif
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 68484a75022..4a932e11bf6 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -944,3 +944,6 @@ Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
+
+ EnumValue
+ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
++
++EnumValue
++Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+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..0a1f91be988
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+new file mode 100644
+index 00000000000..182520ab3dc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+new file mode 100644
+index 00000000000..5c31ddc34fd
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+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..f24d0c060f2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { 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..ad54aaeac4c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+new file mode 100644
+index 00000000000..a8e75254cfe
+--- /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 -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" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { 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..8d39fb6f939
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -0,0 +1,43 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
new file mode 100644
index 000000000..bb12c0e95
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
@@ -0,0 +1,310 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 7f4f2bf1688c81496107993080e68a29a24de702 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 15 Nov 2017 11:20:31 -0800
+Subject: [PATCH 06/17] Add -mindirect-branch=thunk-inline
+
+Add -mindirect-branch=thunk-inline tests
+---
+ gcc/config/i386/i386-opts.h | 3 +-
+ gcc/config/i386/i386.c | 30 +++++++++++-----
+ gcc/config/i386/i386.opt | 3 ++
+ .../gcc.target/i386/indirect-thunk-inline-1.c | 18 ++++++++++
+ .../gcc.target/i386/indirect-thunk-inline-2.c | 18 ++++++++++
+ .../gcc.target/i386/indirect-thunk-inline-3.c | 19 ++++++++++
+ .../gcc.target/i386/indirect-thunk-inline-4.c | 19 ++++++++++
+ .../gcc.target/i386/indirect-thunk-inline-5.c | 15 ++++++++
+ .../gcc.target/i386/indirect-thunk-inline-6.c | 16 +++++++++
+ .../gcc.target/i386/indirect-thunk-inline-7.c | 42 ++++++++++++++++++++++
+ 10 files changed, 173 insertions(+), 10 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index 1565d8fdc65..f301890575a 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -101,7 +101,8 @@ enum stack_protector_guard {
+
+ enum indirect_branch {
+ indirect_branch_keep,
+- indirect_branch_thunk
++ indirect_branch_thunk,
++ indirect_branch_thunk_inline
+ };
+
+ #endif
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 96424361a1c..ac542f79846 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -28600,16 +28600,23 @@ static void
+ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ bool sibcall_p)
+ {
+- char thunk_name[32];
++ char thunk_name_buf[32];
++ char *thunk_name;
+ char push_buf[64];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
+
+- bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
+- if (need_bnd_p)
+- indirect_thunk_bnd_needed |= need_thunk;
++ if (ix86_indirect_branch != indirect_branch_thunk_inline)
++ {
++ bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
++ if (need_bnd_p)
++ indirect_thunk_bnd_needed |= need_thunk;
++ else
++ indirect_thunk_needed |= need_thunk;
++ indirect_thunk_name (thunk_name_buf, need_bnd_p);
++ thunk_name = thunk_name_buf;
++ }
+ else
+- indirect_thunk_needed |= need_thunk;
+- indirect_thunk_name (thunk_name, need_bnd_p);
++ thunk_name = NULL;
+
+ snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
+ TARGET_64BIT ? 'q' : 'l', xasm);
+@@ -28683,10 +28690,15 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+
+ output_asm_insn (push_buf, &call_op);
+
+- if (need_bnd_p)
+- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
+ else
+- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ output_indirect_thunk (need_bnd_p);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 1773e5614cf..68484a75022 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -941,3 +941,6 @@ Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
+
+ EnumValue
+ Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
++
++EnumValue
++Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+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..071e6c89ac7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+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..804c7ccdba7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+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..545a981add5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+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..d9ff4722cff
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+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..f4890fe97b2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { 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..81b09e73ab8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..a0ce06b8232
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
new file mode 100644
index 000000000..edb9a8de5
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
@@ -0,0 +1,729 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 63024dad9c00f1613738fd766e2f0afd455b76d1 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 1 Nov 2017 16:05:50 -0700
+Subject: [PATCH 04/17] Add -mindirect-branch=thunk
+
+Add tests for -mindirect-branch=thunk
+---
+ gcc/config/i386/i386-opts.h | 5 +
+ gcc/config/i386/i386-protos.h | 1 +
+ gcc/config/i386/i386.c | 318 ++++++++++++++++++++++-
+ gcc/config/i386/i386.md | 6 +-
+ gcc/config/i386/i386.opt | 14 +
+ gcc/doc/invoke.texi | 9 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 19 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 19 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 20 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 20 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 16 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 17 ++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 43 +++
+ 13 files changed, 495 insertions(+), 12 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index 542cd0f3d67..1565d8fdc65 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -99,4 +99,9 @@ enum stack_protector_guard {
+ SSP_GLOBAL /* global canary */
+ };
+
++enum indirect_branch {
++ indirect_branch_keep,
++ indirect_branch_thunk
++};
++
+ #endif
+diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
+index 8bdd67eb608..b746429f420 100644
+--- a/gcc/config/i386/i386-protos.h
++++ b/gcc/config/i386/i386-protos.h
+@@ -315,6 +315,7 @@ extern enum attr_cpu ix86_schedule;
+ #endif
+
+ extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
++extern const char * ix86_output_indirect_jmp (rtx call_op);
+ extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ enum machine_mode mode);
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 504530a00cf..96424361a1c 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -11909,6 +11909,145 @@ ix86_setup_frame_addresses (void)
+ # endif
+ #endif
+
++static int indirectlabelno;
++static bool indirect_thunk_needed = false;
++static bool indirect_thunk_bnd_needed = false;
++
++#ifndef INDIRECT_LABEL
++# define INDIRECT_LABEL "LIND"
++#endif
++
++/* Fills in the label name that should be used for the indirect thunk. */
++
++static void
++indirect_thunk_name (char name[32], bool need_bnd_p)
++{
++ if (USE_HIDDEN_LINKONCE)
++ {
++ const char *bnd = need_bnd_p ? "_bnd" : "";
++ sprintf (name, "__x86.indirect_thunk%s", bnd);
++ }
++ else
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ }
++}
++
++static void
++output_indirect_thunk (bool need_bnd_p)
++{
++ char indirectlabel1[32];
++ char indirectlabel2[32];
++
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1, INDIRECT_LABEL,
++ indirectlabelno++);
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2, INDIRECT_LABEL,
++ indirectlabelno++);
++
++ /* Call */
++ if (need_bnd_p)
++ fputs ("\tbnd call\t", asm_out_file);
++ else
++ fputs ("\tcall\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel2);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
++
++ /* lfence . */
++ fprintf (asm_out_file, "\tlfence\n");
++
++ /* Jump. */
++ fputs ("\tjmp\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel1);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
++
++ /* LEA. */
++ rtx xops[2];
++ xops[0] = stack_pointer_rtx;
++ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
++ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
++
++ if (need_bnd_p)
++ fputs ("\tbnd ret\n", asm_out_file);
++ else
++ fputs ("\tret\n", asm_out_file);
++}
++
++static void
++output_indirect_thunk_function (bool need_bnd_p)
++{
++ char name[32];
++ tree decl;
++
++ indirect_thunk_name (name, need_bnd_p);
++ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
++ get_identifier (name),
++ build_function_type_list (void_type_node, NULL_TREE));
++ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
++ NULL_TREE, void_type_node);
++ TREE_PUBLIC (decl) = 1;
++ TREE_STATIC (decl) = 1;
++ DECL_IGNORED_P (decl) = 1;
++
++#if TARGET_MACHO
++ if (TARGET_MACHO)
++ {
++ switch_to_section (darwin_sections[picbase_thunk_section]);
++ fputs ("\t.weak_definition\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ fputs ("\n\t.private_extern\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ putc ('\n', asm_out_file);
++ ASM_OUTPUT_LABEL (asm_out_file, name);
++ DECL_WEAK (decl) = 1;
++ }
++ else
++#endif
++ if (USE_HIDDEN_LINKONCE)
++ {
++ cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
++
++ targetm.asm_out.unique_section (decl, 0);
++ switch_to_section (get_named_section (decl, NULL, 0));
++
++ targetm.asm_out.globalize_label (asm_out_file, name);
++ fputs ("\t.hidden\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ putc ('\n', asm_out_file);
++ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
++ }
++ else
++ {
++ switch_to_section (text_section);
++ ASM_OUTPUT_LABEL (asm_out_file, name);
++ }
++
++ DECL_INITIAL (decl) = make_node (BLOCK);
++ current_function_decl = decl;
++ allocate_struct_function (decl, false);
++ init_function_start (decl);
++ /* We're about to hide the function body from callees of final_* by
++ emitting it directly; tell them we're a thunk, if they care. */
++ cfun->is_thunk = true;
++ first_function_block_is_cold = false;
++ /* Make sure unwind info is emitted for the thunk if needed. */
++ final_start_function (emit_barrier (), asm_out_file, 1);
++
++ output_indirect_thunk (need_bnd_p);
++
++ final_end_function ();
++ init_insn_lengths ();
++ free_after_compilation (cfun);
++ set_cfun (NULL);
++ current_function_decl = NULL;
++}
++
+ static int pic_labels_used;
+
+ /* Fills in the label name that should be used for a pc thunk for
+@@ -11935,6 +12074,11 @@ ix86_code_end (void)
+ rtx xops[2];
+ int regno;
+
++ if (indirect_thunk_needed)
++ output_indirect_thunk_function (false);
++ if (indirect_thunk_bnd_needed)
++ output_indirect_thunk_function (true);
++
+ for (regno = AX_REG; regno <= SP_REG; regno++)
+ {
+ char name[32];
+@@ -28452,12 +28596,132 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
+ return false;
+ }
+
++static void
++ix86_output_indirect_branch (rtx call_op, const char *xasm,
++ bool sibcall_p)
++{
++ char thunk_name[32];
++ char push_buf[64];
++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++
++ bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
++ if (need_bnd_p)
++ indirect_thunk_bnd_needed |= need_thunk;
++ else
++ indirect_thunk_needed |= need_thunk;
++ indirect_thunk_name (thunk_name, need_bnd_p);
++
++ snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
++ TARGET_64BIT ? 'q' : 'l', xasm);
++
++ if (sibcall_p)
++ {
++ output_asm_insn (push_buf, &call_op);
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ else
++ output_indirect_thunk (need_bnd_p);
++ }
++ else
++ {
++ char indirectlabel1[32];
++ char indirectlabel2[32];
++
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++
++ /* Jump. */
++ if (need_bnd_p)
++ fputs ("\tbnd jmp\t", asm_out_file);
++ else
++ fputs ("\tjmp\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel2);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
++
++ if (MEM_P (call_op))
++ {
++ struct ix86_address parts;
++ rtx addr = XEXP (call_op, 0);
++ if (ix86_decompose_address (addr, &parts)
++ && parts.base == stack_pointer_rtx)
++ {
++ /* Since call will adjust stack by -UNITS_PER_WORD,
++ we must convert "disp(stack, index, scale)" to
++ "disp+UNITS_PER_WORD(stack, index, scale)". */
++ if (parts.index)
++ {
++ addr = gen_rtx_MULT (Pmode, parts.index,
++ GEN_INT (parts.scale));
++ addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++ addr);
++ }
++ else
++ addr = stack_pointer_rtx;
++
++ rtx disp;
++ if (parts.disp != NULL_RTX)
++ disp = plus_constant (Pmode, parts.disp,
++ UNITS_PER_WORD);
++ else
++ disp = GEN_INT (UNITS_PER_WORD);
++
++ addr = gen_rtx_PLUS (Pmode, addr, disp);
++ call_op = gen_rtx_MEM (GET_MODE (call_op), addr);
++ }
++ }
++
++ output_asm_insn (push_buf, &call_op);
++
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
++
++ /* Call. */
++ if (need_bnd_p)
++ fputs ("\tbnd call\t", asm_out_file);
++ else
++ fputs ("\tcall\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel1);
++ fputc ('\n', asm_out_file);
++ }
++}
++
++const char *
++ix86_output_indirect_jmp (rtx call_op)
++{
++ if (ix86_red_zone_size == 0
++ && ix86_indirect_branch != indirect_branch_keep)
++ {
++ ix86_output_indirect_branch (call_op, "%0", true);
++ return "";
++ }
++ else
++ return "%!jmp\t%A0";
++}
++
+ /* Output the assembly for a call instruction. */
+
+ const char *
+ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ bool direct_p = constant_call_address_operand (call_op, VOIDmode);
++ bool output_indirect_p
++ = (!TARGET_SEH
++ && ix86_indirect_branch != indirect_branch_keep);
+ bool seh_nop_p = false;
+ const char *xasm;
+
+@@ -28467,10 +28731,21 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ if (ix86_nopic_noplt_attribute_p (call_op))
+ {
++ direct_p = false;
+ if (TARGET_64BIT)
+- xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ else
++ xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ }
+ else
+- xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
++ else
++ xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ }
+ }
+ else
+ xasm = "%!jmp\t%P0";
+@@ -28480,9 +28755,17 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ else if (TARGET_SEH)
+ xasm = "%!rex.W jmp\t%A0";
+ else
+- xasm = "%!jmp\t%A0";
++ {
++ if (output_indirect_p)
++ xasm = "%0";
++ else
++ xasm = "%!jmp\t%A0";
++ }
+
+- output_asm_insn (xasm, &call_op);
++ if (output_indirect_p && !direct_p)
++ ix86_output_indirect_branch (call_op, xasm, true);
++ else
++ output_asm_insn (xasm, &call_op);
+ return "";
+ }
+
+@@ -28520,18 +28803,37 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ if (ix86_nopic_noplt_attribute_p (call_op))
+ {
++ direct_p = false;
+ if (TARGET_64BIT)
+- xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ else
++ xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ }
+ else
+- xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
++ else
++ xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ }
+ }
+ else
+ xasm = "%!call\t%P0";
+ }
+ else
+- xasm = "%!call\t%A0";
++ {
++ if (output_indirect_p)
++ xasm = "%0";
++ else
++ xasm = "%!call\t%A0";
++ }
+
+- output_asm_insn (xasm, &call_op);
++ if (output_indirect_p && !direct_p)
++ ix86_output_indirect_branch (call_op, xasm, false);
++ else
++ output_asm_insn (xasm, &call_op);
+
+ if (seh_nop_p)
+ return "nop";
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index 81cfba57afc..01b7b2039e6 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -11615,7 +11615,7 @@
+ (define_insn "*indirect_jump"
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
+ ""
+- "%!jmp\t%A0"
++ "* return ix86_output_indirect_jmp (operands[0]);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+@@ -11665,7 +11665,7 @@
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
+ (use (label_ref (match_operand 1)))]
+ ""
+- "%!jmp\t%A0"
++ "* return ix86_output_indirect_jmp (operands[0]);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+@@ -12337,7 +12337,7 @@
+ [(simple_return)
+ (use (match_operand:SI 0 "register_operand" "r"))]
+ "reload_completed"
+- "%!jmp\t%A0"
++ "* return ix86_output_indirect_jmp (operands[0]);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 9384e29b1de..1773e5614cf 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -927,3 +927,17 @@ Attempt to avoid generating instruction sequences containing ret bytes.
+ mgeneral-regs-only
+ Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
+ Generate code which uses only the general registers.
++
++mindirect-branch=
++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
++Update indirect call and jump.
++
++Enum
++Name(indirect_branch) Type(enum indirect_branch)
++Known indirect branch choices (for use with the -mindirect-branch= option):
++
++EnumValue
++Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
++
++EnumValue
++Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index a0fb09eb9e1..fafda2926bd 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1210,7 +1210,7 @@ See RS/6000 and PowerPC Options.
+ -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
+ -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
+ -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
+--mmitigate-rop -mgeneral-regs-only}
++-mmitigate-rop -mgeneral-regs-only -mindirect-branch=@var{choice}}
+
+ @emph{x86 Windows Options}
+ @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
+@@ -25648,6 +25648,13 @@ Generate code that uses only the general-purpose registers. This
+ prevents the compiler from using floating-point, vector, mask and bound
+ registers.
+
++@item -mindirect-branch=@var{choice}
++@opindex -mindirect-branch
++Update indirect call and jump with @var{choice}. The default is
++@samp{keep}, which keeps indirect call and jump unmodified.
++@samp{thunk} converts indirect call and jump to push and
++PC-relative call thunk.
++
+ @end table
+
+ These @samp{-m} switches are supported in addition to the above
+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..d8b6f5a06a5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler {\tlfence} } } */
+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..f7d5cb315a8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { 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..736d7cda058
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..cef9b10513e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..1a9bb0e431e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++
++extern void bar (void);
++
++void
++foo (void)
++{
++ bar ();
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { 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..bc7d20ec6ad
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { 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..ea0fa312f64
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -0,0 +1,43 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler {\tlfence} } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch b/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
new file mode 100644
index 000000000..2b4ac1b81
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
@@ -0,0 +1,554 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 2c14ecf03978ce6c60e021a2b0d72778a5fe0982 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 12 Dec 2017 12:34:26 -0800
+Subject: [PATCH 14/17] Add -mno-indirect-branch-register to indirect branch
+ tests
+
+---
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 2 +-
+ 44 files changed, 44 insertions(+), 44 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index 318db1e7f5c..b0625207b92 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index f2700dd36cf..0b289685e6b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index 46685d9a674..79a9f76285f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index 8f701775cea..901d94213bd 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+index f88ac31d07a..d2c9bd9d7ca 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+index d745116d321..f8b028db7a2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index 969cb8c6ddc..465775407ec 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index 12a61c3bbc7..5309d5a3eaa 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index a06907933a2..dd1efca49fd 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+index 7f56725e6b6..e97ca636020 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index fd4ab1dbaa0..b547cbbf255 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 1ffbf3b1181..353689dc415 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 1559072919a..1edef7208f4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index 1717e7bb436..c2e816cdfc6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+index 20903b0f79d..5c10de47b7c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+index aef4bd144f4..9eedd9a5a82 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+index 2cc0343f828..b2b8587eac7 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+index 91560fef661..9459a2417f4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index dc6bd10af4c..b0aa3811e65 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index 955aa256529..75fabcd988c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 1537239416f..1d9dff2e834 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index c82e53068fe..5b464155e38 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+index 23548d85f78..55ce91c73ec 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+index 56c2fe92f25..06180e7bee9 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+index e12b88593fe..790a05cec3e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 87b5429702f..1ce8ca5aff1 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+index a496a41a918..f6b71e868bd 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+index 6fe5ce71abf..84a09d4d0d6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+index 65cd997a33f..cfe3aefa0bf 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+index 7321d015c02..6411454243f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+index 6ec2e5621ab..d4297fe21c4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+index a3d1a13cded..eb318efdf4d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+index f0e8f4949c8..605e32bb584 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+index a577ac2568a..dd7a7b60621 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=nop -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=nop -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+index c8dcb9639c4..338f22c373c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+index 8569dfc92c3..3b083ee30a8 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+index bcf19c9ede1..31a9a81a911 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+index aecea4224f9..74f37ee9a62 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
+
+ extern void (*bar) (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+index 3bacfb54dfd..0a52318e86b 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+index 851115ac507..d2f775490ea 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+index 7acb6fa5eae..82d46165f3e 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { 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")));
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+index bf340fac7c6..6711eb27fa8 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ extern void (*bar) (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+index 735f8648c96..37758c33371 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+index 569e5f47973..70771ea35d7 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
+
+ extern void (*bar) (void);
+
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch b/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
new file mode 100644
index 000000000..e21bb5039
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
@@ -0,0 +1,134 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From ece041bc3083aabd00fab9de5ba409fbd7dcad8c Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 4 Dec 2017 12:58:20 -0800
+Subject: [PATCH 05/17] Add tests for -mindirect-branch=thunk
+ -fcheck-pointer-bounds -mmpx
+
+---
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 19 +++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 20 ++++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 18 ++++++++++++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 19 +++++++++++++++++++
+ 4 files changed, 76 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+
+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..a5b1d38e061
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile { target { ! x32 } } } */
++/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++
++void (*dispatch) (char *);
++char buf[10];
++
++void
++foo (void)
++{
++ dispatch (buf);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { 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 {\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..a42add209e2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile { target { ! x32 } } } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler "bnd ret" } } */
++/* { 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..265e010a0fe
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { 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 {\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..1c01bcb7fc6
+--- /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 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler "bnd ret" } } */
++/* { dg-final { scan-assembler {\tlfence} } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch b/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
new file mode 100644
index 000000000..b22e364af
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
@@ -0,0 +1,147 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From f96e28553b0f2253184441f22852d76976e19968 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 12 Dec 2017 19:15:25 -0800
+Subject: [PATCH 15/17] Disable red zone with local indirect jump
+
+---
+ gcc/config/i386/i386-protos.h | 2 +-
+ gcc/config/i386/i386.c | 22 +++++++++++++++++-----
+ gcc/config/i386/i386.h | 4 ++++
+ gcc/config/i386/i386.md | 8 +++++---
+ 4 files changed, 27 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
+index 213663811de..a78bfa00427 100644
+--- a/gcc/config/i386/i386-protos.h
++++ b/gcc/config/i386/i386-protos.h
+@@ -315,7 +315,7 @@ extern enum attr_cpu ix86_schedule;
+ #endif
+
+ extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+-extern const char * ix86_output_indirect_jmp (rtx call_op);
++extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
+ extern const char * ix86_output_function_return (bool long_p);
+ extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ enum machine_mode mode);
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 7ae3523095c..344cafe3dac 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -4209,12 +4209,19 @@ make_pass_stv (gcc::context *ctxt)
+ return new pass_stv (ctxt);
+ }
+
+-/* Return true if a red-zone is in use. */
++/* Return true if a red-zone is in use. We can't use red-zone when
++ there are local indirect jumps, like "indirect_jump" or "tablejump",
++ which jumps to another place in the function, since "call" in the
++ indirect thunk pushes the return address onto stack, destroying
++ red-zone. */
+
+ bool
+ ix86_using_red_zone (void)
+ {
+- return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
++ return (TARGET_RED_ZONE
++ && !TARGET_64BIT_MS_ABI
++ && (!cfun->machine->has_local_indirect_jump
++ || cfun->machine->indirect_branch_type == indirect_branch_keep));
+ }
+ \f
+ /* Return a string that documents the current -m options. The caller is
+@@ -28919,11 +28926,16 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ }
+
+ const char *
+-ix86_output_indirect_jmp (rtx call_op)
++ix86_output_indirect_jmp (rtx call_op, bool ret_p)
+ {
+- if (ix86_red_zone_size == 0
+- && cfun->machine->indirect_branch_type != indirect_branch_keep)
++ if (cfun->machine->indirect_branch_type != indirect_branch_keep)
+ {
++ /* We can't have red-zone if this isn't a function return since
++ "call" in the indirect thunk pushes the return address onto
++ stack, destroying red-zone. */
++ if (!ret_p && ix86_red_zone_size != 0)
++ gcc_unreachable ();
++
+ ix86_output_indirect_branch (call_op, "%0", true);
+ return "";
+ }
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index f248f3ba2f5..5f30d3f8d19 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2607,6 +2607,10 @@ struct GTY(()) machine_function {
+ /* How to generate indirec branch. */
+ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
+
++ /* If true, the current function has local indirect jumps, like
++ "indirect_jump" or "tablejump". */
++ BOOL_BITFIELD has_local_indirect_jump : 1;
++
+ /* How to generate function return. */
+ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
+
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index 473fa5c089b..ea95aad7540 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -11610,12 +11610,13 @@
+ {
+ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
++ cfun->machine->has_local_indirect_jump = true;
+ })
+
+ (define_insn "*indirect_jump"
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
+ ""
+- "* return ix86_output_indirect_jmp (operands[0]);"
++ "* return ix86_output_indirect_jmp (operands[0], false);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+@@ -11659,13 +11660,14 @@
+
+ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
++ cfun->machine->has_local_indirect_jump = true;
+ })
+
+ (define_insn "*tablejump_1"
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
+ (use (label_ref (match_operand 1)))]
+ ""
+- "* return ix86_output_indirect_jmp (operands[0]);"
++ "* return ix86_output_indirect_jmp (operands[0], false);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+@@ -12342,7 +12344,7 @@
+ [(simple_return)
+ (use (match_operand:SI 0 "register_operand" "r"))]
+ "reload_completed"
+- "* return ix86_output_indirect_jmp (operands[0]);"
++ "* return ix86_output_indirect_jmp (operands[0], true);"
+ [(set_attr "type" "ibr")
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch b/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
new file mode 100644
index 000000000..6379270df
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
@@ -0,0 +1,926 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From a072725899c551d9f3f06f3595e2a49748ab0187 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Sun, 7 Jan 2018 17:27:09 +0000
+Subject: [PATCH 17/17] Rename thunks to __x86_indirect_thunk_rax etc. to
+ remove dots
+
+---
+ gcc/config/i386/i386.c | 8 ++++----
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c | 6 +++---
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 10 +++++-----
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 10 +++++-----
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 10 +++++-----
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 6 +++---
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 6 +++---
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 6 +++---
+ gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 10 +++++-----
+ 58 files changed, 105 insertions(+), 105 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 6cb0681233a..9e6c9bdb514 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -12006,13 +12006,13 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
+ reg_prefix = TARGET_64BIT ? "r" : "e";
+ else
+ reg_prefix = "";
+- sprintf (name, "__x86.indirect_thunk%s.%s%s",
++ sprintf (name, "__x86_indirect_thunk%s_%s%s",
+ bnd, reg_prefix, reg_names[regno]);
+ }
+ else
+ {
+ const char *ret = ret_p ? "return" : "indirect";
+- sprintf (name, "__x86.%s_thunk%s", ret, bnd);
++ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
+ }
+ }
+ else
+@@ -12119,7 +12119,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+ char name[32];
+ tree decl;
+
+- /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
++ /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
+ indirect_thunk_name (name, regno, need_bnd_p, false);
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (name),
+@@ -12165,7 +12165,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+
+ if (regno < 0)
+ {
+- /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
++ /* Create alias for __x86_return_thunk/__x86_return_thunk_bnd. */
+ char alias[32];
+
+ indirect_thunk_name (alias, regno, need_bnd_p, true);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index b0625207b92..f4f2b7debe0 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index 0b289685e6b..d4e5dadd966 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index 79a9f76285f..9802fae5d04 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index 901d94213bd..fad3105b50d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+index d2c9bd9d7ca..e44f2ff5682 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -10,7 +10,7 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { 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
+index f8b028db7a2..f1e03a30854 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -11,7 +11,7 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+ /* { 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
+index 465775407ec..fc91a334459 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -36,8 +36,8 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index 5309d5a3eaa..a8ab95b6451 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index dd1efca49fd..467d62324d5 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\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
+index e97ca636020..02223f8d0f4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -17,5 +17,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index b547cbbf255..a80b46af934 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -16,5 +16,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 353689dc415..4bb1c5f9220 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -17,6 +17,6 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 1edef7208f4..4e33a638862 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -16,6 +16,6 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index c2e816cdfc6..427ba3ddbb4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -37,8 +37,8 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+index af1bb125a22..c246f974610 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+@@ -36,6 +36,6 @@ bar (int i)
+ }
+ }
+
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+ /* { 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-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+index 5c10de47b7c..3399ad56a7f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -12,7 +12,7 @@ foo (void)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd ret" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+index 9eedd9a5a82..daa9528f7bd 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -13,7 +13,7 @@ foo (void)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
+ /* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd ret" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+index b2b8587eac7..647ec5a4ade 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -11,7 +11,7 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "bnd ret" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+index 9459a2417f4..3a7a1cea8bc 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -12,7 +12,7 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk" } } */
+ /* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler "bnd ret" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index b0aa3811e65..5c20a35ecec 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index 75fabcd988c..b2fb6e1bcd2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 1d9dff2e834..9c84547cd7c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { 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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index 5b464155e38..457849564bb 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { 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-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+index 55ce91c73ec..5c07e02df6a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -10,7 +10,7 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+index 06180e7bee9..3eb440693a0 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+@@ -13,5 +13,5 @@ foo (void)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
+ /* { 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
+index 790a05cec3e..d4747ea0764 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -36,8 +36,8 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 1ce8ca5aff1..f7fad345ca4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -14,5 +14,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index f6b71e868bd..91388544a20 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -14,5 +14,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index 84a09d4d0d6..69f03e6472e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index cfe3aefa0bf..226b776abcf 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index 6411454243f..b9120017c10 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -12,4 +12,4 @@ foo (void)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index d4297fe21c4..fbd6f9ec457 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -13,4 +13,4 @@ foo (void)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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
+index eb318efdf4d..2553c56f97f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -39,4 +39,4 @@ bar (int i)
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+index 605e32bb584..c266ca6f2da 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+index dd7a7b60621..f7c1cf6c45a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tnop} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+index 338f22c373c..ef5c4b84312 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+index 3b083ee30a8..941fcdaffb1 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
+@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
++/* { 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-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+index 31a9a81a911..0c5ace58358 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|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-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+index ef493a05bbf..1a28abb4604 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+@@ -11,12 +11,12 @@ 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\]*__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 {\tlfence} } } */
+ /* { 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" } } */
++/* { dg-final { scan-assembler-not "__x86_indirect_thunk_" } } */
++/* { 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
+index 89fc8e6e6c4..428d6f9e986 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
+@@ -17,4 +17,4 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler {\tlfence} } } */
+ /* { 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" } } */
++/* { 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
+index 31af7ac05b8..28dcdcf2855 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+@@ -11,7 +11,7 @@ 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\]*__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(lfence|pause|nop)} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+index 406956f48e5..07f382c21b2 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+@@ -6,7 +6,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+index 74f37ee9a62..da8029bad49 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -12,11 +12,11 @@ foo (void)
+
+ /* { 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-not "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+index 0a52318e86b..6964997871d 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -10,13 +10,13 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { 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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+index d2f775490ea..ff0234bd17d 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -10,12 +10,12 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+index 82d46165f3e..a5b16472051 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -11,11 +11,11 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-times {\tlfence} 2 } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+ /* { 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" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
++/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+index 6711eb27fa8..219d71548bf 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -12,10 +12,10 @@ foo (void)
+ }
+
+ /* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { 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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+index 37758c33371..bad6b16820d 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -11,11 +11,11 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { 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 {\tlfence} 1 } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
+index cf3920563e0..173fe243d7b 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
+@@ -11,8 +11,8 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+-/* { dg-final { scan-assembler-not "__x86.return_thunk" } } */
++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
++/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-not {\tlfence} } } */
+ /* { 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-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+index 190947cc2ca..5516813a290 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+@@ -9,4 +9,4 @@ foo (void)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tlfence} } } */
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
+index d71de3ac520..9f1ade857ef 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
+@@ -6,7 +6,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-not {\tlfence} } } */
+ /* { 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
+index 68c22122f0d..abecde0a550 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
+@@ -6,7 +6,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-not {\tlfence} } } */
+ /* { 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
+index 28c576e2267..3b51a9931db 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
+@@ -8,7 +8,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+index 10ad40b9c26..52160e0ee77 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+@@ -10,4 +10,4 @@ foo (void)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tlfence} } } */
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { 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
+index 7ac0beaa73e..65819c2ab76 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
+@@ -7,7 +7,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-not {\tlfence} } } */
+ /* { 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
+index 777ab7c8088..a6a1bbc054b 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
+@@ -8,7 +8,7 @@ foo (void)
+ {
+ }
+
+-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+ /* { dg-final { scan-assembler-not {\tlfence} } } */
+ /* { 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
+index 70771ea35d7..21a0e6bde3d 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -10,14 +10,14 @@ foo (void)
+ return 0;
+ }
+
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
+-/* { dg-final { scan-assembler-not "__x86.return_thunk:" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
++/* { dg-final { scan-assembler-not "__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 "__x86_indirect_thunk:" } } */
+ /* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch b/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
new file mode 100644
index 000000000..bd6797816
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
@@ -0,0 +1,623 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From e4e33b44a49eaa102806589ce12f021ab6a1e5f1 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Wed, 13 Dec 2017 12:59:50 -0800
+Subject: [PATCH 09/17] Use __x86.indirect_thunk.reg for indirect branch via
+ register
+
+---
+ gcc/config/i386/i386.c | 137 +++++++++++++++++----
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 4 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 4 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 8 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 8 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-attr-1.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-attr-2.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-5.c | 8 +-
+ .../gcc.target/i386/indirect-thunk-attr-6.c | 8 +-
+ .../gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-1.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-extern-2.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-extern-3.c | 8 +-
+ .../gcc.target/i386/indirect-thunk-extern-4.c | 8 +-
+ .../gcc.target/i386/indirect-thunk-extern-7.c | 4 +-
+ .../gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ 23 files changed, 158 insertions(+), 75 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 5e66af08066..590729b3f87 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -11948,6 +11948,9 @@ static int indirectlabelno;
+ static bool indirect_thunk_needed = false;
+ static bool indirect_thunk_bnd_needed = false;
+
++static int indirect_thunks_used;
++static int indirect_thunks_bnd_used;
++
+ #ifndef INDIRECT_LABEL
+ # define INDIRECT_LABEL "LIND"
+ #endif
+@@ -11955,24 +11958,45 @@ static bool indirect_thunk_bnd_needed = false;
+ /* Fills in the label name that should be used for the indirect thunk. */
+
+ static void
+-indirect_thunk_name (char name[32], bool need_bnd_p)
++indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
+ {
+ if (USE_HIDDEN_LINKONCE)
+ {
+ const char *bnd = need_bnd_p ? "_bnd" : "";
+- sprintf (name, "__x86.indirect_thunk%s", bnd);
++ if (regno >= 0)
++ {
++ const char *reg_prefix;
++ if (LEGACY_INT_REGNO_P (regno))
++ reg_prefix = TARGET_64BIT ? "r" : "e";
++ else
++ reg_prefix = "";
++ sprintf (name, "__x86.indirect_thunk%s.%s%s",
++ bnd, reg_prefix, reg_names[regno]);
++ }
++ else
++ sprintf (name, "__x86.indirect_thunk%s", bnd);
+ }
+ else
+ {
+- if (need_bnd_p)
+- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ if (regno >= 0)
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
++ }
+ else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ }
+ }
+ }
+
+ static void
+-output_indirect_thunk (bool need_bnd_p)
++output_indirect_thunk (bool need_bnd_p, int regno)
+ {
+ char indirectlabel1[32];
+ char indirectlabel2[32];
+@@ -12002,11 +12026,22 @@ output_indirect_thunk (bool need_bnd_p)
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+- /* LEA. */
+- rtx xops[2];
+- xops[0] = stack_pointer_rtx;
+- xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
+- output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
++ if (regno >= 0)
++ {
++ /* MOV. */
++ rtx xops[2];
++ xops[0] = gen_rtx_MEM (word_mode, stack_pointer_rtx);
++ xops[1] = gen_rtx_REG (word_mode, regno);
++ output_asm_insn ("mov\t{%1, %0|%0, %1}", xops);
++ }
++ else
++ {
++ /* LEA. */
++ rtx xops[2];
++ xops[0] = stack_pointer_rtx;
++ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
++ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
++ }
+
+ if (need_bnd_p)
+ fputs ("\tbnd ret\n", asm_out_file);
+@@ -12015,12 +12050,13 @@ output_indirect_thunk (bool need_bnd_p)
+ }
+
+ static void
+-output_indirect_thunk_function (bool need_bnd_p)
++output_indirect_thunk_function (bool need_bnd_p, int regno)
+ {
+ char name[32];
+ tree decl;
+
+- indirect_thunk_name (name, need_bnd_p);
++ /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
++ indirect_thunk_name (name, regno, need_bnd_p);
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (name),
+ build_function_type_list (void_type_node, NULL_TREE));
+@@ -12074,7 +12110,7 @@ output_indirect_thunk_function (bool need_bnd_p)
+ /* Make sure unwind info is emitted for the thunk if needed. */
+ final_start_function (emit_barrier (), asm_out_file, 1);
+
+- output_indirect_thunk (need_bnd_p);
++ output_indirect_thunk (need_bnd_p, regno);
+
+ final_end_function ();
+ init_insn_lengths ();
+@@ -12110,15 +12146,31 @@ ix86_code_end (void)
+ int regno;
+
+ if (indirect_thunk_needed)
+- output_indirect_thunk_function (false);
++ output_indirect_thunk_function (false, -1);
+ if (indirect_thunk_bnd_needed)
+- output_indirect_thunk_function (true);
++ output_indirect_thunk_function (true, -1);
++
++ for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
++ {
++ int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1;
++ if ((indirect_thunks_used & (1 << i)))
++ output_indirect_thunk_function (false, regno);
++
++ if ((indirect_thunks_bnd_used & (1 << i)))
++ output_indirect_thunk_function (true, regno);
++ }
+
+ for (regno = AX_REG; regno <= SP_REG; regno++)
+ {
+ char name[32];
+ tree decl;
+
++ if ((indirect_thunks_used & (1 << regno)))
++ output_indirect_thunk_function (false, regno);
++
++ if ((indirect_thunks_bnd_used & (1 << regno)))
++ output_indirect_thunk_function (true, regno);
++
+ if (!(pic_labels_used & (1 << regno)))
+ continue;
+
+@@ -28639,17 +28691,37 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ char *thunk_name;
+ char push_buf[64];
+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++ int regno;
++
++ if (REG_P (call_op))
++ regno = REGNO (call_op);
++ else
++ regno = -1;
+
+ if (cfun->machine->indirect_branch_type
+ != indirect_branch_thunk_inline)
+ {
+- bool need_thunk
+- = cfun->machine->indirect_branch_type == indirect_branch_thunk;
+- if (need_bnd_p)
+- indirect_thunk_bnd_needed |= need_thunk;
+- else
+- indirect_thunk_needed |= need_thunk;
+- indirect_thunk_name (thunk_name_buf, need_bnd_p);
++ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
++ {
++ if (regno >= 0)
++ {
++ int i = regno;
++ if (i >= FIRST_REX_INT_REG)
++ i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
++ if (need_bnd_p)
++ indirect_thunks_bnd_used |= 1 << i;
++ else
++ indirect_thunks_used |= 1 << i;
++ }
++ else
++ {
++ if (need_bnd_p)
++ indirect_thunk_bnd_needed = true;
++ else
++ indirect_thunk_needed = true;
++ }
++ }
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
+ thunk_name = thunk_name_buf;
+ }
+ else
+@@ -28660,7 +28732,8 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+
+ if (sibcall_p)
+ {
+- output_asm_insn (push_buf, &call_op);
++ if (regno < 0)
++ output_asm_insn (push_buf, &call_op);
+ if (thunk_name != NULL)
+ {
+ if (need_bnd_p)
+@@ -28669,10 +28742,19 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+- output_indirect_thunk (need_bnd_p);
++ output_indirect_thunk (need_bnd_p, regno);
+ }
+ else
+ {
++ if (regno >= 0 && thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
++ return;
++ }
++
+ char indirectlabel1[32];
+ char indirectlabel2[32];
+
+@@ -28725,7 +28807,8 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ }
+ }
+
+- output_asm_insn (push_buf, &call_op);
++ if (regno < 0)
++ output_asm_insn (push_buf, &call_op);
+
+ if (thunk_name != NULL)
+ {
+@@ -28735,7 +28818,7 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ }
+ else
+- output_indirect_thunk (need_bnd_p);
++ output_indirect_thunk (need_bnd_p, regno);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index d8b6f5a06a5..785e593405f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index f7d5cb315a8..b69075e6483 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index 736d7cda058..df8109baf55 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index cef9b10513e..8f3b9f4d8a5 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index ea0fa312f64..f0e1cfe1893 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -36,8 +36,8 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index 26550fad4c8..8b88449e625 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index f57bb2a92d6..c69f7bf4f60 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\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
+index a3668a6586c..c845099a83e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -15,7 +15,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+ /* { 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-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index a9c4a137dd4..f636f3422fd 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+ /* { 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-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 9582e0c5824..5f1d6a78041 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { 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-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 66442cacfe8..56c92da9812 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -14,8 +14,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { 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-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index 2a19b54cd2e..cfb6f5b234b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -37,7 +37,7 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+ /* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index 0a1f91be988..f1fa0a11922 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index 182520ab3dc..d6e078d594b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 5c31ddc34fd..3bbe2646955 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 "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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index f24d0c060f2..596fac599f6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 "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
+index 8d39fb6f939..ab367951c45 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -36,8 +36,8 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 071e6c89ac7..09b8ad7d879 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { 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
+index 804c7ccdba7..1f873758fbe 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { 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
+index 545a981add5..b24af1da963 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+ /* { 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
+index d9ff4722cff..1a86608f727 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
+ /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+ /* { 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-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+index a0ce06b8232..01d45782185 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -36,7 +36,7 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch b/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
new file mode 100644
index 000000000..1996a1dfe
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
@@ -0,0 +1,76 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From f83391fb22471a2f1c330e2e78f64630d64f497d Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 19 Dec 2017 08:28:36 -0800
+Subject: [PATCH 16/17] i386: Add 'V' register operand modifier
+
+For
+
+void
+bar (void (*func) (void))
+{
+ asm("call *%V0" : : "r"(func));
+}
+
+it generates:
+
+bar:
+ call *rdi
+ ret
+---
+ gcc/config/i386/i386.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 344cafe3dac..6cb0681233a 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -17886,6 +17886,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
+ If CODE is 'h', pretend the reg is the 'high' byte register.
+ If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
+ If CODE is 'd', duplicate the operand for AVX instruction.
++ If CODE is 'V', print naked register name without %.
+ */
+
+ void
+@@ -17896,7 +17897,7 @@ print_reg (rtx x, int code, FILE *file)
+ unsigned int regno;
+ bool duplicated;
+
+- if (ASSEMBLER_DIALECT == ASM_ATT)
++ if (ASSEMBLER_DIALECT == ASM_ATT && code != 'V')
+ putc ('%', file);
+
+ if (x == pc_rtx)
+@@ -18063,6 +18064,7 @@ print_reg (rtx x, int code, FILE *file)
+ & -- print some in-use local-dynamic symbol name.
+ H -- print a memory address offset by 8; used for sse high-parts
+ Y -- print condition for XOP pcom* instruction.
++ V -- print naked register name without %.
+ + -- print a branch hint as 'cs' or 'ds' prefix
+ ; -- print a semicolon (after prefixes due to bug in older gas).
+ ~ -- print "i" if TARGET_AVX2, "f" otherwise.
+@@ -18287,6 +18289,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
+ case 'X':
+ case 'P':
+ case 'p':
++ case 'V':
+ break;
+
+ case 's':
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
new file mode 100644
index 000000000..3c42dd802
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
@@ -0,0 +1,69 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From d96784e4a7355aaab68dec62f31a97bd10714064 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 28 Nov 2017 10:26:35 -0800
+Subject: [PATCH 03/17] i386: More use reference of struct ix86_frame to avoid
+ copy
+
+When there is no need to make a copy of ix86_frame, we can use reference
+of struct ix86_frame to avoid copy.
+
+ * config/i386/i386.c (ix86_expand_prologue): Use reference of
+ struct ix86_frame.
+ (ix86_expand_epilogue): Likewise.
+---
+ gcc/config/i386/i386.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 01ecda7643b..504530a00cf 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -13656,7 +13656,6 @@ ix86_expand_prologue (void)
+ {
+ struct machine_function *m = cfun->machine;
+ rtx insn, t;
+- struct ix86_frame frame;
+ HOST_WIDE_INT allocate;
+ bool int_registers_saved;
+ bool sse_registers_saved;
+@@ -13680,7 +13679,7 @@ ix86_expand_prologue (void)
+ m->fs.sp_valid = true;
+
+ ix86_compute_frame_layout ();
+- frame = m->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
+ {
+@@ -14343,13 +14342,12 @@ ix86_expand_epilogue (int style)
+ {
+ struct machine_function *m = cfun->machine;
+ struct machine_frame_state frame_state_save = m->fs;
+- struct ix86_frame frame;
+ bool restore_regs_via_mov;
+ bool using_drap;
+
+ ix86_finalize_stack_realign_flags ();
+ ix86_compute_frame_layout ();
+- frame = m->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ m->fs.sp_valid = (!frame_pointer_needed
+ || (crtl->sp_is_unchanging
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
new file mode 100644
index 000000000..908e3cd83
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
@@ -0,0 +1,249 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 85743811dfa4eb648edbbb637632ac53182b6e05 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 6 Nov 2017 09:11:08 -0800
+Subject: [PATCH 01/17] i386: Move struct ix86_frame to machine_function
+
+Make ix86_frame available to i386 code generation.
+
+ * config/i386/i386.c (ix86_frame): Moved to ...
+ * config/i386/i386.h (ix86_frame): Here.
+ (machine_function): Add frame.
+ * config/i386/i386.c (ix86_compute_frame_layout): Repace the
+ frame argument with &cfun->machine->frame.
+ (ix86_can_use_return_insn_p): Don't pass &frame to
+ ix86_compute_frame_layout. Copy frame from cfun->machine->frame.
+ (ix86_can_eliminate): Likewise.
+ (ix86_expand_prologue): Likewise.
+ (ix86_expand_epilogue): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+---
+ gcc/config/i386/i386.c | 68 ++++++++++----------------------------------------
+ gcc/config/i386/i386.h | 53 ++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 65 insertions(+), 56 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index dc14d205de7..c23c259c538 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -2441,53 +2441,6 @@ struct GTY(()) stack_local_entry {
+ struct stack_local_entry *next;
+ };
+
+-/* Structure describing stack frame layout.
+- Stack grows downward:
+-
+- [arguments]
+- <- ARG_POINTER
+- saved pc
+-
+- saved static chain if ix86_static_chain_on_stack
+-
+- saved frame pointer if frame_pointer_needed
+- <- HARD_FRAME_POINTER
+- [saved regs]
+- <- regs_save_offset
+- [padding0]
+-
+- [saved SSE regs]
+- <- sse_regs_save_offset
+- [padding1] |
+- | <- FRAME_POINTER
+- [va_arg registers] |
+- |
+- [frame] |
+- |
+- [padding2] | = to_allocate
+- <- STACK_POINTER
+- */
+-struct ix86_frame
+-{
+- int nsseregs;
+- int nregs;
+- int va_arg_size;
+- int red_zone_size;
+- int outgoing_arguments_size;
+-
+- /* The offsets relative to ARG_POINTER. */
+- HOST_WIDE_INT frame_pointer_offset;
+- HOST_WIDE_INT hard_frame_pointer_offset;
+- HOST_WIDE_INT stack_pointer_offset;
+- HOST_WIDE_INT hfp_save_offset;
+- HOST_WIDE_INT reg_save_offset;
+- HOST_WIDE_INT sse_reg_save_offset;
+-
+- /* When save_regs_using_mov is set, emit prologue using
+- move instead of push instructions. */
+- bool save_regs_using_mov;
+-};
+-
+ /* Which cpu are we scheduling for. */
+ enum attr_cpu ix86_schedule;
+
+@@ -2579,7 +2532,7 @@ static unsigned int ix86_function_arg_boundary (machine_mode,
+ const_tree);
+ static rtx ix86_static_chain (const_tree, bool);
+ static int ix86_function_regparm (const_tree, const_tree);
+-static void ix86_compute_frame_layout (struct ix86_frame *);
++static void ix86_compute_frame_layout (void);
+ static bool ix86_expand_vector_init_one_nonzero (bool, machine_mode,
+ rtx, rtx, int);
+ static void ix86_add_new_builtins (HOST_WIDE_INT, HOST_WIDE_INT);
+@@ -11892,7 +11845,8 @@ ix86_can_use_return_insn_p (void)
+ if (crtl->args.pops_args && crtl->args.size >= 32768)
+ return 0;
+
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = cfun->machine->frame;
+ return (frame.stack_pointer_offset == UNITS_PER_WORD
+ && (frame.nregs + frame.nsseregs) == 0);
+ }
+@@ -12378,8 +12332,8 @@ ix86_can_eliminate (const int from, const int to)
+ HOST_WIDE_INT
+ ix86_initial_elimination_offset (int from, int to)
+ {
+- struct ix86_frame frame;
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ struct ix86_frame frame = cfun->machine->frame;
+
+ if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return frame.hard_frame_pointer_offset;
+@@ -12418,8 +12372,9 @@ ix86_builtin_setjmp_frame_value (void)
+ /* Fill structure ix86_frame about frame of currently computed function. */
+
+ static void
+-ix86_compute_frame_layout (struct ix86_frame *frame)
++ix86_compute_frame_layout (void)
+ {
++ struct ix86_frame *frame = &cfun->machine->frame;
+ unsigned HOST_WIDE_INT stack_alignment_needed;
+ HOST_WIDE_INT offset;
+ unsigned HOST_WIDE_INT preferred_alignment;
+@@ -13726,7 +13681,8 @@ ix86_expand_prologue (void)
+ m->fs.sp_offset = INCOMING_FRAME_SP_OFFSET;
+ m->fs.sp_valid = true;
+
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = m->frame;
+
+ if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
+ {
+@@ -14394,7 +14350,8 @@ ix86_expand_epilogue (int style)
+ bool using_drap;
+
+ ix86_finalize_stack_realign_flags ();
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = m->frame;
+
+ m->fs.sp_valid = (!frame_pointer_needed
+ || (crtl->sp_is_unchanging
+@@ -14904,7 +14861,8 @@ ix86_expand_split_stack_prologue (void)
+ gcc_assert (flag_split_stack && reload_completed);
+
+ ix86_finalize_stack_realign_flags ();
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = cfun->machine->frame;
+ allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
+
+ /* This is the label we will branch to if we have enough stack
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 9e5f4d857d9..7d9f9020fb3 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2446,9 +2446,56 @@ enum avx_u128_state
+ \f
+ #define FASTCALL_PREFIX '@'
+ \f
++#ifndef USED_FOR_TARGET
++/* Structure describing stack frame layout.
++ Stack grows downward:
++
++ [arguments]
++ <- ARG_POINTER
++ saved pc
++
++ saved static chain if ix86_static_chain_on_stack
++
++ saved frame pointer if frame_pointer_needed
++ <- HARD_FRAME_POINTER
++ [saved regs]
++ <- regs_save_offset
++ [padding0]
++
++ [saved SSE regs]
++ <- sse_regs_save_offset
++ [padding1] |
++ | <- FRAME_POINTER
++ [va_arg registers] |
++ |
++ [frame] |
++ |
++ [padding2] | = to_allocate
++ <- STACK_POINTER
++ */
++struct GTY(()) ix86_frame
++{
++ int nsseregs;
++ int nregs;
++ int va_arg_size;
++ int red_zone_size;
++ int outgoing_arguments_size;
++
++ /* The offsets relative to ARG_POINTER. */
++ HOST_WIDE_INT frame_pointer_offset;
++ HOST_WIDE_INT hard_frame_pointer_offset;
++ HOST_WIDE_INT stack_pointer_offset;
++ HOST_WIDE_INT hfp_save_offset;
++ HOST_WIDE_INT reg_save_offset;
++ HOST_WIDE_INT sse_reg_save_offset;
++
++ /* When save_regs_using_mov is set, emit prologue using
++ move instead of push instructions. */
++ bool save_regs_using_mov;
++};
++
+ /* Machine specific frame tracking during prologue/epilogue generation. */
+
+-#ifndef USED_FOR_TARGET
+ struct GTY(()) machine_frame_state
+ {
+ /* This pair tracks the currently active CFA as reg+offset. When reg
+@@ -2507,6 +2554,9 @@ struct GTY(()) machine_function {
+ int varargs_fpr_size;
+ int optimize_mode_switching[MAX_386_ENTITIES];
+
++ /* Cached initial frame layout for the current function. */
++ struct ix86_frame frame;
++
+ /* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE
+ has been computed for. */
+ int use_fast_prologue_epilogue_nregs;
+@@ -2589,6 +2639,7 @@ struct GTY(()) machine_function {
+ #define ix86_current_function_calls_tls_descriptor \
+ (ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
+ #define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
++#define ix86_red_zone_size (cfun->machine->frame.red_zone_size)
+
+ /* Control behavior of x86_file_start. */
+ #define X86_FILE_START_VERSION_DIRECTIVE false
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
new file mode 100644
index 000000000..623ce5094
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
@@ -0,0 +1,85 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-20180107' branch of upstream source repository
+(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
+appears):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 0b1769bdce27304a6a91bec234f47f102a2603d5 Mon Sep 17 00:00:00 2001
+From: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Mon, 6 Nov 2017 23:04:15 +0000
+Subject: [PATCH 02/17] i386: Use reference of struct ix86_frame to avoid copy
+
+When there is no need to make a copy of ix86_frame, we can use reference
+of struct ix86_frame to avoid copy.
+
+Tested on x86-64.
+
+ * config/i386/i386.c (ix86_can_use_return_insn_p): Use reference
+ of struct ix86_frame.
+ (ix86_initial_elimination_offset): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254480 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/config/i386/i386.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index c23c259c538..01ecda7643b 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -11832,8 +11832,6 @@ symbolic_reference_mentioned_p (rtx op)
+ bool
+ ix86_can_use_return_insn_p (void)
+ {
+- struct ix86_frame frame;
+-
+ /* Don't use `ret' instruction in interrupt handler. */
+ if (! reload_completed
+ || frame_pointer_needed
+@@ -11846,7 +11844,7 @@ ix86_can_use_return_insn_p (void)
+ return 0;
+
+ ix86_compute_frame_layout ();
+- frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+ return (frame.stack_pointer_offset == UNITS_PER_WORD
+ && (frame.nregs + frame.nsseregs) == 0);
+ }
+@@ -12333,7 +12331,7 @@ HOST_WIDE_INT
+ ix86_initial_elimination_offset (int from, int to)
+ {
+ ix86_compute_frame_layout ();
+- struct ix86_frame frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return frame.hard_frame_pointer_offset;
+@@ -14849,7 +14847,6 @@ static GTY(()) rtx split_stack_fn_large;
+ void
+ ix86_expand_split_stack_prologue (void)
+ {
+- struct ix86_frame frame;
+ HOST_WIDE_INT allocate;
+ unsigned HOST_WIDE_INT args_size;
+ rtx_code_label *label;
+@@ -14862,7 +14859,7 @@ ix86_expand_split_stack_prologue (void)
+
+ ix86_finalize_stack_realign_flags ();
+ ix86_compute_frame_layout ();
+- frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+ allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
+
+ /* This is the label we will branch to if we have enough stack
+--
+2.15.1
+
--
2.15.1
[-- Attachment #3: Type: text/plain, Size: 14 bytes --]
Cheers,
Alex
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-14 13:07 [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique Alex Vong
@ 2018-01-15 14:29 ` Alex Vong
2018-01-16 13:14 ` Alex Vong
2018-01-27 3:19 ` [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself Alex Vong
` (2 subsequent siblings)
3 siblings, 1 reply; 14+ messages in thread
From: Alex Vong @ 2018-01-15 14:29 UTC (permalink / raw)
To: 30111
Hello,
Please do not review the last patch. It seems the author[0] has
refactor the commits and place them into the new 'retpoline-regnames'
branch. I think these commits get sent to gcc-patches for review[1].
[0]: http://git.infradead.org/users/dwmw2/gcc-retpoline.git
[1]: https://gcc.gnu.org/ml/gcc-patches/2018-01/
Alex Vong <alexvong1995@gmail.com> writes:
> Hello,
>
> This patch adds the repoline patches (totally 17 of them) taken from the
> 'retpoline-20180107' branch at
> ``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
>
> Last time it builds fine on my laptop. I am now re-building since I add
> some comments on the patches. I will reply asap if anything goes wrong
> with the re-build.
>
> From 5be54f7ebe9b0ab6dc65ea974584be0850604b14 Mon Sep 17 00:00:00 2001
> From: Alex Vong <alexvong1995@gmail.com>
> Date: Sun, 14 Jan 2018 20:12:19 +0800
> Subject: [PATCH] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
>
> This is part of Spectre (branch target injection) [CVE-2017-5715]
> mitigation. Suggested by Mark H Weaver <mhw@netris.org>.
>
> * gnu/local.mk (dist_patch_DATA): Add them.
> * gnu/packages/gcc.scm (gcc@7): Use them.
> * gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch,
> gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch,
> gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch,
> gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch,
> gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch,
> gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch,
> gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch,
> gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch,
> gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch,
> gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch,
> gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch,
> gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch,
> gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch,
> gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch,
> gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch,
> gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch,
> gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch:
> New files.
> ---
> gnu/local.mk | 19 +-
> gnu/packages/gcc.scm | 20 +-
> ...-Add-indirect_branch-attribute-with-tests.patch | 475 +++++++++++
> ...tion-return-and-function_return-attribute.patch | 740 ++++++++++++++++
> ...tion-return-keep-to-indirect-branch-tests.patch | 421 ++++++++++
> .../gcc-retpoline-Add-mindirect-branch-loop.patch | 233 ++++++
> ...e-Add-mindirect-branch-register-and-tests.patch | 403 +++++++++
> ...tpoline-Add-mindirect-branch-thunk-extern.patch | 263 ++++++
> ...tpoline-Add-mindirect-branch-thunk-inline.patch | 310 +++++++
> .../gcc-retpoline-Add-mindirect-branch-thunk.patch | 729 ++++++++++++++++
> ...irect-branch-register-to-indirect-branch-.patch | 554 ++++++++++++
> ...or-mindirect-branch-thunk-fcheck-pointer-.patch | 134 +++
> ...Disable-red-zone-with-local-indirect-jump.patch | 147 ++++
> ...ks-to-__x86_indirect_thunk_rax-etc.-to-re.patch | 926 +++++++++++++++++++++
> ...ndirect_thunk.reg-for-indirect-branch-via.patch | 623 ++++++++++++++
> ...line-i386-Add-V-register-operand-modifier.patch | 76 ++
> ...se-reference-of-struct-ix86_frame-to-avoi.patch | 69 ++
> ...ove-struct-ix86_frame-to-machine_function.patch | 249 ++++++
> ...ference-of-struct-ix86_frame-to-avoid-cop.patch | 85 ++
> 19 files changed, 6474 insertions(+), 2 deletions(-)
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
> create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
>
> diff --git a/gnu/local.mk b/gnu/local.mk
> index 6af8bfc4b..122e8ef0c 100644
> --- a/gnu/local.mk
> +++ b/gnu/local.mk
> @@ -9,7 +9,7 @@
> # Copyright © 2016 Adonay "adfeno" Felipe Nogueira <https://libreplanet.org/wiki/User:Adfeno> <adfeno@openmailbox.org>
> # Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net>
> # Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
> -# Copyright © 2016, 2017 Alex Vong <alexvong1995@gmail.com>
> +# Copyright © 2016, 2017, 2018 Alex Vong <alexvong1995@gmail.com>
> # Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
> # Copyright © 2016, 2017 Jan Nieuwenhuizen <janneke@gnu.org>
> # Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
> @@ -652,6 +652,23 @@ dist_patch_DATA = \
> %D%/packages/patches/gcc-asan-powerpc-missing-include.patch \
> %D%/packages/patches/gcc-cross-environment-variables.patch \
> %D%/packages/patches/gcc-libvtv-runpath.patch \
> + %D%/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch \
> + %D%/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch \
> + %D%/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch \
> + %D%/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch \
> + %D%/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch \
> + %D%/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch \
> + %D%/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch \
> + %D%/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch \
> + %D%/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch \
> + %D%/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch \
> %D%/packages/patches/gcc-strmov-store-file-names.patch \
> %D%/packages/patches/gcc-4-compile-with-gcc-5.patch \
> %D%/packages/patches/gcc-4.6-gnu-inline.patch \
> diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
> index ad8992289..6b913aff9 100644
> --- a/gnu/packages/gcc.scm
> +++ b/gnu/packages/gcc.scm
> @@ -5,6 +5,7 @@
> ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
> ;;; Copyright © 2015, 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
> ;;; Copyright © 2016 Carlos Sánchez de La Lama <csanchezdll@gmail.com>
> +;;; Copyright © 2018 ALex Vong <alexvong1995@gmail.com>
> ;;;
> ;;; This file is part of GNU Guix.
> ;;;
> @@ -427,7 +428,24 @@ Go. It also includes runtime support libraries for these languages.")
> (base32
> "16j7i0888j2f1yp9l0nhji6cq65dy6y4nwy8868a8njbzzwavxqw"))
> (patches (search-patches "gcc-strmov-store-file-names.patch"
> - "gcc-5.0-libvtv-runpath.patch"))))
> + "gcc-5.0-libvtv-runpath.patch"
> + "gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch"
> + "gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch"
> + "gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch"
> + "gcc-retpoline-Add-mindirect-branch-thunk.patch"
> + "gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch"
> + "gcc-retpoline-Add-mindirect-branch-thunk-inline.patch"
> + "gcc-retpoline-Add-mindirect-branch-thunk-extern.patch"
> + "gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch"
> + "gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch"
> + "gcc-retpoline-Add-mindirect-branch-loop.patch"
> + "gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch"
> + "gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch"
> + "gcc-retpoline-Add-mindirect-branch-register-and-tests.patch"
> + "gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch"
> + "gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch"
> + "gcc-retpoline-i386-Add-V-register-operand-modifier.patch"
> + "gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch"))))
> (description
> "GCC is the GNU Compiler Collection. It provides compiler front-ends
> for several languages, including C, C++, Objective-C, Fortran, Ada, and Go.
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
> new file mode 100644
> index 000000000..5129a8273
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-indirect_branch-attribute-with-tests.patch
> @@ -0,0 +1,475 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From e9794727bb0384be6d27ad1edaefc71c23cc0d86 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 28 Nov 2017 06:10:39 -0800
> +Subject: [PATCH 08/17] Add indirect_branch attribute with tests
> +
> +__attribute__ ((indirect_branch("thunk")))
> +__attribute__ ((indirect_branch("thunk-inline")))
> +__attribute__ ((indirect_branch("thunk-extern")))
> +__attribute__ ((indirect_branch("keep")))
> +---
> + gcc/config/i386/i386-opts.h | 1 +
> + gcc/config/i386/i386.c | 74 ++++++++++++++++++++--
> + gcc/config/i386/i386.h | 3 +
> + .../gcc.target/i386/indirect-thunk-attr-1.c | 22 +++++++
> + .../gcc.target/i386/indirect-thunk-attr-2.c | 20 ++++++
> + .../gcc.target/i386/indirect-thunk-attr-3.c | 21 ++++++
> + .../gcc.target/i386/indirect-thunk-attr-4.c | 20 ++++++
> + .../gcc.target/i386/indirect-thunk-attr-5.c | 22 +++++++
> + .../gcc.target/i386/indirect-thunk-attr-6.c | 21 ++++++
> + .../gcc.target/i386/indirect-thunk-attr-7.c | 44 +++++++++++++
> + .../gcc.target/i386/indirect-thunk-attr-8.c | 41 ++++++++++++
> + 11 files changed, 283 insertions(+), 6 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +
> +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> +index f8d80ba7ec6..9e56d7f2d12 100644
> +--- a/gcc/config/i386/i386-opts.h
> ++++ b/gcc/config/i386/i386-opts.h
> +@@ -100,6 +100,7 @@ enum stack_protector_guard {
> + };
> +
> + enum indirect_branch {
> ++ indirect_branch_unset = 0,
> + indirect_branch_keep,
> + indirect_branch_thunk,
> + indirect_branch_thunk_inline,
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index ac542f79846..5e66af08066 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -7137,6 +7137,37 @@ ix86_set_func_type (tree fndecl)
> + }
> + }
> +
> ++/* Set the indirect_branch_type field from the function FNDECL. */
> ++
> ++static void
> ++ix86_set_indirect_branch_type (tree fndecl)
> ++{
> ++ if (cfun->machine->indirect_branch_type == indirect_branch_unset)
> ++ {
> ++ tree attr = lookup_attribute ("indirect_branch",
> ++ DECL_ATTRIBUTES (fndecl));
> ++ if (attr != NULL)
> ++ {
> ++ tree args = TREE_VALUE (attr);
> ++ if (args == NULL)
> ++ gcc_unreachable ();
> ++ tree cst = TREE_VALUE (args);
> ++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
> ++ cfun->machine->indirect_branch_type = indirect_branch_keep;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
> ++ cfun->machine->indirect_branch_type = indirect_branch_thunk;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
> ++ cfun->machine->indirect_branch_type = indirect_branch_thunk_inline;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
> ++ cfun->machine->indirect_branch_type = indirect_branch_thunk_extern;
> ++ else
> ++ gcc_unreachable ();
> ++ }
> ++ else
> ++ cfun->machine->indirect_branch_type = ix86_indirect_branch;
> ++ }
> ++}
> ++
> + /* Establish appropriate back-end context for processing the function
> + FNDECL. The argument might be NULL to indicate processing at top
> + level, outside of any function scope. */
> +@@ -7152,7 +7183,10 @@ ix86_set_current_function (tree fndecl)
> + one is extern inline and one isn't. Call ix86_set_func_type
> + to set the func_type field. */
> + if (fndecl != NULL_TREE)
> +- ix86_set_func_type (fndecl);
> ++ {
> ++ ix86_set_func_type (fndecl);
> ++ ix86_set_indirect_branch_type (fndecl);
> ++ }
> + return;
> + }
> +
> +@@ -7172,6 +7206,7 @@ ix86_set_current_function (tree fndecl)
> + }
> +
> + ix86_set_func_type (fndecl);
> ++ ix86_set_indirect_branch_type (fndecl);
> +
> + tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
> + if (new_tree == NULL_TREE)
> +@@ -28605,9 +28640,11 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + char push_buf[64];
> + bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
> +
> +- if (ix86_indirect_branch != indirect_branch_thunk_inline)
> ++ if (cfun->machine->indirect_branch_type
> ++ != indirect_branch_thunk_inline)
> + {
> +- bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
> ++ bool need_thunk
> ++ = cfun->machine->indirect_branch_type == indirect_branch_thunk;
> + if (need_bnd_p)
> + indirect_thunk_bnd_needed |= need_thunk;
> + else
> +@@ -28716,7 +28753,7 @@ const char *
> + ix86_output_indirect_jmp (rtx call_op)
> + {
> + if (ix86_red_zone_size == 0
> +- && ix86_indirect_branch != indirect_branch_keep)
> ++ && cfun->machine->indirect_branch_type != indirect_branch_keep)
> + {
> + ix86_output_indirect_branch (call_op, "%0", true);
> + return "";
> +@@ -28733,7 +28770,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
> + bool direct_p = constant_call_address_operand (call_op, VOIDmode);
> + bool output_indirect_p
> + = (!TARGET_SEH
> +- && ix86_indirect_branch != indirect_branch_keep);
> ++ && cfun->machine->indirect_branch_type != indirect_branch_keep);
> + bool seh_nop_p = false;
> + const char *xasm;
> +
> +@@ -41749,7 +41786,7 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int,
> + }
> +
> + static tree
> +-ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
> ++ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
> + bool *no_add_attrs)
> + {
> + if (TREE_CODE (*node) != FUNCTION_DECL)
> +@@ -41758,6 +41795,29 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
> + name);
> + *no_add_attrs = true;
> + }
> ++
> ++ if (is_attribute_p ("indirect_branch", name))
> ++ {
> ++ tree cst = TREE_VALUE (args);
> ++ if (TREE_CODE (cst) != STRING_CST)
> ++ {
> ++ warning (OPT_Wattributes,
> ++ "%qE attribute requires a string constant argument",
> ++ name);
> ++ *no_add_attrs = true;
> ++ }
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
> ++ {
> ++ warning (OPT_Wattributes,
> ++ "argument to %qE attribute is not "
> ++ "(keep|thunk|thunk-inline|thunk-extern)", name);
> ++ *no_add_attrs = true;
> ++ }
> ++ }
> ++
> + return NULL_TREE;
> + }
> +
> +@@ -46052,6 +46112,8 @@ static const struct attribute_spec ix86_attribute_table[] =
> + ix86_handle_interrupt_attribute, false },
> + { "no_caller_saved_registers", 0, 0, false, true, true,
> + ix86_handle_no_caller_saved_registers_attribute, false },
> ++ { "indirect_branch", 1, 1, true, false, false,
> ++ ix86_handle_fndecl_attribute, false },
> +
> + /* End element. */
> + { NULL, 0, 0, false, false, false, NULL, false }
> +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> +index 7d9f9020fb3..a9c199a107c 100644
> +--- a/gcc/config/i386/i386.h
> ++++ b/gcc/config/i386/i386.h
> +@@ -2604,6 +2604,9 @@ struct GTY(()) machine_function {
> + /* Function type. */
> + ENUM_BITFIELD(function_type) func_type : 2;
> +
> ++ /* How to generate indirec branch. */
> ++ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
> ++
> + /* If true, the current function is a function specified with
> + the "interrupt" or "no_caller_saved_registers" attribute. */
> + BOOL_BITFIELD no_caller_saved_registers : 1;
> +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..26550fad4c8
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +@@ -0,0 +1,22 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler {\tlfence} } } */
> +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..f57bb2a92d6
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { 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..a3668a6586c
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..a9c4a137dd4
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..9582e0c5824
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +@@ -0,0 +1,22 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
> +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..66442cacfe8
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
> +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..2a19b54cd2e
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +@@ -0,0 +1,44 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +new file mode 100644
> +index 00000000000..9f6d12d74a1
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +@@ -0,0 +1,41 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
> new file mode 100644
> index 000000000..0845de4b2
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-and-function_return-attribute.patch
> @@ -0,0 +1,740 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 29d5a3f23c18c96944dd3230a41380a6edcd25fd Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 5 Dec 2017 13:29:06 -0800
> +Subject: [PATCH 11/17] Add -mfunction-return= and function_return attribute
> +
> +Add -mfunction-return= and function_return attribute tests
> +
> +-mfunction-return=thunk
> + Convert function return instruction to PC-relative call thunk.
> +-mfunction-return=thunk-inline
> + Convert function return instruction to PC-relative call thunk with
> + thunk inlined.
> +-mfunction-return=thunk-extern
> + Convert function return instruction to PC-relative call to external
> + thunk.
> +
> +Add function_return attribute to function declaration
> +
> +__attribute__ ((function_return("thunk")))
> +__attribute__ ((function_return("thunk-inline")))
> +__attribute__ ((function_return("thunk-extern")))
> +__attribute__ ((function_return("keep")))
> +---
> + gcc/config/i386/i386-protos.h | 1 +
> + gcc/config/i386/i386.c | 146 +++++++++++++++++++++++++--
> + gcc/config/i386/i386.h | 3 +
> + gcc/config/i386/i386.md | 9 +-
> + gcc/config/i386/i386.opt | 6 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 12 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 22 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 22 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 21 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 21 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 21 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 21 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 18 ++++
> + gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 12 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 12 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 12 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 14 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 13 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 13 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 14 +++
> + gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 23 +++++
> + 21 files changed, 421 insertions(+), 15 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-16.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-5.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-6.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-7.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-8.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> +
> +diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> +index b746429f420..213663811de 100644
> +--- a/gcc/config/i386/i386-protos.h
> ++++ b/gcc/config/i386/i386-protos.h
> +@@ -316,6 +316,7 @@ extern enum attr_cpu ix86_schedule;
> +
> + extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
> + extern const char * ix86_output_indirect_jmp (rtx call_op);
> ++extern const char * ix86_output_function_return (bool long_p);
> + extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
> + enum machine_mode mode);
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index be1ff4752a9..7ae3523095c 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -7166,6 +7166,31 @@ ix86_set_indirect_branch_type (tree fndecl)
> + else
> + cfun->machine->indirect_branch_type = ix86_indirect_branch;
> + }
> ++
> ++ if (cfun->machine->function_return_type == indirect_branch_unset)
> ++ {
> ++ tree attr = lookup_attribute ("function_return",
> ++ DECL_ATTRIBUTES (fndecl));
> ++ if (attr != NULL)
> ++ {
> ++ tree args = TREE_VALUE (attr);
> ++ if (args == NULL)
> ++ gcc_unreachable ();
> ++ tree cst = TREE_VALUE (args);
> ++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
> ++ cfun->machine->function_return_type = indirect_branch_keep;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
> ++ cfun->machine->function_return_type = indirect_branch_thunk;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
> ++ cfun->machine->function_return_type = indirect_branch_thunk_inline;
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
> ++ cfun->machine->function_return_type = indirect_branch_thunk_extern;
> ++ else
> ++ gcc_unreachable ();
> ++ }
> ++ else
> ++ cfun->machine->function_return_type = ix86_function_return;
> ++ }
> + }
> +
> + /* Establish appropriate back-end context for processing the function
> +@@ -11958,8 +11983,12 @@ static int indirect_thunks_bnd_used;
> + /* Fills in the label name that should be used for the indirect thunk. */
> +
> + static void
> +-indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
> ++indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
> ++ bool ret_p)
> + {
> ++ if (regno >= 0 && ret_p)
> ++ gcc_unreachable ();
> ++
> + if (USE_HIDDEN_LINKONCE)
> + {
> + const char *bnd = need_bnd_p ? "_bnd" : "";
> +@@ -11974,7 +12003,10 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
> + bnd, reg_prefix, reg_names[regno]);
> + }
> + else
> +- sprintf (name, "__x86.indirect_thunk%s", bnd);
> ++ {
> ++ const char *ret = ret_p ? "return" : "indirect";
> ++ sprintf (name, "__x86.%s_thunk%s", ret, bnd);
> ++ }
> + }
> + else
> + {
> +@@ -11987,10 +12019,20 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
> + }
> + else
> + {
> +- if (need_bnd_p)
> +- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
> ++ if (ret_p)
> ++ {
> ++ if (need_bnd_p)
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
> ++ else
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
> ++ }
> + else
> +- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
> ++ {
> ++ if (need_bnd_p)
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
> ++ else
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
> ++ }
> + }
> + }
> + }
> +@@ -12071,7 +12113,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
> + tree decl;
> +
> + /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
> +- indirect_thunk_name (name, regno, need_bnd_p);
> ++ indirect_thunk_name (name, regno, need_bnd_p, false);
> + decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
> + get_identifier (name),
> + build_function_type_list (void_type_node, NULL_TREE));
> +@@ -12114,6 +12156,35 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
> + ASM_OUTPUT_LABEL (asm_out_file, name);
> + }
> +
> ++ if (regno < 0)
> ++ {
> ++ /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
> ++ char alias[32];
> ++
> ++ indirect_thunk_name (alias, regno, need_bnd_p, true);
> ++ ASM_OUTPUT_DEF (asm_out_file, alias, name);
> ++#if TARGET_MACHO
> ++ if (TARGET_MACHO)
> ++ {
> ++ fputs ("\t.weak_definition\t", asm_out_file);
> ++ assemble_name (asm_out_file, alias);
> ++ fputs ("\n\t.private_extern\t", asm_out_file);
> ++ assemble_name (asm_out_file, alias);
> ++ putc ('\n', asm_out_file);
> ++ }
> ++#else
> ++ if (USE_HIDDEN_LINKONCE)
> ++ {
> ++ fputs ("\t.globl\t", asm_out_file);
> ++ assemble_name (asm_out_file, alias);
> ++ putc ('\n', asm_out_file);
> ++ fputs ("\t.hidden\t", asm_out_file);
> ++ assemble_name (asm_out_file, alias);
> ++ putc ('\n', asm_out_file);
> ++ }
> ++#endif
> ++ }
> ++
> + DECL_INITIAL (decl) = make_node (BLOCK);
> + current_function_decl = decl;
> + allocate_struct_function (decl, false);
> +@@ -28736,7 +28807,7 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + indirect_thunk_needed = true;
> + }
> + }
> +- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
> ++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
> + thunk_name = thunk_name_buf;
> + }
> + else
> +@@ -28860,6 +28931,43 @@ ix86_output_indirect_jmp (rtx call_op)
> + return "%!jmp\t%A0";
> + }
> +
> ++const char *
> ++ix86_output_function_return (bool long_p)
> ++{
> ++ if (cfun->machine->function_return_type != indirect_branch_keep)
> ++ {
> ++ char thunk_name[32];
> ++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
> ++
> ++ if (cfun->machine->function_return_type
> ++ != indirect_branch_thunk_inline)
> ++ {
> ++ bool need_thunk = (cfun->machine->function_return_type
> ++ == indirect_branch_thunk);
> ++ indirect_thunk_name (thunk_name, -1, need_bnd_p, true);
> ++ if (need_bnd_p)
> ++ {
> ++ indirect_thunk_bnd_needed |= need_thunk;
> ++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
> ++ }
> ++ else
> ++ {
> ++ indirect_thunk_needed |= need_thunk;
> ++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> ++ }
> ++ }
> ++ else
> ++ output_indirect_thunk (need_bnd_p, -1);
> ++
> ++ return "";
> ++ }
> ++
> ++ if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
> ++ return "%!ret";
> ++
> ++ return "rep%; ret";
> ++}
> ++
> + /* Output the assembly for a call instruction. */
> +
> + const char *
> +@@ -41916,6 +42024,28 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
> + }
> + }
> +
> ++ if (is_attribute_p ("function_return", name))
> ++ {
> ++ tree cst = TREE_VALUE (args);
> ++ if (TREE_CODE (cst) != STRING_CST)
> ++ {
> ++ warning (OPT_Wattributes,
> ++ "%qE attribute requires a string constant argument",
> ++ name);
> ++ *no_add_attrs = true;
> ++ }
> ++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
> ++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
> ++ {
> ++ warning (OPT_Wattributes,
> ++ "argument to %qE attribute is not "
> ++ "(keep|thunk|thunk-inline|thunk-extern)", name);
> ++ *no_add_attrs = true;
> ++ }
> ++ }
> ++
> + return NULL_TREE;
> + }
> +
> +@@ -46212,6 +46342,8 @@ static const struct attribute_spec ix86_attribute_table[] =
> + ix86_handle_no_caller_saved_registers_attribute, false },
> + { "indirect_branch", 1, 1, true, false, false,
> + ix86_handle_fndecl_attribute, false },
> ++ { "function_return", 1, 1, true, false, false,
> ++ ix86_handle_fndecl_attribute, false },
> +
> + /* End element. */
> + { NULL, 0, 0, false, false, false, NULL, false }
> +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> +index a9c199a107c..f248f3ba2f5 100644
> +--- a/gcc/config/i386/i386.h
> ++++ b/gcc/config/i386/i386.h
> +@@ -2607,6 +2607,9 @@ struct GTY(()) machine_function {
> + /* How to generate indirec branch. */
> + ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
> +
> ++ /* How to generate function return. */
> ++ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
> ++
> + /* If true, the current function is a function specified with
> + the "interrupt" or "no_caller_saved_registers" attribute. */
> + BOOL_BITFIELD no_caller_saved_registers : 1;
> +diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> +index 01b7b2039e6..00a9afef225 100644
> +--- a/gcc/config/i386/i386.md
> ++++ b/gcc/config/i386/i386.md
> +@@ -12288,7 +12288,7 @@
> + (define_insn "simple_return_internal"
> + [(simple_return)]
> + "reload_completed"
> +- "%!ret"
> ++ "* return ix86_output_function_return (false);"
> + [(set_attr "length" "1")
> + (set_attr "atom_unit" "jeu")
> + (set_attr "length_immediate" "0")
> +@@ -12310,12 +12310,7 @@
> + [(simple_return)
> + (unspec [(const_int 0)] UNSPEC_REP)]
> + "reload_completed"
> +-{
> +- if (ix86_bnd_prefixed_insn_p (insn))
> +- return "%!ret";
> +-
> +- return "rep%; ret";
> +-}
> ++ "* return ix86_output_function_return (true);"
> + [(set_attr "length" "2")
> + (set_attr "atom_unit" "jeu")
> + (set_attr "length_immediate" "0")
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index bc81e6bea86..fc2c81c3fb5 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -932,9 +932,13 @@ mindirect-branch=
> + Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
> + Update indirect call and jump.
> +
> ++mfunction-return=
> ++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
> ++Update function return.
> ++
> + Enum
> + Name(indirect_branch) Type(enum indirect_branch)
> +-Known indirect branch choices (for use with the -mindirect-branch= option):
> ++Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
> +
> + EnumValue
> + Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
> +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..406956f48e5
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
> +@@ -0,0 +1,12 @@
> ++/* { 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 {\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..aecea4224f9
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> +@@ -0,0 +1,22 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\tlfence} 2 } } */
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..3bacfb54dfd
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> +@@ -0,0 +1,22 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..851115ac507
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..7acb6fa5eae
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\tlfence} 2 } } */
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { 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" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..bf340fac7c6
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..735f8648c96
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> +@@ -0,0 +1,21 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 {\tlfence} 1 } } */
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +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..cf3920563e0
> +--- /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 {\tlfence} } } */
> ++/* { 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-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> +new file mode 100644
> +index 00000000000..190947cc2ca
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> +@@ -0,0 +1,12 @@
> ++/* { 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 {\tlfence} } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> +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..d71de3ac520
> +--- /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 {\tlfence} } } */
> ++/* { 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..68c22122f0d
> +--- /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 {\tlfence} } } */
> ++/* { 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..28c576e2267
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
> +@@ -0,0 +1,14 @@
> ++/* { 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 {\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..10ad40b9c26
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
> +@@ -0,0 +1,13 @@
> ++/* { 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 {\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..7ac0beaa73e
> +--- /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 {\tlfence} } } */
> ++/* { 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..777ab7c8088
> +--- /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 {\tlfence} } } */
> ++/* { 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..569e5f47973
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> +@@ -0,0 +1,23 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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-not "__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-times {\tlfence} 1 { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
> new file mode 100644
> index 000000000..ac900bab0
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mfunction-return-keep-to-indirect-branch-tests.patch
> @@ -0,0 +1,421 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From def2b5d75fd6234984ec969f4586fcb8c516a3b9 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Wed, 6 Dec 2017 09:58:42 -0800
> +Subject: [PATCH 12/17] Add -mfunction-return=keep to indirect branch tests
> +
> +---
> + gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
> + 33 files changed, 33 insertions(+), 33 deletions(-)
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +index 785e593405f..318db1e7f5c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +index b69075e6483..f2700dd36cf 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +index df8109baf55..46685d9a674 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +index 8f3b9f4d8a5..8f701775cea 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +index 1a9bb0e431e..f88ac31d07a 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +index bc7d20ec6ad..d745116d321 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +index f0e1cfe1893..969cb8c6ddc 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +index 8b88449e625..12a61c3bbc7 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +index c69f7bf4f60..a06907933a2 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +index c845099a83e..7f56725e6b6 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +index f636f3422fd..fd4ab1dbaa0 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +index 5f1d6a78041..1ffbf3b1181 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +index 56c92da9812..1559072919a 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +index cfb6f5b234b..1717e7bb436 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +index 9f6d12d74a1..af1bb125a22 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +index a5b1d38e061..20903b0f79d 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { ! x32 } } } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> +
> + void (*dispatch) (char *);
> + char buf[10];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +index a42add209e2..aef4bd144f4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { ! x32 } } } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> +
> + void (*dispatch) (char *);
> + char buf[10];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +index 265e010a0fe..2cc0343f828 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> +
> + void bar (char *);
> + char buf[10];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +index 1c01bcb7fc6..91560fef661 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> +
> + void bar (char *);
> + char buf[10];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +index f1fa0a11922..dc6bd10af4c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +index d6e078d594b..955aa256529 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +index 3bbe2646955..1537239416f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +index 596fac599f6..c82e53068fe 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +index ad54aaeac4c..23548d85f78 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +index a8e75254cfe..56c2fe92f25 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +index ab367951c45..e12b88593fe 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +index 09b8ad7d879..87b5429702f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +index 1f873758fbe..a496a41a918 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +index b24af1da963..6fe5ce71abf 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +index 1a86608f727..65cd997a33f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +index f4890fe97b2..7321d015c02 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +index 81b09e73ab8..6ec2e5621ab 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +index 01d45782185..a3d1a13cded 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
> new file mode 100644
> index 000000000..ab715f46a
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-loop.patch
> @@ -0,0 +1,233 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From d667049b53e3d45de057fba2f1ed0e3f268201c1 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Thu, 16 Nov 2017 14:46:20 -0800
> +Subject: [PATCH 10/17] Add -mindirect-branch-loop=
> +
> +Add -mindirect-branch-loop= tests.
> +---
> + gcc/config/i386/i386-opts.h | 6 ++++++
> + gcc/config/i386/i386.c | 19 +++++++++++++++++--
> + gcc/config/i386/i386.opt | 16 ++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 19 +++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 19 +++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 19 +++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 19 +++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 19 +++++++++++++++++++
> + 8 files changed, 134 insertions(+), 2 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +
> +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> +index 9e56d7f2d12..b7b8fd280a3 100644
> +--- a/gcc/config/i386/i386-opts.h
> ++++ b/gcc/config/i386/i386-opts.h
> +@@ -107,4 +107,10 @@ enum indirect_branch {
> + indirect_branch_thunk_extern
> + };
> +
> ++enum indirect_branch_loop {
> ++ indirect_branch_loop_lfence,
> ++ indirect_branch_loop_pause,
> ++ indirect_branch_loop_nop
> ++};
> ++
> + #endif
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 590729b3f87..be1ff4752a9 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -12016,8 +12016,23 @@ output_indirect_thunk (bool need_bnd_p, int regno)
> +
> + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
> +
> +- /* lfence . */
> +- fprintf (asm_out_file, "\tlfence\n");
> ++ switch (ix86_indirect_branch_loop)
> ++ {
> ++ case indirect_branch_loop_lfence:
> ++ /* lfence. */
> ++ fprintf (asm_out_file, "\tlfence\n");
> ++ break;
> ++ case indirect_branch_loop_pause:
> ++ /* pause. */
> ++ fprintf (asm_out_file, "\tpause\n");
> ++ break;
> ++ case indirect_branch_loop_nop:
> ++ /* nop. */
> ++ fprintf (asm_out_file, "\tnop\n");
> ++ break;
> ++ default:
> ++ gcc_unreachable ();
> ++ }
> +
> + /* Jump. */
> + fputs ("\tjmp\t", asm_out_file);
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index 4a932e11bf6..bc81e6bea86 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -947,3 +947,19 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
> +
> + EnumValue
> + Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
> ++
> ++mindirect-branch-loop=
> ++Target Report RejectNegative Joined Enum(indirect_branch_loop) Var(ix86_indirect_branch_loop) Undocumented Init(indirect_branch_loop_lfence)
> ++
> ++Enum
> ++Name(indirect_branch_loop) Type(enum indirect_branch_loop)
> ++Known looop choices (for use with the -mindirect-branch-loop= option):
> ++
> ++EnumValue
> ++Enum(indirect_branch_loop) String(lfence) Value(indirect_branch_loop_lfence)
> ++
> ++EnumValue
> ++Enum(indirect_branch_loop) String(pause) Value(indirect_branch_loop_pause)
> ++
> ++EnumValue
> ++Enum(indirect_branch_loop) String(nop) Value(indirect_branch_loop_nop)
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +new file mode 100644
> +index 00000000000..f0e8f4949c8
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
> ++
> ++typedef void (*dispatch_t)(long offset);
> ++
> ++dispatch_t dispatch;
> ++
> ++void
> ++male_indirect_jump (long offset)
> ++{
> ++ dispatch(offset);
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +new file mode 100644
> +index 00000000000..a577ac2568a
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=nop -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tnop} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +new file mode 100644
> +index 00000000000..c8dcb9639c4
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
> ++
> ++typedef void (*dispatch_t)(long offset);
> ++
> ++dispatch_t dispatch;
> ++
> ++void
> ++male_indirect_jump (long offset)
> ++{
> ++ dispatch(offset);
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +new file mode 100644
> +index 00000000000..8569dfc92c3
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
> ++
> ++typedef void (*dispatch_t)(long offset);
> ++
> ++dispatch_t dispatch;
> ++
> ++void
> ++male_indirect_jump (long offset)
> ++{
> ++ dispatch(offset);
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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-not "__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +new file mode 100644
> +index 00000000000..bcf19c9ede1
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
> ++
> ++typedef void (*dispatch_t)(long offset);
> ++
> ++dispatch_t dispatch;
> ++
> ++void
> ++male_indirect_jump (long offset)
> ++{
> ++ dispatch(offset);
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-not {\t(lfence|pause|nop)} } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
> new file mode 100644
> index 000000000..de9e373fd
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-register-and-tests.patch
> @@ -0,0 +1,403 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From fb8875abab630962dbcb08c822b1b960fa5a51d4 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Wed, 19 Jul 2017 19:23:02 -0700
> +Subject: [PATCH 13/17] Add -mindirect-branch-register and tests
> +
> +Add -mindirect-branch-register to force indirect branch via register.
> +This is implemented by disabling patterns of indirect branch via memory,
> +similar to TARGET_X32. With -mindirect-branch-register:
> +
> +void (*func) (void);
> +
> +void
> +bar (void)
> +{
> + func ();
> +}
> +
> +is compiled into:
> +
> + movq func(%rip), %rax
> + jmp __x86.indirect_thunk.ax
> +
> +__x86.indirect_thunk.ax:
> + call .LIND3
> +.LIND2:
> + lfence
> + jmp .LIND2
> +.LIND3:
> + mov %rax, (%rsp)
> + ret
> +
> +and
> +
> +void (*func) (void);
> +
> +int
> +bar (void)
> +{
> + func ();
> + return 0;
> +}
> +
> +is compiled into:
> +
> + subq $8, %rsp
> + movq func(%rip), %rax
> + call __x86.indirect_thunk.ax
> + xorl %eax, %eax
> + addq $8, %rsp
> + ret
> +
> + * config/i386/constraints.md (Bs): Disallow memory operand for
> + -mindirect-branch-register.
> + (Bw): Likewise.
> + * config/i386/predicates.md (indirect_branch_operand): Likewise.
> + (GOT_memory_operand): Likewise.
> + (call_insn_operand): Likewise.
> + (sibcall_insn_operand): Likewise.
> + (GOT32_symbol_operand): Likewise.
> + * config/i386/i386.md (indirect_jump): Call convert_memory_address
> + for -mindirect-branch-register.
> + (tablejump): Likewise.
> + (*sibcall_memory): Likewise.
> + (*sibcall_value_memory): Likewise.
> + Disallow peepholes of indirect call and jump via memory for
> + -mindirect-branch-register.
> + (*call_pop): Replace m with Bw.
> + (*call_value_pop): Likewise.
> + (*sibcall_pop_memory): Replace m with Bs.
> +---
> + gcc/config/i386/constraints.md | 12 +++++---
> + gcc/config/i386/i386.md | 34 ++++++++++++++--------
> + gcc/config/i386/i386.opt | 4 +++
> + gcc/config/i386/predicates.md | 21 ++++++++-----
> + .../gcc.target/i386/indirect-thunk-register-1.c | 22 ++++++++++++++
> + .../gcc.target/i386/indirect-thunk-register-2.c | 20 +++++++++++++
> + .../gcc.target/i386/indirect-thunk-register-3.c | 19 ++++++++++++
> + 7 files changed, 109 insertions(+), 23 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
> +
> +diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
> +index 38d604fdace..697caf704dd 100644
> +--- a/gcc/config/i386/constraints.md
> ++++ b/gcc/config/i386/constraints.md
> +@@ -198,16 +198,20 @@
> +
> + (define_constraint "Bs"
> + "@internal Sibcall memory operand."
> +- (ior (and (not (match_test "TARGET_X32"))
> ++ (ior (and (not (match_test "TARGET_X32
> ++ || ix86_indirect_branch_thunk_register"))
> + (match_operand 0 "sibcall_memory_operand"))
> +- (and (match_test "TARGET_X32 && Pmode == DImode")
> ++ (and (match_test "TARGET_X32 && Pmode == DImode
> ++ && !ix86_indirect_branch_thunk_register")
> + (match_operand 0 "GOT_memory_operand"))))
> +
> + (define_constraint "Bw"
> + "@internal Call memory operand."
> +- (ior (and (not (match_test "TARGET_X32"))
> ++ (ior (and (not (match_test "TARGET_X32
> ++ || ix86_indirect_branch_thunk_register"))
> + (match_operand 0 "memory_operand"))
> +- (and (match_test "TARGET_X32 && Pmode == DImode")
> ++ (and (match_test "TARGET_X32 && Pmode == DImode
> ++ && !ix86_indirect_branch_thunk_register")
> + (match_operand 0 "GOT_memory_operand"))))
> +
> + (define_constraint "Bz"
> +diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> +index 00a9afef225..473fa5c089b 100644
> +--- a/gcc/config/i386/i386.md
> ++++ b/gcc/config/i386/i386.md
> +@@ -11608,7 +11608,7 @@
> + [(set (pc) (match_operand 0 "indirect_branch_operand"))]
> + ""
> + {
> +- if (TARGET_X32)
> ++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
> + operands[0] = convert_memory_address (word_mode, operands[0]);
> + })
> +
> +@@ -11657,7 +11657,7 @@
> + OPTAB_DIRECT);
> + }
> +
> +- if (TARGET_X32)
> ++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
> + operands[0] = convert_memory_address (word_mode, operands[0]);
> + })
> +
> +@@ -11844,7 +11844,7 @@
> + [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
> + (match_operand 1))
> + (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> +- "!TARGET_X32"
> ++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
> + "* return ix86_output_call_insn (insn, operands[0]);"
> + [(set_attr "type" "call")])
> +
> +@@ -11853,7 +11853,9 @@
> + (match_operand:W 1 "memory_operand"))
> + (call (mem:QI (match_dup 0))
> + (match_operand 3))]
> +- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
> ++ "!TARGET_X32
> ++ && !ix86_indirect_branch_thunk_register
> ++ && SIBLING_CALL_P (peep2_next_insn (1))
> + && !reg_mentioned_p (operands[0],
> + CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
> + [(parallel [(call (mem:QI (match_dup 1))
> +@@ -11866,7 +11868,9 @@
> + (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
> + (call (mem:QI (match_dup 0))
> + (match_operand 3))]
> +- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
> ++ "!TARGET_X32
> ++ && !ix86_indirect_branch_thunk_register
> ++ && SIBLING_CALL_P (peep2_next_insn (2))
> + && !reg_mentioned_p (operands[0],
> + CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
> + [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
> +@@ -11888,7 +11892,7 @@
> + })
> +
> + (define_insn "*call_pop"
> +- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
> ++ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
> + (match_operand 1))
> + (set (reg:SI SP_REG)
> + (plus:SI (reg:SI SP_REG)
> +@@ -11908,7 +11912,7 @@
> + [(set_attr "type" "call")])
> +
> + (define_insn "*sibcall_pop_memory"
> +- [(call (mem:QI (match_operand:SI 0 "memory_operand" "m"))
> ++ [(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
> + (match_operand 1))
> + (set (reg:SI SP_REG)
> + (plus:SI (reg:SI SP_REG)
> +@@ -11962,7 +11966,9 @@
> + [(set (match_operand:W 0 "register_operand")
> + (match_operand:W 1 "memory_operand"))
> + (set (pc) (match_dup 0))]
> +- "!TARGET_X32 && peep2_reg_dead_p (2, operands[0])"
> ++ "!TARGET_X32
> ++ && !ix86_indirect_branch_thunk_register
> ++ && peep2_reg_dead_p (2, operands[0])"
> + [(set (pc) (match_dup 1))])
> +
> + ;; Call subroutine, returning value in operand 0
> +@@ -12043,7 +12049,7 @@
> + (call (mem:QI (match_operand:W 1 "memory_operand" "m"))
> + (match_operand 2)))
> + (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
> +- "!TARGET_X32"
> ++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
> + "* return ix86_output_call_insn (insn, operands[1]);"
> + [(set_attr "type" "callv")])
> +
> +@@ -12053,7 +12059,9 @@
> + (set (match_operand 2)
> + (call (mem:QI (match_dup 0))
> + (match_operand 3)))]
> +- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
> ++ "!TARGET_X32
> ++ && !ix86_indirect_branch_thunk_register
> ++ && SIBLING_CALL_P (peep2_next_insn (1))
> + && !reg_mentioned_p (operands[0],
> + CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
> + [(parallel [(set (match_dup 2)
> +@@ -12068,7 +12076,9 @@
> + (set (match_operand 2)
> + (call (mem:QI (match_dup 0))
> + (match_operand 3)))]
> +- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
> ++ "!TARGET_X32
> ++ && !ix86_indirect_branch_thunk_register
> ++ && SIBLING_CALL_P (peep2_next_insn (2))
> + && !reg_mentioned_p (operands[0],
> + CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
> + [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
> +@@ -12093,7 +12103,7 @@
> +
> + (define_insn "*call_value_pop"
> + [(set (match_operand 0)
> +- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
> ++ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
> + (match_operand 2)))
> + (set (reg:SI SP_REG)
> + (plus:SI (reg:SI SP_REG)
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index fc2c81c3fb5..802245f4efe 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -952,6 +952,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
> + EnumValue
> + Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
> +
> ++mindirect-branch-register
> ++Target Report Var(ix86_indirect_branch_thunk_register) Init(0)
> ++Force indirect call and jump via register.
> ++
> + mindirect-branch-loop=
> + Target Report RejectNegative Joined Enum(indirect_branch_loop) Var(ix86_indirect_branch_loop) Undocumented Init(indirect_branch_loop_lfence)
> +
> +diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
> +index 8f250a2e720..fc4933e4533 100644
> +--- a/gcc/config/i386/predicates.md
> ++++ b/gcc/config/i386/predicates.md
> +@@ -635,7 +635,8 @@
> + ;; Test for a valid operand for indirect branch.
> + (define_predicate "indirect_branch_operand"
> + (ior (match_operand 0 "register_operand")
> +- (and (not (match_test "TARGET_X32"))
> ++ (and (not (match_test "TARGET_X32
> ++ || ix86_indirect_branch_thunk_register"))
> + (match_operand 0 "memory_operand"))))
> +
> + ;; Return true if OP is a memory operands that can be used in sibcalls.
> +@@ -664,7 +665,8 @@
> +
> + ;; Return true if OP is a GOT memory operand.
> + (define_predicate "GOT_memory_operand"
> +- (match_operand 0 "memory_operand")
> ++ (and (match_test "!ix86_indirect_branch_thunk_register")
> ++ (match_operand 0 "memory_operand"))
> + {
> + op = XEXP (op, 0);
> + return (GET_CODE (op) == CONST
> +@@ -678,9 +680,11 @@
> + (ior (match_test "constant_call_address_operand
> + (op, mode == VOIDmode ? mode : Pmode)")
> + (match_operand 0 "call_register_no_elim_operand")
> +- (ior (and (not (match_test "TARGET_X32"))
> ++ (ior (and (not (match_test "TARGET_X32
> ++ || ix86_indirect_branch_thunk_register"))
> + (match_operand 0 "memory_operand"))
> +- (and (match_test "TARGET_X32 && Pmode == DImode")
> ++ (and (match_test "TARGET_X32 && Pmode == DImode
> ++ && !ix86_indirect_branch_thunk_register")
> + (match_operand 0 "GOT_memory_operand")))))
> +
> + ;; Similarly, but for tail calls, in which we cannot allow memory references.
> +@@ -688,14 +692,17 @@
> + (ior (match_test "constant_call_address_operand
> + (op, mode == VOIDmode ? mode : Pmode)")
> + (match_operand 0 "register_no_elim_operand")
> +- (ior (and (not (match_test "TARGET_X32"))
> ++ (ior (and (not (match_test "TARGET_X32
> ++ || ix86_indirect_branch_thunk_register"))
> + (match_operand 0 "sibcall_memory_operand"))
> +- (and (match_test "TARGET_X32 && Pmode == DImode")
> ++ (and (match_test "TARGET_X32 && Pmode == DImode
> ++ && !ix86_indirect_branch_thunk_register")
> + (match_operand 0 "GOT_memory_operand")))))
> +
> + ;; Return true if OP is a 32-bit GOT symbol operand.
> + (define_predicate "GOT32_symbol_operand"
> +- (match_test "GET_CODE (op) == CONST
> ++ (match_test "!ix86_indirect_branch_thunk_register
> ++ && GET_CODE (op) == CONST
> + && GET_CODE (XEXP (op, 0)) == UNSPEC
> + && XINT (XEXP (op, 0), 1) == UNSPEC_GOT"))
> +
> +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..ef493a05bbf
> +--- /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 {\tlfence} } } */
> ++/* { 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..89fc8e6e6c4
> +--- /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 {\tlfence} } } */
> ++/* { 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..31af7ac05b8
> +--- /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(lfence|pause|nop)} } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
> new file mode 100644
> index 000000000..18b2dfaea
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-extern.patch
> @@ -0,0 +1,263 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 4032162fb6d36e20091885d0558f91daaa0080d3 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Mon, 27 Nov 2017 08:38:41 -0800
> +Subject: [PATCH 07/17] Add -mindirect-branch=thunk-extern
> +
> +Add -mindirect-branch=thunk-extern tests
> +---
> + gcc/config/i386/i386-opts.h | 3 +-
> + gcc/config/i386/i386.opt | 3 ++
> + .../gcc.target/i386/indirect-thunk-extern-1.c | 19 ++++++++++
> + .../gcc.target/i386/indirect-thunk-extern-2.c | 19 ++++++++++
> + .../gcc.target/i386/indirect-thunk-extern-3.c | 20 ++++++++++
> + .../gcc.target/i386/indirect-thunk-extern-4.c | 20 ++++++++++
> + .../gcc.target/i386/indirect-thunk-extern-5.c | 16 ++++++++
> + .../gcc.target/i386/indirect-thunk-extern-6.c | 17 +++++++++
> + .../gcc.target/i386/indirect-thunk-extern-7.c | 43 ++++++++++++++++++++++
> + 9 files changed, 159 insertions(+), 1 deletion(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +
> +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> +index f301890575a..f8d80ba7ec6 100644
> +--- a/gcc/config/i386/i386-opts.h
> ++++ b/gcc/config/i386/i386-opts.h
> +@@ -102,7 +102,8 @@ enum stack_protector_guard {
> + enum indirect_branch {
> + indirect_branch_keep,
> + indirect_branch_thunk,
> +- indirect_branch_thunk_inline
> ++ indirect_branch_thunk_inline,
> ++ indirect_branch_thunk_extern
> + };
> +
> + #endif
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index 68484a75022..4a932e11bf6 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -944,3 +944,6 @@ Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
> +
> + EnumValue
> + Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
> ++
> ++EnumValue
> ++Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
> +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..0a1f91be988
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +new file mode 100644
> +index 00000000000..182520ab3dc
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +new file mode 100644
> +index 00000000000..5c31ddc34fd
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
> +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..f24d0c060f2
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { 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..ad54aaeac4c
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +@@ -0,0 +1,16 @@
> ++/* { dg-do compile { target *-*-linux* } } */
> ++/* { dg-options "-O2 -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" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +new file mode 100644
> +index 00000000000..a8e75254cfe
> +--- /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 -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" } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { 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..8d39fb6f939
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +@@ -0,0 +1,43 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
> new file mode 100644
> index 000000000..bb12c0e95
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk-inline.patch
> @@ -0,0 +1,310 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 7f4f2bf1688c81496107993080e68a29a24de702 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Wed, 15 Nov 2017 11:20:31 -0800
> +Subject: [PATCH 06/17] Add -mindirect-branch=thunk-inline
> +
> +Add -mindirect-branch=thunk-inline tests
> +---
> + gcc/config/i386/i386-opts.h | 3 +-
> + gcc/config/i386/i386.c | 30 +++++++++++-----
> + gcc/config/i386/i386.opt | 3 ++
> + .../gcc.target/i386/indirect-thunk-inline-1.c | 18 ++++++++++
> + .../gcc.target/i386/indirect-thunk-inline-2.c | 18 ++++++++++
> + .../gcc.target/i386/indirect-thunk-inline-3.c | 19 ++++++++++
> + .../gcc.target/i386/indirect-thunk-inline-4.c | 19 ++++++++++
> + .../gcc.target/i386/indirect-thunk-inline-5.c | 15 ++++++++
> + .../gcc.target/i386/indirect-thunk-inline-6.c | 16 +++++++++
> + .../gcc.target/i386/indirect-thunk-inline-7.c | 42 ++++++++++++++++++++++
> + 10 files changed, 173 insertions(+), 10 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +
> +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> +index 1565d8fdc65..f301890575a 100644
> +--- a/gcc/config/i386/i386-opts.h
> ++++ b/gcc/config/i386/i386-opts.h
> +@@ -101,7 +101,8 @@ enum stack_protector_guard {
> +
> + enum indirect_branch {
> + indirect_branch_keep,
> +- indirect_branch_thunk
> ++ indirect_branch_thunk,
> ++ indirect_branch_thunk_inline
> + };
> +
> + #endif
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 96424361a1c..ac542f79846 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -28600,16 +28600,23 @@ static void
> + ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + bool sibcall_p)
> + {
> +- char thunk_name[32];
> ++ char thunk_name_buf[32];
> ++ char *thunk_name;
> + char push_buf[64];
> + bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
> +
> +- bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
> +- if (need_bnd_p)
> +- indirect_thunk_bnd_needed |= need_thunk;
> ++ if (ix86_indirect_branch != indirect_branch_thunk_inline)
> ++ {
> ++ bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
> ++ if (need_bnd_p)
> ++ indirect_thunk_bnd_needed |= need_thunk;
> ++ else
> ++ indirect_thunk_needed |= need_thunk;
> ++ indirect_thunk_name (thunk_name_buf, need_bnd_p);
> ++ thunk_name = thunk_name_buf;
> ++ }
> + else
> +- indirect_thunk_needed |= need_thunk;
> +- indirect_thunk_name (thunk_name, need_bnd_p);
> ++ thunk_name = NULL;
> +
> + snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
> + TARGET_64BIT ? 'q' : 'l', xasm);
> +@@ -28683,10 +28690,15 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> +
> + output_asm_insn (push_buf, &call_op);
> +
> +- if (need_bnd_p)
> +- fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
> ++ if (thunk_name != NULL)
> ++ {
> ++ if (need_bnd_p)
> ++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
> ++ else
> ++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> ++ }
> + else
> +- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> ++ output_indirect_thunk (need_bnd_p);
> +
> + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
> +
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index 1773e5614cf..68484a75022 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -941,3 +941,6 @@ Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
> +
> + EnumValue
> + Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
> ++
> ++EnumValue
> ++Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
> +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..071e6c89ac7
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +@@ -0,0 +1,18 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +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..804c7ccdba7
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +@@ -0,0 +1,18 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +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..545a981add5
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +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..d9ff4722cff
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +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..f4890fe97b2
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +@@ -0,0 +1,15 @@
> ++/* { dg-do compile { target *-*-linux* } } */
> ++/* { dg-options "-O2 -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" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { 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..81b09e73ab8
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +@@ -0,0 +1,16 @@
> ++/* { dg-do compile { target *-*-linux* } } */
> ++/* { dg-options "-O2 -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" } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..a0ce06b8232
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +@@ -0,0 +1,42 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
> new file mode 100644
> index 000000000..edb9a8de5
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mindirect-branch-thunk.patch
> @@ -0,0 +1,729 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 63024dad9c00f1613738fd766e2f0afd455b76d1 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Wed, 1 Nov 2017 16:05:50 -0700
> +Subject: [PATCH 04/17] Add -mindirect-branch=thunk
> +
> +Add tests for -mindirect-branch=thunk
> +---
> + gcc/config/i386/i386-opts.h | 5 +
> + gcc/config/i386/i386-protos.h | 1 +
> + gcc/config/i386/i386.c | 318 ++++++++++++++++++++++-
> + gcc/config/i386/i386.md | 6 +-
> + gcc/config/i386/i386.opt | 14 +
> + gcc/doc/invoke.texi | 9 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 19 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 19 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 20 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 20 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 16 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 17 ++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 43 +++
> + 13 files changed, 495 insertions(+), 12 deletions(-)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +
> +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
> +index 542cd0f3d67..1565d8fdc65 100644
> +--- a/gcc/config/i386/i386-opts.h
> ++++ b/gcc/config/i386/i386-opts.h
> +@@ -99,4 +99,9 @@ enum stack_protector_guard {
> + SSP_GLOBAL /* global canary */
> + };
> +
> ++enum indirect_branch {
> ++ indirect_branch_keep,
> ++ indirect_branch_thunk
> ++};
> ++
> + #endif
> +diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> +index 8bdd67eb608..b746429f420 100644
> +--- a/gcc/config/i386/i386-protos.h
> ++++ b/gcc/config/i386/i386-protos.h
> +@@ -315,6 +315,7 @@ extern enum attr_cpu ix86_schedule;
> + #endif
> +
> + extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
> ++extern const char * ix86_output_indirect_jmp (rtx call_op);
> + extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
> + enum machine_mode mode);
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 504530a00cf..96424361a1c 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -11909,6 +11909,145 @@ ix86_setup_frame_addresses (void)
> + # endif
> + #endif
> +
> ++static int indirectlabelno;
> ++static bool indirect_thunk_needed = false;
> ++static bool indirect_thunk_bnd_needed = false;
> ++
> ++#ifndef INDIRECT_LABEL
> ++# define INDIRECT_LABEL "LIND"
> ++#endif
> ++
> ++/* Fills in the label name that should be used for the indirect thunk. */
> ++
> ++static void
> ++indirect_thunk_name (char name[32], bool need_bnd_p)
> ++{
> ++ if (USE_HIDDEN_LINKONCE)
> ++ {
> ++ const char *bnd = need_bnd_p ? "_bnd" : "";
> ++ sprintf (name, "__x86.indirect_thunk%s", bnd);
> ++ }
> ++ else
> ++ {
> ++ if (need_bnd_p)
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
> ++ else
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
> ++ }
> ++}
> ++
> ++static void
> ++output_indirect_thunk (bool need_bnd_p)
> ++{
> ++ char indirectlabel1[32];
> ++ char indirectlabel2[32];
> ++
> ++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1, INDIRECT_LABEL,
> ++ indirectlabelno++);
> ++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2, INDIRECT_LABEL,
> ++ indirectlabelno++);
> ++
> ++ /* Call */
> ++ if (need_bnd_p)
> ++ fputs ("\tbnd call\t", asm_out_file);
> ++ else
> ++ fputs ("\tcall\t", asm_out_file);
> ++ assemble_name_raw (asm_out_file, indirectlabel2);
> ++ fputc ('\n', asm_out_file);
> ++
> ++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
> ++
> ++ /* lfence . */
> ++ fprintf (asm_out_file, "\tlfence\n");
> ++
> ++ /* Jump. */
> ++ fputs ("\tjmp\t", asm_out_file);
> ++ assemble_name_raw (asm_out_file, indirectlabel1);
> ++ fputc ('\n', asm_out_file);
> ++
> ++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
> ++
> ++ /* LEA. */
> ++ rtx xops[2];
> ++ xops[0] = stack_pointer_rtx;
> ++ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
> ++ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
> ++
> ++ if (need_bnd_p)
> ++ fputs ("\tbnd ret\n", asm_out_file);
> ++ else
> ++ fputs ("\tret\n", asm_out_file);
> ++}
> ++
> ++static void
> ++output_indirect_thunk_function (bool need_bnd_p)
> ++{
> ++ char name[32];
> ++ tree decl;
> ++
> ++ indirect_thunk_name (name, need_bnd_p);
> ++ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
> ++ get_identifier (name),
> ++ build_function_type_list (void_type_node, NULL_TREE));
> ++ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
> ++ NULL_TREE, void_type_node);
> ++ TREE_PUBLIC (decl) = 1;
> ++ TREE_STATIC (decl) = 1;
> ++ DECL_IGNORED_P (decl) = 1;
> ++
> ++#if TARGET_MACHO
> ++ if (TARGET_MACHO)
> ++ {
> ++ switch_to_section (darwin_sections[picbase_thunk_section]);
> ++ fputs ("\t.weak_definition\t", asm_out_file);
> ++ assemble_name (asm_out_file, name);
> ++ fputs ("\n\t.private_extern\t", asm_out_file);
> ++ assemble_name (asm_out_file, name);
> ++ putc ('\n', asm_out_file);
> ++ ASM_OUTPUT_LABEL (asm_out_file, name);
> ++ DECL_WEAK (decl) = 1;
> ++ }
> ++ else
> ++#endif
> ++ if (USE_HIDDEN_LINKONCE)
> ++ {
> ++ cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
> ++
> ++ targetm.asm_out.unique_section (decl, 0);
> ++ switch_to_section (get_named_section (decl, NULL, 0));
> ++
> ++ targetm.asm_out.globalize_label (asm_out_file, name);
> ++ fputs ("\t.hidden\t", asm_out_file);
> ++ assemble_name (asm_out_file, name);
> ++ putc ('\n', asm_out_file);
> ++ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
> ++ }
> ++ else
> ++ {
> ++ switch_to_section (text_section);
> ++ ASM_OUTPUT_LABEL (asm_out_file, name);
> ++ }
> ++
> ++ DECL_INITIAL (decl) = make_node (BLOCK);
> ++ current_function_decl = decl;
> ++ allocate_struct_function (decl, false);
> ++ init_function_start (decl);
> ++ /* We're about to hide the function body from callees of final_* by
> ++ emitting it directly; tell them we're a thunk, if they care. */
> ++ cfun->is_thunk = true;
> ++ first_function_block_is_cold = false;
> ++ /* Make sure unwind info is emitted for the thunk if needed. */
> ++ final_start_function (emit_barrier (), asm_out_file, 1);
> ++
> ++ output_indirect_thunk (need_bnd_p);
> ++
> ++ final_end_function ();
> ++ init_insn_lengths ();
> ++ free_after_compilation (cfun);
> ++ set_cfun (NULL);
> ++ current_function_decl = NULL;
> ++}
> ++
> + static int pic_labels_used;
> +
> + /* Fills in the label name that should be used for a pc thunk for
> +@@ -11935,6 +12074,11 @@ ix86_code_end (void)
> + rtx xops[2];
> + int regno;
> +
> ++ if (indirect_thunk_needed)
> ++ output_indirect_thunk_function (false);
> ++ if (indirect_thunk_bnd_needed)
> ++ output_indirect_thunk_function (true);
> ++
> + for (regno = AX_REG; regno <= SP_REG; regno++)
> + {
> + char name[32];
> +@@ -28452,12 +28596,132 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
> + return false;
> + }
> +
> ++static void
> ++ix86_output_indirect_branch (rtx call_op, const char *xasm,
> ++ bool sibcall_p)
> ++{
> ++ char thunk_name[32];
> ++ char push_buf[64];
> ++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
> ++
> ++ bool need_thunk = ix86_indirect_branch == indirect_branch_thunk;
> ++ if (need_bnd_p)
> ++ indirect_thunk_bnd_needed |= need_thunk;
> ++ else
> ++ indirect_thunk_needed |= need_thunk;
> ++ indirect_thunk_name (thunk_name, need_bnd_p);
> ++
> ++ snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
> ++ TARGET_64BIT ? 'q' : 'l', xasm);
> ++
> ++ if (sibcall_p)
> ++ {
> ++ output_asm_insn (push_buf, &call_op);
> ++ if (thunk_name != NULL)
> ++ {
> ++ if (need_bnd_p)
> ++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
> ++ else
> ++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> ++ }
> ++ else
> ++ output_indirect_thunk (need_bnd_p);
> ++ }
> ++ else
> ++ {
> ++ char indirectlabel1[32];
> ++ char indirectlabel2[32];
> ++
> ++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
> ++ INDIRECT_LABEL,
> ++ indirectlabelno++);
> ++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
> ++ INDIRECT_LABEL,
> ++ indirectlabelno++);
> ++
> ++ /* Jump. */
> ++ if (need_bnd_p)
> ++ fputs ("\tbnd jmp\t", asm_out_file);
> ++ else
> ++ fputs ("\tjmp\t", asm_out_file);
> ++ assemble_name_raw (asm_out_file, indirectlabel2);
> ++ fputc ('\n', asm_out_file);
> ++
> ++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
> ++
> ++ if (MEM_P (call_op))
> ++ {
> ++ struct ix86_address parts;
> ++ rtx addr = XEXP (call_op, 0);
> ++ if (ix86_decompose_address (addr, &parts)
> ++ && parts.base == stack_pointer_rtx)
> ++ {
> ++ /* Since call will adjust stack by -UNITS_PER_WORD,
> ++ we must convert "disp(stack, index, scale)" to
> ++ "disp+UNITS_PER_WORD(stack, index, scale)". */
> ++ if (parts.index)
> ++ {
> ++ addr = gen_rtx_MULT (Pmode, parts.index,
> ++ GEN_INT (parts.scale));
> ++ addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
> ++ addr);
> ++ }
> ++ else
> ++ addr = stack_pointer_rtx;
> ++
> ++ rtx disp;
> ++ if (parts.disp != NULL_RTX)
> ++ disp = plus_constant (Pmode, parts.disp,
> ++ UNITS_PER_WORD);
> ++ else
> ++ disp = GEN_INT (UNITS_PER_WORD);
> ++
> ++ addr = gen_rtx_PLUS (Pmode, addr, disp);
> ++ call_op = gen_rtx_MEM (GET_MODE (call_op), addr);
> ++ }
> ++ }
> ++
> ++ output_asm_insn (push_buf, &call_op);
> ++
> ++ if (need_bnd_p)
> ++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
> ++ else
> ++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> ++
> ++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
> ++
> ++ /* Call. */
> ++ if (need_bnd_p)
> ++ fputs ("\tbnd call\t", asm_out_file);
> ++ else
> ++ fputs ("\tcall\t", asm_out_file);
> ++ assemble_name_raw (asm_out_file, indirectlabel1);
> ++ fputc ('\n', asm_out_file);
> ++ }
> ++}
> ++
> ++const char *
> ++ix86_output_indirect_jmp (rtx call_op)
> ++{
> ++ if (ix86_red_zone_size == 0
> ++ && ix86_indirect_branch != indirect_branch_keep)
> ++ {
> ++ ix86_output_indirect_branch (call_op, "%0", true);
> ++ return "";
> ++ }
> ++ else
> ++ return "%!jmp\t%A0";
> ++}
> ++
> + /* Output the assembly for a call instruction. */
> +
> + const char *
> + ix86_output_call_insn (rtx_insn *insn, rtx call_op)
> + {
> + bool direct_p = constant_call_address_operand (call_op, VOIDmode);
> ++ bool output_indirect_p
> ++ = (!TARGET_SEH
> ++ && ix86_indirect_branch != indirect_branch_keep);
> + bool seh_nop_p = false;
> + const char *xasm;
> +
> +@@ -28467,10 +28731,21 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
> + {
> + if (ix86_nopic_noplt_attribute_p (call_op))
> + {
> ++ direct_p = false;
> + if (TARGET_64BIT)
> +- xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ else
> ++ xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ }
> + else
> +- xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ else
> ++ xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ }
> + }
> + else
> + xasm = "%!jmp\t%P0";
> +@@ -28480,9 +28755,17 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
> + else if (TARGET_SEH)
> + xasm = "%!rex.W jmp\t%A0";
> + else
> +- xasm = "%!jmp\t%A0";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "%0";
> ++ else
> ++ xasm = "%!jmp\t%A0";
> ++ }
> +
> +- output_asm_insn (xasm, &call_op);
> ++ if (output_indirect_p && !direct_p)
> ++ ix86_output_indirect_branch (call_op, xasm, true);
> ++ else
> ++ output_asm_insn (xasm, &call_op);
> + return "";
> + }
> +
> +@@ -28520,18 +28803,37 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
> + {
> + if (ix86_nopic_noplt_attribute_p (call_op))
> + {
> ++ direct_p = false;
> + if (TARGET_64BIT)
> +- xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ else
> ++ xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
> ++ }
> + else
> +- xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ else
> ++ xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
> ++ }
> + }
> + else
> + xasm = "%!call\t%P0";
> + }
> + else
> +- xasm = "%!call\t%A0";
> ++ {
> ++ if (output_indirect_p)
> ++ xasm = "%0";
> ++ else
> ++ xasm = "%!call\t%A0";
> ++ }
> +
> +- output_asm_insn (xasm, &call_op);
> ++ if (output_indirect_p && !direct_p)
> ++ ix86_output_indirect_branch (call_op, xasm, false);
> ++ else
> ++ output_asm_insn (xasm, &call_op);
> +
> + if (seh_nop_p)
> + return "nop";
> +diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> +index 81cfba57afc..01b7b2039e6 100644
> +--- a/gcc/config/i386/i386.md
> ++++ b/gcc/config/i386/i386.md
> +@@ -11615,7 +11615,7 @@
> + (define_insn "*indirect_jump"
> + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
> + ""
> +- "%!jmp\t%A0"
> ++ "* return ix86_output_indirect_jmp (operands[0]);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +@@ -11665,7 +11665,7 @@
> + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
> + (use (label_ref (match_operand 1)))]
> + ""
> +- "%!jmp\t%A0"
> ++ "* return ix86_output_indirect_jmp (operands[0]);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +@@ -12337,7 +12337,7 @@
> + [(simple_return)
> + (use (match_operand:SI 0 "register_operand" "r"))]
> + "reload_completed"
> +- "%!jmp\t%A0"
> ++ "* return ix86_output_indirect_jmp (operands[0]);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
> +index 9384e29b1de..1773e5614cf 100644
> +--- a/gcc/config/i386/i386.opt
> ++++ b/gcc/config/i386/i386.opt
> +@@ -927,3 +927,17 @@ Attempt to avoid generating instruction sequences containing ret bytes.
> + mgeneral-regs-only
> + Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
> + Generate code which uses only the general registers.
> ++
> ++mindirect-branch=
> ++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
> ++Update indirect call and jump.
> ++
> ++Enum
> ++Name(indirect_branch) Type(enum indirect_branch)
> ++Known indirect branch choices (for use with the -mindirect-branch= option):
> ++
> ++EnumValue
> ++Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
> ++
> ++EnumValue
> ++Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
> +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> +index a0fb09eb9e1..fafda2926bd 100644
> +--- a/gcc/doc/invoke.texi
> ++++ b/gcc/doc/invoke.texi
> +@@ -1210,7 +1210,7 @@ See RS/6000 and PowerPC Options.
> + -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
> + -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
> + -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
> +--mmitigate-rop -mgeneral-regs-only}
> ++-mmitigate-rop -mgeneral-regs-only -mindirect-branch=@var{choice}}
> +
> + @emph{x86 Windows Options}
> + @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
> +@@ -25648,6 +25648,13 @@ Generate code that uses only the general-purpose registers. This
> + prevents the compiler from using floating-point, vector, mask and bound
> + registers.
> +
> ++@item -mindirect-branch=@var{choice}
> ++@opindex -mindirect-branch
> ++Update indirect call and jump with @var{choice}. The default is
> ++@samp{keep}, which keeps indirect call and jump unmodified.
> ++@samp{thunk} converts indirect call and jump to push and
> ++PC-relative call thunk.
> ++
> + @end table
> +
> + These @samp{-m} switches are supported in addition to the above
> +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..d8b6f5a06a5
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler {\tlfence} } } */
> +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..f7d5cb315a8
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { 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..736d7cda058
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..cef9b10513e
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..1a9bb0e431e
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +@@ -0,0 +1,16 @@
> ++/* { dg-do compile { target *-*-linux* } } */
> ++/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
> ++
> ++extern void bar (void);
> ++
> ++void
> ++foo (void)
> ++{
> ++ bar ();
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { 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..bc7d20ec6ad
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +@@ -0,0 +1,17 @@
> ++/* { dg-do compile { target *-*-linux* } } */
> ++/* { dg-options "-O2 -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" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { 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..ea0fa312f64
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +@@ -0,0 +1,43 @@
> ++/* { dg-do compile } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler {\tlfence} } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch b/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
> new file mode 100644
> index 000000000..2b4ac1b81
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-mno-indirect-branch-register-to-indirect-branch-.patch
> @@ -0,0 +1,554 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 2c14ecf03978ce6c60e021a2b0d72778a5fe0982 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 12 Dec 2017 12:34:26 -0800
> +Subject: [PATCH 14/17] Add -mno-indirect-branch-register to indirect branch
> + tests
> +
> +---
> + gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 2 +-
> + 44 files changed, 44 insertions(+), 44 deletions(-)
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +index 318db1e7f5c..b0625207b92 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +index f2700dd36cf..0b289685e6b 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +index 46685d9a674..79a9f76285f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +index 8f701775cea..901d94213bd 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +index f88ac31d07a..d2c9bd9d7ca 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +index d745116d321..f8b028db7a2 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +index 969cb8c6ddc..465775407ec 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +index 12a61c3bbc7..5309d5a3eaa 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +index a06907933a2..dd1efca49fd 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +index 7f56725e6b6..e97ca636020 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +index fd4ab1dbaa0..b547cbbf255 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +index 1ffbf3b1181..353689dc415 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +index 1559072919a..1edef7208f4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +index 1717e7bb436..c2e816cdfc6 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +index 20903b0f79d..5c10de47b7c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { ! x32 } } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> ++/* { 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];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +index aef4bd144f4..9eedd9a5a82 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { ! x32 } } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> ++/* { 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];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +index 2cc0343f828..b2b8587eac7 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> ++/* { 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];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +index 91560fef661..9459a2417f4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
> ++/* { 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];
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +index dc6bd10af4c..b0aa3811e65 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +index 955aa256529..75fabcd988c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +index 1537239416f..1d9dff2e834 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +index c82e53068fe..5b464155e38 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +index 23548d85f78..55ce91c73ec 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +index 56c2fe92f25..06180e7bee9 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +index e12b88593fe..790a05cec3e 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +index 87b5429702f..1ce8ca5aff1 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +index a496a41a918..f6b71e868bd 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +index 6fe5ce71abf..84a09d4d0d6 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +index 65cd997a33f..cfe3aefa0bf 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +index 7321d015c02..6411454243f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +index 6ec2e5621ab..d4297fe21c4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile { target *-*-linux* } } */
> +-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
> +
> + extern void bar (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +index a3d1a13cded..eb318efdf4d 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> +
> + void func0 (void);
> + void func1 (void);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +index f0e8f4949c8..605e32bb584 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=pause -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +index a577ac2568a..dd7a7b60621 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=nop -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=nop -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +index c8dcb9639c4..338f22c373c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk -mindirect-branch-loop=lfence -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +index 8569dfc92c3..3b083ee30a8 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk-inline -mindirect-branch-loop=pause -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +index bcf19c9ede1..31a9a81a911 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mindirect-branch=thunk-extern -mindirect-branch-loop=pause -fno-pic" } */
> +
> + typedef void (*dispatch_t)(long offset);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> +index aecea4224f9..74f37ee9a62 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
> +
> + extern void (*bar) (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> +index 3bacfb54dfd..0a52318e86b 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> +index 851115ac507..d2f775490ea 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> +index 7acb6fa5eae..82d46165f3e 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
> ++/* { 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")));
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> +index bf340fac7c6..6711eb27fa8 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
> +
> + extern void (*bar) (void);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> +index 735f8648c96..37758c33371 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
> ++/* { 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);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> +index 569e5f47973..70771ea35d7 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> +@@ -1,5 +1,5 @@
> + /* { dg-do compile } */
> +-/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
> ++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
> +
> + extern void (*bar) (void);
> +
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch b/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
> new file mode 100644
> index 000000000..e21bb5039
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Add-tests-for-mindirect-branch-thunk-fcheck-pointer-.patch
> @@ -0,0 +1,134 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From ece041bc3083aabd00fab9de5ba409fbd7dcad8c Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Mon, 4 Dec 2017 12:58:20 -0800
> +Subject: [PATCH 05/17] Add tests for -mindirect-branch=thunk
> + -fcheck-pointer-bounds -mmpx
> +
> +---
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 19 +++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 20 ++++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 18 ++++++++++++++++++
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 19 +++++++++++++++++++
> + 4 files changed, 76 insertions(+)
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +
> +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..a5b1d38e061
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +@@ -0,0 +1,19 @@
> ++/* { dg-do compile { target { ! x32 } } } */
> ++/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
> ++
> ++void (*dispatch) (char *);
> ++char buf[10];
> ++
> ++void
> ++foo (void)
> ++{
> ++ dispatch (buf);
> ++}
> ++
> ++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { 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 {\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..a42add209e2
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +@@ -0,0 +1,20 @@
> ++/* { dg-do compile { target { ! x32 } } } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler "bnd ret" } } */
> ++/* { 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..265e010a0fe
> +--- /dev/null
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +@@ -0,0 +1,18 @@
> ++/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
> ++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { 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 {\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..1c01bcb7fc6
> +--- /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 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
> ++/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler "bnd ret" } } */
> ++/* { dg-final { scan-assembler {\tlfence} } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch b/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
> new file mode 100644
> index 000000000..b22e364af
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Disable-red-zone-with-local-indirect-jump.patch
> @@ -0,0 +1,147 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From f96e28553b0f2253184441f22852d76976e19968 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 12 Dec 2017 19:15:25 -0800
> +Subject: [PATCH 15/17] Disable red zone with local indirect jump
> +
> +---
> + gcc/config/i386/i386-protos.h | 2 +-
> + gcc/config/i386/i386.c | 22 +++++++++++++++++-----
> + gcc/config/i386/i386.h | 4 ++++
> + gcc/config/i386/i386.md | 8 +++++---
> + 4 files changed, 27 insertions(+), 9 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> +index 213663811de..a78bfa00427 100644
> +--- a/gcc/config/i386/i386-protos.h
> ++++ b/gcc/config/i386/i386-protos.h
> +@@ -315,7 +315,7 @@ extern enum attr_cpu ix86_schedule;
> + #endif
> +
> + extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
> +-extern const char * ix86_output_indirect_jmp (rtx call_op);
> ++extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
> + extern const char * ix86_output_function_return (bool long_p);
> + extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
> + enum machine_mode mode);
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 7ae3523095c..344cafe3dac 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -4209,12 +4209,19 @@ make_pass_stv (gcc::context *ctxt)
> + return new pass_stv (ctxt);
> + }
> +
> +-/* Return true if a red-zone is in use. */
> ++/* Return true if a red-zone is in use. We can't use red-zone when
> ++ there are local indirect jumps, like "indirect_jump" or "tablejump",
> ++ which jumps to another place in the function, since "call" in the
> ++ indirect thunk pushes the return address onto stack, destroying
> ++ red-zone. */
> +
> + bool
> + ix86_using_red_zone (void)
> + {
> +- return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
> ++ return (TARGET_RED_ZONE
> ++ && !TARGET_64BIT_MS_ABI
> ++ && (!cfun->machine->has_local_indirect_jump
> ++ || cfun->machine->indirect_branch_type == indirect_branch_keep));
> + }
> + \f
> + /* Return a string that documents the current -m options. The caller is
> +@@ -28919,11 +28926,16 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + }
> +
> + const char *
> +-ix86_output_indirect_jmp (rtx call_op)
> ++ix86_output_indirect_jmp (rtx call_op, bool ret_p)
> + {
> +- if (ix86_red_zone_size == 0
> +- && cfun->machine->indirect_branch_type != indirect_branch_keep)
> ++ if (cfun->machine->indirect_branch_type != indirect_branch_keep)
> + {
> ++ /* We can't have red-zone if this isn't a function return since
> ++ "call" in the indirect thunk pushes the return address onto
> ++ stack, destroying red-zone. */
> ++ if (!ret_p && ix86_red_zone_size != 0)
> ++ gcc_unreachable ();
> ++
> + ix86_output_indirect_branch (call_op, "%0", true);
> + return "";
> + }
> +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> +index f248f3ba2f5..5f30d3f8d19 100644
> +--- a/gcc/config/i386/i386.h
> ++++ b/gcc/config/i386/i386.h
> +@@ -2607,6 +2607,10 @@ struct GTY(()) machine_function {
> + /* How to generate indirec branch. */
> + ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
> +
> ++ /* If true, the current function has local indirect jumps, like
> ++ "indirect_jump" or "tablejump". */
> ++ BOOL_BITFIELD has_local_indirect_jump : 1;
> ++
> + /* How to generate function return. */
> + ENUM_BITFIELD(indirect_branch) function_return_type : 3;
> +
> +diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> +index 473fa5c089b..ea95aad7540 100644
> +--- a/gcc/config/i386/i386.md
> ++++ b/gcc/config/i386/i386.md
> +@@ -11610,12 +11610,13 @@
> + {
> + if (TARGET_X32 || ix86_indirect_branch_thunk_register)
> + operands[0] = convert_memory_address (word_mode, operands[0]);
> ++ cfun->machine->has_local_indirect_jump = true;
> + })
> +
> + (define_insn "*indirect_jump"
> + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
> + ""
> +- "* return ix86_output_indirect_jmp (operands[0]);"
> ++ "* return ix86_output_indirect_jmp (operands[0], false);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +@@ -11659,13 +11660,14 @@
> +
> + if (TARGET_X32 || ix86_indirect_branch_thunk_register)
> + operands[0] = convert_memory_address (word_mode, operands[0]);
> ++ cfun->machine->has_local_indirect_jump = true;
> + })
> +
> + (define_insn "*tablejump_1"
> + [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
> + (use (label_ref (match_operand 1)))]
> + ""
> +- "* return ix86_output_indirect_jmp (operands[0]);"
> ++ "* return ix86_output_indirect_jmp (operands[0], false);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +@@ -12342,7 +12344,7 @@
> + [(simple_return)
> + (use (match_operand:SI 0 "register_operand" "r"))]
> + "reload_completed"
> +- "* return ix86_output_indirect_jmp (operands[0]);"
> ++ "* return ix86_output_indirect_jmp (operands[0], true);"
> + [(set_attr "type" "ibr")
> + (set_attr "length_immediate" "0")
> + (set_attr "maybe_prefix_bnd" "1")])
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch b/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
> new file mode 100644
> index 000000000..6379270df
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Rename-thunks-to-__x86_indirect_thunk_rax-etc.-to-re.patch
> @@ -0,0 +1,926 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From a072725899c551d9f3f06f3595e2a49748ab0187 Mon Sep 17 00:00:00 2001
> +From: David Woodhouse <dwmw2@infradead.org>
> +Date: Sun, 7 Jan 2018 17:27:09 +0000
> +Subject: [PATCH 17/17] Rename thunks to __x86_indirect_thunk_rax etc. to
> + remove dots
> +
> +---
> + gcc/config/i386/i386.c | 8 ++++----
> + gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c | 6 +++---
> + gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 10 +++++-----
> + gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 10 +++++-----
> + gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 10 +++++-----
> + gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 6 +++---
> + gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 6 +++---
> + gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 6 +++---
> + gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 4 ++--
> + gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 2 +-
> + gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 10 +++++-----
> + 58 files changed, 105 insertions(+), 105 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 6cb0681233a..9e6c9bdb514 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -12006,13 +12006,13 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
> + reg_prefix = TARGET_64BIT ? "r" : "e";
> + else
> + reg_prefix = "";
> +- sprintf (name, "__x86.indirect_thunk%s.%s%s",
> ++ sprintf (name, "__x86_indirect_thunk%s_%s%s",
> + bnd, reg_prefix, reg_names[regno]);
> + }
> + else
> + {
> + const char *ret = ret_p ? "return" : "indirect";
> +- sprintf (name, "__x86.%s_thunk%s", ret, bnd);
> ++ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
> + }
> + }
> + else
> +@@ -12119,7 +12119,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
> + char name[32];
> + tree decl;
> +
> +- /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
> ++ /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
> + indirect_thunk_name (name, regno, need_bnd_p, false);
> + decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
> + get_identifier (name),
> +@@ -12165,7 +12165,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
> +
> + if (regno < 0)
> + {
> +- /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
> ++ /* Create alias for __x86_return_thunk/__x86_return_thunk_bnd. */
> + char alias[32];
> +
> + indirect_thunk_name (alias, regno, need_bnd_p, true);
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +index b0625207b92..f4f2b7debe0 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +index 0b289685e6b..d4e5dadd966 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +index 79a9f76285f..9802fae5d04 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +index 901d94213bd..fad3105b50d 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +index d2c9bd9d7ca..e44f2ff5682 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
> +@@ -10,7 +10,7 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { 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
> +index f8b028db7a2..f1e03a30854 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
> +@@ -11,7 +11,7 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> + /* { 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
> +index 465775407ec..fc91a334459 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +@@ -36,8 +36,8 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +index 5309d5a3eaa..a8ab95b6451 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +index dd1efca49fd..467d62324d5 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\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
> +index e97ca636020..02223f8d0f4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +@@ -17,5 +17,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +index b547cbbf255..a80b46af934 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +@@ -16,5 +16,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +index 353689dc415..4bb1c5f9220 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +@@ -17,6 +17,6 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +index 1edef7208f4..4e33a638862 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +@@ -16,6 +16,6 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +index c2e816cdfc6..427ba3ddbb4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +@@ -37,8 +37,8 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +index af1bb125a22..c246f974610 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
> +@@ -36,6 +36,6 @@ bar (int i)
> + }
> + }
> +
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
> + /* { 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-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +index 5c10de47b7c..3399ad56a7f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
> +@@ -12,7 +12,7 @@ foo (void)
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd ret" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +index 9eedd9a5a82..daa9528f7bd 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
> +@@ -13,7 +13,7 @@ foo (void)
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
> + /* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd ret" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +index b2b8587eac7..647ec5a4ade 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
> +@@ -11,7 +11,7 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> +-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk_bnd" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "bnd ret" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +index 9459a2417f4..3a7a1cea8bc 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
> +@@ -12,7 +12,7 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> +-/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk" } } */
> + /* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler "bnd ret" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +index b0aa3811e65..5c20a35ecec 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +index 75fabcd988c..b2fb6e1bcd2 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +index 1d9dff2e834..9c84547cd7c 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { 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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +index 5b464155e38..457849564bb 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { 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-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +index 55ce91c73ec..5c07e02df6a 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
> +@@ -10,7 +10,7 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +index 06180e7bee9..3eb440693a0 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
> +@@ -13,5 +13,5 @@ foo (void)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
> + /* { 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
> +index 790a05cec3e..d4747ea0764 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +@@ -36,8 +36,8 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +index 1ce8ca5aff1..f7fad345ca4 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +@@ -14,5 +14,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index f6b71e868bd..91388544a20 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +@@ -14,5 +14,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index 84a09d4d0d6..69f03e6472e 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index cfe3aefa0bf..226b776abcf 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index 6411454243f..b9120017c10 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
> +@@ -12,4 +12,4 @@ foo (void)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index d4297fe21c4..fbd6f9ec457 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
> +@@ -13,4 +13,4 @@ foo (void)
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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
> +index eb318efdf4d..2553c56f97f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +@@ -39,4 +39,4 @@ bar (int i)
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +index 605e32bb584..c266ca6f2da 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-1.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +index dd7a7b60621..f7c1cf6c45a 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-2.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tnop} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +index 338f22c373c..ef5c4b84312 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-3.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +index 3b083ee30a8..941fcdaffb1 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-4.c
> +@@ -15,5 +15,5 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler {\tpause} } } */
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> ++/* { 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-loop-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +index 31a9a81a911..0c5ace58358 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-loop-5.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
> + /* { dg-final { scan-assembler-not {\t(lfence|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-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
> +index ef493a05bbf..1a28abb4604 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
> +@@ -11,12 +11,12 @@ 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\]*__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 {\tlfence} } } */
> + /* { 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" } } */
> ++/* { dg-final { scan-assembler-not "__x86_indirect_thunk_" } } */
> ++/* { 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
> +index 89fc8e6e6c4..428d6f9e986 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
> +@@ -17,4 +17,4 @@ male_indirect_jump (long offset)
> + /* { dg-final { scan-assembler {\tlfence} } } */
> + /* { 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" } } */
> ++/* { 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
> +index 31af7ac05b8..28dcdcf2855 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
> +@@ -11,7 +11,7 @@ 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\]*__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(lfence|pause|nop)} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
> +index 406956f48e5..07f382c21b2 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
> +@@ -6,7 +6,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> +index 74f37ee9a62..da8029bad49 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
> +@@ -12,11 +12,11 @@ foo (void)
> +
> + /* { 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-not "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-times {\tlfence} 2 } } */
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> +index 0a52318e86b..6964997871d 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
> +@@ -10,13 +10,13 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { 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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> +index d2f775490ea..ff0234bd17d 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
> +@@ -10,12 +10,12 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk:" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> +-/* { dg-final { scan-assembler "__x86.indirect_thunk\.(r|e)ax:" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> +index 82d46165f3e..a5b16472051 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
> +@@ -11,11 +11,11 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-times {\tlfence} 2 } } */
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> + /* { 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" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> +index 6711eb27fa8..219d71548bf 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
> +@@ -12,10 +12,10 @@ foo (void)
> + }
> +
> + /* { dg-final { scan-assembler-times {\tlfence} 1 } } */
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { 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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> +index 37758c33371..bad6b16820d 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
> +@@ -11,11 +11,11 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { 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 {\tlfence} 1 } } */
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
> +index cf3920563e0..173fe243d7b 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
> +@@ -11,8 +11,8 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +-/* { dg-final { scan-assembler-not "__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
> ++/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-not {\tlfence} } } */
> + /* { 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-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> +index 190947cc2ca..5516813a290 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
> +@@ -9,4 +9,4 @@ foo (void)
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler {\tlfence} } } */
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
> +index d71de3ac520..9f1ade857ef 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
> +@@ -6,7 +6,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-not {\tlfence} } } */
> + /* { 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
> +index 68c22122f0d..abecde0a550 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
> +@@ -6,7 +6,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-not {\tlfence} } } */
> + /* { 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
> +index 28c576e2267..3b51a9931db 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
> +@@ -8,7 +8,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
> +index 10ad40b9c26..52160e0ee77 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
> +@@ -10,4 +10,4 @@ foo (void)
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler {\tlfence} } } */
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { 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
> +index 7ac0beaa73e..65819c2ab76 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
> +@@ -7,7 +7,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-not {\tlfence} } } */
> + /* { 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
> +index 777ab7c8088..a6a1bbc054b 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
> +@@ -8,7 +8,7 @@ foo (void)
> + {
> + }
> +
> +-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86.return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
> + /* { dg-final { scan-assembler-not {\tlfence} } } */
> + /* { 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
> +index 70771ea35d7..21a0e6bde3d 100644
> +--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> ++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
> +@@ -10,14 +10,14 @@ foo (void)
> + return 0;
> + }
> +
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.return_thunk" } } */
> +-/* { dg-final { scan-assembler-not "__x86.return_thunk:" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
> ++/* { dg-final { scan-assembler-not "__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 "__x86_indirect_thunk:" } } */
> + /* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
> + /* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
> +-/* { dg-final { scan-assembler "call\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target { x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
> + /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch b/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
> new file mode 100644
> index 000000000..bd6797816
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-Use-__x86.indirect_thunk.reg-for-indirect-branch-via.patch
> @@ -0,0 +1,623 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From e4e33b44a49eaa102806589ce12f021ab6a1e5f1 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Wed, 13 Dec 2017 12:59:50 -0800
> +Subject: [PATCH 09/17] Use __x86.indirect_thunk.reg for indirect branch via
> + register
> +
> +---
> + gcc/config/i386/i386.c | 137 +++++++++++++++++----
> + gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 4 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 4 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 8 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 8 +-
> + gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-attr-1.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-attr-2.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-attr-5.c | 8 +-
> + .../gcc.target/i386/indirect-thunk-attr-6.c | 8 +-
> + .../gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-extern-1.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-extern-2.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-extern-3.c | 8 +-
> + .../gcc.target/i386/indirect-thunk-extern-4.c | 8 +-
> + .../gcc.target/i386/indirect-thunk-extern-7.c | 4 +-
> + .../gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
> + .../gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
> + 23 files changed, 158 insertions(+), 75 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 5e66af08066..590729b3f87 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -11948,6 +11948,9 @@ static int indirectlabelno;
> + static bool indirect_thunk_needed = false;
> + static bool indirect_thunk_bnd_needed = false;
> +
> ++static int indirect_thunks_used;
> ++static int indirect_thunks_bnd_used;
> ++
> + #ifndef INDIRECT_LABEL
> + # define INDIRECT_LABEL "LIND"
> + #endif
> +@@ -11955,24 +11958,45 @@ static bool indirect_thunk_bnd_needed = false;
> + /* Fills in the label name that should be used for the indirect thunk. */
> +
> + static void
> +-indirect_thunk_name (char name[32], bool need_bnd_p)
> ++indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
> + {
> + if (USE_HIDDEN_LINKONCE)
> + {
> + const char *bnd = need_bnd_p ? "_bnd" : "";
> +- sprintf (name, "__x86.indirect_thunk%s", bnd);
> ++ if (regno >= 0)
> ++ {
> ++ const char *reg_prefix;
> ++ if (LEGACY_INT_REGNO_P (regno))
> ++ reg_prefix = TARGET_64BIT ? "r" : "e";
> ++ else
> ++ reg_prefix = "";
> ++ sprintf (name, "__x86.indirect_thunk%s.%s%s",
> ++ bnd, reg_prefix, reg_names[regno]);
> ++ }
> ++ else
> ++ sprintf (name, "__x86.indirect_thunk%s", bnd);
> + }
> + else
> + {
> +- if (need_bnd_p)
> +- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
> ++ if (regno >= 0)
> ++ {
> ++ if (need_bnd_p)
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno);
> ++ else
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
> ++ }
> + else
> +- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
> ++ {
> ++ if (need_bnd_p)
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
> ++ else
> ++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
> ++ }
> + }
> + }
> +
> + static void
> +-output_indirect_thunk (bool need_bnd_p)
> ++output_indirect_thunk (bool need_bnd_p, int regno)
> + {
> + char indirectlabel1[32];
> + char indirectlabel2[32];
> +@@ -12002,11 +12026,22 @@ output_indirect_thunk (bool need_bnd_p)
> +
> + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
> +
> +- /* LEA. */
> +- rtx xops[2];
> +- xops[0] = stack_pointer_rtx;
> +- xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
> +- output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
> ++ if (regno >= 0)
> ++ {
> ++ /* MOV. */
> ++ rtx xops[2];
> ++ xops[0] = gen_rtx_MEM (word_mode, stack_pointer_rtx);
> ++ xops[1] = gen_rtx_REG (word_mode, regno);
> ++ output_asm_insn ("mov\t{%1, %0|%0, %1}", xops);
> ++ }
> ++ else
> ++ {
> ++ /* LEA. */
> ++ rtx xops[2];
> ++ xops[0] = stack_pointer_rtx;
> ++ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
> ++ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
> ++ }
> +
> + if (need_bnd_p)
> + fputs ("\tbnd ret\n", asm_out_file);
> +@@ -12015,12 +12050,13 @@ output_indirect_thunk (bool need_bnd_p)
> + }
> +
> + static void
> +-output_indirect_thunk_function (bool need_bnd_p)
> ++output_indirect_thunk_function (bool need_bnd_p, int regno)
> + {
> + char name[32];
> + tree decl;
> +
> +- indirect_thunk_name (name, need_bnd_p);
> ++ /* Create __x86.indirect_thunk/__x86.indirect_thunk_bnd. */
> ++ indirect_thunk_name (name, regno, need_bnd_p);
> + decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
> + get_identifier (name),
> + build_function_type_list (void_type_node, NULL_TREE));
> +@@ -12074,7 +12110,7 @@ output_indirect_thunk_function (bool need_bnd_p)
> + /* Make sure unwind info is emitted for the thunk if needed. */
> + final_start_function (emit_barrier (), asm_out_file, 1);
> +
> +- output_indirect_thunk (need_bnd_p);
> ++ output_indirect_thunk (need_bnd_p, regno);
> +
> + final_end_function ();
> + init_insn_lengths ();
> +@@ -12110,15 +12146,31 @@ ix86_code_end (void)
> + int regno;
> +
> + if (indirect_thunk_needed)
> +- output_indirect_thunk_function (false);
> ++ output_indirect_thunk_function (false, -1);
> + if (indirect_thunk_bnd_needed)
> +- output_indirect_thunk_function (true);
> ++ output_indirect_thunk_function (true, -1);
> ++
> ++ for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
> ++ {
> ++ int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1;
> ++ if ((indirect_thunks_used & (1 << i)))
> ++ output_indirect_thunk_function (false, regno);
> ++
> ++ if ((indirect_thunks_bnd_used & (1 << i)))
> ++ output_indirect_thunk_function (true, regno);
> ++ }
> +
> + for (regno = AX_REG; regno <= SP_REG; regno++)
> + {
> + char name[32];
> + tree decl;
> +
> ++ if ((indirect_thunks_used & (1 << regno)))
> ++ output_indirect_thunk_function (false, regno);
> ++
> ++ if ((indirect_thunks_bnd_used & (1 << regno)))
> ++ output_indirect_thunk_function (true, regno);
> ++
> + if (!(pic_labels_used & (1 << regno)))
> + continue;
> +
> +@@ -28639,17 +28691,37 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + char *thunk_name;
> + char push_buf[64];
> + bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
> ++ int regno;
> ++
> ++ if (REG_P (call_op))
> ++ regno = REGNO (call_op);
> ++ else
> ++ regno = -1;
> +
> + if (cfun->machine->indirect_branch_type
> + != indirect_branch_thunk_inline)
> + {
> +- bool need_thunk
> +- = cfun->machine->indirect_branch_type == indirect_branch_thunk;
> +- if (need_bnd_p)
> +- indirect_thunk_bnd_needed |= need_thunk;
> +- else
> +- indirect_thunk_needed |= need_thunk;
> +- indirect_thunk_name (thunk_name_buf, need_bnd_p);
> ++ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
> ++ {
> ++ if (regno >= 0)
> ++ {
> ++ int i = regno;
> ++ if (i >= FIRST_REX_INT_REG)
> ++ i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
> ++ if (need_bnd_p)
> ++ indirect_thunks_bnd_used |= 1 << i;
> ++ else
> ++ indirect_thunks_used |= 1 << i;
> ++ }
> ++ else
> ++ {
> ++ if (need_bnd_p)
> ++ indirect_thunk_bnd_needed = true;
> ++ else
> ++ indirect_thunk_needed = true;
> ++ }
> ++ }
> ++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
> + thunk_name = thunk_name_buf;
> + }
> + else
> +@@ -28660,7 +28732,8 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> +
> + if (sibcall_p)
> + {
> +- output_asm_insn (push_buf, &call_op);
> ++ if (regno < 0)
> ++ output_asm_insn (push_buf, &call_op);
> + if (thunk_name != NULL)
> + {
> + if (need_bnd_p)
> +@@ -28669,10 +28742,19 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> + }
> + else
> +- output_indirect_thunk (need_bnd_p);
> ++ output_indirect_thunk (need_bnd_p, regno);
> + }
> + else
> + {
> ++ if (regno >= 0 && thunk_name != NULL)
> ++ {
> ++ if (need_bnd_p)
> ++ fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name);
> ++ else
> ++ fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
> ++ return;
> ++ }
> ++
> + char indirectlabel1[32];
> + char indirectlabel2[32];
> +
> +@@ -28725,7 +28807,8 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + }
> + }
> +
> +- output_asm_insn (push_buf, &call_op);
> ++ if (regno < 0)
> ++ output_asm_insn (push_buf, &call_op);
> +
> + if (thunk_name != NULL)
> + {
> +@@ -28735,7 +28818,7 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
> + fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
> + }
> + else
> +- output_indirect_thunk (need_bnd_p);
> ++ output_indirect_thunk (need_bnd_p, regno);
> +
> + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
> +
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +index d8b6f5a06a5..785e593405f 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +index f7d5cb315a8..b69075e6483 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +index 736d7cda058..df8109baf55 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +index cef9b10513e..8f3b9f4d8a5 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { target { ! x32 } } } } */
> ++/* { dg-final { scan-assembler "call\[ \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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +index ea0fa312f64..f0e1cfe1893 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
> +@@ -36,8 +36,8 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +index 26550fad4c8..8b88449e625 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
> +@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\tlfence} } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +index f57bb2a92d6..c69f7bf4f60 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 {\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
> +index a3668a6586c..c845099a83e 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
> +@@ -15,7 +15,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> + /* { 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-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +index a9c4a137dd4..f636f3422fd 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
> +@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> + /* { 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-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +index 9582e0c5824..5f1d6a78041 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
> +@@ -15,8 +15,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { 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-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +index 66442cacfe8..56c92da9812 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
> +@@ -14,8 +14,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { 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 "jmp\[ \t\]*__x86.indirect_thunk" { 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-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +index 2a19b54cd2e..cfb6f5b234b 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
> +@@ -37,7 +37,7 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk\.(r|e)ax" { target x32 } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> + /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
> + /* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
> +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +index 0a1f91be988..f1fa0a11922 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +index 182520ab3dc..d6e078d594b 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
> +@@ -12,8 +12,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +index 5c31ddc34fd..3bbe2646955 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 "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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +index f24d0c060f2..596fac599f6 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
> +@@ -13,8 +13,8 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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 "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
> +index 8d39fb6f939..ab367951c45 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
> +@@ -36,8 +36,8 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> +-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" } } */
> ++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86.indirect_thunk" { 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-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +index 071e6c89ac7..09b8ad7d879 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
> +@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { 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
> +index 804c7ccdba7..1f873758fbe 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
> +@@ -12,7 +12,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { 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
> +index 545a981add5..b24af1da963 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
> +@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> + /* { 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
> +index d9ff4722cff..1a86608f727 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
> +@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
> + /* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
> + /* { 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-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +index a0ce06b8232..01d45782185 100644
> +--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
> +@@ -36,7 +36,7 @@ bar (int i)
> + }
> +
> + /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
> +-/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
> ++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
> + /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
> + /* { dg-final { scan-assembler-not "__x86.indirect_thunk" } } */
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch b/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
> new file mode 100644
> index 000000000..1996a1dfe
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-i386-Add-V-register-operand-modifier.patch
> @@ -0,0 +1,76 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From f83391fb22471a2f1c330e2e78f64630d64f497d Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 19 Dec 2017 08:28:36 -0800
> +Subject: [PATCH 16/17] i386: Add 'V' register operand modifier
> +
> +For
> +
> +void
> +bar (void (*func) (void))
> +{
> + asm("call *%V0" : : "r"(func));
> +}
> +
> +it generates:
> +
> +bar:
> + call *rdi
> + ret
> +---
> + gcc/config/i386/i386.c | 5 ++++-
> + 1 file changed, 4 insertions(+), 1 deletion(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 344cafe3dac..6cb0681233a 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -17886,6 +17886,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
> + If CODE is 'h', pretend the reg is the 'high' byte register.
> + If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
> + If CODE is 'd', duplicate the operand for AVX instruction.
> ++ If CODE is 'V', print naked register name without %.
> + */
> +
> + void
> +@@ -17896,7 +17897,7 @@ print_reg (rtx x, int code, FILE *file)
> + unsigned int regno;
> + bool duplicated;
> +
> +- if (ASSEMBLER_DIALECT == ASM_ATT)
> ++ if (ASSEMBLER_DIALECT == ASM_ATT && code != 'V')
> + putc ('%', file);
> +
> + if (x == pc_rtx)
> +@@ -18063,6 +18064,7 @@ print_reg (rtx x, int code, FILE *file)
> + & -- print some in-use local-dynamic symbol name.
> + H -- print a memory address offset by 8; used for sse high-parts
> + Y -- print condition for XOP pcom* instruction.
> ++ V -- print naked register name without %.
> + + -- print a branch hint as 'cs' or 'ds' prefix
> + ; -- print a semicolon (after prefixes due to bug in older gas).
> + ~ -- print "i" if TARGET_AVX2, "f" otherwise.
> +@@ -18287,6 +18289,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
> + case 'X':
> + case 'P':
> + case 'p':
> ++ case 'V':
> + break;
> +
> + case 's':
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
> new file mode 100644
> index 000000000..3c42dd802
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
> @@ -0,0 +1,69 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From d96784e4a7355aaab68dec62f31a97bd10714064 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Tue, 28 Nov 2017 10:26:35 -0800
> +Subject: [PATCH 03/17] i386: More use reference of struct ix86_frame to avoid
> + copy
> +
> +When there is no need to make a copy of ix86_frame, we can use reference
> +of struct ix86_frame to avoid copy.
> +
> + * config/i386/i386.c (ix86_expand_prologue): Use reference of
> + struct ix86_frame.
> + (ix86_expand_epilogue): Likewise.
> +---
> + gcc/config/i386/i386.c | 6 ++----
> + 1 file changed, 2 insertions(+), 4 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index 01ecda7643b..504530a00cf 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -13656,7 +13656,6 @@ ix86_expand_prologue (void)
> + {
> + struct machine_function *m = cfun->machine;
> + rtx insn, t;
> +- struct ix86_frame frame;
> + HOST_WIDE_INT allocate;
> + bool int_registers_saved;
> + bool sse_registers_saved;
> +@@ -13680,7 +13679,7 @@ ix86_expand_prologue (void)
> + m->fs.sp_valid = true;
> +
> + ix86_compute_frame_layout ();
> +- frame = m->frame;
> ++ struct ix86_frame &frame = cfun->machine->frame;
> +
> + if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
> + {
> +@@ -14343,13 +14342,12 @@ ix86_expand_epilogue (int style)
> + {
> + struct machine_function *m = cfun->machine;
> + struct machine_frame_state frame_state_save = m->fs;
> +- struct ix86_frame frame;
> + bool restore_regs_via_mov;
> + bool using_drap;
> +
> + ix86_finalize_stack_realign_flags ();
> + ix86_compute_frame_layout ();
> +- frame = m->frame;
> ++ struct ix86_frame &frame = cfun->machine->frame;
> +
> + m->fs.sp_valid = (!frame_pointer_needed
> + || (crtl->sp_is_unchanging
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
> new file mode 100644
> index 000000000..908e3cd83
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
> @@ -0,0 +1,249 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 85743811dfa4eb648edbbb637632ac53182b6e05 Mon Sep 17 00:00:00 2001
> +From: "H.J. Lu" <hjl.tools@gmail.com>
> +Date: Mon, 6 Nov 2017 09:11:08 -0800
> +Subject: [PATCH 01/17] i386: Move struct ix86_frame to machine_function
> +
> +Make ix86_frame available to i386 code generation.
> +
> + * config/i386/i386.c (ix86_frame): Moved to ...
> + * config/i386/i386.h (ix86_frame): Here.
> + (machine_function): Add frame.
> + * config/i386/i386.c (ix86_compute_frame_layout): Repace the
> + frame argument with &cfun->machine->frame.
> + (ix86_can_use_return_insn_p): Don't pass &frame to
> + ix86_compute_frame_layout. Copy frame from cfun->machine->frame.
> + (ix86_can_eliminate): Likewise.
> + (ix86_expand_prologue): Likewise.
> + (ix86_expand_epilogue): Likewise.
> + (ix86_expand_split_stack_prologue): Likewise.
> +---
> + gcc/config/i386/i386.c | 68 ++++++++++----------------------------------------
> + gcc/config/i386/i386.h | 53 ++++++++++++++++++++++++++++++++++++++-
> + 2 files changed, 65 insertions(+), 56 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index dc14d205de7..c23c259c538 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -2441,53 +2441,6 @@ struct GTY(()) stack_local_entry {
> + struct stack_local_entry *next;
> + };
> +
> +-/* Structure describing stack frame layout.
> +- Stack grows downward:
> +-
> +- [arguments]
> +- <- ARG_POINTER
> +- saved pc
> +-
> +- saved static chain if ix86_static_chain_on_stack
> +-
> +- saved frame pointer if frame_pointer_needed
> +- <- HARD_FRAME_POINTER
> +- [saved regs]
> +- <- regs_save_offset
> +- [padding0]
> +-
> +- [saved SSE regs]
> +- <- sse_regs_save_offset
> +- [padding1] |
> +- | <- FRAME_POINTER
> +- [va_arg registers] |
> +- |
> +- [frame] |
> +- |
> +- [padding2] | = to_allocate
> +- <- STACK_POINTER
> +- */
> +-struct ix86_frame
> +-{
> +- int nsseregs;
> +- int nregs;
> +- int va_arg_size;
> +- int red_zone_size;
> +- int outgoing_arguments_size;
> +-
> +- /* The offsets relative to ARG_POINTER. */
> +- HOST_WIDE_INT frame_pointer_offset;
> +- HOST_WIDE_INT hard_frame_pointer_offset;
> +- HOST_WIDE_INT stack_pointer_offset;
> +- HOST_WIDE_INT hfp_save_offset;
> +- HOST_WIDE_INT reg_save_offset;
> +- HOST_WIDE_INT sse_reg_save_offset;
> +-
> +- /* When save_regs_using_mov is set, emit prologue using
> +- move instead of push instructions. */
> +- bool save_regs_using_mov;
> +-};
> +-
> + /* Which cpu are we scheduling for. */
> + enum attr_cpu ix86_schedule;
> +
> +@@ -2579,7 +2532,7 @@ static unsigned int ix86_function_arg_boundary (machine_mode,
> + const_tree);
> + static rtx ix86_static_chain (const_tree, bool);
> + static int ix86_function_regparm (const_tree, const_tree);
> +-static void ix86_compute_frame_layout (struct ix86_frame *);
> ++static void ix86_compute_frame_layout (void);
> + static bool ix86_expand_vector_init_one_nonzero (bool, machine_mode,
> + rtx, rtx, int);
> + static void ix86_add_new_builtins (HOST_WIDE_INT, HOST_WIDE_INT);
> +@@ -11892,7 +11845,8 @@ ix86_can_use_return_insn_p (void)
> + if (crtl->args.pops_args && crtl->args.size >= 32768)
> + return 0;
> +
> +- ix86_compute_frame_layout (&frame);
> ++ ix86_compute_frame_layout ();
> ++ frame = cfun->machine->frame;
> + return (frame.stack_pointer_offset == UNITS_PER_WORD
> + && (frame.nregs + frame.nsseregs) == 0);
> + }
> +@@ -12378,8 +12332,8 @@ ix86_can_eliminate (const int from, const int to)
> + HOST_WIDE_INT
> + ix86_initial_elimination_offset (int from, int to)
> + {
> +- struct ix86_frame frame;
> +- ix86_compute_frame_layout (&frame);
> ++ ix86_compute_frame_layout ();
> ++ struct ix86_frame frame = cfun->machine->frame;
> +
> + if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
> + return frame.hard_frame_pointer_offset;
> +@@ -12418,8 +12372,9 @@ ix86_builtin_setjmp_frame_value (void)
> + /* Fill structure ix86_frame about frame of currently computed function. */
> +
> + static void
> +-ix86_compute_frame_layout (struct ix86_frame *frame)
> ++ix86_compute_frame_layout (void)
> + {
> ++ struct ix86_frame *frame = &cfun->machine->frame;
> + unsigned HOST_WIDE_INT stack_alignment_needed;
> + HOST_WIDE_INT offset;
> + unsigned HOST_WIDE_INT preferred_alignment;
> +@@ -13726,7 +13681,8 @@ ix86_expand_prologue (void)
> + m->fs.sp_offset = INCOMING_FRAME_SP_OFFSET;
> + m->fs.sp_valid = true;
> +
> +- ix86_compute_frame_layout (&frame);
> ++ ix86_compute_frame_layout ();
> ++ frame = m->frame;
> +
> + if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
> + {
> +@@ -14394,7 +14350,8 @@ ix86_expand_epilogue (int style)
> + bool using_drap;
> +
> + ix86_finalize_stack_realign_flags ();
> +- ix86_compute_frame_layout (&frame);
> ++ ix86_compute_frame_layout ();
> ++ frame = m->frame;
> +
> + m->fs.sp_valid = (!frame_pointer_needed
> + || (crtl->sp_is_unchanging
> +@@ -14904,7 +14861,8 @@ ix86_expand_split_stack_prologue (void)
> + gcc_assert (flag_split_stack && reload_completed);
> +
> + ix86_finalize_stack_realign_flags ();
> +- ix86_compute_frame_layout (&frame);
> ++ ix86_compute_frame_layout ();
> ++ frame = cfun->machine->frame;
> + allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
> +
> + /* This is the label we will branch to if we have enough stack
> +diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
> +index 9e5f4d857d9..7d9f9020fb3 100644
> +--- a/gcc/config/i386/i386.h
> ++++ b/gcc/config/i386/i386.h
> +@@ -2446,9 +2446,56 @@ enum avx_u128_state
> + \f
> + #define FASTCALL_PREFIX '@'
> + \f
> ++#ifndef USED_FOR_TARGET
> ++/* Structure describing stack frame layout.
> ++ Stack grows downward:
> ++
> ++ [arguments]
> ++ <- ARG_POINTER
> ++ saved pc
> ++
> ++ saved static chain if ix86_static_chain_on_stack
> ++
> ++ saved frame pointer if frame_pointer_needed
> ++ <- HARD_FRAME_POINTER
> ++ [saved regs]
> ++ <- regs_save_offset
> ++ [padding0]
> ++
> ++ [saved SSE regs]
> ++ <- sse_regs_save_offset
> ++ [padding1] |
> ++ | <- FRAME_POINTER
> ++ [va_arg registers] |
> ++ |
> ++ [frame] |
> ++ |
> ++ [padding2] | = to_allocate
> ++ <- STACK_POINTER
> ++ */
> ++struct GTY(()) ix86_frame
> ++{
> ++ int nsseregs;
> ++ int nregs;
> ++ int va_arg_size;
> ++ int red_zone_size;
> ++ int outgoing_arguments_size;
> ++
> ++ /* The offsets relative to ARG_POINTER. */
> ++ HOST_WIDE_INT frame_pointer_offset;
> ++ HOST_WIDE_INT hard_frame_pointer_offset;
> ++ HOST_WIDE_INT stack_pointer_offset;
> ++ HOST_WIDE_INT hfp_save_offset;
> ++ HOST_WIDE_INT reg_save_offset;
> ++ HOST_WIDE_INT sse_reg_save_offset;
> ++
> ++ /* When save_regs_using_mov is set, emit prologue using
> ++ move instead of push instructions. */
> ++ bool save_regs_using_mov;
> ++};
> ++
> + /* Machine specific frame tracking during prologue/epilogue generation. */
> +
> +-#ifndef USED_FOR_TARGET
> + struct GTY(()) machine_frame_state
> + {
> + /* This pair tracks the currently active CFA as reg+offset. When reg
> +@@ -2507,6 +2554,9 @@ struct GTY(()) machine_function {
> + int varargs_fpr_size;
> + int optimize_mode_switching[MAX_386_ENTITIES];
> +
> ++ /* Cached initial frame layout for the current function. */
> ++ struct ix86_frame frame;
> ++
> + /* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE
> + has been computed for. */
> + int use_fast_prologue_epilogue_nregs;
> +@@ -2589,6 +2639,7 @@ struct GTY(()) machine_function {
> + #define ix86_current_function_calls_tls_descriptor \
> + (ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
> + #define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
> ++#define ix86_red_zone_size (cfun->machine->frame.red_zone_size)
> +
> + /* Control behavior of x86_file_start. */
> + #define X86_FILE_START_VERSION_DIRECTIVE false
> +--
> +2.15.1
> +
> diff --git a/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
> new file mode 100644
> index 000000000..623ce5094
> --- /dev/null
> +++ b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
> @@ -0,0 +1,85 @@
> +'Retpoline' mitigation technique for Spectre (branch target injection)
> +[CVE-2017-5715]:
> +
> +https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
> +https://support.google.com/faqs/answer/7625886
> +https://spectreattack.com/
> +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
> +
> +Patch copied from the 'retpoline-20180107' branch of upstream source repository
> +(please add new / update existing patches when new 'retpoline-xxxxxxxx' branch
> +appears):
> +
> +http://git.infradead.org/users/dwmw2/gcc-retpoline.git
> +
> +From 0b1769bdce27304a6a91bec234f47f102a2603d5 Mon Sep 17 00:00:00 2001
> +From: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
> +Date: Mon, 6 Nov 2017 23:04:15 +0000
> +Subject: [PATCH 02/17] i386: Use reference of struct ix86_frame to avoid copy
> +
> +When there is no need to make a copy of ix86_frame, we can use reference
> +of struct ix86_frame to avoid copy.
> +
> +Tested on x86-64.
> +
> + * config/i386/i386.c (ix86_can_use_return_insn_p): Use reference
> + of struct ix86_frame.
> + (ix86_initial_elimination_offset): Likewise.
> + (ix86_expand_split_stack_prologue): Likewise.
> +
> +git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254480 138bc75d-0d04-0410-961f-82ee72b054a4
> +---
> + gcc/config/i386/i386.c | 9 +++------
> + 1 file changed, 3 insertions(+), 6 deletions(-)
> +
> +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> +index c23c259c538..01ecda7643b 100644
> +--- a/gcc/config/i386/i386.c
> ++++ b/gcc/config/i386/i386.c
> +@@ -11832,8 +11832,6 @@ symbolic_reference_mentioned_p (rtx op)
> + bool
> + ix86_can_use_return_insn_p (void)
> + {
> +- struct ix86_frame frame;
> +-
> + /* Don't use `ret' instruction in interrupt handler. */
> + if (! reload_completed
> + || frame_pointer_needed
> +@@ -11846,7 +11844,7 @@ ix86_can_use_return_insn_p (void)
> + return 0;
> +
> + ix86_compute_frame_layout ();
> +- frame = cfun->machine->frame;
> ++ struct ix86_frame &frame = cfun->machine->frame;
> + return (frame.stack_pointer_offset == UNITS_PER_WORD
> + && (frame.nregs + frame.nsseregs) == 0);
> + }
> +@@ -12333,7 +12331,7 @@ HOST_WIDE_INT
> + ix86_initial_elimination_offset (int from, int to)
> + {
> + ix86_compute_frame_layout ();
> +- struct ix86_frame frame = cfun->machine->frame;
> ++ struct ix86_frame &frame = cfun->machine->frame;
> +
> + if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
> + return frame.hard_frame_pointer_offset;
> +@@ -14849,7 +14847,6 @@ static GTY(()) rtx split_stack_fn_large;
> + void
> + ix86_expand_split_stack_prologue (void)
> + {
> +- struct ix86_frame frame;
> + HOST_WIDE_INT allocate;
> + unsigned HOST_WIDE_INT args_size;
> + rtx_code_label *label;
> +@@ -14862,7 +14859,7 @@ ix86_expand_split_stack_prologue (void)
> +
> + ix86_finalize_stack_realign_flags ();
> + ix86_compute_frame_layout ();
> +- frame = cfun->machine->frame;
> ++ struct ix86_frame &frame = cfun->machine->frame;
> + allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
> +
> + /* This is the label we will branch to if we have enough stack
> +--
> +2.15.1
> +
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-15 14:29 ` Alex Vong
@ 2018-01-16 13:14 ` Alex Vong
2018-01-16 14:33 ` Ludovic Courtès
0 siblings, 1 reply; 14+ messages in thread
From: Alex Vong @ 2018-01-16 13:14 UTC (permalink / raw)
To: 30111
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Hello,
This is the new patch. Similar to last time, I haven't test it yet, but
I will report if it doesn't build.
[-- Attachment #2: 0001-gnu-gcc-7-Apply-the-retpoline-mitigation-technique.patch --]
[-- Type: text/x-diff, Size: 248343 bytes --]
From aea3d11f59e260111bdb8bcac458c97a946fa900 Mon Sep 17 00:00:00 2001
From: Alex Vong <alexvong1995@gmail.com>
Date: Tue, 16 Jan 2018 20:32:32 +0800
Subject: [PATCH] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
This is part of Spectre (branch target injection) [CVE-2017-5715]
mitigation. Suggested by Mark H Weaver <mhw@netris.org>.
* gnu/local.mk (dist_patch_DATA): Add them.
* gnu/packages/gcc.scm (gcc@7): Use them.
* gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch,
gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch,
gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch,
gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch,
gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch,
gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch,
gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch,
gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch,
gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch,
gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch:
New files.
---
gnu/local.mk | 12 +-
gnu/packages/gcc.scm | 13 +-
.../gcc-retpoline-Change-V-to-bare-reg-names.patch | 51 +
...se-reference-of-struct-ix86_frame-to-avoi.patch | 69 +
...ove-struct-ix86_frame-to-machine_function.patch | 252 +++
...ference-of-struct-ix86_frame-to-avoid-cop.patch | 83 +
.../gcc-retpoline-indirect-thunk-reg-names.patch | 365 ++++
...oline-x86-Add-V-register-operand-modifier.patch | 143 ++
.../gcc-retpoline-x86-Add-mfunction-return.patch | 1303 ++++++++++++
...tpoline-x86-Add-mindirect-branch-register.patch | 907 ++++++++
.../gcc-retpoline-x86-Add-mindirect-branch.patch | 2171 ++++++++++++++++++++
...w-mindirect-branch-mfunction-return-with-.patch | 308 +++
12 files changed, 5675 insertions(+), 2 deletions(-)
create mode 100644 gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch
create mode 100644 gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch
diff --git a/gnu/local.mk b/gnu/local.mk
index fb4babfdb..b84d0b545 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -9,7 +9,7 @@
# Copyright © 2016 Adonay "adfeno" Felipe Nogueira <https://libreplanet.org/wiki/User:Adfeno> <adfeno@openmailbox.org>
# Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
-# Copyright © 2016, 2017 Alex Vong <alexvong1995@gmail.com>
+# Copyright © 2016, 2017, 2018 Alex Vong <alexvong1995@gmail.com>
# Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
# Copyright © 2016, 2017 Jan Nieuwenhuizen <janneke@gnu.org>
# Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
@@ -654,6 +654,16 @@ dist_patch_DATA = \
%D%/packages/patches/gcc-asan-powerpc-missing-include.patch \
%D%/packages/patches/gcc-cross-environment-variables.patch \
%D%/packages/patches/gcc-libvtv-runpath.patch \
+ %D%/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch \
+ %D%/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch \
+ %D%/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch \
+ %D%/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch \
+ %D%/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch \
+ %D%/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch \
+ %D%/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch \
+ %D%/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch \
+ %D%/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch \
+ %D%/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch \
%D%/packages/patches/gcc-strmov-store-file-names.patch \
%D%/packages/patches/gcc-4-compile-with-gcc-5.patch \
%D%/packages/patches/gcc-4.6-gnu-inline.patch \
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index ad8992289..89d2ab7fd 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -5,6 +5,7 @@
;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2015, 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Carlos Sánchez de La Lama <csanchezdll@gmail.com>
+;;; Copyright © 2018 ALex Vong <alexvong1995@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -427,7 +428,17 @@ Go. It also includes runtime support libraries for these languages.")
(base32
"16j7i0888j2f1yp9l0nhji6cq65dy6y4nwy8868a8njbzzwavxqw"))
(patches (search-patches "gcc-strmov-store-file-names.patch"
- "gcc-5.0-libvtv-runpath.patch"))))
+ "gcc-5.0-libvtv-runpath.patch"
+ "gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch"
+ "gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch"
+ "gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch"
+ "gcc-retpoline-x86-Add-mindirect-branch.patch"
+ "gcc-retpoline-x86-Add-mfunction-return.patch"
+ "gcc-retpoline-x86-Add-mindirect-branch-register.patch"
+ "gcc-retpoline-x86-Add-V-register-operand-modifier.patch"
+ "gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch"
+ "gcc-retpoline-Change-V-to-bare-reg-names.patch"
+ "gcc-retpoline-indirect-thunk-reg-names.patch"))))
(description
"GCC is the GNU Compiler Collection. It provides compiler front-ends
for several languages, including C, C++, Objective-C, Fortran, Ada, and Go.
diff --git a/gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch b/gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch
new file mode 100644
index 000000000..1d893a621
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch
@@ -0,0 +1,51 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From c26d2b96599ebc9ff24c685a2dc3b01709aa3cce Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Sun, 14 Jan 2018 21:27:35 +0000
+Subject: [PATCH 09/10] Change %V to bare reg names
+
+---
+ gcc/config/i386/i386.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 318a71840c9..6d345031a82 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -18029,7 +18029,7 @@ print_reg (rtx x, int code, FILE *file)
+ warning (0, "unsupported size for integer register");
+ /* FALLTHRU */
+ case 4:
+- if (LEGACY_INT_REGNO_P (regno))
++ if (LEGACY_INT_REGNO_P (regno) && code != 'V')
+ putc (msize > 4 && TARGET_64BIT ? 'r' : 'e', file);
+ /* FALLTHRU */
+ case 2:
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
+index f0cd9b75be8..6791890944c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
+@@ -9,5 +9,5 @@ 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 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target ia32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { ! ia32 } } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
new file mode 100644
index 000000000..e115e3f6c
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch
@@ -0,0 +1,69 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From ec4a7ca4051bb5cbefe03a2e1fb690b9738b8c6d Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 28 Nov 2017 10:26:35 -0800
+Subject: [PATCH 03/10] i386: More use reference of struct ix86_frame to avoid
+ copy
+
+When there is no need to make a copy of ix86_frame, we can use reference
+of struct ix86_frame to avoid copy.
+
+ Backport from mainline
+ * config/i386/i386.c (ix86_expand_prologue): Use reference of
+ struct ix86_frame.
+ (ix86_expand_epilogue): Likewise.
+---
+ gcc/config/i386/i386.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 397ef7cac26..986e6d79584 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -13667,7 +13667,6 @@ ix86_expand_prologue (void)
+ {
+ struct machine_function *m = cfun->machine;
+ rtx insn, t;
+- struct ix86_frame frame;
+ HOST_WIDE_INT allocate;
+ bool int_registers_saved;
+ bool sse_registers_saved;
+@@ -13691,7 +13690,7 @@ ix86_expand_prologue (void)
+ m->fs.sp_valid = true;
+
+ ix86_compute_frame_layout ();
+- frame = m->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
+ {
+@@ -14354,13 +14353,12 @@ ix86_expand_epilogue (int style)
+ {
+ struct machine_function *m = cfun->machine;
+ struct machine_frame_state frame_state_save = m->fs;
+- struct ix86_frame frame;
+ bool restore_regs_via_mov;
+ bool using_drap;
+
+ ix86_finalize_stack_realign_flags ();
+ ix86_compute_frame_layout ();
+- frame = m->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ m->fs.sp_valid = (!frame_pointer_needed
+ || (crtl->sp_is_unchanging
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
new file mode 100644
index 000000000..b55ee3407
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch
@@ -0,0 +1,252 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From f23f45109139911714e2164191c0228500ebef92 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 6 Nov 2017 09:11:08 -0800
+Subject: [PATCH 01/10] i386: Move struct ix86_frame to machine_function
+
+Make ix86_frame available to i386 code generation. This is needed to
+backport the patch set of -mindirect-branch= to mitigate variant #2 of
+the speculative execution vulnerabilities on x86 processors identified
+by CVE-2017-5715, aka Spectre.
+
+ Backport from mainline
+ * config/i386/i386.c (ix86_frame): Moved to ...
+ * config/i386/i386.h (ix86_frame): Here.
+ (machine_function): Add frame.
+ * config/i386/i386.c (ix86_compute_frame_layout): Repace the
+ frame argument with &cfun->machine->frame.
+ (ix86_can_use_return_insn_p): Don't pass &frame to
+ ix86_compute_frame_layout. Copy frame from cfun->machine->frame.
+ (ix86_can_eliminate): Likewise.
+ (ix86_expand_prologue): Likewise.
+ (ix86_expand_epilogue): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+---
+ gcc/config/i386/i386.c | 68 ++++++++++----------------------------------------
+ gcc/config/i386/i386.h | 53 ++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 65 insertions(+), 56 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 8a3782c0298..813337242d8 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -2444,53 +2444,6 @@ struct GTY(()) stack_local_entry {
+ struct stack_local_entry *next;
+ };
+
+-/* Structure describing stack frame layout.
+- Stack grows downward:
+-
+- [arguments]
+- <- ARG_POINTER
+- saved pc
+-
+- saved static chain if ix86_static_chain_on_stack
+-
+- saved frame pointer if frame_pointer_needed
+- <- HARD_FRAME_POINTER
+- [saved regs]
+- <- regs_save_offset
+- [padding0]
+-
+- [saved SSE regs]
+- <- sse_regs_save_offset
+- [padding1] |
+- | <- FRAME_POINTER
+- [va_arg registers] |
+- |
+- [frame] |
+- |
+- [padding2] | = to_allocate
+- <- STACK_POINTER
+- */
+-struct ix86_frame
+-{
+- int nsseregs;
+- int nregs;
+- int va_arg_size;
+- int red_zone_size;
+- int outgoing_arguments_size;
+-
+- /* The offsets relative to ARG_POINTER. */
+- HOST_WIDE_INT frame_pointer_offset;
+- HOST_WIDE_INT hard_frame_pointer_offset;
+- HOST_WIDE_INT stack_pointer_offset;
+- HOST_WIDE_INT hfp_save_offset;
+- HOST_WIDE_INT reg_save_offset;
+- HOST_WIDE_INT sse_reg_save_offset;
+-
+- /* When save_regs_using_mov is set, emit prologue using
+- move instead of push instructions. */
+- bool save_regs_using_mov;
+-};
+-
+ /* Which cpu are we scheduling for. */
+ enum attr_cpu ix86_schedule;
+
+@@ -2582,7 +2535,7 @@ static unsigned int ix86_function_arg_boundary (machine_mode,
+ const_tree);
+ static rtx ix86_static_chain (const_tree, bool);
+ static int ix86_function_regparm (const_tree, const_tree);
+-static void ix86_compute_frame_layout (struct ix86_frame *);
++static void ix86_compute_frame_layout (void);
+ static bool ix86_expand_vector_init_one_nonzero (bool, machine_mode,
+ rtx, rtx, int);
+ static void ix86_add_new_builtins (HOST_WIDE_INT, HOST_WIDE_INT);
+@@ -11903,7 +11856,8 @@ ix86_can_use_return_insn_p (void)
+ if (crtl->args.pops_args && crtl->args.size >= 32768)
+ return 0;
+
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = cfun->machine->frame;
+ return (frame.stack_pointer_offset == UNITS_PER_WORD
+ && (frame.nregs + frame.nsseregs) == 0);
+ }
+@@ -12389,8 +12343,8 @@ ix86_can_eliminate (const int from, const int to)
+ HOST_WIDE_INT
+ ix86_initial_elimination_offset (int from, int to)
+ {
+- struct ix86_frame frame;
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ struct ix86_frame frame = cfun->machine->frame;
+
+ if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return frame.hard_frame_pointer_offset;
+@@ -12429,8 +12383,9 @@ ix86_builtin_setjmp_frame_value (void)
+ /* Fill structure ix86_frame about frame of currently computed function. */
+
+ static void
+-ix86_compute_frame_layout (struct ix86_frame *frame)
++ix86_compute_frame_layout (void)
+ {
++ struct ix86_frame *frame = &cfun->machine->frame;
+ unsigned HOST_WIDE_INT stack_alignment_needed;
+ HOST_WIDE_INT offset;
+ unsigned HOST_WIDE_INT preferred_alignment;
+@@ -13737,7 +13692,8 @@ ix86_expand_prologue (void)
+ m->fs.sp_offset = INCOMING_FRAME_SP_OFFSET;
+ m->fs.sp_valid = true;
+
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = m->frame;
+
+ if (!TARGET_64BIT && ix86_function_ms_hook_prologue (current_function_decl))
+ {
+@@ -14405,7 +14361,8 @@ ix86_expand_epilogue (int style)
+ bool using_drap;
+
+ ix86_finalize_stack_realign_flags ();
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = m->frame;
+
+ m->fs.sp_valid = (!frame_pointer_needed
+ || (crtl->sp_is_unchanging
+@@ -14915,7 +14872,8 @@ ix86_expand_split_stack_prologue (void)
+ gcc_assert (flag_split_stack && reload_completed);
+
+ ix86_finalize_stack_realign_flags ();
+- ix86_compute_frame_layout (&frame);
++ ix86_compute_frame_layout ();
++ frame = cfun->machine->frame;
+ allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
+
+ /* This is the label we will branch to if we have enough stack
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 9c776dc5172..f9b91286a01 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2451,9 +2451,56 @@ enum avx_u128_state
+ \f
+ #define FASTCALL_PREFIX '@'
+ \f
++#ifndef USED_FOR_TARGET
++/* Structure describing stack frame layout.
++ Stack grows downward:
++
++ [arguments]
++ <- ARG_POINTER
++ saved pc
++
++ saved static chain if ix86_static_chain_on_stack
++
++ saved frame pointer if frame_pointer_needed
++ <- HARD_FRAME_POINTER
++ [saved regs]
++ <- regs_save_offset
++ [padding0]
++
++ [saved SSE regs]
++ <- sse_regs_save_offset
++ [padding1] |
++ | <- FRAME_POINTER
++ [va_arg registers] |
++ |
++ [frame] |
++ |
++ [padding2] | = to_allocate
++ <- STACK_POINTER
++ */
++struct GTY(()) ix86_frame
++{
++ int nsseregs;
++ int nregs;
++ int va_arg_size;
++ int red_zone_size;
++ int outgoing_arguments_size;
++
++ /* The offsets relative to ARG_POINTER. */
++ HOST_WIDE_INT frame_pointer_offset;
++ HOST_WIDE_INT hard_frame_pointer_offset;
++ HOST_WIDE_INT stack_pointer_offset;
++ HOST_WIDE_INT hfp_save_offset;
++ HOST_WIDE_INT reg_save_offset;
++ HOST_WIDE_INT sse_reg_save_offset;
++
++ /* When save_regs_using_mov is set, emit prologue using
++ move instead of push instructions. */
++ bool save_regs_using_mov;
++};
++
+ /* Machine specific frame tracking during prologue/epilogue generation. */
+
+-#ifndef USED_FOR_TARGET
+ struct GTY(()) machine_frame_state
+ {
+ /* This pair tracks the currently active CFA as reg+offset. When reg
+@@ -2512,6 +2559,9 @@ struct GTY(()) machine_function {
+ int varargs_fpr_size;
+ int optimize_mode_switching[MAX_386_ENTITIES];
+
++ /* Cached initial frame layout for the current function. */
++ struct ix86_frame frame;
++
+ /* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE
+ has been computed for. */
+ int use_fast_prologue_epilogue_nregs;
+@@ -2594,6 +2644,7 @@ struct GTY(()) machine_function {
+ #define ix86_current_function_calls_tls_descriptor \
+ (ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
+ #define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
++#define ix86_red_zone_size (cfun->machine->frame.red_zone_size)
+
+ /* Control behavior of x86_file_start. */
+ #define X86_FILE_START_VERSION_DIRECTIVE false
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
new file mode 100644
index 000000000..30eca1a43
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch
@@ -0,0 +1,83 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From ca658cd57c02a81327ec09474e24f0688ac1a190 Mon Sep 17 00:00:00 2001
+From: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Mon, 6 Nov 2017 23:04:15 +0000
+Subject: [PATCH 02/10] i386: Use reference of struct ix86_frame to avoid copy
+
+When there is no need to make a copy of ix86_frame, we can use reference
+of struct ix86_frame to avoid copy.
+
+Tested on x86-64.
+
+ Backport from mainline
+ * config/i386/i386.c (ix86_can_use_return_insn_p): Use reference
+ of struct ix86_frame.
+ (ix86_initial_elimination_offset): Likewise.
+ (ix86_expand_split_stack_prologue): Likewise.
+---
+ gcc/config/i386/i386.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 813337242d8..397ef7cac26 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -11843,8 +11843,6 @@ symbolic_reference_mentioned_p (rtx op)
+ bool
+ ix86_can_use_return_insn_p (void)
+ {
+- struct ix86_frame frame;
+-
+ /* Don't use `ret' instruction in interrupt handler. */
+ if (! reload_completed
+ || frame_pointer_needed
+@@ -11857,7 +11855,7 @@ ix86_can_use_return_insn_p (void)
+ return 0;
+
+ ix86_compute_frame_layout ();
+- frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+ return (frame.stack_pointer_offset == UNITS_PER_WORD
+ && (frame.nregs + frame.nsseregs) == 0);
+ }
+@@ -12344,7 +12342,7 @@ HOST_WIDE_INT
+ ix86_initial_elimination_offset (int from, int to)
+ {
+ ix86_compute_frame_layout ();
+- struct ix86_frame frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+
+ if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return frame.hard_frame_pointer_offset;
+@@ -14860,7 +14858,6 @@ static GTY(()) rtx split_stack_fn_large;
+ void
+ ix86_expand_split_stack_prologue (void)
+ {
+- struct ix86_frame frame;
+ HOST_WIDE_INT allocate;
+ unsigned HOST_WIDE_INT args_size;
+ rtx_code_label *label;
+@@ -14873,7 +14870,7 @@ ix86_expand_split_stack_prologue (void)
+
+ ix86_finalize_stack_realign_flags ();
+ ix86_compute_frame_layout ();
+- frame = cfun->machine->frame;
++ struct ix86_frame &frame = cfun->machine->frame;
+ allocate = frame.stack_pointer_offset - INCOMING_FRAME_SP_OFFSET;
+
+ /* This is the label we will branch to if we have enough stack
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch b/gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch
new file mode 100644
index 000000000..6da7b48c3
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch
@@ -0,0 +1,365 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From f6d256da9cefa1409598fa5ffe632647a30ad6f9 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Sun, 14 Jan 2018 21:36:59 +0000
+Subject: [PATCH 10/10] indirect thunk reg names
+
+---
+ gcc/config/i386/i386.c | 9 ++-------
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 4 ++--
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 2 +-
+ 25 files changed, 29 insertions(+), 34 deletions(-)
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 6d345031a82..89eb68032a2 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -12052,13 +12052,8 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
+ const char *bnd = need_bnd_p ? "_bnd" : "";
+ if (regno >= 0)
+ {
+- const char *reg_prefix;
+- if (LEGACY_INT_REGNO_P (regno))
+- reg_prefix = TARGET_64BIT ? "r" : "e";
+- else
+- reg_prefix = "";
+- sprintf (name, "__x86_indirect_thunk%s_%s%s",
+- bnd, reg_prefix, reg_names[regno]);
++ sprintf (name, "__x86_indirect_thunk%s_%s",
++ bnd, reg_names[regno]);
+ }
+ else
+ {
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index 9eb9b273ade..fb56b2db3b6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index c63795e4127..337f455aa44 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index 82973cda771..2e40ec71609 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index a5f3d1cbed8..309d1f6c10b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index ebfb8aab937..47674395309 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -37,7 +37,7 @@ bar (int i)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index a08022db8e4..e8cdc4fa05d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -16,7 +16,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index b257c695ad1..5f333d86e18 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -14,7 +14,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler {\tpause} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 4bb1c5f9220..fa067b0acc8 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -18,5 +18,5 @@ male_indirect_jump (long offset)
+ /* { 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 "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 4e33a638862..442f97c123c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -17,5 +17,5 @@ male_indirect_jump (long offset)
+ /* { 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 "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index 427ba3ddbb4..64b85fc7b96 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -37,7 +37,7 @@ bar (int i)
+ }
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+ /* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index 5c20a35ecec..cb95a09ea34 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index b2fb6e1bcd2..b2af9e96b7e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -13,7 +13,7 @@ male_indirect_jump (long offset)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 9c84547cd7c..a9a1a8bc177 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -16,5 +16,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index 457849564bb..bbf3dd24f37 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -16,5 +16,5 @@ male_indirect_jump (long offset)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_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
+index d4747ea0764..39acad399d3 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -37,7 +37,7 @@ bar (int i)
+
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_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-register-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+index 7d396a31953..0660feeed73 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+@@ -11,7 +11,7 @@ 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\]*__x86_indirect_thunk_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)\\)" } } */
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+index 5320e923be2..d39e387586e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+@@ -11,7 +11,7 @@ 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\]*__x86_indirect_thunk_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)} } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+index b4f9d48065d..2f373c362d0 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -18,6 +18,6 @@ foo (void)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+index 0312577a043..11e041fda7e 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -18,6 +18,6 @@ foo (void)
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+index fa3181303c9..f16c1a5d0c6 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -17,6 +17,6 @@ foo (void)
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
+-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_ax:" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+index 7a08e71c76b..b4553216f99 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -18,5 +18,5 @@ foo (void)
+ /* { 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" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+index dacf0c769fc..28e5434a004 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -18,5 +18,5 @@ foo (void)
+ /* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+index cf06a5f35c7..20fad48b790 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -18,5 +18,5 @@ foo (void)
+ /* { dg-final { scan-assembler-times {\tlfence} 1 } } */
+ /* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target x32 } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+index 6da5ab97081..8f0375b5def 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -21,5 +21,5 @@ foo (void)
+ /* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
+ /* { dg-final { scan-assembler-times {\tpause} 2 { target { x32 } } } } */
+ /* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
+-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_ax" { target { x32 } } } } */
+ /* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch b/gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch
new file mode 100644
index 000000000..d47f23942
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch
@@ -0,0 +1,143 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 5e977dfedb93e764dc480c0e0674500590ef5604 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 6 Jan 2018 22:29:56 -0800
+Subject: [PATCH 07/10] x86: Add 'V' register operand modifier
+
+Add 'V', a special modifier which prints the name of the full integer
+register without '%'. For
+
+extern void (*func_p) (void);
+
+void
+foo (void)
+{
+ asm ("call __x86_indirect_thunk_%V0" : : "a" (func_p));
+}
+
+it generates:
+
+foo:
+ movq func_p(%rip), %rax
+ call __x86_indirect_thunk_rax
+ ret
+
+gcc/
+
+ Backport from mainline
+ * config/i386/i386.c (print_reg): Print the name of the full
+ integer register without '%'.
+ (ix86_print_operand): Handle 'V'.
+ * doc/extend.texi: Document 'V' modifier.
+
+gcc/testsuite/
+
+ Backport from mainline
+ * gcc.target/i386/indirect-thunk-register-4.c: New test.
+---
+ gcc/config/i386/i386.c | 13 ++++++++++++-
+ gcc/doc/extend.texi | 3 +++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c | 13 +++++++++++++
+ 3 files changed, 28 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 4bfe2fa8c1d..e32de13688a 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -17925,6 +17925,7 @@ put_condition_code (enum rtx_code code, machine_mode mode, bool reverse,
+ If CODE is 'h', pretend the reg is the 'high' byte register.
+ If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.
+ If CODE is 'd', duplicate the operand for AVX instruction.
++ If CODE is 'V', print naked full integer register name without %.
+ */
+
+ void
+@@ -17935,7 +17936,7 @@ print_reg (rtx x, int code, FILE *file)
+ unsigned int regno;
+ bool duplicated;
+
+- if (ASSEMBLER_DIALECT == ASM_ATT)
++ if (ASSEMBLER_DIALECT == ASM_ATT && code != 'V')
+ putc ('%', file);
+
+ if (x == pc_rtx)
+@@ -17983,6 +17984,14 @@ print_reg (rtx x, int code, FILE *file)
+ return;
+ }
+
++ if (code == 'V')
++ {
++ if (GENERAL_REGNO_P (regno))
++ msize = GET_MODE_SIZE (word_mode);
++ else
++ error ("'V' modifier on non-integer register");
++ }
++
+ duplicated = code == 'd' && TARGET_AVX;
+
+ switch (msize)
+@@ -18102,6 +18111,7 @@ print_reg (rtx x, int code, FILE *file)
+ & -- print some in-use local-dynamic symbol name.
+ H -- print a memory address offset by 8; used for sse high-parts
+ Y -- print condition for XOP pcom* instruction.
++ V -- print naked full integer register name without %.
+ + -- print a branch hint as 'cs' or 'ds' prefix
+ ; -- print a semicolon (after prefixes due to bug in older gas).
+ ~ -- print "i" if TARGET_AVX2, "f" otherwise.
+@@ -18326,6 +18336,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
+ case 'X':
+ case 'P':
+ case 'p':
++ case 'V':
+ break;
+
+ case 's':
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 46e0a3623a6..9db9e0e27e9 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -8778,6 +8778,9 @@ The table below shows the list of supported modifiers and their effects.
+ @tab @code{2}
+ @end multitable
+
++@code{V} is a special modifier which prints the name of the full integer
++register without @code{%}.
++
+ @anchor{x86floatingpointasmoperands}
+ @subsubsection x86 Floating-Point @code{asm} Operands
+
+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 } } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch b/gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch
new file mode 100644
index 000000000..bfd154eaa
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch
@@ -0,0 +1,1303 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From dfa5f37da1fed9d9439e396fdf49847f4d9184d4 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 6 Jan 2018 22:29:56 -0800
+Subject: [PATCH 05/10] x86: Add -mfunction-return=
+
+Add -mfunction-return= option to convert function return to call and
+return thunks. The default is 'keep', which keeps function return
+unmodified. 'thunk' converts function return to call and return thunk.
+'thunk-inline' converts function return to inlined call and return thunk.
+'thunk-extern' converts function return to external call and return
+thunk provided in a separate object file. You can control this behavior
+for a specific function by using the function attribute function_return.
+
+Function return thunk is the same as memory thunk for -mindirect-branch=
+where the return address is at the top of the stack:
+
+__x86_return_thunk:
+ call L2
+L1:
+ pause
+ lfence
+ jmp L1
+L2:
+ lea 8(%rsp), %rsp|lea 4(%esp), %esp
+ ret
+
+and function return becomes
+
+ jmp __x86_return_thunk
+
+-mindirect-branch= tests are updated with -mfunction-return=keep to
+avoid false test failures when -mfunction-return=thunk is added to
+RUNTESTFLAGS for "make check".
+
+gcc/
+
+ Backport from mainline
+ * config/i386/i386-protos.h (ix86_output_function_return): New.
+ * config/i386/i386.c (ix86_set_indirect_branch_type): Also
+ set function_return_type.
+ (indirect_thunk_name): Add ret_p to indicate thunk for function
+ return.
+ (output_indirect_thunk_function): Pass false to
+ indirect_thunk_name.
+ (ix86_output_indirect_branch): Likewise.
+ (output_indirect_thunk_function): Create alias for function
+ return thunk if regno < 0.
+ (ix86_output_function_return): New function.
+ (ix86_handle_fndecl_attribute): Handle function_return.
+ (ix86_attribute_table): Add function_return.
+ * config/i386/i386.h (machine_function): Add
+ function_return_type.
+ * config/i386/i386.md (simple_return_internal): Use
+ ix86_output_function_return.
+ (simple_return_internal_long): Likewise.
+ * config/i386/i386.opt (mfunction-return=): New option.
+ (indirect_branch): Mention -mfunction-return=.
+ * doc/extend.texi: Document function_return function attribute.
+ * doc/invoke.texi: Document -mfunction-return= option.
+
+gcc/testsuite/
+
+ Backport from mainline
+ * gcc.target/i386/indirect-thunk-1.c (dg-options): Add
+ -mfunction-return=keep.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-1.c: New test.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-16.c: Likewise.
+ * gcc.target/i386/ret-thunk-2.c: Likewise.
+ * gcc.target/i386/ret-thunk-3.c: Likewise.
+ * gcc.target/i386/ret-thunk-4.c: Likewise.
+ * gcc.target/i386/ret-thunk-5.c: Likewise.
+ * gcc.target/i386/ret-thunk-6.c: Likewise.
+ * gcc.target/i386/ret-thunk-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-8.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+---
+ gcc/config/i386/i386-protos.h | 1 +
+ gcc/config/i386/i386.c | 151 +++++++++++++++++++--
+ gcc/config/i386/i386.h | 3 +
+ gcc/config/i386/i386.md | 9 +-
+ gcc/config/i386/i386.opt | 6 +-
+ gcc/doc/extend.texi | 9 ++
+ gcc/doc/invoke.texi | 13 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-8.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-1.c | 13 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 23 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 23 ++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 22 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 22 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 22 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 22 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-16.c | 18 +++
+ gcc/testsuite/gcc.target/i386/ret-thunk-2.c | 13 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-3.c | 12 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-4.c | 12 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-5.c | 15 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-6.c | 14 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-7.c | 13 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-8.c | 14 ++
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 25 ++++
+ 56 files changed, 491 insertions(+), 50 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-16.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-8.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+
+diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
+index bcdd9872db9..42eece35766 100644
+--- a/gcc/config/i386/i386-protos.h
++++ b/gcc/config/i386/i386-protos.h
+@@ -314,6 +314,7 @@ extern enum attr_cpu ix86_schedule;
+
+ extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+ extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
++extern const char * ix86_output_function_return (bool long_p);
+ extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ enum machine_mode mode);
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index f1c58faa035..4bfe2fa8c1d 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -7188,6 +7188,31 @@ ix86_set_indirect_branch_type (tree fndecl)
+ else
+ cfun->machine->indirect_branch_type = ix86_indirect_branch;
+ }
++
++ if (cfun->machine->function_return_type == indirect_branch_unset)
++ {
++ tree attr = lookup_attribute ("function_return",
++ DECL_ATTRIBUTES (fndecl));
++ if (attr != NULL)
++ {
++ tree args = TREE_VALUE (attr);
++ if (args == NULL)
++ gcc_unreachable ();
++ tree cst = TREE_VALUE (args);
++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
++ cfun->machine->function_return_type = indirect_branch_keep;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk_inline;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
++ cfun->machine->function_return_type = indirect_branch_thunk_extern;
++ else
++ gcc_unreachable ();
++ }
++ else
++ cfun->machine->function_return_type = ix86_function_return;
++ }
+ }
+
+ /* Establish appropriate back-end context for processing the function
+@@ -11990,8 +12015,12 @@ static int indirect_thunks_bnd_used;
+ /* Fills in the label name that should be used for the indirect thunk. */
+
+ static void
+-indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
++indirect_thunk_name (char name[32], int regno, bool need_bnd_p,
++ bool ret_p)
+ {
++ if (regno >= 0 && ret_p)
++ gcc_unreachable ();
++
+ if (USE_HIDDEN_LINKONCE)
+ {
+ const char *bnd = need_bnd_p ? "_bnd" : "";
+@@ -12006,7 +12035,10 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
+ bnd, reg_prefix, reg_names[regno]);
+ }
+ else
+- sprintf (name, "__x86_indirect_thunk%s", bnd);
++ {
++ const char *ret = ret_p ? "return" : "indirect";
++ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
++ }
+ }
+ else
+ {
+@@ -12019,10 +12051,20 @@ indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
+ }
+ else
+ {
+- if (need_bnd_p)
+- ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ if (ret_p)
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LRTB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LRT", 0);
++ }
+ else
+- ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ }
+ }
+ }
+ }
+@@ -12117,7 +12159,7 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+ tree decl;
+
+ /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
+- indirect_thunk_name (name, regno, need_bnd_p);
++ indirect_thunk_name (name, regno, need_bnd_p, false);
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ get_identifier (name),
+ build_function_type_list (void_type_node, NULL_TREE));
+@@ -12160,6 +12202,35 @@ output_indirect_thunk_function (bool need_bnd_p, int regno)
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ }
+
++ if (regno < 0)
++ {
++ /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
++ char alias[32];
++
++ indirect_thunk_name (alias, regno, need_bnd_p, true);
++ ASM_OUTPUT_DEF (asm_out_file, alias, name);
++#if TARGET_MACHO
++ if (TARGET_MACHO)
++ {
++ fputs ("\t.weak_definition\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ fputs ("\n\t.private_extern\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ }
++#else
++ if (USE_HIDDEN_LINKONCE)
++ {
++ fputs ("\t.globl\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ fputs ("\t.hidden\t", asm_out_file);
++ assemble_name (asm_out_file, alias);
++ putc ('\n', asm_out_file);
++ }
++#endif
++ }
++
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ allocate_struct_function (decl, false);
+@@ -28760,7 +28831,7 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
+ else
+ indirect_thunks_used |= 1 << i;
+ }
+- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
+ thunk_name = thunk_name_buf;
+ }
+ else
+@@ -28869,7 +28940,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
+ else
+ indirect_thunk_needed = true;
+ }
+- indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p, false);
+ thunk_name = thunk_name_buf;
+ }
+ else
+@@ -29004,6 +29075,46 @@ ix86_output_indirect_jmp (rtx call_op, bool ret_p)
+ return "%!jmp\t%A0";
+ }
+
++/* Output function return. CALL_OP is the jump target. Add a REP
++ prefix to RET if LONG_P is true and function return is kept. */
++
++const char *
++ix86_output_function_return (bool long_p)
++{
++ if (cfun->machine->function_return_type != indirect_branch_keep)
++ {
++ char thunk_name[32];
++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++
++ if (cfun->machine->function_return_type
++ != indirect_branch_thunk_inline)
++ {
++ bool need_thunk = (cfun->machine->function_return_type
++ == indirect_branch_thunk);
++ indirect_thunk_name (thunk_name, -1, need_bnd_p, true);
++ if (need_bnd_p)
++ {
++ indirect_thunk_bnd_needed |= need_thunk;
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ }
++ else
++ {
++ indirect_thunk_needed |= need_thunk;
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ }
++ else
++ output_indirect_thunk (need_bnd_p, -1);
++
++ return "";
++ }
++
++ if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn))
++ return "%!ret";
++
++ return "rep%; ret";
++}
++
+ /* Output the assembly for a call instruction. */
+
+ const char *
+@@ -42075,6 +42186,28 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
+ }
+ }
+
++ if (is_attribute_p ("function_return", name))
++ {
++ tree cst = TREE_VALUE (args);
++ if (TREE_CODE (cst) != STRING_CST)
++ {
++ warning (OPT_Wattributes,
++ "%qE attribute requires a string constant argument",
++ name);
++ *no_add_attrs = true;
++ }
++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
++ {
++ warning (OPT_Wattributes,
++ "argument to %qE attribute is not "
++ "(keep|thunk|thunk-inline|thunk-extern)", name);
++ *no_add_attrs = true;
++ }
++ }
++
+ return NULL_TREE;
+ }
+
+@@ -46385,6 +46518,8 @@ static const struct attribute_spec ix86_attribute_table[] =
+ ix86_handle_no_caller_saved_registers_attribute, false },
+ { "indirect_branch", 1, 1, true, false, false,
+ ix86_handle_fndecl_attribute, false },
++ { "function_return", 1, 1, true, false, false,
++ ix86_handle_fndecl_attribute, false },
+
+ /* End element. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index 9d2209e605b..45593068905 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2616,6 +2616,9 @@ struct GTY(()) machine_function {
+ "indirect_jump" or "tablejump". */
+ BOOL_BITFIELD has_local_indirect_jump : 1;
+
++ /* How to generate function return. */
++ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
++
+ /* If true, the current function is a function specified with
+ the "interrupt" or "no_caller_saved_registers" attribute. */
+ BOOL_BITFIELD no_caller_saved_registers : 1;
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index cd2e73cf9d3..d112bdb8552 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -12315,7 +12315,7 @@
+ (define_insn "simple_return_internal"
+ [(simple_return)]
+ "reload_completed"
+- "%!ret"
++ "* return ix86_output_function_return (false);"
+ [(set_attr "length" "1")
+ (set_attr "atom_unit" "jeu")
+ (set_attr "length_immediate" "0")
+@@ -12337,12 +12337,7 @@
+ [(simple_return)
+ (unspec [(const_int 0)] UNSPEC_REP)]
+ "reload_completed"
+-{
+- if (ix86_bnd_prefixed_insn_p (insn))
+- return "%!ret";
+-
+- return "rep%; ret";
+-}
++ "* return ix86_output_function_return (true);"
+ [(set_attr "length" "2")
+ (set_attr "atom_unit" "jeu")
+ (set_attr "length_immediate" "0")
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index c076d9c70ab..b07388d95a9 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -932,9 +932,13 @@ mindirect-branch=
+ Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
+ Convert indirect call and jump to call and return thunks.
+
++mfunction-return=
++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
++Convert function return to call and return thunk.
++
+ Enum
+ Name(indirect_branch) Type(enum indirect_branch)
+-Known indirect branch choices (for use with the -mindirect-branch= option):
++Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
+
+ EnumValue
+ Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index 935381da6fa..46e0a3623a6 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -5550,6 +5550,15 @@ call and jump to call and return thunk. @samp{thunk-inline} converts
+ indirect call and jump to inlined call and return thunk.
+ @samp{thunk-extern} converts indirect call and jump to external call
+ and return thunk provided in a separate object file.
++
++@item function_return("@var{choice}")
++@cindex @code{function_return} function attribute, x86
++On x86 targets, the @code{function_return} attribute causes the compiler
++to convert function return with @var{choice}. @samp{keep} keeps function
++return unmodified. @samp{thunk} converts function return to call and
++return thunk. @samp{thunk-inline} converts function return to inlined
++call and return thunk. @samp{thunk-extern} converts function return to
++external call and return thunk provided in a separate object file.
+ @end table
+
+ On the x86, the inliner does not inline a
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 4979c8c939d..f3eb54b1668 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1211,7 +1211,7 @@ See RS/6000 and PowerPC Options.
+ -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
+ -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
+ -mmitigate-rop -mgeneral-regs-only @gol
+--mindirect-branch=@var{choice}}
++-mindirect-branch=@var{choice} -mfunction-return==@var{choice}}
+
+ @emph{x86 Windows Options}
+ @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
+@@ -25698,6 +25698,17 @@ to external call and return thunk provided in a separate object file.
+ You can control this behavior for a specific function by using the
+ function attribute @code{indirect_branch}. @xref{Function Attributes}.
+
++@item -mfunction-return=@var{choice}
++@opindex -mfunction-return
++Convert function return with @var{choice}. The default is @samp{keep},
++which keeps function return unmodified. @samp{thunk} converts function
++return to call and return thunk. @samp{thunk-inline} converts function
++return to inlined call and return thunk. @samp{thunk-extern} converts
++function return to external call and return thunk provided in a separate
++object file. You can control this behavior for a specific function by
++using the function attribute @code{function_return}.
++@xref{Function Attributes}.
++
+ @end table
+
+ These @samp{-m} switches are supported in addition to the above
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index d983e1c3e26..f076155c91a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index 58f09b42d8a..d7984f592fe 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index f20d35c19b6..3257d0a2e16 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index 0eff8fb658a..7cab2df6474 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+index a25b20dd808..b4836c38d6c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+index cff114a6c29..1f06bd1af74 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index afdb6007986..0b3fef86a20 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index d64d978b699..5f6cfc17b56 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index 93067454d3d..b256160ec80 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+index 97744d65729..567c95051d6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index bfce3ea5cb2..3b662af7d5d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 0833606046b..98785a38248 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index 2eba0fbd9b2..a498a39e404 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index f58427eae11..66f295d1eb6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+index 564ed39547c..d730d31bda1 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+index 50fbee20a5a..aacb814d737 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+ void (*dispatch) (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+index 2976e67adce..7b44dda23df 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
+
+ void (*dispatch) (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+index da4bc98ef23..70b4fb36eea 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+ void bar (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+index c64d12ef989..3baf03ee77c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
+
+ void bar (char *);
+ char buf[10];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index 49f27b49465..637fc3d3f4e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index a1e3eb6fc74..ff9efe03fe6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 395634e7e5c..2686a5f2db4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index fd3f63379a1..f07f6b214ad 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+index ba2f92b6f34..21740ac5b7f 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+index 0c5a2d472c6..a77c1f470b8 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+index 665252327aa..e64910fd4aa 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 68c0ff713b3..365cf2ee226 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+index e2da1fcb683..72646a4960b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+index 244fec708d6..f48945e3dfc 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+index 107ebe32f54..4b1d558fc4e 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+index 17b04ef2229..0f687c3b027 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+index d9eb11285aa..b27c6fc96a2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+index d02b1dcb1b9..2c496492eaa 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+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..1630e2fa2b5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..876159cf783
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..01b0a02f80b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..e028c2b6a99
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { 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" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..c14ee3ae4c0
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..2f21e138ec2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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-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-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..f6ccad98da7
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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-not "__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-times {\tpause} 1 { target { ! x32 } } } } */
++/* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler-times {\tpause} 2 { target { x32 } } } } */
++/* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch b/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch
new file mode 100644
index 000000000..5fbced669
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch
@@ -0,0 +1,907 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 139dd2c61a11430263f91030910e2b63a73a11e7 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 6 Jan 2018 22:29:56 -0800
+Subject: [PATCH 06/10] x86: Add -mindirect-branch-register
+
+Add -mindirect-branch-register to force indirect branch via register.
+This is implemented by disabling patterns of indirect branch via memory,
+similar to TARGET_X32.
+
+-mindirect-branch= and -mfunction-return= tests are updated with
+-mno-indirect-branch-register to avoid false test failures when
+-mindirect-branch-register is added to RUNTESTFLAGS for "make check".
+
+gcc/
+
+ Backport from mainline
+ * config/i386/constraints.md (Bs): Disallow memory operand for
+ -mindirect-branch-register.
+ (Bw): Likewise.
+ * config/i386/predicates.md (indirect_branch_operand): Likewise.
+ (GOT_memory_operand): Likewise.
+ (call_insn_operand): Likewise.
+ (sibcall_insn_operand): Likewise.
+ (GOT32_symbol_operand): Likewise.
+ * config/i386/i386.md (indirect_jump): Call convert_memory_address
+ for -mindirect-branch-register.
+ (tablejump): Likewise.
+ (*sibcall_memory): Likewise.
+ (*sibcall_value_memory): Likewise.
+ Disallow peepholes of indirect call and jump via memory for
+ -mindirect-branch-register.
+ (*call_pop): Replace m with Bw.
+ (*call_value_pop): Likewise.
+ (*sibcall_pop_memory): Replace m with Bs.
+ * config/i386/i386.opt (mindirect-branch-register): New option.
+ * doc/invoke.texi: Document -mindirect-branch-register option.
+
+gcc/testsuite/
+
+ Backport from mainline
+ * gcc.target/i386/indirect-thunk-1.c (dg-options): Add
+ -mno-indirect-branch-register.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-1.c: New test.
+ * gcc.target/i386/indirect-thunk-register-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-3.c: Likewise.
+---
+ gcc/config/i386/constraints.md | 12 +++++---
+ gcc/config/i386/i386.md | 34 ++++++++++++++--------
+ gcc/config/i386/i386.opt | 4 +++
+ gcc/config/i386/predicates.md | 21 ++++++++-----
+ gcc/doc/invoke.texi | 7 ++++-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 2 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-bnd-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-1.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-2.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-3.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-4.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-5.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-6.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-inline-7.c | 2 +-
+ .../gcc.target/i386/indirect-thunk-register-1.c | 22 ++++++++++++++
+ .../gcc.target/i386/indirect-thunk-register-2.c | 20 +++++++++++++
+ .../gcc.target/i386/indirect-thunk-register-3.c | 19 ++++++++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-10.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-11.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-12.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-13.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-14.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-15.c | 2 +-
+ gcc/testsuite/gcc.target/i386/ret-thunk-9.c | 2 +-
+ 47 files changed, 154 insertions(+), 63 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+
+diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
+index 38d604fdace..697caf704dd 100644
+--- a/gcc/config/i386/constraints.md
++++ b/gcc/config/i386/constraints.md
+@@ -198,16 +198,20 @@
+
+ (define_constraint "Bs"
+ "@internal Sibcall memory operand."
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "sibcall_memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand"))))
+
+ (define_constraint "Bw"
+ "@internal Call memory operand."
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand"))))
+
+ (define_constraint "Bz"
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index d112bdb8552..96941e8c5c4 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -11625,7 +11625,7 @@
+ [(set (pc) (match_operand 0 "indirect_branch_operand"))]
+ ""
+ {
+- if (TARGET_X32)
++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
+ })
+@@ -11679,7 +11679,7 @@
+ OPTAB_DIRECT);
+ }
+
+- if (TARGET_X32)
++ if (TARGET_X32 || ix86_indirect_branch_thunk_register)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
+ cfun->machine->has_local_indirect_jump = true;
+ })
+@@ -11871,7 +11871,7 @@
+ [(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
+ (match_operand 1))
+ (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
+- "!TARGET_X32"
++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
+ "* return ix86_output_call_insn (insn, operands[0]);"
+ [(set_attr "type" "call")])
+
+@@ -11880,7 +11880,9 @@
+ (match_operand:W 1 "memory_operand"))
+ (call (mem:QI (match_dup 0))
+ (match_operand 3))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (1))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
+ [(parallel [(call (mem:QI (match_dup 1))
+@@ -11893,7 +11895,9 @@
+ (unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (2))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+@@ -11915,7 +11919,7 @@
+ })
+
+ (define_insn "*call_pop"
+- [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
++ [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
+ (match_operand 1))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+@@ -11935,7 +11939,7 @@
+ [(set_attr "type" "call")])
+
+ (define_insn "*sibcall_pop_memory"
+- [(call (mem:QI (match_operand:SI 0 "memory_operand" "m"))
++ [(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
+ (match_operand 1))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+@@ -11989,7 +11993,9 @@
+ [(set (match_operand:W 0 "register_operand")
+ (match_operand:W 1 "memory_operand"))
+ (set (pc) (match_dup 0))]
+- "!TARGET_X32 && peep2_reg_dead_p (2, operands[0])"
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && peep2_reg_dead_p (2, operands[0])"
+ [(set (pc) (match_dup 1))])
+
+ ;; Call subroutine, returning value in operand 0
+@@ -12070,7 +12076,7 @@
+ (call (mem:QI (match_operand:W 1 "memory_operand" "m"))
+ (match_operand 2)))
+ (unspec [(const_int 0)] UNSPEC_PEEPSIB)]
+- "!TARGET_X32"
++ "!TARGET_X32 && !ix86_indirect_branch_thunk_register"
+ "* return ix86_output_call_insn (insn, operands[1]);"
+ [(set_attr "type" "callv")])
+
+@@ -12080,7 +12086,9 @@
+ (set (match_operand 2)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3)))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (1))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (1)))"
+ [(parallel [(set (match_dup 2)
+@@ -12095,7 +12103,9 @@
+ (set (match_operand 2)
+ (call (mem:QI (match_dup 0))
+ (match_operand 3)))]
+- "!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
++ "!TARGET_X32
++ && !ix86_indirect_branch_thunk_register
++ && SIBLING_CALL_P (peep2_next_insn (2))
+ && !reg_mentioned_p (operands[0],
+ CALL_INSN_FUNCTION_USAGE (peep2_next_insn (2)))"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
+@@ -12120,7 +12130,7 @@
+
+ (define_insn "*call_value_pop"
+ [(set (match_operand 0)
+- (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
++ (call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
+ (match_operand 2)))
+ (set (reg:SI SP_REG)
+ (plus:SI (reg:SI SP_REG)
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index b07388d95a9..852033cbb67 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -951,3 +951,7 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+
+ EnumValue
+ Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
++
++mindirect-branch-register
++Target Report Var(ix86_indirect_branch_thunk_register) Init(0)
++Force indirect call and jump via register.
+diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
+index 2fc2c60f6ac..a88b1d860ca 100644
+--- a/gcc/config/i386/predicates.md
++++ b/gcc/config/i386/predicates.md
+@@ -635,7 +635,8 @@
+ ;; Test for a valid operand for indirect branch.
+ (define_predicate "indirect_branch_operand"
+ (ior (match_operand 0 "register_operand")
+- (and (not (match_test "TARGET_X32"))
++ (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))))
+
+ ;; Return true if OP is a memory operands that can be used in sibcalls.
+@@ -664,7 +665,8 @@
+
+ ;; Return true if OP is a GOT memory operand.
+ (define_predicate "GOT_memory_operand"
+- (match_operand 0 "memory_operand")
++ (and (match_test "!ix86_indirect_branch_thunk_register")
++ (match_operand 0 "memory_operand"))
+ {
+ op = XEXP (op, 0);
+ return (GET_CODE (op) == CONST
+@@ -678,9 +680,11 @@
+ (ior (match_test "constant_call_address_operand
+ (op, mode == VOIDmode ? mode : Pmode)")
+ (match_operand 0 "call_register_no_elim_operand")
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand")))))
+
+ ;; Similarly, but for tail calls, in which we cannot allow memory references.
+@@ -688,14 +692,17 @@
+ (ior (match_test "constant_call_address_operand
+ (op, mode == VOIDmode ? mode : Pmode)")
+ (match_operand 0 "register_no_elim_operand")
+- (ior (and (not (match_test "TARGET_X32"))
++ (ior (and (not (match_test "TARGET_X32
++ || ix86_indirect_branch_thunk_register"))
+ (match_operand 0 "sibcall_memory_operand"))
+- (and (match_test "TARGET_X32 && Pmode == DImode")
++ (and (match_test "TARGET_X32 && Pmode == DImode
++ && !ix86_indirect_branch_thunk_register")
+ (match_operand 0 "GOT_memory_operand")))))
+
+ ;; Return true if OP is a 32-bit GOT symbol operand.
+ (define_predicate "GOT32_symbol_operand"
+- (match_test "GET_CODE (op) == CONST
++ (match_test "!ix86_indirect_branch_thunk_register
++ && GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == UNSPEC
+ && XINT (XEXP (op, 0), 1) == UNSPEC_GOT"))
+
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index f3eb54b1668..1e572b1f9a2 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1211,7 +1211,8 @@ See RS/6000 and PowerPC Options.
+ -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
+ -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
+ -mmitigate-rop -mgeneral-regs-only @gol
+--mindirect-branch=@var{choice} -mfunction-return==@var{choice}}
++-mindirect-branch=@var{choice} -mfunction-return==@var{choice} @gol
++-mindirect-branch-register}
+
+ @emph{x86 Windows Options}
+ @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
+@@ -25709,6 +25710,10 @@ object file. You can control this behavior for a specific function by
+ using the function attribute @code{function_return}.
+ @xref{Function Attributes}.
+
++@item -mindirect-branch-register
++@opindex -mindirect-branch-register
++Force indirect call and jump via register.
++
+ @end table
+
+ These @samp{-m} switches are supported in addition to the above
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+index f076155c91a..9eb9b273ade 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+index d7984f592fe..c63795e4127 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+index 3257d0a2e16..82973cda771 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+index 7cab2df6474..a5f3d1cbed8 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+index b4836c38d6c..fcaa18d10b7 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+index 1f06bd1af74..e4649283d10 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+index 0b3fef86a20..ebfb8aab937 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+index 5f6cfc17b56..a08022db8e4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+index b256160ec80..b257c695ad1 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+index 567c95051d6..dfb1370d23d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+index 3b662af7d5d..a6e3f6f9f2b 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+index 98785a38248..4bb1c5f9220 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+index a498a39e404..4e33a638862 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+index 66f295d1eb6..427ba3ddbb4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+index aacb814d737..dc7143414fb 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+index 7b44dda23df..737c60946f6 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { ! x32 } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+index 70b4fb36eea..d34485a0010 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+index 3baf03ee77c..0e19830de4d 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fpic -fno-plt" } */
++/* { 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];
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+index 637fc3d3f4e..5c20a35ecec 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+index ff9efe03fe6..b2fb6e1bcd2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+index 2686a5f2db4..9c84547cd7c 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+index f07f6b214ad..457849564bb 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+index 21740ac5b7f..5c07e02df6a 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+index a77c1f470b8..3eb440693a0 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-extern" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+index e64910fd4aa..d4747ea0764 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+index 365cf2ee226..536abfa74e4 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+index 72646a4960b..bd2b6246aa1 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+index f48945e3dfc..9885eebbcff 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+index 4b1d558fc4e..7b3983949d2 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ typedef void (*dispatch_t)(long offset);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+index 0f687c3b027..c6d77e10352 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+index b27c6fc96a2..6454827b780 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile { target *-*-linux* } } */
+-/* { dg-options "-O2 -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fpic -fno-plt -mindirect-branch=thunk-inline" } */
+
+ extern void bar (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+index 2c496492eaa..cc592f89aba 100644
+--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+
+ void func0 (void);
+ void func1 (void);
+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/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+index 1630e2fa2b5..b4f9d48065d 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
+
+ extern void (*bar) (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+index 876159cf783..0312577a043 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+index 01b0a02f80b..fa3181303c9 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+index e028c2b6a99..7a08e71c76b 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
++/* { 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")));
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+index c14ee3ae4c0..dacf0c769fc 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+
+ extern void (*bar) (void);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+index 2f21e138ec2..cf06a5f35c7 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
++/* { 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);
+
+diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+index f6ccad98da7..6da5ab97081 100644
+--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
++++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
++/* { dg-options "-O2 -mno-indirect-branch-register -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
+
+ extern void (*bar) (void);
+
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch b/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch
new file mode 100644
index 000000000..e622601ea
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch
@@ -0,0 +1,2171 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 09f7c546376f7ed6770fc64f24aed77229f95f67 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 6 Jan 2018 22:29:55 -0800
+Subject: [PATCH 04/10] x86: Add -mindirect-branch=
+
+Add -mindirect-branch= option to convert indirect call and jump to call
+and return thunks. The default is 'keep', which keeps indirect call and
+jump unmodified. 'thunk' converts indirect call and jump to call and
+return thunk. 'thunk-inline' converts indirect call and jump to inlined
+call and return thunk. 'thunk-extern' converts indirect call and jump to
+external call and return thunk provided in a separate object file. You
+can control this behavior for a specific function by using the function
+attribute indirect_branch.
+
+2 kinds of thunks are geneated. Memory thunk where the function address
+is at the top of the stack:
+
+__x86_indirect_thunk:
+ call L2
+L1:
+ pause
+ lfence
+ jmp L1
+L2:
+ lea 8(%rsp), %rsp|lea 4(%esp), %esp
+ ret
+
+Indirect jmp via memory, "jmp mem", is converted to
+
+ push memory
+ jmp __x86_indirect_thunk
+
+Indirect call via memory, "call mem", is converted to
+
+ jmp L2
+L1:
+ push [mem]
+ jmp __x86_indirect_thunk
+L2:
+ call L1
+
+Register thunk where the function address is in a register, reg:
+
+__x86_indirect_thunk_reg:
+ call L2
+L1:
+ pause
+ lfence
+ jmp L1
+L2:
+ movq %reg, (%rsp)|movl %reg, (%esp)
+ ret
+
+where reg is one of (r|e)ax, (r|e)dx, (r|e)cx, (r|e)bx, (r|e)si, (r|e)di,
+(r|e)bp, r8, r9, r10, r11, r12, r13, r14 and r15.
+
+Indirect jmp via register, "jmp reg", is converted to
+
+ jmp __x86_indirect_thunk_reg
+
+Indirect call via register, "call reg", is converted to
+
+ call __x86_indirect_thunk_reg
+
+gcc/
+
+ Backport from mainline
+ * config/i386/i386-opts.h (indirect_branch): New.
+ * config/i386/i386-protos.h (ix86_output_indirect_jmp): Likewise.
+ * config/i386/i386.c (ix86_using_red_zone): Disallow red-zone
+ with local indirect jump when converting indirect call and jump.
+ (ix86_set_indirect_branch_type): New.
+ (ix86_set_current_function): Call ix86_set_indirect_branch_type.
+ (indirectlabelno): New.
+ (indirect_thunk_needed): Likewise.
+ (indirect_thunk_bnd_needed): Likewise.
+ (indirect_thunks_used): Likewise.
+ (indirect_thunks_bnd_used): Likewise.
+ (INDIRECT_LABEL): Likewise.
+ (indirect_thunk_name): Likewise.
+ (output_indirect_thunk): Likewise.
+ (output_indirect_thunk_function): Likewise.
+ (ix86_output_indirect_branch): Likewise.
+ (ix86_output_indirect_jmp): Likewise.
+ (ix86_code_end): Call output_indirect_thunk_function if needed.
+ (ix86_output_call_insn): Call ix86_output_indirect_branch if
+ needed.
+ (ix86_handle_fndecl_attribute): Handle indirect_branch.
+ (ix86_attribute_table): Add indirect_branch.
+ * config/i386/i386.h (machine_function): Add indirect_branch_type
+ and has_local_indirect_jump.
+ * config/i386/i386.md (indirect_jump): Set has_local_indirect_jump
+ to true.
+ (tablejump): Likewise.
+ (*indirect_jump): Use ix86_output_indirect_jmp.
+ (*tablejump_1): Likewise.
+ (simple_return_indirect_internal): Likewise.
+ * config/i386/i386.opt (mindirect-branch=): New option.
+ (indirect_branch): New.
+ (keep): Likewise.
+ (thunk): Likewise.
+ (thunk-inline): Likewise.
+ (thunk-extern): Likewise.
+ * doc/extend.texi: Document indirect_branch function attribute.
+ * doc/invoke.texi: Document -mindirect-branch= option.
+
+gcc/testsuite/
+
+ Backport from mainline
+ * gcc.target/i386/indirect-thunk-1.c: New test.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-bnd-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+---
+ gcc/config/i386/i386-opts.h | 13 +
+ gcc/config/i386/i386-protos.h | 1 +
+ gcc/config/i386/i386.c | 648 ++++++++++++++++++++-
+ gcc/config/i386/i386.h | 7 +
+ gcc/config/i386/i386.md | 26 +-
+ gcc/config/i386/i386.opt | 20 +
+ gcc/doc/extend.texi | 10 +
+ gcc/doc/invoke.texi | 14 +-
+ gcc/testsuite/gcc.target/i386/indirect-thunk-1.c | 20 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-2.c | 20 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-3.c | 21 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-4.c | 21 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-5.c | 17 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-6.c | 18 +
+ gcc/testsuite/gcc.target/i386/indirect-thunk-7.c | 44 ++
+ .../gcc.target/i386/indirect-thunk-attr-1.c | 23 +
+ .../gcc.target/i386/indirect-thunk-attr-2.c | 21 +
+ .../gcc.target/i386/indirect-thunk-attr-3.c | 23 +
+ .../gcc.target/i386/indirect-thunk-attr-4.c | 22 +
+ .../gcc.target/i386/indirect-thunk-attr-5.c | 22 +
+ .../gcc.target/i386/indirect-thunk-attr-6.c | 21 +
+ .../gcc.target/i386/indirect-thunk-attr-7.c | 44 ++
+ .../gcc.target/i386/indirect-thunk-attr-8.c | 42 ++
+ .../gcc.target/i386/indirect-thunk-bnd-1.c | 20 +
+ .../gcc.target/i386/indirect-thunk-bnd-2.c | 21 +
+ .../gcc.target/i386/indirect-thunk-bnd-3.c | 19 +
+ .../gcc.target/i386/indirect-thunk-bnd-4.c | 20 +
+ .../gcc.target/i386/indirect-thunk-extern-1.c | 19 +
+ .../gcc.target/i386/indirect-thunk-extern-2.c | 19 +
+ .../gcc.target/i386/indirect-thunk-extern-3.c | 20 +
+ .../gcc.target/i386/indirect-thunk-extern-4.c | 20 +
+ .../gcc.target/i386/indirect-thunk-extern-5.c | 16 +
+ .../gcc.target/i386/indirect-thunk-extern-6.c | 17 +
+ .../gcc.target/i386/indirect-thunk-extern-7.c | 43 ++
+ .../gcc.target/i386/indirect-thunk-inline-1.c | 20 +
+ .../gcc.target/i386/indirect-thunk-inline-2.c | 20 +
+ .../gcc.target/i386/indirect-thunk-inline-3.c | 21 +
+ .../gcc.target/i386/indirect-thunk-inline-4.c | 21 +
+ .../gcc.target/i386/indirect-thunk-inline-5.c | 17 +
+ .../gcc.target/i386/indirect-thunk-inline-6.c | 18 +
+ .../gcc.target/i386/indirect-thunk-inline-7.c | 44 ++
+ 41 files changed, 1494 insertions(+), 19 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+
+diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
+index 542cd0f3d67..efcdc3b1a14 100644
+--- a/gcc/config/i386/i386-opts.h
++++ b/gcc/config/i386/i386-opts.h
+@@ -99,4 +99,17 @@ enum stack_protector_guard {
+ SSP_GLOBAL /* global canary */
+ };
+
++/* This is used to mitigate variant #2 of the speculative execution
++ vulnerabilities on x86 processors identified by CVE-2017-5715, aka
++ Spectre. They convert indirect branches and function returns to
++ call and return thunks to avoid speculative execution via indirect
++ call, jmp and ret. */
++enum indirect_branch {
++ indirect_branch_unset = 0,
++ indirect_branch_keep,
++ indirect_branch_thunk,
++ indirect_branch_thunk_inline,
++ indirect_branch_thunk_extern
++};
++
+ #endif
+diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
+index d2cccf14735..bcdd9872db9 100644
+--- a/gcc/config/i386/i386-protos.h
++++ b/gcc/config/i386/i386-protos.h
+@@ -313,6 +313,7 @@ extern enum attr_cpu ix86_schedule;
+ #endif
+
+ extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
++extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
+ extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ enum machine_mode mode);
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index 986e6d79584..f1c58faa035 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -4212,12 +4212,23 @@ make_pass_stv (gcc::context *ctxt)
+ return new pass_stv (ctxt);
+ }
+
+-/* Return true if a red-zone is in use. */
++/* Return true if a red-zone is in use. We can't use red-zone when
++ there are local indirect jumps, like "indirect_jump" or "tablejump",
++ which jumps to another place in the function, since "call" in the
++ indirect thunk pushes the return address onto stack, destroying
++ red-zone.
++
++ TODO: If we can reserve the first 2 WORDs, for PUSH and, another
++ for CALL, in red-zone, we can allow local indirect jumps with
++ indirect thunk. */
+
+ bool
+ ix86_using_red_zone (void)
+ {
+- return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
++ return (TARGET_RED_ZONE
++ && !TARGET_64BIT_MS_ABI
++ && (!cfun->machine->has_local_indirect_jump
++ || cfun->machine->indirect_branch_type == indirect_branch_keep));
+ }
+ \f
+ /* Return a string that documents the current -m options. The caller is
+@@ -7148,6 +7159,37 @@ ix86_set_func_type (tree fndecl)
+ }
+ }
+
++/* Set the indirect_branch_type field from the function FNDECL. */
++
++static void
++ix86_set_indirect_branch_type (tree fndecl)
++{
++ if (cfun->machine->indirect_branch_type == indirect_branch_unset)
++ {
++ tree attr = lookup_attribute ("indirect_branch",
++ DECL_ATTRIBUTES (fndecl));
++ if (attr != NULL)
++ {
++ tree args = TREE_VALUE (attr);
++ if (args == NULL)
++ gcc_unreachable ();
++ tree cst = TREE_VALUE (args);
++ if (strcmp (TREE_STRING_POINTER (cst), "keep") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_keep;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-inline") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk_inline;
++ else if (strcmp (TREE_STRING_POINTER (cst), "thunk-extern") == 0)
++ cfun->machine->indirect_branch_type = indirect_branch_thunk_extern;
++ else
++ gcc_unreachable ();
++ }
++ else
++ cfun->machine->indirect_branch_type = ix86_indirect_branch;
++ }
++}
++
+ /* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+@@ -7163,7 +7205,10 @@ ix86_set_current_function (tree fndecl)
+ one is extern inline and one isn't. Call ix86_set_func_type
+ to set the func_type field. */
+ if (fndecl != NULL_TREE)
+- ix86_set_func_type (fndecl);
++ {
++ ix86_set_func_type (fndecl);
++ ix86_set_indirect_branch_type (fndecl);
++ }
+ return;
+ }
+
+@@ -7183,6 +7228,7 @@ ix86_set_current_function (tree fndecl)
+ }
+
+ ix86_set_func_type (fndecl);
++ ix86_set_indirect_branch_type (fndecl);
+
+ tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (new_tree == NULL_TREE)
+@@ -11920,6 +11966,220 @@ ix86_setup_frame_addresses (void)
+ # endif
+ #endif
+
++/* Label count for call and return thunks. It is used to make unique
++ labels in call and return thunks. */
++static int indirectlabelno;
++
++/* True if call and return thunk functions are needed. */
++static bool indirect_thunk_needed = false;
++/* True if call and return thunk functions with the BND prefix are
++ needed. */
++static bool indirect_thunk_bnd_needed = false;
++
++/* Bit masks of integer registers, which contain branch target, used
++ by call and return thunks functions. */
++static int indirect_thunks_used;
++/* Bit masks of integer registers, which contain branch target, used
++ by call and return thunks functions with the BND prefix. */
++static int indirect_thunks_bnd_used;
++
++#ifndef INDIRECT_LABEL
++# define INDIRECT_LABEL "LIND"
++#endif
++
++/* Fills in the label name that should be used for the indirect thunk. */
++
++static void
++indirect_thunk_name (char name[32], int regno, bool need_bnd_p)
++{
++ if (USE_HIDDEN_LINKONCE)
++ {
++ const char *bnd = need_bnd_p ? "_bnd" : "";
++ if (regno >= 0)
++ {
++ const char *reg_prefix;
++ if (LEGACY_INT_REGNO_P (regno))
++ reg_prefix = TARGET_64BIT ? "r" : "e";
++ else
++ reg_prefix = "";
++ sprintf (name, "__x86_indirect_thunk%s_%s%s",
++ bnd, reg_prefix, reg_names[regno]);
++ }
++ else
++ sprintf (name, "__x86_indirect_thunk%s", bnd);
++ }
++ else
++ {
++ if (regno >= 0)
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITBR", regno);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITR", regno);
++ }
++ else
++ {
++ if (need_bnd_p)
++ ASM_GENERATE_INTERNAL_LABEL (name, "LITB", 0);
++ else
++ ASM_GENERATE_INTERNAL_LABEL (name, "LIT", 0);
++ }
++ }
++}
++
++/* Output a call and return thunk for indirect branch. If BND_P is
++ true, the BND prefix is needed. If REGNO != -1, the function
++ address is in REGNO and the call and return thunk looks like:
++
++ call L2
++ L1:
++ pause
++ jmp L1
++ L2:
++ mov %REG, (%sp)
++ ret
++
++ Otherwise, the function address is on the top of stack and the
++ call and return thunk looks like:
++
++ call L2
++ L1:
++ pause
++ jmp L1
++ L2:
++ lea WORD_SIZE(%sp), %sp
++ ret
++ */
++
++static void
++output_indirect_thunk (bool need_bnd_p, int regno)
++{
++ char indirectlabel1[32];
++ char indirectlabel2[32];
++
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1, INDIRECT_LABEL,
++ indirectlabelno++);
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2, INDIRECT_LABEL,
++ indirectlabelno++);
++
++ /* Call */
++ if (need_bnd_p)
++ fputs ("\tbnd call\t", asm_out_file);
++ else
++ fputs ("\tcall\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel2);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
++
++ /* Pause + lfence. */
++ fprintf (asm_out_file, "\tpause\n\tlfence\n");
++
++ /* Jump. */
++ fputs ("\tjmp\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel1);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
++
++ if (regno >= 0)
++ {
++ /* MOV. */
++ rtx xops[2];
++ xops[0] = gen_rtx_MEM (word_mode, stack_pointer_rtx);
++ xops[1] = gen_rtx_REG (word_mode, regno);
++ output_asm_insn ("mov\t{%1, %0|%0, %1}", xops);
++ }
++ else
++ {
++ /* LEA. */
++ rtx xops[2];
++ xops[0] = stack_pointer_rtx;
++ xops[1] = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
++ output_asm_insn ("lea\t{%E1, %0|%0, %E1}", xops);
++ }
++
++ if (need_bnd_p)
++ fputs ("\tbnd ret\n", asm_out_file);
++ else
++ fputs ("\tret\n", asm_out_file);
++}
++
++/* Output a funtion with a call and return thunk for indirect branch.
++ If BND_P is true, the BND prefix is needed. If REGNO != -1, the
++ function address is in REGNO. Otherwise, the function address is
++ on the top of stack. */
++
++static void
++output_indirect_thunk_function (bool need_bnd_p, int regno)
++{
++ char name[32];
++ tree decl;
++
++ /* Create __x86_indirect_thunk/__x86_indirect_thunk_bnd. */
++ indirect_thunk_name (name, regno, need_bnd_p);
++ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
++ get_identifier (name),
++ build_function_type_list (void_type_node, NULL_TREE));
++ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
++ NULL_TREE, void_type_node);
++ TREE_PUBLIC (decl) = 1;
++ TREE_STATIC (decl) = 1;
++ DECL_IGNORED_P (decl) = 1;
++
++#if TARGET_MACHO
++ if (TARGET_MACHO)
++ {
++ switch_to_section (darwin_sections[picbase_thunk_section]);
++ fputs ("\t.weak_definition\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ fputs ("\n\t.private_extern\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ putc ('\n', asm_out_file);
++ ASM_OUTPUT_LABEL (asm_out_file, name);
++ DECL_WEAK (decl) = 1;
++ }
++ else
++#endif
++ if (USE_HIDDEN_LINKONCE)
++ {
++ cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
++
++ targetm.asm_out.unique_section (decl, 0);
++ switch_to_section (get_named_section (decl, NULL, 0));
++
++ targetm.asm_out.globalize_label (asm_out_file, name);
++ fputs ("\t.hidden\t", asm_out_file);
++ assemble_name (asm_out_file, name);
++ putc ('\n', asm_out_file);
++ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
++ }
++ else
++ {
++ switch_to_section (text_section);
++ ASM_OUTPUT_LABEL (asm_out_file, name);
++ }
++
++ DECL_INITIAL (decl) = make_node (BLOCK);
++ current_function_decl = decl;
++ allocate_struct_function (decl, false);
++ init_function_start (decl);
++ /* We're about to hide the function body from callees of final_* by
++ emitting it directly; tell them we're a thunk, if they care. */
++ cfun->is_thunk = true;
++ first_function_block_is_cold = false;
++ /* Make sure unwind info is emitted for the thunk if needed. */
++ final_start_function (emit_barrier (), asm_out_file, 1);
++
++ output_indirect_thunk (need_bnd_p, regno);
++
++ final_end_function ();
++ init_insn_lengths ();
++ free_after_compilation (cfun);
++ set_cfun (NULL);
++ current_function_decl = NULL;
++}
++
+ static int pic_labels_used;
+
+ /* Fills in the label name that should be used for a pc thunk for
+@@ -11946,11 +12206,32 @@ ix86_code_end (void)
+ rtx xops[2];
+ int regno;
+
++ if (indirect_thunk_needed)
++ output_indirect_thunk_function (false, -1);
++ if (indirect_thunk_bnd_needed)
++ output_indirect_thunk_function (true, -1);
++
++ for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
++ {
++ int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1;
++ if ((indirect_thunks_used & (1 << i)))
++ output_indirect_thunk_function (false, regno);
++
++ if ((indirect_thunks_bnd_used & (1 << i)))
++ output_indirect_thunk_function (true, regno);
++ }
++
+ for (regno = AX_REG; regno <= SP_REG; regno++)
+ {
+ char name[32];
+ tree decl;
+
++ if ((indirect_thunks_used & (1 << regno)))
++ output_indirect_thunk_function (false, regno);
++
++ if ((indirect_thunks_bnd_used & (1 << regno)))
++ output_indirect_thunk_function (true, regno);
++
+ if (!(pic_labels_used & (1 << regno)))
+ continue;
+
+@@ -28446,12 +28727,292 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
+ return false;
+ }
+
++/* Output indirect branch via a call and return thunk. CALL_OP is a
++ register which contains the branch target. XASM is the assembly
++ template for CALL_OP. Branch is a tail call if SIBCALL_P is true.
++ A normal call is converted to:
++
++ call __x86_indirect_thunk_reg
++
++ and a tail call is converted to:
++
++ jmp __x86_indirect_thunk_reg
++ */
++
++static void
++ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
++{
++ char thunk_name_buf[32];
++ char *thunk_name;
++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++ int regno = REGNO (call_op);
++
++ if (cfun->machine->indirect_branch_type
++ != indirect_branch_thunk_inline)
++ {
++ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
++ {
++ int i = regno;
++ if (i >= FIRST_REX_INT_REG)
++ i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
++ if (need_bnd_p)
++ indirect_thunks_bnd_used |= 1 << i;
++ else
++ indirect_thunks_used |= 1 << i;
++ }
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
++ thunk_name = thunk_name_buf;
++ }
++ else
++ thunk_name = NULL;
++
++ if (sibcall_p)
++ {
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ else
++ output_indirect_thunk (need_bnd_p, regno);
++ }
++ else
++ {
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd call\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
++ return;
++ }
++
++ char indirectlabel1[32];
++ char indirectlabel2[32];
++
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++
++ /* Jump. */
++ if (need_bnd_p)
++ fputs ("\tbnd jmp\t", asm_out_file);
++ else
++ fputs ("\tjmp\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel2);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
++
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ else
++ output_indirect_thunk (need_bnd_p, regno);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
++
++ /* Call. */
++ if (need_bnd_p)
++ fputs ("\tbnd call\t", asm_out_file);
++ else
++ fputs ("\tcall\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel1);
++ fputc ('\n', asm_out_file);
++ }
++}
++
++/* Output indirect branch via a call and return thunk. CALL_OP is
++ the branch target. XASM is the assembly template for CALL_OP.
++ Branch is a tail call if SIBCALL_P is true. A normal call is
++ converted to:
++
++ jmp L2
++ L1:
++ push CALL_OP
++ jmp __x86_indirect_thunk
++ L2:
++ call L1
++
++ and a tail call is converted to:
++
++ push CALL_OP
++ jmp __x86_indirect_thunk
++ */
++
++static void
++ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
++ bool sibcall_p)
++{
++ char thunk_name_buf[32];
++ char *thunk_name;
++ char push_buf[64];
++ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
++ int regno = -1;
++
++ if (cfun->machine->indirect_branch_type
++ != indirect_branch_thunk_inline)
++ {
++ if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
++ {
++ if (need_bnd_p)
++ indirect_thunk_bnd_needed = true;
++ else
++ indirect_thunk_needed = true;
++ }
++ indirect_thunk_name (thunk_name_buf, regno, need_bnd_p);
++ thunk_name = thunk_name_buf;
++ }
++ else
++ thunk_name = NULL;
++
++ snprintf (push_buf, sizeof (push_buf), "push{%c}\t%s",
++ TARGET_64BIT ? 'q' : 'l', xasm);
++
++ if (sibcall_p)
++ {
++ output_asm_insn (push_buf, &call_op);
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ else
++ output_indirect_thunk (need_bnd_p, regno);
++ }
++ else
++ {
++ char indirectlabel1[32];
++ char indirectlabel2[32];
++
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel1,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++ ASM_GENERATE_INTERNAL_LABEL (indirectlabel2,
++ INDIRECT_LABEL,
++ indirectlabelno++);
++
++ /* Jump. */
++ if (need_bnd_p)
++ fputs ("\tbnd jmp\t", asm_out_file);
++ else
++ fputs ("\tjmp\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel2);
++ fputc ('\n', asm_out_file);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
++
++ /* An external function may be called via GOT, instead of PLT. */
++ if (MEM_P (call_op))
++ {
++ struct ix86_address parts;
++ rtx addr = XEXP (call_op, 0);
++ if (ix86_decompose_address (addr, &parts)
++ && parts.base == stack_pointer_rtx)
++ {
++ /* Since call will adjust stack by -UNITS_PER_WORD,
++ we must convert "disp(stack, index, scale)" to
++ "disp+UNITS_PER_WORD(stack, index, scale)". */
++ if (parts.index)
++ {
++ addr = gen_rtx_MULT (Pmode, parts.index,
++ GEN_INT (parts.scale));
++ addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
++ addr);
++ }
++ else
++ addr = stack_pointer_rtx;
++
++ rtx disp;
++ if (parts.disp != NULL_RTX)
++ disp = plus_constant (Pmode, parts.disp,
++ UNITS_PER_WORD);
++ else
++ disp = GEN_INT (UNITS_PER_WORD);
++
++ addr = gen_rtx_PLUS (Pmode, addr, disp);
++ call_op = gen_rtx_MEM (GET_MODE (call_op), addr);
++ }
++ }
++
++ output_asm_insn (push_buf, &call_op);
++
++ if (thunk_name != NULL)
++ {
++ if (need_bnd_p)
++ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
++ else
++ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
++ }
++ else
++ output_indirect_thunk (need_bnd_p, regno);
++
++ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
++
++ /* Call. */
++ if (need_bnd_p)
++ fputs ("\tbnd call\t", asm_out_file);
++ else
++ fputs ("\tcall\t", asm_out_file);
++ assemble_name_raw (asm_out_file, indirectlabel1);
++ fputc ('\n', asm_out_file);
++ }
++}
++
++/* Output indirect branch via a call and return thunk. CALL_OP is
++ the branch target. XASM is the assembly template for CALL_OP.
++ Branch is a tail call if SIBCALL_P is true. */
++
++static void
++ix86_output_indirect_branch (rtx call_op, const char *xasm,
++ bool sibcall_p)
++{
++ if (REG_P (call_op))
++ ix86_output_indirect_branch_via_reg (call_op, sibcall_p);
++ else
++ ix86_output_indirect_branch_via_push (call_op, xasm, sibcall_p);
++}
++/* Output indirect jump. CALL_OP is the jump target. Jump is a
++ function return if RET_P is true. */
++
++const char *
++ix86_output_indirect_jmp (rtx call_op, bool ret_p)
++{
++ if (cfun->machine->indirect_branch_type != indirect_branch_keep)
++ {
++ /* We can't have red-zone if this isn't a function return since
++ "call" in the indirect thunk pushes the return address onto
++ stack, destroying red-zone. */
++ if (!ret_p && ix86_red_zone_size != 0)
++ gcc_unreachable ();
++
++ ix86_output_indirect_branch (call_op, "%0", true);
++ return "";
++ }
++ else
++ return "%!jmp\t%A0";
++}
++
+ /* Output the assembly for a call instruction. */
+
+ const char *
+ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ bool direct_p = constant_call_address_operand (call_op, VOIDmode);
++ bool output_indirect_p
++ = (!TARGET_SEH
++ && cfun->machine->indirect_branch_type != indirect_branch_keep);
+ bool seh_nop_p = false;
+ const char *xasm;
+
+@@ -28461,10 +29022,21 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ if (ix86_nopic_noplt_attribute_p (call_op))
+ {
++ direct_p = false;
+ if (TARGET_64BIT)
+- xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ else
++ xasm = "%!jmp\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ }
+ else
+- xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
++ else
++ xasm = "%!jmp\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ }
+ }
+ else
+ xasm = "%!jmp\t%P0";
+@@ -28474,9 +29046,17 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ else if (TARGET_SEH)
+ xasm = "%!rex.W jmp\t%A0";
+ else
+- xasm = "%!jmp\t%A0";
++ {
++ if (output_indirect_p)
++ xasm = "%0";
++ else
++ xasm = "%!jmp\t%A0";
++ }
+
+- output_asm_insn (xasm, &call_op);
++ if (output_indirect_p && !direct_p)
++ ix86_output_indirect_branch (call_op, xasm, true);
++ else
++ output_asm_insn (xasm, &call_op);
+ return "";
+ }
+
+@@ -28514,18 +29094,37 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
+ {
+ if (ix86_nopic_noplt_attribute_p (call_op))
+ {
++ direct_p = false;
+ if (TARGET_64BIT)
+- xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ else
++ xasm = "%!call\t{*%p0@GOTPCREL(%%rip)|[QWORD PTR %p0@GOTPCREL[rip]]}";
++ }
+ else
+- xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ {
++ if (output_indirect_p)
++ xasm = "{%p0@GOT|[DWORD PTR %p0@GOT]}";
++ else
++ xasm = "%!call\t{*%p0@GOT|[DWORD PTR %p0@GOT]}";
++ }
+ }
+ else
+ xasm = "%!call\t%P0";
+ }
+ else
+- xasm = "%!call\t%A0";
++ {
++ if (output_indirect_p)
++ xasm = "%0";
++ else
++ xasm = "%!call\t%A0";
++ }
+
+- output_asm_insn (xasm, &call_op);
++ if (output_indirect_p && !direct_p)
++ ix86_output_indirect_branch (call_op, xasm, false);
++ else
++ output_asm_insn (xasm, &call_op);
+
+ if (seh_nop_p)
+ return "nop";
+@@ -41444,7 +42043,7 @@ ix86_handle_struct_attribute (tree *node, tree name, tree, int,
+ }
+
+ static tree
+-ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
++ix86_handle_fndecl_attribute (tree *node, tree name, tree args, int,
+ bool *no_add_attrs)
+ {
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+@@ -41453,6 +42052,29 @@ ix86_handle_fndecl_attribute (tree *node, tree name, tree, int,
+ name);
+ *no_add_attrs = true;
+ }
++
++ if (is_attribute_p ("indirect_branch", name))
++ {
++ tree cst = TREE_VALUE (args);
++ if (TREE_CODE (cst) != STRING_CST)
++ {
++ warning (OPT_Wattributes,
++ "%qE attribute requires a string constant argument",
++ name);
++ *no_add_attrs = true;
++ }
++ else if (strcmp (TREE_STRING_POINTER (cst), "keep") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-inline") != 0
++ && strcmp (TREE_STRING_POINTER (cst), "thunk-extern") != 0)
++ {
++ warning (OPT_Wattributes,
++ "argument to %qE attribute is not "
++ "(keep|thunk|thunk-inline|thunk-extern)", name);
++ *no_add_attrs = true;
++ }
++ }
++
+ return NULL_TREE;
+ }
+
+@@ -45761,6 +46383,8 @@ static const struct attribute_spec ix86_attribute_table[] =
+ ix86_handle_interrupt_attribute, false },
+ { "no_caller_saved_registers", 0, 0, false, true, true,
+ ix86_handle_no_caller_saved_registers_attribute, false },
++ { "indirect_branch", 1, 1, true, false, false,
++ ix86_handle_fndecl_attribute, false },
+
+ /* End element. */
+ { NULL, 0, 0, false, false, false, NULL, false }
+diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
+index f9b91286a01..9d2209e605b 100644
+--- a/gcc/config/i386/i386.h
++++ b/gcc/config/i386/i386.h
+@@ -2609,6 +2609,13 @@ struct GTY(()) machine_function {
+ /* Function type. */
+ ENUM_BITFIELD(function_type) func_type : 2;
+
++ /* How to generate indirec branch. */
++ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
++
++ /* If true, the current function has local indirect jumps, like
++ "indirect_jump" or "tablejump". */
++ BOOL_BITFIELD has_local_indirect_jump : 1;
++
+ /* If true, the current function is a function specified with
+ the "interrupt" or "no_caller_saved_registers" attribute. */
+ BOOL_BITFIELD no_caller_saved_registers : 1;
+diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
+index dbe88f40c8f..cd2e73cf9d3 100644
+--- a/gcc/config/i386/i386.md
++++ b/gcc/config/i386/i386.md
+@@ -11627,13 +11627,18 @@
+ {
+ if (TARGET_X32)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
++ cfun->machine->has_local_indirect_jump = true;
+ })
+
+ (define_insn "*indirect_jump"
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
+ ""
+- "%!jmp\t%A0"
+- [(set_attr "type" "ibr")
++ "* return ix86_output_indirect_jmp (operands[0], false);"
++ [(set (attr "type")
++ (if_then_else (match_test "(cfun->machine->indirect_branch_type
++ != indirect_branch_keep)")
++ (const_string "multi")
++ (const_string "ibr")))
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+
+@@ -11676,14 +11681,19 @@
+
+ if (TARGET_X32)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
++ cfun->machine->has_local_indirect_jump = true;
+ })
+
+ (define_insn "*tablejump_1"
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
+ (use (label_ref (match_operand 1)))]
+ ""
+- "%!jmp\t%A0"
+- [(set_attr "type" "ibr")
++ "* return ix86_output_indirect_jmp (operands[0], false);"
++ [(set (attr "type")
++ (if_then_else (match_test "(cfun->machine->indirect_branch_type
++ != indirect_branch_keep)")
++ (const_string "multi")
++ (const_string "ibr")))
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+ \f
+@@ -12354,8 +12364,12 @@
+ [(simple_return)
+ (use (match_operand:SI 0 "register_operand" "r"))]
+ "reload_completed"
+- "%!jmp\t%A0"
+- [(set_attr "type" "ibr")
++ "* return ix86_output_indirect_jmp (operands[0], true);"
++ [(set (attr "type")
++ (if_then_else (match_test "(cfun->machine->indirect_branch_type
++ != indirect_branch_keep)")
++ (const_string "multi")
++ (const_string "ibr")))
+ (set_attr "length_immediate" "0")
+ (set_attr "maybe_prefix_bnd" "1")])
+
+diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
+index 9384e29b1de..c076d9c70ab 100644
+--- a/gcc/config/i386/i386.opt
++++ b/gcc/config/i386/i386.opt
+@@ -927,3 +927,23 @@ Attempt to avoid generating instruction sequences containing ret bytes.
+ mgeneral-regs-only
+ Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
+ Generate code which uses only the general registers.
++
++mindirect-branch=
++Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
++Convert indirect call and jump to call and return thunks.
++
++Enum
++Name(indirect_branch) Type(enum indirect_branch)
++Known indirect branch choices (for use with the -mindirect-branch= option):
++
++EnumValue
++Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
++
++EnumValue
++Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
++
++EnumValue
++Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
++
++EnumValue
++Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index ba309d01a9b..935381da6fa 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -5540,6 +5540,16 @@ Specify which floating-point unit to use. You must specify the
+ @code{target("fpmath=sse,387")} option as
+ @code{target("fpmath=sse+387")} because the comma would separate
+ different options.
++
++@item indirect_branch("@var{choice}")
++@cindex @code{indirect_branch} function attribute, x86
++On x86 targets, the @code{indirect_branch} attribute causes the compiler
++to convert indirect call and jump with @var{choice}. @samp{keep}
++keeps indirect call and jump unmodified. @samp{thunk} converts indirect
++call and jump to call and return thunk. @samp{thunk-inline} converts
++indirect call and jump to inlined call and return thunk.
++@samp{thunk-extern} converts indirect call and jump to external call
++and return thunk provided in a separate object file.
+ @end table
+
+ On the x86, the inliner does not inline a
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 7311c10a754..4979c8c939d 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -1210,7 +1210,8 @@ See RS/6000 and PowerPC Options.
+ -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol
+ -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol
+ -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol
+--mmitigate-rop -mgeneral-regs-only}
++-mmitigate-rop -mgeneral-regs-only @gol
++-mindirect-branch=@var{choice}}
+
+ @emph{x86 Windows Options}
+ @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
+@@ -25686,6 +25687,17 @@ Generate code that uses only the general-purpose registers. This
+ prevents the compiler from using floating-point, vector, mask and bound
+ registers.
+
++@item -mindirect-branch=@var{choice}
++@opindex -mindirect-branch
++Convert indirect call and jump with @var{choice}. The default is
++@samp{keep}, which keeps indirect call and jump unmodified.
++@samp{thunk} converts indirect call and jump to call and return thunk.
++@samp{thunk-inline} converts indirect call and jump to inlined call
++and return thunk. @samp{thunk-extern} converts indirect call and jump
++to external call and return thunk provided in a separate object file.
++You can control this behavior for a specific function by using the
++function attribute @code{indirect_branch}. @xref{Function Attributes}.
++
+ @end table
+
+ These @samp{-m} switches are supported in addition to the above
+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..d983e1c3e26
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+new file mode 100644
+index 00000000000..58f09b42d8a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+new file mode 100644
+index 00000000000..f20d35c19b6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+new file mode 100644
+index 00000000000..0eff8fb658a
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "call\[ \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-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+new file mode 100644
+index 00000000000..a25b20dd808
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-5.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -fpic -fno-plt -mindirect-branch=thunk" } */
++
++extern void bar (void);
++
++void
++foo (void)
++{
++ bar ();
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_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/indirect-thunk-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+new file mode 100644
+index 00000000000..cff114a6c29
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-6.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
++/* { 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} } } */
+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..afdb6007986
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+new file mode 100644
+index 00000000000..d64d978b699
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+new file mode 100644
+index 00000000000..93067454d3d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+new file mode 100644
+index 00000000000..97744d65729
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { 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" } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..bfce3ea5cb2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { 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" } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
+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..0833606046b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+new file mode 100644
+index 00000000000..2eba0fbd9b2
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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 "jmp\[ \t\]*__x86_indirect_thunk" { 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-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+new file mode 100644
+index 00000000000..f58427eae11
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+new file mode 100644
+index 00000000000..564ed39547c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+@@ -0,0 +1,42 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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-bnd-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-1.c
+new file mode 100644
+index 00000000000..50fbee20a5a
+--- /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 -mindirect-branch=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
++
++void (*dispatch) (char *);
++char buf[10];
++
++void
++foo (void)
++{
++ dispatch (buf);
++}
++
++/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
++/* { 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..2976e67adce
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-2.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile { target { ! x32 } } } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "pushq\[ \t\]%rax" { target x32 } } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
++/* { dg-final { scan-assembler "bnd 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+new file mode 100644
+index 00000000000..da4bc98ef23
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-3.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk_bnd" } } */
++/* { 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..c64d12ef989
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-bnd-4.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile { target { *-*-linux* && { ! x32 } } } } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*bar@GOT" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*__x86_indirect_thunk" } } */
++/* { dg-final { scan-assembler "bnd jmp\[ \t\]*\.LIND" } } */
++/* { dg-final { scan-assembler-times "bnd call\[ \t\]*\.LIND" 2 } } */
++/* { 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..49f27b49465
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+new file mode 100644
+index 00000000000..a1e3eb6fc74
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+new file mode 100644
+index 00000000000..395634e7e5c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "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-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+new file mode 100644
+index 00000000000..fd3f63379a1
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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 "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-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+new file mode 100644
+index 00000000000..ba2f92b6f34
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-5.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__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-extern-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-6.c
+new file mode 100644
+index 00000000000..0c5a2d472c6
+--- /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 -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" } } */
++/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */
++/* { 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..665252327aa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+@@ -0,0 +1,43 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { 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-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+new file mode 100644
+index 00000000000..68c0ff713b3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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" } } */
++/* { 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..e2da1fcb683
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+@@ -0,0 +1,20 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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" } } */
++/* { 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..244fec708d6
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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" } } */
++/* { 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..107ebe32f54
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*_?dispatch" { 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" } } */
++/* { 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..17b04ef2229
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-5.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { 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..d9eb11285aa
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-6.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile { target *-*-linux* } } */
++/* { dg-options "-O2 -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" } } */
++/* { 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..d02b1dcb1b9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+@@ -0,0 +1,44 @@
++/* { dg-do compile } */
++/* { dg-options "-O2 -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 "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { ! x32 } } } } */
++/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { 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" } } */
+--
+2.15.1
+
diff --git a/gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch b/gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch
new file mode 100644
index 000000000..1dae0b493
--- /dev/null
+++ b/gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch
@@ -0,0 +1,308 @@
+'Retpoline' mitigation technique for Spectre (branch target injection)
+[CVE-2017-5715]:
+
+https://security.googleblog.com/2018/01/more-details-about-mitigations-for-cpu_4.html
+https://support.google.com/faqs/answer/7625886
+https://spectreattack.com/
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
+
+Patch copied from the 'retpoline-regnames' branch of upstream source repository
+(please keep an eye for new branches or updates for existing branches):
+
+http://git.infradead.org/users/dwmw2/gcc-retpoline.git
+
+From 13dce7cceef28026c4fc2e505d724526141fe4c1 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 13 Jan 2018 18:01:54 -0800
+Subject: [PATCH 08/10] x86: Disallow -mindirect-branch=/-mfunction-return=
+ with -mcmodel=large
+
+Since the thunk function may not be reachable in large code model,
+-mcmodel=large is incompatible with -mindirect-branch=thunk,
+-mindirect-branch=thunk-extern, -mfunction-return=thunk and
+-mfunction-return=thunk-extern. Issue an error when they are used with
+-mcmodel=large.
+
+gcc/
+
+ Backport from mainline
+ * config/i386/i386.c (ix86_set_indirect_branch_type): Disallow
+ -mcmodel=large with -mindirect-branch=thunk,
+ -mindirect-branch=thunk-extern, -mfunction-return=thunk and
+ -mfunction-return=thunk-extern.
+ * doc/invoke.texi: Document -mcmodel=large is incompatible with
+ -mindirect-branch=thunk, -mindirect-branch=thunk-extern,
+ -mfunction-return=thunk and -mfunction-return=thunk-extern.
+
+gcc/testsuite/
+
+ Backport from mainline
+ * gcc.target/i386/indirect-thunk-10.c: New test.
+ * gcc.target/i386/indirect-thunk-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-9.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-10.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-11.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-9.c: Likewise.
+ * gcc.target/i386/ret-thunk-17.c: Likewise.
+ * gcc.target/i386/ret-thunk-18.c: Likewise.
+ * gcc.target/i386/ret-thunk-19.c: Likewise.
+ * gcc.target/i386/ret-thunk-20.c: Likewise.
+ * gcc.target/i386/ret-thunk-21.c: Likewise.
+---
+ gcc/config/i386/i386.c | 26 ++++++++++++++++++++++
+ gcc/doc/invoke.texi | 11 +++++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-10.c | 7 ++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-8.c | 7 ++++++
+ gcc/testsuite/gcc.target/i386/indirect-thunk-9.c | 7 ++++++
+ .../gcc.target/i386/indirect-thunk-attr-10.c | 9 ++++++++
+ .../gcc.target/i386/indirect-thunk-attr-11.c | 9 ++++++++
+ .../gcc.target/i386/indirect-thunk-attr-9.c | 9 ++++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-17.c | 7 ++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-18.c | 8 +++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-19.c | 8 +++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-20.c | 9 ++++++++
+ gcc/testsuite/gcc.target/i386/ret-thunk-21.c | 9 ++++++++
+ 13 files changed, 126 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-10.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-8.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-9.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-10.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-11.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-attr-9.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-17.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-18.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-19.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-20.c
+ create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-21.c
+
+diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
+index e32de13688a..318a71840c9 100644
+--- a/gcc/config/i386/i386.c
++++ b/gcc/config/i386/i386.c
+@@ -7187,6 +7187,19 @@ ix86_set_indirect_branch_type (tree fndecl)
+ }
+ else
+ cfun->machine->indirect_branch_type = ix86_indirect_branch;
++
++ /* -mcmodel=large is not compatible with -mindirect-branch=thunk
++ nor -mindirect-branch=thunk-extern. */
++ if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
++ && ((cfun->machine->indirect_branch_type
++ == indirect_branch_thunk_extern)
++ || (cfun->machine->indirect_branch_type
++ == indirect_branch_thunk)))
++ error ("%<-mindirect-branch=%s%> and %<-mcmodel=large%> are not "
++ "compatible",
++ ((cfun->machine->indirect_branch_type
++ == indirect_branch_thunk_extern)
++ ? "thunk-extern" : "thunk"));
+ }
+
+ if (cfun->machine->function_return_type == indirect_branch_unset)
+@@ -7212,6 +7225,19 @@ ix86_set_indirect_branch_type (tree fndecl)
+ }
+ else
+ cfun->machine->function_return_type = ix86_function_return;
++
++ /* -mcmodel=large is not compatible with -mfunction-return=thunk
++ nor -mfunction-return=thunk-extern. */
++ if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
++ && ((cfun->machine->function_return_type
++ == indirect_branch_thunk_extern)
++ || (cfun->machine->function_return_type
++ == indirect_branch_thunk)))
++ error ("%<-mfunction-return=%s%> and %<-mcmodel=large%> are not "
++ "compatible",
++ ((cfun->machine->function_return_type
++ == indirect_branch_thunk_extern)
++ ? "thunk-extern" : "thunk"));
+ }
+ }
+
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 1e572b1f9a2..6f3c344476c 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -25699,6 +25699,11 @@ to external call and return thunk provided in a separate object file.
+ You can control this behavior for a specific function by using the
+ function attribute @code{indirect_branch}. @xref{Function Attributes}.
+
++Note that @option{-mcmodel=large} is incompatible with
++@option{-mindirect-branch=thunk} nor
++@option{-mindirect-branch=thunk-extern} since the thunk function may
++not be reachable in large code model.
++
+ @item -mfunction-return=@var{choice}
+ @opindex -mfunction-return
+ Convert function return with @var{choice}. The default is @samp{keep},
+@@ -25710,6 +25715,12 @@ object file. You can control this behavior for a specific function by
+ using the function attribute @code{function_return}.
+ @xref{Function Attributes}.
+
++Note that @option{-mcmodel=large} is incompatible with
++@option{-mfunction-return=thunk} nor
++@option{-mfunction-return=thunk-extern} since the thunk function may
++not be reachable in large code model.
++
++
+ @item -mindirect-branch-register
+ @opindex -mindirect-branch-register
+ Force indirect call and jump via register.
+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-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-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-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/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-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)
++{
++}
+--
+2.15.1
+
--
2.15.1
[-- Attachment #3: Type: text/plain, Size: 14 bytes --]
Cheers,
Alex
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-16 13:14 ` Alex Vong
@ 2018-01-16 14:33 ` Ludovic Courtès
2018-01-16 15:24 ` Alex Vong
0 siblings, 1 reply; 14+ messages in thread
From: Ludovic Courtès @ 2018-01-16 14:33 UTC (permalink / raw)
To: Alex Vong; +Cc: 30111
Hi Alex,
Alex Vong <alexvong1995@gmail.com> skribis:
> From aea3d11f59e260111bdb8bcac458c97a946fa900 Mon Sep 17 00:00:00 2001
> From: Alex Vong <alexvong1995@gmail.com>
> Date: Tue, 16 Jan 2018 20:32:32 +0800
> Subject: [PATCH] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
>
> This is part of Spectre (branch target injection) [CVE-2017-5715]
> mitigation. Suggested by Mark H Weaver <mhw@netris.org>.
>
> * gnu/local.mk (dist_patch_DATA): Add them.
> * gnu/packages/gcc.scm (gcc@7): Use them.
> * gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch,
> gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch,
> gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch,
> gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch,
> gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch,
> gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch,
> gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch,
> gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch,
> gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch,
> gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch:
> New files.
I’d suggest removing the test suite changes from the patches (currently
we don’t run GCC’s test suite.) Also, ‘guix lint’ may suggest using
shorter file names.
Do you know if a new 7.x including retpoline support is scheduled for
release soon?
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-16 14:33 ` Ludovic Courtès
@ 2018-01-16 15:24 ` Alex Vong
2018-01-17 13:11 ` Ludovic Courtès
0 siblings, 1 reply; 14+ messages in thread
From: Alex Vong @ 2018-01-16 15:24 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 30111
ludo@gnu.org (Ludovic Courtès) writes:
> Hi Alex,
>
> Alex Vong <alexvong1995@gmail.com> skribis:
>
>> From aea3d11f59e260111bdb8bcac458c97a946fa900 Mon Sep 17 00:00:00 2001
>> From: Alex Vong <alexvong1995@gmail.com>
>> Date: Tue, 16 Jan 2018 20:32:32 +0800
>> Subject: [PATCH] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
>>
>> This is part of Spectre (branch target injection) [CVE-2017-5715]
>> mitigation. Suggested by Mark H Weaver <mhw@netris.org>.
>>
>> * gnu/local.mk (dist_patch_DATA): Add them.
>> * gnu/packages/gcc.scm (gcc@7): Use them.
>> * gnu/packages/patches/gcc-retpoline-Change-V-to-bare-reg-names.patch,
>> gnu/packages/patches/gcc-retpoline-i386-More-use-reference-of-struct-ix86_frame-to-avoi.patch,
>> gnu/packages/patches/gcc-retpoline-i386-Move-struct-ix86_frame-to-machine_function.patch,
>> gnu/packages/patches/gcc-retpoline-i386-Use-reference-of-struct-ix86_frame-to-avoid-cop.patch,
>> gnu/packages/patches/gcc-retpoline-indirect-thunk-reg-names.patch,
>> gnu/packages/patches/gcc-retpoline-x86-Add-V-register-operand-modifier.patch,
>> gnu/packages/patches/gcc-retpoline-x86-Add-mfunction-return.patch,
>> gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch-register.patch,
>> gnu/packages/patches/gcc-retpoline-x86-Add-mindirect-branch.patch,
>> gnu/packages/patches/gcc-retpoline-x86-Disallow-mindirect-branch-mfunction-return-with-.patch:
>> New files.
>
> I’d suggest removing the test suite changes from the patches (currently
> we don’t run GCC’s test suite.) Also, ‘guix lint’ may suggest using
> shorter file names.
>
OK, no problem.
> Do you know if a new 7.x including retpoline support is scheduled for
> release soon?
>
Yes, I think they will appear in 7.3 according to [0]. Also, some
changes appear to be in gcc-7-branch already[1]. Do you think we should
wait for it instead?
[0]: https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01400.html
[1]: https://gcc.gnu.org/git/?p=gcc.git;a=shortlog;h=refs/heads/gcc-7-branch
> Thanks,
> Ludo’.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-16 15:24 ` Alex Vong
@ 2018-01-17 13:11 ` Ludovic Courtès
2018-01-17 23:31 ` Leo Famulari
0 siblings, 1 reply; 14+ messages in thread
From: Ludovic Courtès @ 2018-01-17 13:11 UTC (permalink / raw)
To: Alex Vong; +Cc: 30111
Hi Alex,
Alex Vong <alexvong1995@gmail.com> skribis:
> ludo@gnu.org (Ludovic Courtès) writes:
[...]
>> Do you know if a new 7.x including retpoline support is scheduled for
>> release soon?
>>
> Yes, I think they will appear in 7.3 according to [0]. Also, some
> changes appear to be in gcc-7-branch already[1]. Do you think we should
> wait for it instead?
Yes, perhaps we should wait for that release.
What do people think?
Ludo’.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-17 13:11 ` Ludovic Courtès
@ 2018-01-17 23:31 ` Leo Famulari
0 siblings, 0 replies; 14+ messages in thread
From: Leo Famulari @ 2018-01-17 23:31 UTC (permalink / raw)
To: Ludovic Courtès; +Cc: 30111, Alex Vong
[-- Attachment #1: Type: text/plain, Size: 703 bytes --]
On Wed, Jan 17, 2018 at 02:11:14PM +0100, Ludovic Courtès wrote:
> Hi Alex,
>
> Alex Vong <alexvong1995@gmail.com> skribis:
>
> > ludo@gnu.org (Ludovic Courtès) writes:
>
> [...]
>
> >> Do you know if a new 7.x including retpoline support is scheduled for
> >> release soon?
> >>
> > Yes, I think they will appear in 7.3 according to [0]. Also, some
> > changes appear to be in gcc-7-branch already[1]. Do you think we should
> > wait for it instead?
>
> Yes, perhaps we should wait for that release.
>
> What do people think?
It depends on whether or not the GCC team is confident in the
implementation yet. If they are still working out the kinks then I
suggest waiting.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself.
2018-01-14 13:07 [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique Alex Vong
2018-01-15 14:29 ` Alex Vong
@ 2018-01-27 3:19 ` Alex Vong
2018-02-27 9:37 ` Ludovic Courtès
2018-06-22 20:07 ` [bug#30111] gnu: gcc@7: Use retpoline options when building itself. Previous Next Gábor Boskovits
2020-12-18 23:22 ` [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique zimoun
3 siblings, 1 reply; 14+ messages in thread
From: Alex Vong @ 2018-01-27 3:19 UTC (permalink / raw)
To: 30111
[-- Attachment #1: Type: text/plain, Size: 338 bytes --]
Hello,
This patch makes gcc use retpoline options when building itself. My last
attempt to build it was successful. But after that I have changed
something, I hope it wouldn't make it fail to build. (It shouldn't,
since the options passed aren't changed.)
Are we going to add these options to other natively compiled programs as
well?
[-- Attachment #2: 0001-gnu-gcc-7-Use-retpoline-options-when-building-itself.patch --]
[-- Type: text/x-diff, Size: 3619 bytes --]
From f6b9caae6e13936be65550c871208a3425fe4ce4 Mon Sep 17 00:00:00 2001
From: Alex Vong <alexvong1995@gmail.com>
Date: Thu, 25 Jan 2018 23:24:24 +0800
Subject: [PATCH] gnu: gcc@7: Use retpoline options when building itself.
* gnu/packages/gcc.scm (gcc@7)[arguments]: Add retpoline options
to #:make-flags.
---
gnu/packages/gcc.scm | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index 48e7b8ee3..6344ce734 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -5,6 +5,7 @@
;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2015, 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
;;; Copyright © 2016 Carlos Sánchez de La Lama <csanchezdll@gmail.com>
+;;; Copyright © 2018 Alex Vong <alexvong1995@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -428,6 +429,45 @@ Go. It also includes runtime support libraries for these languages.")
"0p71bij6bfhzyrs8676a8jmpjsfz392s2rg862sdnsk30jpacb43"))
(patches (search-patches "gcc-strmov-store-file-names.patch"
"gcc-5.0-libvtv-runpath.patch"))))
+ (arguments
+ (substitute-keyword-arguments `(#:modules ((guix build gnu-build-system)
+ (guix build utils)
+ (ice-9 regex)
+ (srfi srfi-1)
+ (srfi srfi-26))
+ ,@(package-arguments gcc-6))
+ ;; Use retpoline options when building itself.
+ ((#:make-flags flags)
+ `(let* ((cross-compiling? ,(%current-target-system))
+ (system (if cross-compiling?
+ ,(%current-target-system)
+ ,(%current-system)))
+ (retpoline-opts '("-mindirect-branch=thunk"
+ "-mfunction-return=thunk"
+ "-mindirect-branch-register"))
+ (append-flag
+ (lambda (flag)
+ (if (string-match "^((BOOT_)?CFLAGS|C(XX)?FLAGS_FOR_TARGET)="
+ flag)
+ (string-join (cons flag retpoline-opts))
+ flag)))
+ (add-flag
+ (lambda (prefix flags)
+ (if (any (cut string-prefix? prefix <>) flags)
+ flags
+ (cons (string-append prefix
+ (string-join retpoline-opts))
+ flags))))
+ (add-gcc-flag (cut add-flag
+ (if cross-compiling? "CFLAGS=" "BOOT_CFLAGS=")
+ <>))
+ (add-c-lib-flag (cut add-flag "CFLAGS_FOR_TARGET=" <>))
+ (add-c++-lib-flag (cut add-flag "CXXFLAGS_FOR_TARGET=" <>)))
+ ;; Right now, the retpoline options are x86-specific.
+ (if (any (cut string-prefix? <> system) '("x86_64" "i686"))
+ (add-gcc-flag (add-c-lib-flag (add-c++-lib-flag (map append-flag
+ ,flags))))
+ ,flags)))))
(description
"GCC is the GNU Compiler Collection. It provides compiler front-ends
for several languages, including C, C++, Objective-C, Fortran, Ada, and Go.
--
2.15.1
[-- Attachment #3: Type: text/plain, Size: 14 bytes --]
Cheers,
Alex
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself.
2018-01-27 3:19 ` [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself Alex Vong
@ 2018-02-27 9:37 ` Ludovic Courtès
0 siblings, 0 replies; 14+ messages in thread
From: Ludovic Courtès @ 2018-02-27 9:37 UTC (permalink / raw)
To: Alex Vong; +Cc: 30111
Hi Alex,
Sorry for the delay.
Alex Vong <alexvong1995@gmail.com> skribis:
> This patch makes gcc use retpoline options when building itself. My last
> attempt to build it was successful. But after that I have changed
> something, I hope it wouldn't make it fail to build. (It shouldn't,
> since the options passed aren't changed.)
Any idea what upstream thinks of compiling GCC itself with these
options? Do they offer a configure flag or something to help with that?
> Are we going to add these options to other natively compiled programs as
> well?
I don’t have a good answer. Clearly we’ll want that in key packages,
but then where do we draw the line, and also how do we make sure we
don’t repeat ourselves?
Thoughts?
>>From f6b9caae6e13936be65550c871208a3425fe4ce4 Mon Sep 17 00:00:00 2001
> From: Alex Vong <alexvong1995@gmail.com>
> Date: Thu, 25 Jan 2018 23:24:24 +0800
> Subject: [PATCH] gnu: gcc@7: Use retpoline options when building itself.
>
> * gnu/packages/gcc.scm (gcc@7)[arguments]: Add retpoline options
> to #:make-flags.
[...]
> + (arguments
> + (substitute-keyword-arguments `(#:modules ((guix build gnu-build-system)
> + (guix build utils)
> + (ice-9 regex)
> + (srfi srfi-1)
> + (srfi srfi-26))
> + ,@(package-arguments gcc-6))
> + ;; Use retpoline options when building itself.
> + ((#:make-flags flags)
> + `(let* ((cross-compiling? ,(%current-target-system))
> + (system (if cross-compiling?
> + ,(%current-target-system)
> + ,(%current-system)))
> + (retpoline-opts '("-mindirect-branch=thunk"
> + "-mfunction-return=thunk"
> + "-mindirect-branch-register"))
> + (append-flag
> + (lambda (flag)
> + (if (string-match "^((BOOT_)?CFLAGS|C(XX)?FLAGS_FOR_TARGET)="
> + flag)
> + (string-join (cons flag retpoline-opts))
> + flag)))
> + (add-flag
> + (lambda (prefix flags)
> + (if (any (cut string-prefix? prefix <>) flags)
> + flags
> + (cons (string-append prefix
> + (string-join retpoline-opts))
> + flags))))
> + (add-gcc-flag (cut add-flag
> + (if cross-compiling? "CFLAGS=" "BOOT_CFLAGS=")
> + <>))
> + (add-c-lib-flag (cut add-flag "CFLAGS_FOR_TARGET=" <>))
> + (add-c++-lib-flag (cut add-flag "CXXFLAGS_FOR_TARGET=" <>)))
> + ;; Right now, the retpoline options are x86-specific.
> + (if (any (cut string-prefix? <> system) '("x86_64" "i686"))
> + (add-gcc-flag (add-c-lib-flag (add-c++-lib-flag (map append-flag
> + ,flags))))
> + ,flags)))))
I’m a bit concerned by the apparent complexity and the extra maintenance
burden it may entail. I don’t have any concrete suggestions though. I
suppose we should somehow abstract GCC compilation to make it easier to
pass new flags?
Thanks,
Ludo’.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Use retpoline options when building itself. Previous Next
2018-01-14 13:07 [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique Alex Vong
2018-01-15 14:29 ` Alex Vong
2018-01-27 3:19 ` [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself Alex Vong
@ 2018-06-22 20:07 ` Gábor Boskovits
2020-12-18 23:22 ` [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique zimoun
3 siblings, 0 replies; 14+ messages in thread
From: Gábor Boskovits @ 2018-06-22 20:07 UTC (permalink / raw)
To: 30111
[-- Attachment #1: Type: text/plain, Size: 53 bytes --]
We already have gcc 7.3, what is the status of this?
[-- Attachment #2: Type: text/html, Size: 74 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2018-01-14 13:07 [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique Alex Vong
` (2 preceding siblings ...)
2018-06-22 20:07 ` [bug#30111] gnu: gcc@7: Use retpoline options when building itself. Previous Next Gábor Boskovits
@ 2020-12-18 23:22 ` zimoun
2021-01-11 15:43 ` zimoun
3 siblings, 1 reply; 14+ messages in thread
From: zimoun @ 2020-12-18 23:22 UTC (permalink / raw)
To: Alex Vong, Ludovic Courtès, Leo Famulari,
Gábor Boskovits; +Cc: 30111
Hi,
On Sun, 14 Jan 2018 at 21:07, Alex Vong <alexvong1995@gmail.com> wrote:
> This patch adds the repoline patches (totally 17 of them) taken from the
> 'retpoline-20180107' branch at
> ``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
As asked here: <http://issues.guix.gnu.org/issue/30111#12>, since gcc
7.3 is in, and now even more recent, I am inclined to close this
submission since it appears to me no more relevant.
WDYT?
All the best,
simon
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2020-12-18 23:22 ` [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique zimoun
@ 2021-01-11 15:43 ` zimoun
2021-01-11 20:03 ` Efraim Flashner
0 siblings, 1 reply; 14+ messages in thread
From: zimoun @ 2021-01-11 15:43 UTC (permalink / raw)
To: Alex Vong; +Cc: 30111
Hi,
On Sat, 19 Dec 2020 at 00:22, zimoun <zimon.toutoune@gmail.com> wrote:
> Hi,
>
> On Sun, 14 Jan 2018 at 21:07, Alex Vong <alexvong1995@gmail.com> wrote:
>
>> This patch adds the repoline patches (totally 17 of them) taken from the
>> 'retpoline-20180107' branch at
>> ``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
>
> As asked here: <http://issues.guix.gnu.org/issue/30111#12>, since gcc
> 7.3 is in, and now even more recent, I am inclined to close this
> submission since it appears to me no more relevant.
If no objection, I will close this in the coming days.
All the best,
simon
^ permalink raw reply [flat|nested] 14+ messages in thread
* [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2021-01-11 15:43 ` zimoun
@ 2021-01-11 20:03 ` Efraim Flashner
2021-02-09 1:07 ` bug#30111: " zimoun
0 siblings, 1 reply; 14+ messages in thread
From: Efraim Flashner @ 2021-01-11 20:03 UTC (permalink / raw)
To: zimoun; +Cc: 30111, Alex Vong
[-- Attachment #1: Type: text/plain, Size: 1185 bytes --]
On Mon, Jan 11, 2021 at 04:43:41PM +0100, zimoun wrote:
> Hi,
>
> On Sat, 19 Dec 2020 at 00:22, zimoun <zimon.toutoune@gmail.com> wrote:
> > Hi,
> >
> > On Sun, 14 Jan 2018 at 21:07, Alex Vong <alexvong1995@gmail.com> wrote:
> >
> >> This patch adds the repoline patches (totally 17 of them) taken from the
> >> 'retpoline-20180107' branch at
> >> ``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
> >
> > As asked here: <http://issues.guix.gnu.org/issue/30111#12>, since gcc
> > 7.3 is in, and now even more recent, I am inclined to close this
> > submission since it appears to me no more relevant.
>
> If no objection, I will close this in the coming days.
>
I believe we're good
(ins)efraim@3900XT ~$ lscpu | grep retpoline
Vulnerability Spectre v2: Mitigation; Full AMD retpoline, IBPB conditional, STIBP conditional, RSB filling
(ins)efraim@3900XT ~$ uname -a
Linux 3900XT 5.10.6-gnu #1 SMP 1 x86_64 GNU/Linux
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* bug#30111: gnu: gcc@7: Apply the 'retpoline' mitigation technique.
2021-01-11 20:03 ` Efraim Flashner
@ 2021-02-09 1:07 ` zimoun
0 siblings, 0 replies; 14+ messages in thread
From: zimoun @ 2021-02-09 1:07 UTC (permalink / raw)
To: Efraim Flashner; +Cc: 30111-done, Alex Vong
Hi,
On Mon, 11 Jan 2021 at 22:03, Efraim Flashner <efraim@flashner.co.il> wrote:
> On Mon, Jan 11, 2021 at 04:43:41PM +0100, zimoun wrote:
>> On Sat, 19 Dec 2020 at 00:22, zimoun <zimon.toutoune@gmail.com> wrote:
>> > On Sun, 14 Jan 2018 at 21:07, Alex Vong <alexvong1995@gmail.com> wrote:
>> >
>> >> This patch adds the repoline patches (totally 17 of them) taken from the
>> >> 'retpoline-20180107' branch at
>> >> ``http://git.infradead.org/users/dwmw2/gcc-retpoline.git'' to gcc@7.
>> >
>> > As asked here: <http://issues.guix.gnu.org/issue/30111#12>, since gcc
>> > 7.3 is in, and now even more recent, I am inclined to close this
>> > submission since it appears to me no more relevant.
>>
>> If no objection, I will close this in the coming days.
>
> I believe we're good
>
> (ins)efraim@3900XT ~$ lscpu | grep retpoline
> Vulnerability Spectre v2: Mitigation; Full AMD retpoline, IBPB conditional, STIBP conditional, RSB filling
> (ins)efraim@3900XT ~$ uname -a
> Linux 3900XT 5.10.6-gnu #1 SMP 1 x86_64 GNU/Linux
Thanks Efraim. If I miss something, please reopen it.
Cheers,
simon
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2021-02-09 1:10 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-14 13:07 [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique Alex Vong
2018-01-15 14:29 ` Alex Vong
2018-01-16 13:14 ` Alex Vong
2018-01-16 14:33 ` Ludovic Courtès
2018-01-16 15:24 ` Alex Vong
2018-01-17 13:11 ` Ludovic Courtès
2018-01-17 23:31 ` Leo Famulari
2018-01-27 3:19 ` [bug#30111] [PATCH] gnu: gcc@7: Use retpoline options when building itself Alex Vong
2018-02-27 9:37 ` Ludovic Courtès
2018-06-22 20:07 ` [bug#30111] gnu: gcc@7: Use retpoline options when building itself. Previous Next Gábor Boskovits
2020-12-18 23:22 ` [bug#30111] gnu: gcc@7: Apply the 'retpoline' mitigation technique zimoun
2021-01-11 15:43 ` zimoun
2021-01-11 20:03 ` Efraim Flashner
2021-02-09 1:07 ` bug#30111: " zimoun
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.