-fcf-protection -mcet can't be used with IFUNC features, like symbol
multiversioning or target clone, since IBT/SHSTK are applied to the whole
program and they may be disabled in some functions. But -fcf-protection
is implemented with multi-byte NOPs on all 64-bit processors as well as
32-bit processors starting with Pentium Pro. If -fcf-protection requires
-mcet, IFUNC features can't be used on Linux when -fcf-protection is
enabled by default.
This patch changes -fcf-protection to to enable the NOP portion of CET
ISAs unless IBT and/or SHSTK are disabled explicitly. The rest of CET
ISAs, including intrinsics, still requires -mcet, -mibt or -mshstk.
OK for trunk?
H.J.
---
gcc/
PR target/85417
* config/i386/cet.c (file_end_indicate_exec_stack_and_cet):
Check flag_cf_protection instead of TARGET_IBT and TARGET_SHSTK.
* config/i386/i386.c (pass_insert_endbranch::gate): Don't check
TARGET_IBT.
(ix86_option_override_internal): For -fcf-protection, set
x_flag_cet to 1 if not set and also check x_flag_cet.
(ix86_trampoline_init): Don't check TARGET_IBT.
(x86_output_mi_thunk): Likewise.
(ix86_notrack_prefixed_insn_p): Likewise.
* config/i386/i386.md (rdssp<mode>): Also enable for flag_cet.
(incssp<mode>): Likewise.
(nop_endbr): Also enable for flag_cet.
* config/i386/i386.opt (flag_cet): Initialized to -1.
gcc/testsuite/
PR target/85417
* c-c++-common/attr-nocf-check-1.c: Compile with
-fcf-protection=none.
* c-c++-common/attr-nocf-check-3.c: Likewise.
* gcc.dg/march-generic.c: Likewise.
* gcc.target/i386/align-limit.c: Likewise.
* c-c++-common/fcf-protection-1.c: Remove dg-error for x86
targets.
* c-c++-common/fcf-protection-2.c: Likewise.
* c-c++-common/fcf-protection-3.c: Likewise.
* c-c++-common/fcf-protection-5.c: Likewise.
* c-c++-common/fcf-protection-6.c: Remove dg-additional-options
and dg-error for x86 targets.
* c-c++-common/fcf-protection-7.c: Likewise.
* gcc.target/i386/cet-notrack-icf-1.c: Compile with
-fcf-protection=none -mno-cet.
* gcc.target/i386/cet-notrack-icf-3.c: Likewise.
* gcc.target/i386/cet-property-2.c: Compile with
-fcf-protection=none.
* gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
* gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
* gcc.target/i386/ret-thunk-26.c: Likewise.
* gcc.target/i386/cet-label-3.c: New test.
* gcc.target/i386/cet-property-3.c: Likewise.
* gcc.target/i386/cet-sjlj-7.c: Likewise.
* gcc.target/i386/pr85417-1.c: Likewise.
* gcc.target/i386/pr85417-2.c: Likewise.
---
gcc/config/i386/cet.c | 4 +-
gcc/config/i386/i386.c | 23 +++++++----
gcc/config/i386/i386.md | 6 +--
gcc/config/i386/i386.opt | 2 +-
gcc/testsuite/c-c++-common/attr-nocf-check-1.c | 1 +
gcc/testsuite/c-c++-common/attr-nocf-check-3.c | 1 +
gcc/testsuite/c-c++-common/fcf-protection-1.c | 1 -
gcc/testsuite/c-c++-common/fcf-protection-2.c | 1 -
gcc/testsuite/c-c++-common/fcf-protection-3.c | 1 -
gcc/testsuite/c-c++-common/fcf-protection-5.c | 1 -
gcc/testsuite/c-c++-common/fcf-protection-6.c | 3 +-
gcc/testsuite/c-c++-common/fcf-protection-7.c | 3 +-
gcc/testsuite/gcc.dg/march-generic.c | 2 +-
gcc/testsuite/gcc.target/i386/align-limit.c | 2 +-
gcc/testsuite/gcc.target/i386/cet-label-3.c | 16 ++++++++
gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c | 2 +-
gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c | 2 +-
gcc/testsuite/gcc.target/i386/cet-property-2.c | 2 +-
gcc/testsuite/gcc.target/i386/cet-property-3.c | 11 +++++
gcc/testsuite/gcc.target/i386/cet-sjlj-7.c | 48 ++++++++++++++++++++++
.../gcc.target/i386/indirect-thunk-attr-7.c | 2 +-
.../gcc.target/i386/indirect-thunk-extern-7.c | 2 +-
gcc/testsuite/gcc.target/i386/pr85417-1.c | 4 ++
gcc/testsuite/gcc.target/i386/pr85417-2.c | 17 ++++++++
gcc/testsuite/gcc.target/i386/ret-thunk-26.c | 2 +-
25 files changed, 129 insertions(+), 30 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/i386/cet-label-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/cet-property-3.c
create mode 100644 gcc/testsuite/gcc.target/i386/cet-sjlj-7.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr85417-1.c
create mode 100644 gcc/testsuite/gcc.target/i386/pr85417-2.c
diff --git a/gcc/config/i386/cet.c b/gcc/config/i386/cet.c
index 4a1e013fdde..eb3be171471 100644
--- a/gcc/config/i386/cet.c
+++ b/gcc/config/i386/cet.c
@@ -34,11 +34,11 @@ file_end_indicate_exec_stack_and_cet (void)
unsigned int feature_1 = 0;
- if (TARGET_IBT)
+ if (flag_cf_protection & CF_BRANCH)
/* GNU_PROPERTY_X86_FEATURE_1_IBT. */
feature_1 |= 0x1;
- if (TARGET_SHSTK)
+ if (flag_cf_protection & CF_RETURN)
/* GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
feature_1 |= 0x2;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 9074526b8a1..5e96e19a0fb 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2701,7 +2701,7 @@ public:
/* opt_pass methods: */
virtual bool gate (function *)
{
- return ((flag_cf_protection & CF_BRANCH) && TARGET_IBT);
+ return ((flag_cf_protection & CF_BRANCH));
}
virtual unsigned int execute (function *)
@@ -4936,10 +4936,15 @@ ix86_option_override_internal (bool main_args_p,
= (cf_protection_level) (opts->x_flag_cf_protection & ~CF_SET);
if (cf_protection != CF_NONE)
{
+ /* Since -fcf-protection is implemented with multi-byte NOPs on
+ all 64-bit processors as well as 32-bit processors starting
+ with Pentium Pro, allow -fcf-protection to enable the NOP
+ portion of CET unless CET is disabled explicitly. */
switch (cf_protection)
{
case CF_BRANCH:
- if (! TARGET_IBT_P (opts->x_ix86_isa_flags2))
+ if (!TARGET_IBT_P (opts->x_ix86_isa_flags2)
+ && opts->x_flag_cet >= 0)
{
error ("%<-fcf-protection=branch%> requires Intel CET "
"support. Use -mcet or -mibt option to enable CET");
@@ -4948,7 +4953,8 @@ ix86_option_override_internal (bool main_args_p,
}
break;
case CF_RETURN:
- if (! TARGET_SHSTK_P (opts->x_ix86_isa_flags))
+ if (!TARGET_SHSTK_P (opts->x_ix86_isa_flags)
+ && opts->x_flag_cet >= 0)
{
error ("%<-fcf-protection=return%> requires Intel CET "
"support. Use -mcet or -mshstk option to enable CET");
@@ -4957,8 +4963,9 @@ ix86_option_override_internal (bool main_args_p,
}
break;
case CF_FULL:
- if ( ! TARGET_IBT_P (opts->x_ix86_isa_flags2)
- || ! TARGET_SHSTK_P (opts->x_ix86_isa_flags))
+ if ((!TARGET_IBT_P (opts->x_ix86_isa_flags2)
+ || !TARGET_SHSTK_P (opts->x_ix86_isa_flags))
+ && opts->x_flag_cet >= 0)
{
error ("%<-fcf-protection=full%> requires Intel CET "
"support. Use -mcet or both of -mibt and "
@@ -30399,7 +30406,7 @@ ix86_trampoline_init (rtx m_tramp, tree fndecl, rtx
chain_value)
rtx mem, fnaddr;
int opcode;
int offset = 0;
- bool need_endbr = (flag_cf_protection & CF_BRANCH) && TARGET_IBT;
+ bool need_endbr = (flag_cf_protection & CF_BRANCH);
fnaddr = XEXP (DECL_RTL (fndecl), 0);
@@ -41757,7 +41764,7 @@ x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT
delta,
emit_note (NOTE_INSN_PROLOGUE_END);
/* CET is enabled, insert EB instruction. */
- if ((flag_cf_protection & CF_BRANCH) && TARGET_IBT)
+ if ((flag_cf_protection & CF_BRANCH))
emit_insn (gen_nop_endbr ());
/* If VCALL_OFFSET, we'll need THIS in a register. Might as well
@@ -49757,7 +49764,7 @@ ix86_bnd_prefixed_insn_p (rtx insn)
static bool
ix86_notrack_prefixed_insn_p (rtx insn)
{
- if (!insn || !((flag_cf_protection & CF_BRANCH) && TARGET_IBT))
+ if (!insn || !((flag_cf_protection & CF_BRANCH)))
return false;
if (CALL_P (insn))
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 352212094ec..b7bd71dc3ec 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -20278,7 +20278,7 @@
(define_insn "rdssp<mode>"
[(set (match_operand:SWI48x 0 "register_operand" "=r")
(unspec_volatile:SWI48x [(const_int 0)] UNSPECV_NOP_RDSSP))]
- "TARGET_SHSTK"
+ "TARGET_SHSTK || flag_cet"
"xor{l}\t%k0, %k0\n\trdssp<mskmodesuffix>\t%0"
[(set_attr "length" "6")
(set_attr "type" "other")])
@@ -20286,7 +20286,7 @@
(define_insn "incssp<mode>"
[(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
UNSPECV_INCSSP)]
- "TARGET_SHSTK"
+ "TARGET_SHSTK || flag_cet"
"incssp<mskmodesuffix>\t%0"
[(set_attr "length" "4")
(set_attr "type" "other")])
@@ -20341,7 +20341,7 @@
(define_insn "nop_endbr"
[(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
- "TARGET_IBT"
+ "TARGET_IBT || flag_cet"
"*
{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
[(set_attr "length" "4")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index c063ae8b1ae..dea8551bf7f 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1007,7 +1007,7 @@ Target Report RejectNegative Mask(GENERAL_REGS_ONLY)
Var(ix86_target_flags) Save
Generate code which uses only the general registers.
mcet
-Target Report Var(flag_cet) Init(0)
+Target Report Var(flag_cet) Init(-1)
Support Control-flow Enforcement Technology (CET) built-in functions
and code generation.
diff --git a/gcc/testsuite/c-c++-common/attr-nocf-check-1.c
b/gcc/testsuite/c-c++-common/attr-nocf-check-1.c
index 15f69731b91..c5ac7cb9f86 100644
--- a/gcc/testsuite/c-c++-common/attr-nocf-check-1.c
+++ b/gcc/testsuite/c-c++-common/attr-nocf-check-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-fcf-protection=none" } */
int func (int) __attribute__ ((nocf_check)); /* { dg-warning "'nocf_check'
attribute ignored" } */
int (*fptr) (int) __attribute__ ((nocf_check)); /* { dg-warning "'nocf_check'
attribute ignored" } */
diff --git a/gcc/testsuite/c-c++-common/attr-nocf-check-3.c
b/gcc/testsuite/c-c++-common/attr-nocf-check-3.c
index ad1ca7eec9b..02b56cb155e 100644
--- a/gcc/testsuite/c-c++-common/attr-nocf-check-3.c
+++ b/gcc/testsuite/c-c++-common/attr-nocf-check-3.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-additional-options "-fcf-protection=none" } */
int foo (void) __attribute__ ((nocf_check)); /* { dg-warning "'nocf_check'
attribute ignored" } */
void (*foo1) (void) __attribute__((nocf_check)); /* { dg-warning "'nocf_check'
attribute ignored" } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-1.c
b/gcc/testsuite/c-c++-common/fcf-protection-1.c
index 8e71f47dde0..f59a8fbdfdc 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-1.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-1.c
@@ -1,4 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection=full" } */
-/* { dg-error "'-fcf-protection=full' requires Intel CET.*-mcet.*-mibt and
-mshstk option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
/* { dg-error "'-fcf-protection=full' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-2.c
b/gcc/testsuite/c-c++-common/fcf-protection-2.c
index d7d6db0e95d..61059725af6 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-2.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-2.c
@@ -1,4 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection=branch" } */
-/* { dg-error "'-fcf-protection=branch' requires Intel CET.*-mcet or -mibt
option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
/* { dg-error "'-fcf-protection=branch' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-3.c
b/gcc/testsuite/c-c++-common/fcf-protection-3.c
index 5b903c5fa51..257e944c4a6 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-3.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-3.c
@@ -1,4 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection=return" } */
-/* { dg-error "'-fcf-protection=return' requires Intel CET.*-mcet or -mshstk
option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
/* { dg-error "'-fcf-protection=return' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-5.c
b/gcc/testsuite/c-c++-common/fcf-protection-5.c
index d7a67801e2e..dc317f84b07 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-5.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-5.c
@@ -1,4 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection" } */
-/* { dg-error "'-fcf-protection=full' requires Intel CET.*-mcet.*-mibt and
-mshstk option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
/* { dg-error "'-fcf-protection=full' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-6.c
b/gcc/testsuite/c-c++-common/fcf-protection-6.c
index 532e76e6915..a1e919a2f63 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-6.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-6.c
@@ -1,5 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection=branch" } */
-/* { dg-additional-options "-mshstk" { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-error "'-fcf-protection=branch' requires Intel CET.*-mcet or -mibt
option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
+/* { dg-additional-options "-mshstk -mno-ibt" { target { i?86-*-* x86_64-*-* }
} } */
/* { dg-error "'-fcf-protection=branch' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/c-c++-common/fcf-protection-7.c
b/gcc/testsuite/c-c++-common/fcf-protection-7.c
index 4c879692708..9e89becdaad 100644
--- a/gcc/testsuite/c-c++-common/fcf-protection-7.c
+++ b/gcc/testsuite/c-c++-common/fcf-protection-7.c
@@ -1,5 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-fcf-protection=return" } */
-/* { dg-additional-options "-mibt" { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-error "'-fcf-protection=return' requires Intel CET.*-mcet or -mshstk
option" "" { target { "i?86-*-* x86_64-*-*" } } 0 } */
+/* { dg-additional-options "-mibt -mno-shstk" { target { i?86-*-* x86_64-*-* }
} } */
/* { dg-error "'-fcf-protection=return' is not supported for this target" "" {
target { ! "i?86-*-* x86_64-*-*" } } 0 } */
diff --git a/gcc/testsuite/gcc.dg/march-generic.c
b/gcc/testsuite/gcc.dg/march-generic.c
index fb5b83c7d74..f9c00e4a1c1 100644
--- a/gcc/testsuite/gcc.dg/march-generic.c
+++ b/gcc/testsuite/gcc.dg/march-generic.c
@@ -1,6 +1,6 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-skip-if "" { *-*-* } { "-march=*" } { "" } } */
-/* { dg-options "-march=generic" } */
+/* { dg-options "-march=generic -fcf-protection=none" } */
/* { dg-error "'generic' CPU can be used only for '-mtune=' switch" "" {
target *-*-* } 0 } */
/* { dg-bogus "march" "" { target *-*-* } 0 } */
int i;
diff --git a/gcc/testsuite/gcc.target/i386/align-limit.c
b/gcc/testsuite/gcc.target/i386/align-limit.c
index d3d8dc5656e..849d741189c 100644
--- a/gcc/testsuite/gcc.target/i386/align-limit.c
+++ b/gcc/testsuite/gcc.target/i386/align-limit.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -falign-functions=64 -flimit-function-alignment
-march=amdfam10" } */
+/* { dg-options "-O2 -falign-functions=64 -flimit-function-alignment
-march=amdfam10 -fcf-protection=none" } */
/* { dg-final { scan-assembler ".p2align 6,,1" } } */
/* { dg-final { scan-assembler-not ".p2align 6,,63" } } */
diff --git a/gcc/testsuite/gcc.target/i386/cet-label-3.c
b/gcc/testsuite/gcc.target/i386/cet-label-3.c
new file mode 100644
index 00000000000..ae3ea632a27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-label-3.c
@@ -0,0 +1,16 @@
+/* Verify that CET works. */
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection" } */
+/* { dg-final { scan-assembler-times "endbr32" 3 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 3 { target { ! ia32 } } } } */
+
+int func (int arg)
+{
+ static void *array[] = { &&foo, &&bar };
+
+ goto *array[arg];
+foo:
+ return arg*111;
+bar:
+ return arg*777;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
index 7987d53d305..00a3f3e5d5f 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
@@ -1,6 +1,6 @@
/* Verify nocf_check functions are not ICF optimized. */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fcf-protection=none -mno-cet" } */
/* { dg-final { scan-assembler-not "endbr" } } */
/* { dg-final { scan-assembler-not "fn3:" } } */
/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" } } */
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
index 07c4a6b61ef..c8b26f947d3 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
@@ -1,6 +1,6 @@
/* Verify nocf_check function calls are not ICF optimized. */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fcf-protection=none -mno-cet" } */
/* { dg-final { scan-assembler-not "endbr" } } */
/* { dg-final { scan-assembler-not "fn2:" } } */
/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" } } */
diff --git a/gcc/testsuite/gcc.target/i386/cet-property-2.c
b/gcc/testsuite/gcc.target/i386/cet-property-2.c
index 5a87dab92f1..bca6f6cdeb7 100644
--- a/gcc/testsuite/gcc.target/i386/cet-property-2.c
+++ b/gcc/testsuite/gcc.target/i386/cet-property-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcet" } */
+/* { dg-options "-mcet -fcf-protection=none" } */
/* { dg-final { scan-assembler-not ".note.gnu.property" } } */
extern void foo (void);
diff --git a/gcc/testsuite/gcc.target/i386/cet-property-3.c
b/gcc/testsuite/gcc.target/i386/cet-property-3.c
new file mode 100644
index 00000000000..3e211c970aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-property-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-fcf-protection" } */
+/* { dg-final { scan-assembler ".note.gnu.property" } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-7.c
b/gcc/testsuite/gcc.target/i386/cet-sjlj-7.c
new file mode 100644
index 00000000000..1b624327d0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-7.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fcf-protection" } */
+/* { dg-final { scan-assembler-times "endbr32" 2 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 2 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "call _?setjmp" 1 } } */
+/* { dg-final { scan-assembler-times "call longjmp" 1 } } */
+
+#include <stdio.h>
+#include <setjmp.h>
+
+jmp_buf buf;
+static int bar (int);
+
+__attribute__ ((noinline, noclone))
+static int
+foo (int i)
+{
+ int j = i * 11;
+
+ if (!setjmp (buf))
+ {
+ j += 33;
+ printf ("After setjmp: j = %d\n", j);
+ bar (j);
+ }
+
+ return j + i;
+}
+
+__attribute__ ((noinline, noclone))
+static int
+bar (int i)
+{
+ int j = i;
+
+ j -= 111;
+ printf ("In longjmp: j = %d\n", j);
+ longjmp (buf, 1);
+
+ return j;
+}
+
+int
+main ()
+{
+ foo (10);
+ return 0;
+}
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 d53fc887dcc..5c120519ad9 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 -mno-indirect-branch-register -mfunction-return=keep
-fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep
-fno-pic -fcf-protection=none" } */
void func0 (void);
void func1 (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 2b9a33e93dc..74af6198bf4 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 -mno-indirect-branch-register -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 -fcf-protection=none" } */
void func0 (void);
void func1 (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr85417-1.c
b/gcc/testsuite/gcc.target/i386/pr85417-1.c
new file mode 100644
index 00000000000..ee345961b73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85417-1.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-march=native -fcf-protection" } */
+
+int foo;
diff --git a/gcc/testsuite/gcc.target/i386/pr85417-2.c
b/gcc/testsuite/gcc.target/i386/pr85417-2.c
new file mode 100644
index 00000000000..17d52403744
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr85417-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O3 -fcf-protection" } */
+/* { dg-final { scan-assembler "vpshufb" } } */
+/* { dg-final { scan-assembler "punpcklbw" } } */
+
+__attribute__((target_clones("arch=core-avx2","arch=slm","default")))
+void
+foo(char *in, char *out, int size)
+{
+ int i;
+ for(i = 0; i < size; i++)
+ {
+ out[2 * i] = in[i];
+ out[2 * i + 1] = in[i];
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
index 9144e988735..dc722c2f5f9 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
@@ -1,6 +1,6 @@
/* PR target/r84530 */
/* { dg-do run } */
-/* { dg-options "-Os -mfunction-return=thunk" } */
+/* { dg-options "-Os -mfunction-return=thunk -fcf-protection=none" } */
struct S { int i; };
__attribute__((const, noinline, noclone))
--
2.14.3