public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
@ 2017-09-18  9:58 Uros Bizjak
  2017-09-19 15:05 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
  2017-11-06 10:33 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
  0 siblings, 2 replies; 6+ messages in thread
From: Uros Bizjak @ 2017-09-18  9:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tsimbalist, Igor V

Hello!

> gcc/
>
> * common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
> (OPTION_MASK_ISA_SHSTK_SET): Likewise.
> (OPTION_MASK_ISA_IBT_UNSET): Likewise.
> (OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
> (ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
> * config.gcc (extra_headers): Add cetintrin.h for x86 targets.
> (extra_objs): Add cet.o for Linux/x86 targets.
> (tmake_file): Add i386/t-cet for Linux/x86 targets.
> * config/i386/cet.c: New file.
> * config/i386/cetintrin.h: Likewise.
> * config/i386/t-cet: Likewise.
> * config/i386/cpuid.h (bit_SHSTK): New.
> (bit_IBT): Likewise.
> * config/i386/driver-i386.c (host_detect_local_cpu): Detect and
> pass IBT and SHSTK bits.
> * config/i386/i386-builtin-types.def
> (VOID_FTYPE_UNSIGNED_PVOID): New.
> (VOID_FTYPE_UINT64_PVOID): Likewise.
> * config/i386/i386-builtin.def: Add CET intrinsics.
> * config/i386/i386-c.c (ix86_target_macros_internal): Add
> OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
> * config/i386/i386-passes.def: Add pass_insert_endbranch pass.
> * config/i386/i386-protos.h (make_pass_insert_endbranch): New
> prototype.
> * config/i386/i386.c (rest_of_insert_endbranch): New.
> (pass_data_insert_endbranch): Likewise.
> (pass_insert_endbranch): Likewise.
> (make_pass_insert_endbranch): Likewise.
> (ix86_notrack_prefixed_insn_p): Likewise.
> (ix86_target_string): Add -mibt, -mshstk flags.
> (ix86_option_override_internal): Add flag_instrument_control_flow
> processing.
> (ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
> (ix86_print_operand): Add 'notrack' prefix output.
> (ix86_init_mmx_sse_builtins): Add CET intrinsics.
> (ix86_expand_builtin): Expand CET intrinsics.
> (x86_output_mi_thunk): Add 'endbranch' instruction.
> * config/i386/i386.h (TARGET_IBT): New.
> (TARGET_IBT_P): Likewise.
> (TARGET_SHSTK): Likewise.
> (TARGET_SHSTK_P): Likewise.
> * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
> UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
> UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
> (builtin_setjmp_setup): New pattern.
> (builtin_longjmp): Likewise.
> (rdssp<mode>): Likewise.
> (incssp<mode>): Likewise.
> (saveprevssp): Likewise.
> (rstorssp): Likewise.
> (wrss<mode>): Likewise.
> (wruss<mode>): Likewise.
> (setssbsy): Likewise.
> (clrssbsy): Likewise.
> (nop_endbr): Likewise.
> * config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
> options.
> * config/i386/immintrin.h: Include <cetintrin.h>.
> * config/i386/linux-common.h
> (file_end_indicate_exec_stack_and_cet): New prototype.
> (TARGET_ASM_FILE_END): New.

LGTM.

OK for mainline.

Thanks,
Uros.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
  2017-09-18  9:58 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
@ 2017-09-19 15:05 ` Tsimbalist, Igor V
  2017-10-12 18:50   ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
  2017-11-06 10:33 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
  1 sibling, 1 reply; 6+ messages in thread
From: Tsimbalist, Igor V @ 2017-09-19 15:05 UTC (permalink / raw)
  To: Uros Bizjak, gcc-patches; +Cc: Tsimbalist, Igor V

Uros, thank you for the approval. Based on the approval of the first 3 patches (I've submitted them today), I need to adjust option and attribute names. I will resubmit the patch when I fix option and attribute names.

Thanks,
Igor


> -----Original Message-----
> From: Uros Bizjak [mailto:ubizjak@gmail.com]
> Sent: Monday, September 18, 2017 11:58 AM
> To: gcc-patches@gcc.gnu.org
> Cc: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>; Tsimbalist, Igor V
> <igor.v.tsimbalist@intel.com>
> Subject: Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
> 
> Hello!
> 
> > gcc/
> >
> > * common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET):
> New.
> > (OPTION_MASK_ISA_SHSTK_SET): Likewise.
> > (OPTION_MASK_ISA_IBT_UNSET): Likewise.
> > (OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
> > (ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
> > * config.gcc (extra_headers): Add cetintrin.h for x86 targets.
> > (extra_objs): Add cet.o for Linux/x86 targets.
> > (tmake_file): Add i386/t-cet for Linux/x86 targets.
> > * config/i386/cet.c: New file.
> > * config/i386/cetintrin.h: Likewise.
> > * config/i386/t-cet: Likewise.
> > * config/i386/cpuid.h (bit_SHSTK): New.
> > (bit_IBT): Likewise.
> > * config/i386/driver-i386.c (host_detect_local_cpu): Detect and pass
> > IBT and SHSTK bits.
> > * config/i386/i386-builtin-types.def
> > (VOID_FTYPE_UNSIGNED_PVOID): New.
> > (VOID_FTYPE_UINT64_PVOID): Likewise.
> > * config/i386/i386-builtin.def: Add CET intrinsics.
> > * config/i386/i386-c.c (ix86_target_macros_internal): Add
> > OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
> > * config/i386/i386-passes.def: Add pass_insert_endbranch pass.
> > * config/i386/i386-protos.h (make_pass_insert_endbranch): New
> > prototype.
> > * config/i386/i386.c (rest_of_insert_endbranch): New.
> > (pass_data_insert_endbranch): Likewise.
> > (pass_insert_endbranch): Likewise.
> > (make_pass_insert_endbranch): Likewise.
> > (ix86_notrack_prefixed_insn_p): Likewise.
> > (ix86_target_string): Add -mibt, -mshstk flags.
> > (ix86_option_override_internal): Add flag_instrument_control_flow
> > processing.
> > (ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
> > (ix86_print_operand): Add 'notrack' prefix output.
> > (ix86_init_mmx_sse_builtins): Add CET intrinsics.
> > (ix86_expand_builtin): Expand CET intrinsics.
> > (x86_output_mi_thunk): Add 'endbranch' instruction.
> > * config/i386/i386.h (TARGET_IBT): New.
> > (TARGET_IBT_P): Likewise.
> > (TARGET_SHSTK): Likewise.
> > (TARGET_SHSTK_P): Likewise.
> > * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
> > UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
> UNSPECV_WRSS,
> > UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
> > (builtin_setjmp_setup): New pattern.
> > (builtin_longjmp): Likewise.
> > (rdssp<mode>): Likewise.
> > (incssp<mode>): Likewise.
> > (saveprevssp): Likewise.
> > (rstorssp): Likewise.
> > (wrss<mode>): Likewise.
> > (wruss<mode>): Likewise.
> > (setssbsy): Likewise.
> > (clrssbsy): Likewise.
> > (nop_endbr): Likewise.
> > * config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
> > options.
> > * config/i386/immintrin.h: Include <cetintrin.h>.
> > * config/i386/linux-common.h
> > (file_end_indicate_exec_stack_and_cet): New prototype.
> > (TARGET_ASM_FILE_END): New.
> 
> LGTM.
> 
> OK for mainline.
> 
> Thanks,
> Uros.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
  2017-09-19 15:05 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
@ 2017-10-12 18:50   ` Tsimbalist, Igor V
  2017-10-13  7:03     ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
  0 siblings, 1 reply; 6+ messages in thread
From: Tsimbalist, Igor V @ 2017-10-12 18:50 UTC (permalink / raw)
  To: Uros Bizjak, gcc-patches; +Cc: Tsimbalist, Igor V

[-- Attachment #1: Type: text/plain, Size: 4066 bytes --]

Uros,

Attached is an updated patch. The main difference is in option name and attribute name change. Other code is the same.

Igor


> -----Original Message-----
> From: Tsimbalist, Igor V
> Sent: Tuesday, September 19, 2017 5:06 PM
> To: Uros Bizjak <ubizjak@gmail.com>; gcc-patches@gcc.gnu.org
> Cc: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>
> Subject: RE: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
> 
> Uros, thank you for the approval. Based on the approval of the first 3 patches
> (I've submitted them today), I need to adjust option and attribute names. I
> will resubmit the patch when I fix option and attribute names.
> 
> Thanks,
> Igor
> 
> 
> > -----Original Message-----
> > From: Uros Bizjak [mailto:ubizjak@gmail.com]
> > Sent: Monday, September 18, 2017 11:58 AM
> > To: gcc-patches@gcc.gnu.org
> > Cc: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>; Tsimbalist, Igor
> > V <igor.v.tsimbalist@intel.com>
> > Subject: Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
> >
> > Hello!
> >
> > > gcc/
> > >
> > > * common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET):
> > New.
> > > (OPTION_MASK_ISA_SHSTK_SET): Likewise.
> > > (OPTION_MASK_ISA_IBT_UNSET): Likewise.
> > > (OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
> > > (ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
> > > * config.gcc (extra_headers): Add cetintrin.h for x86 targets.
> > > (extra_objs): Add cet.o for Linux/x86 targets.
> > > (tmake_file): Add i386/t-cet for Linux/x86 targets.
> > > * config/i386/cet.c: New file.
> > > * config/i386/cetintrin.h: Likewise.
> > > * config/i386/t-cet: Likewise.
> > > * config/i386/cpuid.h (bit_SHSTK): New.
> > > (bit_IBT): Likewise.
> > > * config/i386/driver-i386.c (host_detect_local_cpu): Detect and pass
> > > IBT and SHSTK bits.
> > > * config/i386/i386-builtin-types.def
> > > (VOID_FTYPE_UNSIGNED_PVOID): New.
> > > (VOID_FTYPE_UINT64_PVOID): Likewise.
> > > * config/i386/i386-builtin.def: Add CET intrinsics.
> > > * config/i386/i386-c.c (ix86_target_macros_internal): Add
> > > OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
> > > * config/i386/i386-passes.def: Add pass_insert_endbranch pass.
> > > * config/i386/i386-protos.h (make_pass_insert_endbranch): New
> > > prototype.
> > > * config/i386/i386.c (rest_of_insert_endbranch): New.
> > > (pass_data_insert_endbranch): Likewise.
> > > (pass_insert_endbranch): Likewise.
> > > (make_pass_insert_endbranch): Likewise.
> > > (ix86_notrack_prefixed_insn_p): Likewise.
> > > (ix86_target_string): Add -mibt, -mshstk flags.
> > > (ix86_option_override_internal): Add flag_instrument_control_flow
> > > processing.
> > > (ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
> > > (ix86_print_operand): Add 'notrack' prefix output.
> > > (ix86_init_mmx_sse_builtins): Add CET intrinsics.
> > > (ix86_expand_builtin): Expand CET intrinsics.
> > > (x86_output_mi_thunk): Add 'endbranch' instruction.
> > > * config/i386/i386.h (TARGET_IBT): New.
> > > (TARGET_IBT_P): Likewise.
> > > (TARGET_SHSTK): Likewise.
> > > (TARGET_SHSTK_P): Likewise.
> > > * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
> > > UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
> > UNSPECV_WRSS,
> > > UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
> > > (builtin_setjmp_setup): New pattern.
> > > (builtin_longjmp): Likewise.
> > > (rdssp<mode>): Likewise.
> > > (incssp<mode>): Likewise.
> > > (saveprevssp): Likewise.
> > > (rstorssp): Likewise.
> > > (wrss<mode>): Likewise.
> > > (wruss<mode>): Likewise.
> > > (setssbsy): Likewise.
> > > (clrssbsy): Likewise.
> > > (nop_endbr): Likewise.
> > > * config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
> > > options.
> > > * config/i386/immintrin.h: Include <cetintrin.h>.
> > > * config/i386/linux-common.h
> > > (file_end_indicate_exec_stack_and_cet): New prototype.
> > > (TARGET_ASM_FILE_END): New.
> >
> > LGTM.
> >
> > OK for mainline.
> >
> > Thanks,
> > Uros.

[-- Attachment #2: 0004-Update-x86-backend-to-enable-Intel-CET.PATCH --]
[-- Type: application/octet-stream, Size: 44708 bytes --]

From 344afba569ebf22be91f6bddb08ac99f861f5e2b Mon Sep 17 00:00:00 2001
From: Igor Tsimbalist <igor.v.tsimbalist@intel.com>
Date: Tue, 4 Jul 2017 13:54:08 +0300
Subject: [PATCH 4/6] Update x86 backend to enable Intel CET.

All platforms except i386 will report the error and do no
instrumentation with -finstrument-control-flow option. i386
will provide the implementation based on a specification
published by Intel for a new technology called Control-flow
Enforcement Technology (CET). The spec is available at

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

The implementation in this patch:
1) enables Control-flow Enforcement Technology (CET), published by
Intel. This part introduces i386 specific options -mcet, -mibt and
-mshstk, new instructions and intrinsics;

2) provides support for -fcf-protection option and 'nocf_check'
attribute by doing needed code instrumentation, which is based on
CET features.

gcc/

	* common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
	(OPTION_MASK_ISA_SHSTK_SET): Likewise.
	(OPTION_MASK_ISA_IBT_UNSET): Likewise.
	(OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
	(ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
	* config.gcc (extra_headers): Add cetintrin.h for x86 targets.
	(extra_objs): Add cet.o for Linux/x86 targets.
	(tmake_file): Add i386/t-cet for Linux/x86 targets.
	* config/i386/cet.c: New file.
	* config/i386/cetintrin.h: Likewise.
	* config/i386/t-cet: Likewise.
	* config/i386/cpuid.h (bit_SHSTK): New.
	(bit_IBT): Likewise.
	* config/i386/driver-i386.c (host_detect_local_cpu): Detect and
	pass IBT and SHSTK bits.
	* config/i386/i386-builtin-types.def
	(VOID_FTYPE_UNSIGNED_PVOID): New.
	(VOID_FTYPE_UINT64_PVOID): Likewise.
	* config/i386/i386-builtin.def: Add CET intrinsics.
	* config/i386/i386-c.c (ix86_target_macros_internal): Add
	OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
	* config/i386/i386-passes.def: Add pass_insert_endbranch pass.
	* config/i386/i386-protos.h (make_pass_insert_endbranch): New
	prototype.
	* config/i386/i386.c (rest_of_insert_endbranch): New.
	(pass_data_insert_endbranch): Likewise.
	(pass_insert_endbranch): Likewise.
	(make_pass_insert_endbranch): Likewise.
	(ix86_notrack_prefixed_insn_p): Likewise.
	(ix86_target_string): Add -mibt, -mshstk flags.
	(ix86_option_override_internal): Add flag_cf_protection
	processing.
	(ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
	(ix86_print_operand): Add 'notrack' prefix output.
	(ix86_init_mmx_sse_builtins): Add CET intrinsics.
	(ix86_expand_builtin): Expand CET intrinsics.
	(x86_output_mi_thunk): Add 'endbranch' instruction.
	* config/i386/i386.h (TARGET_IBT): New.
	(TARGET_IBT_P): Likewise.
	(TARGET_SHSTK): Likewise.
	(TARGET_SHSTK_P): Likewise.
   	* config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
	UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
	UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
	(builtin_setjmp_setup): New pattern.
	(builtin_longjmp): Likewise.
	(rdssp<mode>): Likewise.
	(incssp<mode>): Likewise.
	(saveprevssp): Likewise.
	(rstorssp): Likewise.
	(wrss<mode>): Likewise.
	(wruss<mode>): Likewise.
	(setssbsy): Likewise.
	(clrssbsy): Likewise.
	(nop_endbr): Likewise.
	* config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
	options.
	* config/i386/immintrin.h: Include <cetintrin.h>.
	* config/i386/linux-common.h
	(file_end_indicate_exec_stack_and_cet): New prototype.
	(TARGET_ASM_FILE_END): New.
---
 gcc/common/config/i386/i386-common.c   |  33 ++++
 gcc/config.gcc                         |   7 +-
 gcc/config/i386/cet.c                  |  76 ++++++++
 gcc/config/i386/cetintrin.h            | 134 +++++++++++++
 gcc/config/i386/cpuid.h                |   2 +
 gcc/config/i386/driver-i386.c          |   8 +-
 gcc/config/i386/i386-builtin-types.def |   2 +
 gcc/config/i386/i386-builtin.def       |  23 ++-
 gcc/config/i386/i386-c.c               |  12 ++
 gcc/config/i386/i386-passes.def        |   2 +
 gcc/config/i386/i386-protos.h          |   1 +
 gcc/config/i386/i386.c                 | 330 ++++++++++++++++++++++++++++++++-
 gcc/config/i386/i386.h                 |   4 +
 gcc/config/i386/i386.md                | 189 ++++++++++++++++++-
 gcc/config/i386/i386.opt               |  20 ++
 gcc/config/i386/immintrin.h            |   2 +
 gcc/config/i386/linux-common.h         |   5 +
 gcc/config/i386/t-cet                  |  21 +++
 18 files changed, 863 insertions(+), 8 deletions(-)
 create mode 100644 gcc/config/i386/cet.c
 create mode 100644 gcc/config/i386/cetintrin.h
 create mode 100644 gcc/config/i386/t-cet

diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 4185176..774dc2c 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -137,6 +137,8 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA_CLZERO_SET OPTION_MASK_ISA_CLZERO
 #define OPTION_MASK_ISA_PKU_SET OPTION_MASK_ISA_PKU
 #define OPTION_MASK_ISA_RDPID_SET OPTION_MASK_ISA_RDPID
+#define OPTION_MASK_ISA_IBT_SET OPTION_MASK_ISA_IBT
+#define OPTION_MASK_ISA_SHSTK_SET OPTION_MASK_ISA_SHSTK
 
 /* Define a set of ISAs which aren't available when a given ISA is
    disabled.  MMX and SSE ISAs are handled separately.  */
@@ -202,6 +204,8 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA_CLZERO_UNSET OPTION_MASK_ISA_CLZERO
 #define OPTION_MASK_ISA_PKU_UNSET OPTION_MASK_ISA_PKU
 #define OPTION_MASK_ISA_RDPID_UNSET OPTION_MASK_ISA_RDPID
+#define OPTION_MASK_ISA_IBT_UNSET OPTION_MASK_ISA_IBT
+#define OPTION_MASK_ISA_SHSTK_UNSET OPTION_MASK_ISA_SHSTK
 
 /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
    as -mno-sse4.1. */
@@ -484,6 +488,35 @@ ix86_handle_option (struct gcc_options *opts,
 	}
       return true;
 
+    case OPT_mcet:
+    case OPT_mibt:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_IBT_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_IBT_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_UNSET;
+	}
+      if (code != OPT_mcet)
+	return true;
+      /* fall through.  */
+
+    case OPT_mshstk:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_SHSTK_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_SHSTK_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_UNSET;
+	}
+      return true;
+
     case OPT_mavx5124fmaps:
       if (value)
 	{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 630832f..cdda262 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -377,7 +377,7 @@ i[34567]86-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -400,7 +400,7 @@ x86_64-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
 	;;
 ia64-*-*)
 	extra_headers=ia64intrin.h
@@ -4547,7 +4547,8 @@ case ${target} in
 	i[34567]86-*-darwin* | x86_64-*-darwin*)
 		;;
 	i[34567]86-*-linux* | x86_64-*-linux*)
-		tmake_file="$tmake_file i386/t-linux"
+		extra_objs="${extra_objs} cet.o"
+		tmake_file="$tmake_file i386/t-linux i386/t-cet"
 		;;
 	i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
 		tmake_file="$tmake_file i386/t-kfreebsd"
diff --git a/gcc/config/i386/cet.c b/gcc/config/i386/cet.c
new file mode 100644
index 0000000..a53c499
--- /dev/null
+++ b/gcc/config/i386/cet.c
@@ -0,0 +1,76 @@
+/* Functions for CET/x86.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "output.h"
+#include "linux-common.h"
+
+void
+file_end_indicate_exec_stack_and_cet (void)
+{
+  file_end_indicate_exec_stack ();
+
+  if (flag_cf_protection == CF_NONE)
+    return;
+
+  unsigned int feature_1 = 0;
+
+  if (TARGET_IBT)
+    /* GNU_PROPERTY_X86_FEATURE_1_IBT.  */
+    feature_1 |= 0x1;
+
+  if (TARGET_SHSTK)
+    /* GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
+    feature_1 |= 0x2;
+
+  if (feature_1)
+    {
+      int p2align = ptr_mode == SImode ? 2 : 3;
+
+      /* Generate GNU_PROPERTY_X86_FEATURE_1_XXX.  */
+      switch_to_section (get_section (".note.gnu.property",
+				      SECTION_NOTYPE, NULL));
+
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      /* name length.  */
+      fprintf (asm_out_file, ASM_LONG " 1f - 0f\n");
+      /* data length.  */
+      fprintf (asm_out_file, ASM_LONG " 4f - 1f\n");
+      /* note type: NT_GNU_PROPERTY_TYPE_0.  */
+      fprintf (asm_out_file, ASM_LONG " 5\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "0");
+      /* vendor name: "GNU".  */
+      fprintf (asm_out_file, STRING_ASM_OP " \"GNU\"\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "1");
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      /* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND.  */
+      fprintf (asm_out_file, ASM_LONG " 0xc0000002\n");
+      /* pr_datasz.  */\
+      fprintf (asm_out_file, ASM_LONG " 3f - 2f\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "2");
+      /* GNU_PROPERTY_X86_FEATURE_1_XXX.  */
+      fprintf (asm_out_file, ASM_LONG " 0x%x\n", feature_1);
+      ASM_OUTPUT_LABEL (asm_out_file, "3");
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      ASM_OUTPUT_LABEL (asm_out_file, "4");
+    }
+}
diff --git a/gcc/config/i386/cetintrin.h b/gcc/config/i386/cetintrin.h
new file mode 100644
index 0000000..b15a776
--- /dev/null
+++ b/gcc/config/i386/cetintrin.h
@@ -0,0 +1,134 @@
+/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if !defined _IMMINTRIN_H_INCLUDED
+# error "Never use <cetintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _CETINTRIN_H_INCLUDED
+#define _CETINTRIN_H_INCLUDED
+
+#ifndef __SHSTK__
+#pragma GCC push_options
+#pragma GCC target ("shstk")
+#define __DISABLE_SHSTK__
+#endif /* __SHSTK__ */
+
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdsspd (unsigned int __B)
+{
+  return __builtin_ia32_rdsspd (__B);
+}
+
+#ifdef __x86_64__
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdsspq (unsigned long long __B)
+{
+  return __builtin_ia32_rdsspq (__B);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_incsspd (unsigned int __B)
+{
+  __builtin_ia32_incsspd (__B);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_incsspq (unsigned long long __B)
+{
+  __builtin_ia32_incsspq (__B);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_saveprevssp (void)
+{
+  __builtin_ia32_saveprevssp ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rstorssp (void *__B)
+{
+  __builtin_ia32_rstorssp (__B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrssd (unsigned int __B, void *__C)
+{
+  __builtin_ia32_wrssd (__B, __C);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrssq (unsigned long long __B, void *__C)
+{
+  __builtin_ia32_wrssq (__B, __C);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrussd (unsigned int __B, void *__C)
+{
+  __builtin_ia32_wrussd (__B, __C);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrussq (unsigned long long __B, void *__C)
+{
+  __builtin_ia32_wrussq (__B, __C);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_setssbsy (void)
+{
+  __builtin_ia32_setssbsy ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_clrssbsy (void *__B)
+{
+  __builtin_ia32_clrssbsy (__B);
+}
+
+#ifdef __DISABLE_SHSTK__
+#undef __DISABLE_SHSTK__
+#pragma GCC pop_options
+#endif /* __DISABLE_SHSTK__ */
+
+#endif /* _CETINTRIN_H_INCLUDED.  */
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index b3b0f91..0053a32 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -97,12 +97,14 @@
 #define bit_AVX512VBMI	(1 << 1)
 #define bit_PKU	(1 << 3)
 #define bit_OSPKE	(1 << 4)
+#define bit_SHSTK	(1 << 7)
 #define bit_AVX512VPOPCNTDQ	(1 << 14)
 #define bit_RDPID	(1 << 22)
 
 /* %edx */
 #define bit_AVX5124VNNIW (1 << 2)
 #define bit_AVX5124FMAPS (1 << 3)
+#define bit_IBT	(1 << 20)
 
 /* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */
 #define bit_BNDREGS     (1 << 3)
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 570c490..a4b8091 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -415,6 +415,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
   unsigned int has_avx512vbmi = 0, has_avx512ifma = 0, has_clwb = 0;
   unsigned int has_mwaitx = 0, has_clzero = 0, has_pku = 0, has_rdpid = 0;
   unsigned int has_avx5124fmaps = 0, has_avx5124vnniw = 0;
+  unsigned int has_ibt = 0, has_shstk = 0;
 
   bool arch;
 
@@ -507,6 +508,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 
       has_avx5124vnniw = edx & bit_AVX5124VNNIW;
       has_avx5124fmaps = edx & bit_AVX5124FMAPS;
+
+      has_shstk = ecx & bit_SHSTK;
+      has_ibt = edx & bit_IBT;
     }
 
   if (max_level >= 13)
@@ -1041,6 +1045,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
       const char *clzero  = has_clzero  ? " -mclzero"  : " -mno-clzero";
       const char *pku = has_pku ? " -mpku" : " -mno-pku";
       const char *rdpid = has_rdpid ? " -mrdpid" : " -mno-rdpid";
+      const char *ibt = has_ibt ? " -mibt" : " -mno-ibt";
+      const char *shstk = has_shstk ? " -mshstk" : " -mno-shstk";
       options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
 			sse4a, cx16, sahf, movbe, aes, sha, pclmul,
 			popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2,
@@ -1050,7 +1056,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 			avx512cd, avx512pf, prefetchwt1, clflushopt,
 			xsavec, xsaves, avx512dq, avx512bw, avx512vl,
 			avx512ifma, avx512vbmi, avx5124fmaps, avx5124vnniw,
-			clwb, mwaitx, clzero, pku, rdpid, NULL);
+			clwb, mwaitx, clzero, pku, rdpid, ibt, shstk, NULL);
     }
 
 done:
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 8d584db..1c0c6b4 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -286,7 +286,9 @@ DEF_FUNCTION_TYPE (V8SI, V8SI)
 DEF_FUNCTION_TYPE (VOID, PCVOID)
 DEF_FUNCTION_TYPE (VOID, PVOID)
 DEF_FUNCTION_TYPE (VOID, UINT64)
+DEF_FUNCTION_TYPE (VOID, UINT64, PVOID)
 DEF_FUNCTION_TYPE (VOID, UNSIGNED)
+DEF_FUNCTION_TYPE (VOID, UNSIGNED, PVOID)
 DEF_FUNCTION_TYPE (INT, PUSHORT)
 DEF_FUNCTION_TYPE (INT, PUNSIGNED)
 DEF_FUNCTION_TYPE (INT, PULONGLONG)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index 7ff1bb1..3006ef4 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -2779,4 +2779,25 @@ BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4sf3,     "__builtin_ia32_vper
 BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4df3,     "__builtin_ia32_vpermil2pd256", IX86_BUILTIN_VPERMIL2PD256, UNKNOWN, (int)MULTI_ARG_4_DF2_DI_I1)
 BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v8sf3,     "__builtin_ia32_vpermil2ps256", IX86_BUILTIN_VPERMIL2PS256, UNKNOWN, (int)MULTI_ARG_4_SF2_SI_I1)
 
-BDESC_END (MULTI_ARG, MAX)
+BDESC_END (MULTI_ARG, CET)
+
+/* CET.  */
+BDESC_FIRST (cet, CET,
+       OPTION_MASK_ISA_SHSTK, CODE_FOR_incsspsi, "__builtin_ia32_incsspd", IX86_BUILTIN_INCSSPD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_incsspdi, "__builtin_ia32_incsspq", IX86_BUILTIN_INCSSPQ, UNKNOWN, (int) VOID_FTYPE_UINT64)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_saveprevssp, "__builtin_ia32_saveprevssp", IX86_BUILTIN_SAVEPREVSSP, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_rstorssp, "__builtin_ia32_rstorssp", IX86_BUILTIN_RSTORSSP, UNKNOWN, (int) VOID_FTYPE_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrsssi, "__builtin_ia32_wrssd", IX86_BUILTIN_WRSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrssdi, "__builtin_ia32_wrssq", IX86_BUILTIN_WRSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrusssi, "__builtin_ia32_wrussd", IX86_BUILTIN_WRUSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrussdi, "__builtin_ia32_wrussq", IX86_BUILTIN_WRUSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_setssbsy, "__builtin_ia32_setssbsy", IX86_BUILTIN_SETSSBSY, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_clrssbsy, "__builtin_ia32_clrssbsy", IX86_BUILTIN_CLRSSBSY, UNKNOWN, (int) VOID_FTYPE_PVOID)
+
+BDESC_END (CET, CET_NORMAL)
+
+BDESC_FIRST (cet_rdssp, CET_NORMAL,
+       OPTION_MASK_ISA_SHSTK, CODE_FOR_rdsspsi, "__builtin_ia32_rdsspd", IX86_BUILTIN_RDSSPD, UNKNOWN, (int) UINT_FTYPE_UINT)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_rdsspdi, "__builtin_ia32_rdsspq", IX86_BUILTIN_RDSSPQ, UNKNOWN, (int) UINT64_FTYPE_UINT64)
+
+BDESC_END (CET_NORMAL, MAX)
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 9a79a21..8c1387d 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -450,6 +450,18 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__PKU__");
   if (isa_flag2 & OPTION_MASK_ISA_RDPID)
     def_or_undef (parse_in, "__RDPID__");
+  if (isa_flag2 & OPTION_MASK_ISA_IBT)
+    {
+      def_or_undef (parse_in, "__IBT__");
+      if (flag_cf_protection != CF_NONE)
+	def_or_undef (parse_in, "__CET__");
+    }
+  if (isa_flag2 & OPTION_MASK_ISA_SHSTK)
+    {
+      def_or_undef (parse_in, "__SHSTK__");
+      if (flag_cf_protection != CF_NONE)
+	def_or_undef (parse_in, "__CET__");
+    }
   if (TARGET_IAMCU)
     {
       def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def
index 4953461..5c6e9c3 100644
--- a/gcc/config/i386/i386-passes.def
+++ b/gcc/config/i386/i386-passes.def
@@ -29,3 +29,5 @@ along with GCC; see the file COPYING3.  If not see
   /* Run the 64-bit STV pass before the CSE pass so that CONST0_RTX and
      CONSTM1_RTX generated by the STV pass can be CSEed.  */
   INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
+
+  INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbranch);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index ecb0a4c..3201bba 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -344,3 +344,4 @@ class rtl_opt_pass;
 
 extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
 extern rtl_opt_pass *make_pass_stv (gcc::context *);
+extern rtl_opt_pass *make_pass_insert_endbranch (gcc::context *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b2b02ac..384c429 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -98,6 +98,7 @@ static rtx legitimize_pe_coff_symbol (rtx, bool);
 static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool);
 static bool ix86_save_reg (unsigned int, bool, bool);
 static bool ix86_function_naked (const_tree);
+static bool ix86_notrack_prefixed_insn_p (rtx);
 
 #ifndef CHECK_STACK_LIMIT
 #define CHECK_STACK_LIMIT (-1)
@@ -4618,6 +4619,150 @@ make_pass_stv (gcc::context *ctxt)
   return new pass_stv (ctxt);
 }
 
+/* Inserting ENDBRANCH instructions.  */
+
+static unsigned int
+rest_of_insert_endbranch (void)
+{
+  timevar_push (TV_MACH_DEP);
+
+  rtx cet_eb;
+  rtx_insn *insn;
+  basic_block bb;
+
+  /* Currently emit EB if it's a tracking function, i.e. 'nocf_check' is
+     absent among function attributes.  Later an optimization will be
+     introduced to make analysis if an address of a static function is
+     taken.  A static function whose address is not taken will get a
+     nocf_check attribute.  This will allow to reduce the number of EB.  */
+
+  if (!lookup_attribute ("nocf_check",
+			 TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))))
+    {
+      cet_eb = gen_nop_endbr ();
+
+      bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+      insn = BB_HEAD (bb);
+      emit_insn_before (cet_eb, insn);
+    }
+
+  bb = 0;
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
+	   insn = NEXT_INSN (insn))
+	{
+	  if (INSN_P (insn) && GET_CODE (insn) == CALL_INSN)
+	    {
+	      rtx_insn *next_insn = insn;
+
+	      while ((next_insn != BB_END (bb))
+		      && (DEBUG_INSN_P (NEXT_INSN (next_insn))
+			  || NOTE_P (NEXT_INSN (next_insn))
+			  || BARRIER_P (NEXT_INSN (next_insn))))
+		next_insn = NEXT_INSN (next_insn);
+
+	      /* Generate ENDBRANCH after CALL, which can return more than
+		 twice, setjmp-like functions.  */
+	      if (find_reg_note (insn, REG_SETJMP, NULL) != NULL)
+		{
+		  cet_eb = gen_nop_endbr ();
+		  emit_insn_after (cet_eb, next_insn);
+		}
+	      continue;
+	    }
+
+	  if (INSN_P (insn) && JUMP_P (insn) && flag_cet_switch)
+	    {
+	      rtx target = JUMP_LABEL (insn);
+	      if (target == NULL_RTX || ANY_RETURN_P (target))
+		continue;
+
+	      /* Check the jump is a switch table.  */
+	      rtx_insn *label = as_a<rtx_insn *> (target);
+	      rtx_insn *table = next_insn (label);
+	      if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
+		continue;
+
+	      /* For the indirect jump find out all places it jumps and insert
+		 ENDBRANCH there.  It should be done under a special flag to
+		 control ENDBRANCH generation for switch stmts.  */
+	      edge_iterator ei;
+	      edge e;
+	      basic_block dest_blk;
+
+	      FOR_EACH_EDGE (e, ei, bb->succs)
+		{
+		  rtx_insn *insn;
+
+		  dest_blk = e->dest;
+		  insn = BB_HEAD (dest_blk);
+		  gcc_assert (LABEL_P (insn));
+		  cet_eb = gen_nop_endbr ();
+		  emit_insn_after (cet_eb, insn);
+		}
+	      continue;
+	    }
+
+	  if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn))
+	      || (NOTE_P (insn)
+		  && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
+/* TODO.  Check /s bit also.  */
+	    {
+	      cet_eb = gen_nop_endbr ();
+	      emit_insn_after (cet_eb, insn);
+	      continue;
+	    }
+	}
+    }
+
+  timevar_pop (TV_MACH_DEP);
+  return 0;
+}
+
+namespace {
+
+const pass_data pass_data_insert_endbranch =
+{
+  RTL_PASS, /* type.  */
+  "cet", /* name.  */
+  OPTGROUP_NONE, /* optinfo_flags.  */
+  TV_MACH_DEP, /* tv_id.  */
+  0, /* properties_required.  */
+  0, /* properties_provided.  */
+  0, /* properties_destroyed.  */
+  0, /* todo_flags_start.  */
+  0, /* todo_flags_finish.  */
+};
+
+class pass_insert_endbranch : public rtl_opt_pass
+{
+public:
+  pass_insert_endbranch (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_insert_endbranch, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return ((flag_cf_protection & CF_BRANCH) && TARGET_IBT);
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return rest_of_insert_endbranch ();
+    }
+
+}; // class pass_insert_endbranch
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_insert_endbranch (gcc::context *ctxt)
+{
+  return new pass_insert_endbranch (ctxt);
+}
+
 /* Return true if a red-zone is in use.  */
 
 bool
@@ -4649,7 +4794,9 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
     { "-msgx",		OPTION_MASK_ISA_SGX },
     { "-mavx5124vnniw", OPTION_MASK_ISA_AVX5124VNNIW },
     { "-mavx5124fmaps", OPTION_MASK_ISA_AVX5124FMAPS },
-    { "-mavx512vpopcntdq", OPTION_MASK_ISA_AVX512VPOPCNTDQ }
+    { "-mavx512vpopcntdq", OPTION_MASK_ISA_AVX512VPOPCNTDQ },
+    { "-mibt",	OPTION_MASK_ISA_IBT },
+    { "-mshstk",	OPTION_MASK_ISA_SHSTK }
   };
   static struct ix86_target_opts isa_opts[] =
   {
@@ -6738,6 +6885,37 @@ ix86_option_override_internal (bool main_args_p,
     target_option_default_node = target_option_current_node
       = build_target_option_node (opts);
 
+  /* Do not support control flow instrumentation if CET is not enabled.  */
+  if (opts->x_flag_cf_protection != CF_NONE)
+    {
+      if (!(TARGET_IBT_P (opts->x_ix86_isa_flags2)
+	    || TARGET_SHSTK_P (opts->x_ix86_isa_flags2)))
+	{
+	  if (flag_cf_protection == CF_FULL)
+	    {
+	      error ("%<-fcf-protection=full%> requires CET support "
+		     "on this target. Use -mcet or one of -mibt, "
+		     "-mshstk options to enable CET");
+	    }
+	  else if (flag_cf_protection == CF_BRANCH)
+	    {
+	      error ("%<-fcf-protection=branch%> requires CET support "
+		     "on this target. Use -mcet or one of -mibt, "
+		     "-mshstk options to enable CET");
+	    }
+	  else if (flag_cf_protection == CF_RETURN)
+	    {
+	      error ("%<-fcf-protection=return%> requires CET support "
+		     "on this target. Use -mcet or one of -mibt, "
+		     "-mshstk options to enable CET");
+	    }
+	  flag_cf_protection = CF_NONE;
+	  return false;
+	}
+      opts->x_flag_cf_protection =
+	(cf_protection_level) (opts->x_flag_cf_protection | CF_SET);
+    }
+
   return true;
 }
 
@@ -7143,6 +7321,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
     IX86_ATTR_ISA ("mpx",	OPT_mmpx),
     IX86_ATTR_ISA ("clwb",	OPT_mclwb),
     IX86_ATTR_ISA ("rdpid",	OPT_mrdpid),
+    IX86_ATTR_ISA ("ibt",	OPT_mibt),
+    IX86_ATTR_ISA ("shstk",	OPT_mshstk),
 
     /* enum options */
     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
@@ -19481,6 +19661,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
 	case '!':
 	  if (ix86_bnd_prefixed_insn_p (current_output_insn))
 	    fputs ("bnd ", file);
+	  if (ix86_notrack_prefixed_insn_p (current_output_insn))
+	    fputs ("notrack ", file);
 	  return;
 
 	default:
@@ -32707,8 +32889,12 @@ BDESC_VERIFYS (IX86_BUILTIN__BDESC_MPX_CONST_FIRST,
 	       IX86_BUILTIN__BDESC_MPX_LAST, 1);
 BDESC_VERIFYS (IX86_BUILTIN__BDESC_MULTI_ARG_FIRST,
 	       IX86_BUILTIN__BDESC_MPX_CONST_LAST, 1);
-BDESC_VERIFYS (IX86_BUILTIN_MAX,
+BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_FIRST,
 	       IX86_BUILTIN__BDESC_MULTI_ARG_LAST, 1);
+BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_NORMAL_FIRST,
+	       IX86_BUILTIN__BDESC_CET_LAST, 1);
+BDESC_VERIFYS (IX86_BUILTIN_MAX,
+	       IX86_BUILTIN__BDESC_CET_NORMAL_LAST, 1);
 
 /* Set up all the MMX/SSE builtins, even builtins for instructions that are not
    in the current target ISA to allow the user to compile particular modules
@@ -33369,6 +33555,35 @@ ix86_init_mmx_sse_builtins (void)
   BDESC_VERIFYS (IX86_BUILTIN__BDESC_MULTI_ARG_LAST,
 		 IX86_BUILTIN__BDESC_MULTI_ARG_FIRST,
 		 ARRAY_SIZE (bdesc_multi_arg) - 1);
+
+  /* Add CET inrinsics.  */
+  for (i = 0, d = bdesc_cet; i < ARRAY_SIZE (bdesc_cet); i++, d++)
+    {
+      BDESC_VERIFY (d->code, IX86_BUILTIN__BDESC_CET_FIRST, i);
+      if (d->name == 0)
+	continue;
+
+      ftype = (enum ix86_builtin_func_type) d->flag;
+      def_builtin2 (d->mask, d->name, ftype, d->code);
+    }
+  BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_LAST,
+		 IX86_BUILTIN__BDESC_CET_FIRST,
+		 ARRAY_SIZE (bdesc_cet) - 1);
+
+  for (i = 0, d = bdesc_cet_rdssp;
+       i < ARRAY_SIZE (bdesc_cet_rdssp);
+       i++, d++)
+    {
+      BDESC_VERIFY (d->code, IX86_BUILTIN__BDESC_CET_NORMAL_FIRST, i);
+      if (d->name == 0)
+	continue;
+
+      ftype = (enum ix86_builtin_func_type) d->flag;
+      def_builtin2 (d->mask, d->name, ftype, d->code);
+    }
+  BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_NORMAL_LAST,
+		 IX86_BUILTIN__BDESC_CET_NORMAL_FIRST,
+		 ARRAY_SIZE (bdesc_cet_rdssp) - 1);
 }
 
 static void
@@ -39540,6 +39755,57 @@ rdseed_step:
       emit_insn (gen_xabort (op0));
       return 0;
 
+    case IX86_BUILTIN_RSTORSSP:
+    case IX86_BUILTIN_CLRSSBSY:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+      icode = (fcode == IX86_BUILTIN_RSTORSSP
+	  ? CODE_FOR_rstorssp
+	  : CODE_FOR_clrssbsy);
+      if (!address_operand (op0, VOIDmode))
+	{
+	  op1 = convert_memory_address (Pmode, op0);
+	  op0 = copy_addr_to_reg (op1);
+	}
+      emit_insn (GEN_FCN (icode) (gen_rtx_MEM (Pmode, op0)));
+      return 0;
+
+    case IX86_BUILTIN_WRSSD:
+    case IX86_BUILTIN_WRSSQ:
+    case IX86_BUILTIN_WRUSSD:
+    case IX86_BUILTIN_WRUSSQ:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+      arg1 = CALL_EXPR_ARG (exp, 1);
+      op1 = expand_normal (arg1);
+      switch (fcode)
+	{
+	case IX86_BUILTIN_WRSSD:
+	  icode = CODE_FOR_wrsssi;
+	  mode = SImode;
+	  break;
+	case IX86_BUILTIN_WRSSQ:
+	  icode = CODE_FOR_wrssdi;
+	  mode = DImode;
+	  break;
+	case IX86_BUILTIN_WRUSSD:
+	  icode = CODE_FOR_wrusssi;
+	  mode = SImode;
+	  break;
+	case IX86_BUILTIN_WRUSSQ:
+	  icode = CODE_FOR_wrussdi;
+	  mode = DImode;
+	  break;
+	}
+      op0 = force_reg (mode, op0);
+      if (!address_operand (op1, VOIDmode))
+	{
+	  op2 = convert_memory_address (Pmode, op1);
+	  op1 = copy_addr_to_reg (op2);
+	}
+      emit_insn (GEN_FCN (icode) (op0, gen_rtx_MEM (mode, op1)));
+      return 0;
+
     default:
       break;
     }
@@ -39842,6 +40108,22 @@ s4fma_expand:
 					    d->flag, d->comparison);
     }
 
+  if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
+      && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
+    {
+      i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
+      return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
+					       target);
+    }
+
+  if (fcode >= IX86_BUILTIN__BDESC_CET_NORMAL_FIRST
+      && fcode <= IX86_BUILTIN__BDESC_CET_NORMAL_LAST)
+    {
+      i = fcode - IX86_BUILTIN__BDESC_CET_NORMAL_FIRST;
+      return ix86_expand_args_builtin (bdesc_cet_rdssp + i, exp,
+				       target);
+    }
+
   gcc_unreachable ();
 }
 
@@ -42703,6 +42985,10 @@ 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)
+    emit_insn (gen_nop_endbr ());
+
   /* If VCALL_OFFSET, we'll need THIS in a register.  Might as well
      pull it in now and let DELTA benefit.  */
   if (REG_P (this_param))
@@ -50520,6 +50806,46 @@ ix86_bnd_prefixed_insn_p (rtx insn)
   return chkp_function_instrumented_p (current_function_decl);
 }
 
+/* Return 1 if control tansfer instruction INSN
+   should be encoded with notrack prefix.  */
+
+static bool
+ix86_notrack_prefixed_insn_p (rtx insn)
+{
+  if (!insn || !((flag_cf_protection & CF_BRANCH) && TARGET_IBT))
+    return false;
+
+  if (CALL_P (insn))
+    {
+      rtx call = get_call_rtx_from (insn);
+      gcc_assert (call != NULL_RTX);
+      rtx addr = XEXP (call, 0);
+
+      /* Do not emit 'notrack' if it's not an indirect call.  */
+      if (MEM_P (addr)
+	  && GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
+	return false;
+      else
+	return find_reg_note (insn, REG_CALL_NOCF_CHECK, 0);
+    }
+
+  if (JUMP_P (insn) && !flag_cet_switch)
+    {
+      rtx target = JUMP_LABEL (insn);
+      if (target == NULL_RTX || ANY_RETURN_P (target))
+	return false;
+
+      /* Check the jump is a switch table.  */
+      rtx_insn *label = as_a<rtx_insn *> (target);
+      rtx_insn *table = next_insn (label);
+      if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
+	return false;
+      else
+	return true;
+    }
+  return false;
+}
+
 /* Calculate integer abs() using only SSE2 instructions.  */
 
 void
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index cbd6a11..5796727 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -167,6 +167,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_MWAITX_P(x)	TARGET_ISA_MWAITX_P(x)
 #define TARGET_PKU	TARGET_ISA_PKU
 #define TARGET_PKU_P(x)	TARGET_ISA_PKU_P(x)
+#define TARGET_IBT	TARGET_ISA_IBT
+#define TARGET_IBT_P(x)	TARGET_ISA_IBT_P(x)
+#define TARGET_SHSTK	TARGET_ISA_SHSTK
+#define TARGET_SHSTK_P(x)	TARGET_ISA_SHSTK_P(x)
 
 #define TARGET_LP64	TARGET_ABI_64
 #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 43227dc..076a48e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -62,7 +62,7 @@
 ;; ; -- print a semicolon (after prefixes due to bug in older gas).
 ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
 ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
-;; ! -- print MPX prefix for jxx/call/ret instructions if required.
+;; ! -- print MPX or NOTRACK prefix for jxx/call/ret instructions if required.
 
 (define_c_enum "unspec" [
   ;; Relocation specifiers
@@ -274,6 +274,17 @@
 
   ;; For RDPID support
   UNSPECV_RDPID
+
+  ;; For CET support
+  UNSPECV_NOP_ENDBR
+  UNSPECV_NOP_RDSSP
+  UNSPECV_INCSSP
+  UNSPECV_SAVEPREVSSP
+  UNSPECV_RSTORSSP
+  UNSPECV_WRSS
+  UNSPECV_WRUSS
+  UNSPECV_SETSSBSY
+  UNSPECV_CLRSSBSY
 ])
 
 ;; Constants to represent rounding modes in the ROUND instruction
@@ -17791,6 +17802,28 @@
   "* return output_probe_stack_range (operands[0], operands[2]);"
   [(set_attr "type" "multi")])
 
+/* Additional processing for builtin_setjmp.  Store the shadow stack pointer
+   as a forth element in jmpbuf.  */
+(define_expand "builtin_setjmp_setup"
+  [(match_operand 0 "address_operand")]
+  "TARGET_SHSTK"
+{
+  if (flag_cf_protection & CF_RETURN)
+    {
+      rtx mem, reg_ssp;
+
+      mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+					       3 * GET_MODE_SIZE (Pmode)));
+      reg_ssp = gen_reg_rtx (Pmode);
+      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      emit_insn ((Pmode == SImode)
+		  ? gen_rdsspsi (reg_ssp, reg_ssp)
+		  : gen_rdsspdi (reg_ssp, reg_ssp));
+      emit_move_insn (mem, reg_ssp);
+    }
+  DONE;
+})
+
 (define_expand "builtin_setjmp_receiver"
   [(label_ref (match_operand 0))]
   "!TARGET_64BIT && flag_pic"
@@ -17811,6 +17844,83 @@
   DONE;
 })
 
+(define_expand "builtin_longjmp"
+  [(match_operand 0 "address_operand")]
+  "TARGET_SHSTK"
+{
+  rtx fp, lab, stack;
+  rtx jump, label, reg_adj, reg_ssp, reg_minus, mem_buf, tmp, clob;
+  machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+
+  /* Adjust the shadow stack pointer (ssp) to the value saved in the
+     jmp_buf.  The saving was done in the builtin_setjmp_setup.  */
+  if (flag_cf_protection & CF_RETURN)
+    {
+      /* Get current shadow stack pointer.  The code below will check if
+	 SHSTK feature is enabled.  If it's not enabled RDSSP instruction
+	 is a NOP.  */
+      reg_ssp = gen_reg_rtx (Pmode);
+      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      emit_insn ((Pmode == SImode)
+		 ? gen_rdsspsi (reg_ssp, reg_ssp)
+		 : gen_rdsspdi (reg_ssp, reg_ssp));
+      mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+						   3 * GET_MODE_SIZE (Pmode))),
+
+      /* Compare through substraction the saved and the current ssp to decide
+	 if ssp has to be adjusted.  */
+      reg_minus = gen_reg_rtx (Pmode);
+      tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+      emit_insn (tmp);
+
+      /* Jump over adjustment code.  */
+      label = gen_label_rtx ();
+      tmp = gen_rtx_REG (CCmode, FLAGS_REG);
+      tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+				  gen_rtx_LABEL_REF (VOIDmode, label),
+				  pc_rtx);
+      jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+      JUMP_LABEL (jump) = label;
+
+      /* Adjust the ssp.  */
+      reg_adj = gen_reg_rtx (Pmode);
+      tmp = gen_rtx_SET (reg_adj,
+			 gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus),
+					   GEN_INT (3)));
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+      emit_insn (tmp);
+      emit_insn ((Pmode == SImode)
+		 ? gen_incsspsi (reg_adj)
+		 : gen_incsspdi (reg_adj));
+
+      emit_label (label);
+      LABEL_NUSES (label) = 1;
+    }
+
+  /* This code is the same as in expand_buildin_longjmp.  */
+  fp = gen_rtx_MEM (Pmode, operands[0]);
+  lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+					   GET_MODE_SIZE (Pmode)));
+  stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0],
+					       2 * GET_MODE_SIZE (Pmode)));
+  lab = copy_to_reg (lab);
+
+  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
+  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack);
+
+  emit_use (hard_frame_pointer_rtx);
+  emit_use (stack_pointer_rtx);
+  emit_indirect_jump (lab);
+})
+
+
 ;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
 ;; Do not split instructions with mask registers.
 (define_split
@@ -19431,6 +19541,83 @@
   [(set_attr "length" "2")
    (set_attr "memory" "unknown")])
 
+;; CET instructions
+(define_insn "rdssp<mode>"
+  [(set (match_operand:SWI48x 0 "register_operand" "=r")
+	(unspec_volatile:SWI48x
+	  [(match_operand:SWI48x 1 "register_operand" "0")]
+	  UNSPECV_NOP_RDSSP))]
+  "TARGET_SHSTK"
+  "rdssp<mskmodesuffix>\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "incssp<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
+		   UNSPECV_INCSSP)]
+  "TARGET_SHSTK"
+  "incssp<mskmodesuffix>\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "saveprevssp"
+  [(unspec_volatile [(const_int 0)] UNSPECV_SAVEPREVSSP)]
+  "TARGET_SHSTK"
+  "saveprevssp"
+  [(set_attr "length" "5")
+   (set_attr "type" "other")])
+
+(define_insn "rstorssp"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+		   UNSPECV_RSTORSSP)]
+  "TARGET_SHSTK"
+  "rstorssp\t%0"
+  [(set_attr "length" "5")
+   (set_attr "type" "other")])
+
+(define_insn "wrss<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+		     (match_operand:SWI48x 1 "memory_operand" "m")]
+		   UNSPECV_WRSS)]
+  "TARGET_SHSTK"
+  "wrss<mskmodesuffix>\t%0, %1"
+  [(set_attr "length" "3")
+   (set_attr "type" "other")])
+
+(define_insn "wruss<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+		     (match_operand:SWI48x 1 "memory_operand" "m")]
+		   UNSPECV_WRUSS)]
+  "TARGET_SHSTK"
+  "wruss<mskmodesuffix>\t%0, %1"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "setssbsy"
+  [(unspec_volatile [(const_int 0)] UNSPECV_SETSSBSY)]
+  "TARGET_SHSTK"
+  "setssbsy"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "clrssbsy"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+		   UNSPECV_CLRSSBSY)]
+  "TARGET_SHSTK"
+  "clrssbsy\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "nop_endbr"
+  [(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
+  "TARGET_IBT"
+  "*
+{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
+  [(set_attr "length" "4")
+   (set_attr "length_immediate" "0")
+   (set_attr "modrm" "0")])
+
+;; For RTM support
 (define_expand "xbegin"
   [(set (match_operand:SI 0 "register_operand")
 	(unspec_volatile:SI [(const_int 0)] UNSPECV_XBEGIN))]
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 81bbc1e..f556573 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -949,3 +949,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.
+
+mcet
+Target Report Var(flag_cet) Init(0)
+Support Control-flow  Enforcment Technology (CET) built-in functions
+and code generation.
+
+mibt
+Target Report Mask(ISA_IBT) Var(ix86_isa_flags2) Save
+Specifically enables an indirect branch tracking feature from Control-flow
+Enforcment Technology (CET).
+
+mshstk
+Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags2) Save
+Specifically enables an shadow stack support feature from Control-flow
+Enforcment Technology (CET).
+
+mcet-switch
+Target Report Undocumented Var(flag_cet_switch) Init(0)
+Turn on CET instrumentation for switch statements, which use jump table and
+indirect jump.
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index b52f58e..696cd20 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -90,6 +90,8 @@
 
 #include <xtestintrin.h>
 
+#include <cetintrin.h>
+
 #ifndef __RDRND__
 #pragma GCC push_options
 #pragma GCC target("rdrnd")
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index 6380639..6613807 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -121,3 +121,8 @@ along with GCC; see the file COPYING3.  If not see
 #define CHKP_SPEC "\
 %{!nostdlib:%{!nodefaultlibs:" LIBMPX_SPEC LIBMPXWRAPPERS_SPEC "}}" MPX_SPEC
 #endif
+
+extern void file_end_indicate_exec_stack_and_cet (void);
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet
diff --git a/gcc/config/i386/t-cet b/gcc/config/i386/t-cet
new file mode 100644
index 0000000..317f30d
--- /dev/null
+++ b/gcc/config/i386/t-cet
@@ -0,0 +1,21 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+cet.o: $(srcdir)/config/i386/cet.c
+	  $(COMPILE) $<
+	  $(POSTCOMPILE)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
  2017-10-12 18:50   ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
@ 2017-10-13  7:03     ` Uros Bizjak
  0 siblings, 0 replies; 6+ messages in thread
From: Uros Bizjak @ 2017-10-13  7:03 UTC (permalink / raw)
  To: Tsimbalist, Igor V; +Cc: gcc-patches

On Thu, Oct 12, 2017 at 8:45 PM, Tsimbalist, Igor V
<igor.v.tsimbalist@intel.com> wrote:
> Uros,
>
> Attached is an updated patch. The main difference is in option name and attribute name change. Other code is the same.

Trivial changes (if they fall under "trivial" rule) don't need extra
approval, but OK nevertheless.

Thanks,
Uros.

> Igor
>
>
>> -----Original Message-----
>> From: Tsimbalist, Igor V
>> Sent: Tuesday, September 19, 2017 5:06 PM
>> To: Uros Bizjak <ubizjak@gmail.com>; gcc-patches@gcc.gnu.org
>> Cc: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>
>> Subject: RE: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
>>
>> Uros, thank you for the approval. Based on the approval of the first 3 patches
>> (I've submitted them today), I need to adjust option and attribute names. I
>> will resubmit the patch when I fix option and attribute names.
>>
>> Thanks,
>> Igor
>>
>>
>> > -----Original Message-----
>> > From: Uros Bizjak [mailto:ubizjak@gmail.com]
>> > Sent: Monday, September 18, 2017 11:58 AM
>> > To: gcc-patches@gcc.gnu.org
>> > Cc: Tsimbalist, Igor V <igor.v.tsimbalist@intel.com>; Tsimbalist, Igor
>> > V <igor.v.tsimbalist@intel.com>
>> > Subject: Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
>> >
>> > Hello!
>> >
>> > > gcc/
>> > >
>> > > * common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET):
>> > New.
>> > > (OPTION_MASK_ISA_SHSTK_SET): Likewise.
>> > > (OPTION_MASK_ISA_IBT_UNSET): Likewise.
>> > > (OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
>> > > (ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
>> > > * config.gcc (extra_headers): Add cetintrin.h for x86 targets.
>> > > (extra_objs): Add cet.o for Linux/x86 targets.
>> > > (tmake_file): Add i386/t-cet for Linux/x86 targets.
>> > > * config/i386/cet.c: New file.
>> > > * config/i386/cetintrin.h: Likewise.
>> > > * config/i386/t-cet: Likewise.
>> > > * config/i386/cpuid.h (bit_SHSTK): New.
>> > > (bit_IBT): Likewise.
>> > > * config/i386/driver-i386.c (host_detect_local_cpu): Detect and pass
>> > > IBT and SHSTK bits.
>> > > * config/i386/i386-builtin-types.def
>> > > (VOID_FTYPE_UNSIGNED_PVOID): New.
>> > > (VOID_FTYPE_UINT64_PVOID): Likewise.
>> > > * config/i386/i386-builtin.def: Add CET intrinsics.
>> > > * config/i386/i386-c.c (ix86_target_macros_internal): Add
>> > > OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
>> > > * config/i386/i386-passes.def: Add pass_insert_endbranch pass.
>> > > * config/i386/i386-protos.h (make_pass_insert_endbranch): New
>> > > prototype.
>> > > * config/i386/i386.c (rest_of_insert_endbranch): New.
>> > > (pass_data_insert_endbranch): Likewise.
>> > > (pass_insert_endbranch): Likewise.
>> > > (make_pass_insert_endbranch): Likewise.
>> > > (ix86_notrack_prefixed_insn_p): Likewise.
>> > > (ix86_target_string): Add -mibt, -mshstk flags.
>> > > (ix86_option_override_internal): Add flag_instrument_control_flow
>> > > processing.
>> > > (ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
>> > > (ix86_print_operand): Add 'notrack' prefix output.
>> > > (ix86_init_mmx_sse_builtins): Add CET intrinsics.
>> > > (ix86_expand_builtin): Expand CET intrinsics.
>> > > (x86_output_mi_thunk): Add 'endbranch' instruction.
>> > > * config/i386/i386.h (TARGET_IBT): New.
>> > > (TARGET_IBT_P): Likewise.
>> > > (TARGET_SHSTK): Likewise.
>> > > (TARGET_SHSTK_P): Likewise.
>> > > * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
>> > > UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
>> > UNSPECV_WRSS,
>> > > UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
>> > > (builtin_setjmp_setup): New pattern.
>> > > (builtin_longjmp): Likewise.
>> > > (rdssp<mode>): Likewise.
>> > > (incssp<mode>): Likewise.
>> > > (saveprevssp): Likewise.
>> > > (rstorssp): Likewise.
>> > > (wrss<mode>): Likewise.
>> > > (wruss<mode>): Likewise.
>> > > (setssbsy): Likewise.
>> > > (clrssbsy): Likewise.
>> > > (nop_endbr): Likewise.
>> > > * config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
>> > > options.
>> > > * config/i386/immintrin.h: Include <cetintrin.h>.
>> > > * config/i386/linux-common.h
>> > > (file_end_indicate_exec_stack_and_cet): New prototype.
>> > > (TARGET_ASM_FILE_END): New.
>> >
>> > LGTM.
>> >
>> > OK for mainline.
>> >
>> > Thanks,
>> > Uros.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
  2017-09-18  9:58 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
  2017-09-19 15:05 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
@ 2017-11-06 10:33 ` Uros Bizjak
  1 sibling, 0 replies; 6+ messages in thread
From: Uros Bizjak @ 2017-11-06 10:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: Tsimbalist, Igor V

[-- Attachment #1: Type: text/plain, Size: 3481 bytes --]

On Mon, Sep 18, 2017 at 11:58 AM, Uros Bizjak <ubizjak@gmail.com> wrote:

>> gcc/
>>
>> * common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
>> (OPTION_MASK_ISA_SHSTK_SET): Likewise.
>> (OPTION_MASK_ISA_IBT_UNSET): Likewise.
>> (OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
>> (ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
>> * config.gcc (extra_headers): Add cetintrin.h for x86 targets.
>> (extra_objs): Add cet.o for Linux/x86 targets.
>> (tmake_file): Add i386/t-cet for Linux/x86 targets.
>> * config/i386/cet.c: New file.
>> * config/i386/cetintrin.h: Likewise.
>> * config/i386/t-cet: Likewise.
>> * config/i386/cpuid.h (bit_SHSTK): New.
>> (bit_IBT): Likewise.
>> * config/i386/driver-i386.c (host_detect_local_cpu): Detect and
>> pass IBT and SHSTK bits.
>> * config/i386/i386-builtin-types.def
>> (VOID_FTYPE_UNSIGNED_PVOID): New.
>> (VOID_FTYPE_UINT64_PVOID): Likewise.
>> * config/i386/i386-builtin.def: Add CET intrinsics.
>> * config/i386/i386-c.c (ix86_target_macros_internal): Add
>> OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
>> * config/i386/i386-passes.def: Add pass_insert_endbranch pass.
>> * config/i386/i386-protos.h (make_pass_insert_endbranch): New
>> prototype.
>> * config/i386/i386.c (rest_of_insert_endbranch): New.
>> (pass_data_insert_endbranch): Likewise.
>> (pass_insert_endbranch): Likewise.
>> (make_pass_insert_endbranch): Likewise.
>> (ix86_notrack_prefixed_insn_p): Likewise.
>> (ix86_target_string): Add -mibt, -mshstk flags.
>> (ix86_option_override_internal): Add flag_instrument_control_flow
>> processing.
>> (ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
>> (ix86_print_operand): Add 'notrack' prefix output.
>> (ix86_init_mmx_sse_builtins): Add CET intrinsics.
>> (ix86_expand_builtin): Expand CET intrinsics.
>> (x86_output_mi_thunk): Add 'endbranch' instruction.
>> * config/i386/i386.h (TARGET_IBT): New.
>> (TARGET_IBT_P): Likewise.
>> (TARGET_SHSTK): Likewise.
>> (TARGET_SHSTK_P): Likewise.
>> * config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
>> UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
>> UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
>> (builtin_setjmp_setup): New pattern.
>> (builtin_longjmp): Likewise.
>> (rdssp<mode>): Likewise.
>> (incssp<mode>): Likewise.
>> (saveprevssp): Likewise.
>> (rstorssp): Likewise.
>> (wrss<mode>): Likewise.
>> (wruss<mode>): Likewise.
>> (setssbsy): Likewise.
>> (clrssbsy): Likewise.
>> (nop_endbr): Likewise.
>> * config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
>> options.
>> * config/i386/immintrin.h: Include <cetintrin.h>.
>> * config/i386/linux-common.h
>> (file_end_indicate_exec_stack_and_cet): New prototype.
>> (TARGET_ASM_FILE_END): New.

This patch introduced following warnings during the compilation:

../../git/gcc/gcc/config/i386/i386.md:20072:1: warning: operand 0 missing mode?
../../git/gcc/gcc/config/i386/i386.md:20105:1: warning: operand 0 missing mode?

This warning suggests that operand 0 of rstorssp and clrssbsy needs
their mode defined. If the size of the memory access is not known,
then the mode should be BLKmode (not recommended), otherwise, please
specify the mode explicitly.

Looking a bit further, it looks to me that these new CET patterns
should be defined with SWI48 mode iterators that disable DImode on
32bit targets.

Please consider the attached patch that also includes a couple of
related cleanups. The patch is only lightly tested.

Uros.

[-- Attachment #2: p.diff.txt --]
[-- Type: text/plain, Size: 4075 bytes --]

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4123edf982f3..649738321673 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -36990,7 +36990,7 @@ rdseed_step:
 	  op1 = convert_memory_address (Pmode, op0);
 	  op0 = copy_addr_to_reg (op1);
 	}
-      emit_insn (GEN_FCN (icode) (gen_rtx_MEM (Pmode, op0)));
+      emit_insn (GEN_FCN (icode) (gen_rtx_MEM (BLKmode, op0)));
       return 0;
 
     case IX86_BUILTIN_WRSSD:
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d48decbb7d99..74dad48c813e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18316,8 +18316,7 @@
 
       mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
 					       3 * GET_MODE_SIZE (Pmode)));
-      reg_ssp = gen_reg_rtx (Pmode);
-      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      reg_ssp = force_reg (Pmode, const0_rtx);
       emit_insn ((Pmode == SImode)
 		  ? gen_rdsspsi (reg_ssp, reg_ssp)
 		  : gen_rdsspdi (reg_ssp, reg_ssp));
@@ -18361,8 +18360,7 @@
       /* Get current shadow stack pointer.  The code below will check if
 	 SHSTK feature is enabled.  If it's not enabled RDSSP instruction
 	 is a NOP.  */
-      reg_ssp = gen_reg_rtx (Pmode);
-      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      reg_ssp = force_reg (Pmode, const0_rtx);
       emit_insn ((Pmode == SImode)
 		 ? gen_rdsspsi (reg_ssp, reg_ssp)
 		 : gen_rdsspdi (reg_ssp, reg_ssp));
@@ -20045,9 +20043,9 @@
 
 ;; CET instructions
 (define_insn "rdssp<mode>"
-  [(set (match_operand:SWI48x 0 "register_operand" "=r")
-	(unspec_volatile:SWI48x
-	  [(match_operand:SWI48x 1 "register_operand" "0")]
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+	(unspec_volatile:SWI48
+	  [(match_operand:SWI48 1 "register_operand" "0")]
 	  UNSPECV_NOP_RDSSP))]
   "TARGET_SHSTK"
   "rdssp<mskmodesuffix>\t%0"
@@ -20055,8 +20053,8 @@
    (set_attr "type" "other")])
 
 (define_insn "incssp<mode>"
-  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
-		   UNSPECV_INCSSP)]
+  [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")]
+		    UNSPECV_INCSSP)]
   "TARGET_SHSTK"
   "incssp<mskmodesuffix>\t%0"
   [(set_attr "length" "4")
@@ -20070,26 +20068,26 @@
    (set_attr "type" "other")])
 
 (define_insn "rstorssp"
-  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
-		   UNSPECV_RSTORSSP)]
+  [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")]
+		    UNSPECV_RSTORSSP)]
   "TARGET_SHSTK"
   "rstorssp\t%0"
   [(set_attr "length" "5")
    (set_attr "type" "other")])
 
 (define_insn "wrss<mode>"
-  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
-		     (match_operand:SWI48x 1 "memory_operand" "m")]
-		   UNSPECV_WRSS)]
+  [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")
+		     (match_operand:SWI48 1 "memory_operand" "m")]
+		    UNSPECV_WRSS)]
   "TARGET_SHSTK"
   "wrss<mskmodesuffix>\t%0, %1"
   [(set_attr "length" "3")
    (set_attr "type" "other")])
 
 (define_insn "wruss<mode>"
-  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
-		     (match_operand:SWI48x 1 "memory_operand" "m")]
-		   UNSPECV_WRUSS)]
+  [(unspec_volatile [(match_operand:SWI48 0 "register_operand" "r")
+		     (match_operand:SWI48 1 "memory_operand" "m")]
+		    UNSPECV_WRUSS)]
   "TARGET_SHSTK"
   "wruss<mskmodesuffix>\t%0, %1"
   [(set_attr "length" "4")
@@ -20103,8 +20101,8 @@
    (set_attr "type" "other")])
 
 (define_insn "clrssbsy"
-  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
-		   UNSPECV_CLRSSBSY)]
+  [(unspec_volatile [(match_operand:BLK 0 "memory_operand" "m")]
+		    UNSPECV_CLRSSBSY)]
   "TARGET_SHSTK"
   "clrssbsy\t%0"
   [(set_attr "length" "4")
@@ -20113,8 +20111,7 @@
 (define_insn "nop_endbr"
   [(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
   "TARGET_IBT"
-  "*
-{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
+  "* return TARGET_64BIT ? \"endbr64\" : \"endbr32\";"
   [(set_attr "length" "4")
    (set_attr "length_immediate" "0")
    (set_attr "modrm" "0")])

^ permalink raw reply	[flat|nested] 6+ messages in thread

* 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET
@ 2017-08-01  8:57 Tsimbalist, Igor V
  0 siblings, 0 replies; 6+ messages in thread
From: Tsimbalist, Igor V @ 2017-08-01  8:57 UTC (permalink / raw)
  To: 'gcc-patches@gcc.gnu.org'; +Cc: Tsimbalist, Igor V

[-- Attachment #1: Type: text/plain, Size: 805 bytes --]

Part#4. Update x86 backend to enable Intel CET.

All platforms except i386 will report the error and do no
instrumentation with -finstrument-control-flow option. i386 will provide
the implementation based on a specification published by Intel for a new
technology called Control-flow Enforcement Technology (CET). The spec is
available at

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

The implementation in this patch:
1) enables Control-flow Enforcement Technology (CET), published by
Intel. This part introduces i386 specific options -mcet, -mibt and
-mshstk, new instructions and intrinsics;

2) provides support for -finstrument-control-flow option by doing needed
code instrumentation, which is based on CET features.

[-- Attachment #2: 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET.PATCH --]
[-- Type: application/octet-stream, Size: 45201 bytes --]

From 598a96d2308538d33286383c5e56b527c626aee8 Mon Sep 17 00:00:00 2001
From: Igor Tsimbalist <igor.v.tsimbalist@intel.com>
Date: Tue, 4 Jul 2017 13:54:08 +0300
Subject: [PATCH 4/9] Part#4. Update x86 backend to enable Intel CET.

All platforms except i386 will report the error and do no
instrumentation with -finstrument-control-flow option. i386 will provide
the implementation based on a specification published by Intel for a new
technology called Control-flow Enforcement Technology (CET). The spec is
available at

https://software.intel.com/sites/default/files/managed/4d/2a/control-flow-enforcement-technology-preview.pdf

The implementation in this patch:
1) enables Control-flow Enforcement Technology (CET), published by
Intel. This part introduces i386 specific options -mcet, -mibt and
-mshstk, new instructions and intrinsics;

2) provides support for -finstrument-control-flow option by doing needed
code instrumentation, which is based on CET features.

gcc/

	* common/config/i386/i386-common.c (OPTION_MASK_ISA_IBT_SET): New.
	(OPTION_MASK_ISA_SHSTK_SET): Likewise.
	(OPTION_MASK_ISA_IBT_UNSET): Likewise.
	(OPTION_MASK_ISA_SHSTK_UNSET): Likewise.
	(ix86_handle_option): Add -mibt, -mshstk, -mcet handling.
	* config.gcc (extra_headers): Add cetintrin.h for x86 targets.
	(extra_objs): Add cet.o for Linux/x86 targets.
	(tmake_file): Add i386/t-cet for Linux/x86 targets.
	* config/i386/cet.c: New file.
	* config/i386/cetintrin.h: Likewise.
	* config/i386/t-cet: Likewise.
	* config/i386/cpuid.h (bit_SHSTK): New.
	(bit_IBT): Likewise.
	* config/i386/driver-i386.c (host_detect_local_cpu): Detect and
	pass IBT and SHSTK bits.
	* config/i386/i386-builtin-types.def
	(VOID_FTYPE_UNSIGNED_PVOID): New.
	(VOID_FTYPE_UINT64_PVOID): Likewise.
	* config/i386/i386-builtin.def: Add CET intrinsics.
	* config/i386/i386-c.c (ix86_target_macros_internal): Add
	OPTION_MASK_ISA_IBT, OPTION_MASK_ISA_SHSTK handling.
	* config/i386/i386-passes.def: Add pass_insert_endbranch pass.
	* config/i386/i386-protos.h (make_pass_insert_endbranch): New
	prototype.
	* config/i386/i386.c (rest_of_insert_endbranch): New.
	(pass_data_insert_endbranch): Likewise.
	(pass_insert_endbranch): Likewise.
	(make_pass_insert_endbranch): Likewise.
	(ix86_notrack_prefixed_insn_p): Likewise.
	(ix86_target_string): Add -mibt, -mshstk flags.
	(ix86_option_override_internal): Add flag_instrument_control_flow
	processing.
	(ix86_valid_target_attribute_inner_p): Set OPT_mibt, OPT_mshstk.
	(ix86_print_operand): Add 'notrack' prefix output.
	(ix86_init_mmx_sse_builtins): Add CET intrinsics.
	(ix86_expand_builtin): Expand CET intrinsics.
	(x86_output_mi_thunk): Add 'endbranch' instruction.
	* config/i386/i386.h (TARGET_IBT): New.
	(TARGET_IBT_P): Likewise.
	(TARGET_SHSTK): Likewise.
	(TARGET_SHSTK_P): Likewise.
   	* config/i386/i386.md (unspecv): Add UNSPECV_NOP_RDSSP,
	UNSPECV_INCSSP, UNSPECV_SAVEPREVSSP, UNSPECV_RSTORSSP,
	UNSPECV_WRSS, UNSPECV_WRUSS, UNSPECV_SETSSBSY, UNSPECV_CLRSSBSY.
	(builtin_setjmp_setup): New pattern.
	(builtin_longjmp): Likewise.
	(rdssp<mode>): Likewise.
	(incssp<mode>): Likewise.
	(saveprevssp): Likewise.
	(rstorssp): Likewise.
	(wrss<mode>): Likewise.
	(wruss<mode>): Likewise.
	(setssbsy): Likewise.
	(clrssbsy): Likewise.
	(nop_endbr): Likewise.
	* config/i386/i386.opt: Add -mcet, -mibt, -mshstk and -mcet-switch
	options.
	* config/i386/immintrin.h: Include <cetintrin.h>.
	* config/i386/linux-common.h
	(file_end_indicate_exec_stack_and_cet): New prototype.
	(TARGET_ASM_FILE_END): New.
---
 gcc/common/config/i386/i386-common.c   |  33 ++++
 gcc/config.gcc                         |   7 +-
 gcc/config/i386/cet.c                  |  76 ++++++++
 gcc/config/i386/cetintrin.h            | 134 ++++++++++++++
 gcc/config/i386/cpuid.h                |   2 +
 gcc/config/i386/driver-i386.c          |   8 +-
 gcc/config/i386/i386-builtin-types.def |   2 +
 gcc/config/i386/i386-builtin.def       |  23 ++-
 gcc/config/i386/i386-c.c               |  12 ++
 gcc/config/i386/i386-passes.def        |   2 +
 gcc/config/i386/i386-protos.h          |   1 +
 gcc/config/i386/i386.c                 | 315 ++++++++++++++++++++++++++++++++-
 gcc/config/i386/i386.h                 |   4 +
 gcc/config/i386/i386.md                | 189 +++++++++++++++++++-
 gcc/config/i386/i386.opt               |  20 +++
 gcc/config/i386/immintrin.h            |   2 +
 gcc/config/i386/linux-common.h         |   5 +
 gcc/config/i386/t-cet                  |  21 +++
 18 files changed, 848 insertions(+), 8 deletions(-)
 create mode 100644 gcc/config/i386/cet.c
 create mode 100644 gcc/config/i386/cetintrin.h
 create mode 100644 gcc/config/i386/t-cet
---
 gcc/common/config/i386/i386-common.c   |  33 ++++
 gcc/config.gcc                         |   7 +-
 gcc/config/i386/cet.c                  |  76 ++++++++
 gcc/config/i386/cetintrin.h            | 134 ++++++++++++++
 gcc/config/i386/cpuid.h                |   2 +
 gcc/config/i386/driver-i386.c          |   8 +-
 gcc/config/i386/i386-builtin-types.def |   2 +
 gcc/config/i386/i386-builtin.def       |  23 ++-
 gcc/config/i386/i386-c.c               |  12 ++
 gcc/config/i386/i386-passes.def        |   2 +
 gcc/config/i386/i386-protos.h          |   1 +
 gcc/config/i386/i386.c                 | 315 ++++++++++++++++++++++++++++++++-
 gcc/config/i386/i386.h                 |   4 +
 gcc/config/i386/i386.md                | 189 +++++++++++++++++++-
 gcc/config/i386/i386.opt               |  20 +++
 gcc/config/i386/immintrin.h            |   2 +
 gcc/config/i386/linux-common.h         |   5 +
 gcc/config/i386/t-cet                  |  21 +++
 18 files changed, 848 insertions(+), 8 deletions(-)
 create mode 100644 gcc/config/i386/cet.c
 create mode 100644 gcc/config/i386/cetintrin.h
 create mode 100644 gcc/config/i386/t-cet

diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 4185176..774dc2c 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -137,6 +137,8 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA_CLZERO_SET OPTION_MASK_ISA_CLZERO
 #define OPTION_MASK_ISA_PKU_SET OPTION_MASK_ISA_PKU
 #define OPTION_MASK_ISA_RDPID_SET OPTION_MASK_ISA_RDPID
+#define OPTION_MASK_ISA_IBT_SET OPTION_MASK_ISA_IBT
+#define OPTION_MASK_ISA_SHSTK_SET OPTION_MASK_ISA_SHSTK
 
 /* Define a set of ISAs which aren't available when a given ISA is
    disabled.  MMX and SSE ISAs are handled separately.  */
@@ -202,6 +204,8 @@ along with GCC; see the file COPYING3.  If not see
 #define OPTION_MASK_ISA_CLZERO_UNSET OPTION_MASK_ISA_CLZERO
 #define OPTION_MASK_ISA_PKU_UNSET OPTION_MASK_ISA_PKU
 #define OPTION_MASK_ISA_RDPID_UNSET OPTION_MASK_ISA_RDPID
+#define OPTION_MASK_ISA_IBT_UNSET OPTION_MASK_ISA_IBT
+#define OPTION_MASK_ISA_SHSTK_UNSET OPTION_MASK_ISA_SHSTK
 
 /* SSE4 includes both SSE4.1 and SSE4.2.  -mno-sse4 should the same
    as -mno-sse4.1. */
@@ -484,6 +488,35 @@ ix86_handle_option (struct gcc_options *opts,
 	}
       return true;
 
+    case OPT_mcet:
+    case OPT_mibt:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_IBT_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_IBT_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_IBT_UNSET;
+	}
+      if (code != OPT_mcet)
+	return true;
+      /* fall through.  */
+
+    case OPT_mshstk:
+      if (value)
+	{
+	  opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_SHSTK_SET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_SET;
+	}
+      else
+	{
+	  opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_SHSTK_UNSET;
+	  opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_SHSTK_UNSET;
+	}
+      return true;
+
     case OPT_mavx5124fmaps:
       if (value)
 	{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index f281646..046e602 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -377,7 +377,7 @@ i[34567]86-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
 	;;
 x86_64-*-*)
 	cpu_type=i386
@@ -400,7 +400,7 @@ x86_64-*-*)
 		       avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
 		       avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
 		       avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
-		       clzerointrin.h pkuintrin.h sgxintrin.h"
+		       clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h"
 	;;
 ia64-*-*)
 	extra_headers=ia64intrin.h
@@ -4534,7 +4534,8 @@ case ${target} in
 	i[34567]86-*-darwin* | x86_64-*-darwin*)
 		;;
 	i[34567]86-*-linux* | x86_64-*-linux*)
-		tmake_file="$tmake_file i386/t-linux"
+		extra_objs="${extra_objs} cet.o"
+		tmake_file="$tmake_file i386/t-linux i386/t-cet"
 		;;
 	i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
 		tmake_file="$tmake_file i386/t-kfreebsd"
diff --git a/gcc/config/i386/cet.c b/gcc/config/i386/cet.c
new file mode 100644
index 0000000..e725ca6
--- /dev/null
+++ b/gcc/config/i386/cet.c
@@ -0,0 +1,76 @@
+/* Functions for CET/x86.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "output.h"
+#include "linux-common.h"
+
+void
+file_end_indicate_exec_stack_and_cet (void)
+{
+  file_end_indicate_exec_stack ();
+
+  if (!flag_instrument_control_flow)
+    return;
+
+  unsigned int feature_1 = 0;
+
+  if (TARGET_IBT)
+    /* GNU_PROPERTY_X86_FEATURE_1_IBT.  */
+    feature_1 |= 0x1;
+
+  if (TARGET_SHSTK)
+    /* GNU_PROPERTY_X86_FEATURE_1_SHSTK.  */
+    feature_1 |= 0x2;
+
+  if (feature_1)
+    {
+      int p2align = ptr_mode == SImode ? 2 : 3;
+
+      /* Generate GNU_PROPERTY_X86_FEATURE_1_XXX.  */
+      switch_to_section (get_section (".note.gnu.property",
+				      SECTION_NOTYPE, NULL));
+
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      /* name length.  */
+      fprintf (asm_out_file, ASM_LONG " 1f - 0f\n");
+      /* data length.  */
+      fprintf (asm_out_file, ASM_LONG " 4f - 1f\n");
+      /* note type: NT_GNU_PROPERTY_TYPE_0.  */
+      fprintf (asm_out_file, ASM_LONG " 5\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "0");
+      /* vendor name: "GNU".  */
+      fprintf (asm_out_file, STRING_ASM_OP " \"GNU\"\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "1");
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      /* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND.  */
+      fprintf (asm_out_file, ASM_LONG " 0xc0000002\n");
+      /* pr_datasz.  */\
+      fprintf (asm_out_file, ASM_LONG " 3f - 2f\n");
+      ASM_OUTPUT_LABEL (asm_out_file, "2");
+      /* GNU_PROPERTY_X86_FEATURE_1_XXX.  */
+      fprintf (asm_out_file, ASM_LONG " 0x%x\n", feature_1);
+      ASM_OUTPUT_LABEL (asm_out_file, "3");
+      ASM_OUTPUT_ALIGN (asm_out_file, p2align);
+      ASM_OUTPUT_LABEL (asm_out_file, "4");
+    }
+}
diff --git a/gcc/config/i386/cetintrin.h b/gcc/config/i386/cetintrin.h
new file mode 100644
index 0000000..b15a776
--- /dev/null
+++ b/gcc/config/i386/cetintrin.h
@@ -0,0 +1,134 @@
+/* Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if !defined _IMMINTRIN_H_INCLUDED
+# error "Never use <cetintrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _CETINTRIN_H_INCLUDED
+#define _CETINTRIN_H_INCLUDED
+
+#ifndef __SHSTK__
+#pragma GCC push_options
+#pragma GCC target ("shstk")
+#define __DISABLE_SHSTK__
+#endif /* __SHSTK__ */
+
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdsspd (unsigned int __B)
+{
+  return __builtin_ia32_rdsspd (__B);
+}
+
+#ifdef __x86_64__
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rdsspq (unsigned long long __B)
+{
+  return __builtin_ia32_rdsspq (__B);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_incsspd (unsigned int __B)
+{
+  __builtin_ia32_incsspd (__B);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_incsspq (unsigned long long __B)
+{
+  __builtin_ia32_incsspq (__B);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_saveprevssp (void)
+{
+  __builtin_ia32_saveprevssp ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_rstorssp (void *__B)
+{
+  __builtin_ia32_rstorssp (__B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrssd (unsigned int __B, void *__C)
+{
+  __builtin_ia32_wrssd (__B, __C);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrssq (unsigned long long __B, void *__C)
+{
+  __builtin_ia32_wrssq (__B, __C);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrussd (unsigned int __B, void *__C)
+{
+  __builtin_ia32_wrussd (__B, __C);
+}
+
+#ifdef __x86_64__
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_wrussq (unsigned long long __B, void *__C)
+{
+  __builtin_ia32_wrussq (__B, __C);
+}
+#endif
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_setssbsy (void)
+{
+  __builtin_ia32_setssbsy ();
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_clrssbsy (void *__B)
+{
+  __builtin_ia32_clrssbsy (__B);
+}
+
+#ifdef __DISABLE_SHSTK__
+#undef __DISABLE_SHSTK__
+#pragma GCC pop_options
+#endif /* __DISABLE_SHSTK__ */
+
+#endif /* _CETINTRIN_H_INCLUDED.  */
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index b3b0f91..0053a32 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -97,12 +97,14 @@
 #define bit_AVX512VBMI	(1 << 1)
 #define bit_PKU	(1 << 3)
 #define bit_OSPKE	(1 << 4)
+#define bit_SHSTK	(1 << 7)
 #define bit_AVX512VPOPCNTDQ	(1 << 14)
 #define bit_RDPID	(1 << 22)
 
 /* %edx */
 #define bit_AVX5124VNNIW (1 << 2)
 #define bit_AVX5124FMAPS (1 << 3)
+#define bit_IBT	(1 << 20)
 
 /* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */
 #define bit_BNDREGS     (1 << 3)
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 570c490..a4b8091 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -415,6 +415,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
   unsigned int has_avx512vbmi = 0, has_avx512ifma = 0, has_clwb = 0;
   unsigned int has_mwaitx = 0, has_clzero = 0, has_pku = 0, has_rdpid = 0;
   unsigned int has_avx5124fmaps = 0, has_avx5124vnniw = 0;
+  unsigned int has_ibt = 0, has_shstk = 0;
 
   bool arch;
 
@@ -507,6 +508,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 
       has_avx5124vnniw = edx & bit_AVX5124VNNIW;
       has_avx5124fmaps = edx & bit_AVX5124FMAPS;
+
+      has_shstk = ecx & bit_SHSTK;
+      has_ibt = edx & bit_IBT;
     }
 
   if (max_level >= 13)
@@ -1041,6 +1045,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
       const char *clzero  = has_clzero  ? " -mclzero"  : " -mno-clzero";
       const char *pku = has_pku ? " -mpku" : " -mno-pku";
       const char *rdpid = has_rdpid ? " -mrdpid" : " -mno-rdpid";
+      const char *ibt = has_ibt ? " -mibt" : " -mno-ibt";
+      const char *shstk = has_shstk ? " -mshstk" : " -mno-shstk";
       options = concat (options, mmx, mmx3dnow, sse, sse2, sse3, ssse3,
 			sse4a, cx16, sahf, movbe, aes, sha, pclmul,
 			popcnt, abm, lwp, fma, fma4, xop, bmi, sgx, bmi2,
@@ -1050,7 +1056,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
 			avx512cd, avx512pf, prefetchwt1, clflushopt,
 			xsavec, xsaves, avx512dq, avx512bw, avx512vl,
 			avx512ifma, avx512vbmi, avx5124fmaps, avx5124vnniw,
-			clwb, mwaitx, clzero, pku, rdpid, NULL);
+			clwb, mwaitx, clzero, pku, rdpid, ibt, shstk, NULL);
     }
 
 done:
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 8d584db..1c0c6b4 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -286,7 +286,9 @@ DEF_FUNCTION_TYPE (V8SI, V8SI)
 DEF_FUNCTION_TYPE (VOID, PCVOID)
 DEF_FUNCTION_TYPE (VOID, PVOID)
 DEF_FUNCTION_TYPE (VOID, UINT64)
+DEF_FUNCTION_TYPE (VOID, UINT64, PVOID)
 DEF_FUNCTION_TYPE (VOID, UNSIGNED)
+DEF_FUNCTION_TYPE (VOID, UNSIGNED, PVOID)
 DEF_FUNCTION_TYPE (INT, PUSHORT)
 DEF_FUNCTION_TYPE (INT, PUNSIGNED)
 DEF_FUNCTION_TYPE (INT, PULONGLONG)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index e91468a..77a86c5 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -2779,4 +2779,25 @@ BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4sf3,     "__builtin_ia32_vper
 BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v4df3,     "__builtin_ia32_vpermil2pd256", IX86_BUILTIN_VPERMIL2PD256, UNKNOWN, (int)MULTI_ARG_4_DF2_DI_I1)
 BDESC (OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v8sf3,     "__builtin_ia32_vpermil2ps256", IX86_BUILTIN_VPERMIL2PS256, UNKNOWN, (int)MULTI_ARG_4_SF2_SI_I1)
 
-BDESC_END (MULTI_ARG, MAX)
+BDESC_END (MULTI_ARG, CET)
+
+/* CET.  */
+BDESC_FIRST (cet, CET,
+       OPTION_MASK_ISA_SHSTK, CODE_FOR_incsspsi, "__builtin_ia32_incsspd", IX86_BUILTIN_INCSSPD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_incsspdi, "__builtin_ia32_incsspq", IX86_BUILTIN_INCSSPQ, UNKNOWN, (int) VOID_FTYPE_UINT64)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_saveprevssp, "__builtin_ia32_saveprevssp", IX86_BUILTIN_SAVEPREVSSP, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_rstorssp, "__builtin_ia32_rstorssp", IX86_BUILTIN_RSTORSSP, UNKNOWN, (int) VOID_FTYPE_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrsssi, "__builtin_ia32_wrssd", IX86_BUILTIN_WRSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrssdi, "__builtin_ia32_wrssq", IX86_BUILTIN_WRSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_wrusssi, "__builtin_ia32_wrussd", IX86_BUILTIN_WRUSSD, UNKNOWN, (int) VOID_FTYPE_UNSIGNED_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_wrussdi, "__builtin_ia32_wrussq", IX86_BUILTIN_WRUSSQ, UNKNOWN, (int) VOID_FTYPE_UINT64_PVOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_setssbsy, "__builtin_ia32_setssbsy", IX86_BUILTIN_SETSSBSY, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_SHSTK, CODE_FOR_clrssbsy, "__builtin_ia32_clrssbsy", IX86_BUILTIN_CLRSSBSY, UNKNOWN, (int) VOID_FTYPE_PVOID)
+
+BDESC_END (CET, CET_NORMAL)
+
+BDESC_FIRST (cet_rdssp, CET_NORMAL,
+       OPTION_MASK_ISA_SHSTK, CODE_FOR_rdsspsi, "__builtin_ia32_rdsspd", IX86_BUILTIN_RDSSPD, UNKNOWN, (int) UINT_FTYPE_UINT)
+BDESC (OPTION_MASK_ISA_SHSTK | OPTION_MASK_ISA_64BIT, CODE_FOR_rdsspdi, "__builtin_ia32_rdsspq", IX86_BUILTIN_RDSSPQ, UNKNOWN, (int) UINT64_FTYPE_UINT64)
+
+BDESC_END (CET_NORMAL, MAX)
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 9a79a21..765a5d8 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -450,6 +450,18 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__PKU__");
   if (isa_flag2 & OPTION_MASK_ISA_RDPID)
     def_or_undef (parse_in, "__RDPID__");
+  if (isa_flag2 & OPTION_MASK_ISA_IBT)
+    {
+      def_or_undef (parse_in, "__IBT__");
+      if (flag_instrument_control_flow)
+	def_or_undef (parse_in, "__CET__");
+    }
+  if (isa_flag2 & OPTION_MASK_ISA_SHSTK)
+    {
+      def_or_undef (parse_in, "__SHSTK__");
+      if (flag_instrument_control_flow)
+	def_or_undef (parse_in, "__CET__");
+    }
   if (TARGET_IAMCU)
     {
       def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386-passes.def b/gcc/config/i386/i386-passes.def
index 4953461..5c6e9c3 100644
--- a/gcc/config/i386/i386-passes.def
+++ b/gcc/config/i386/i386-passes.def
@@ -29,3 +29,5 @@ along with GCC; see the file COPYING3.  If not see
   /* Run the 64-bit STV pass before the CSE pass so that CONST0_RTX and
      CONSTM1_RTX generated by the STV pass can be CSEed.  */
   INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
+
+  INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_insert_endbranch);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index bf8a049..e61f4b3 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -344,3 +344,4 @@ class rtl_opt_pass;
 
 extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
 extern rtl_opt_pass *make_pass_stv (gcc::context *);
+extern rtl_opt_pass *make_pass_insert_endbranch (gcc::context *);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f1486ff..26456d5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -94,6 +94,8 @@ static rtx legitimize_pe_coff_extern_decl (rtx, bool);
 static rtx legitimize_pe_coff_symbol (rtx, bool);
 static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool);
 static bool ix86_save_reg (unsigned int, bool, bool);
+static bool ix86_notrack_prefixed_insn_p (rtx);
+
 
 #ifndef CHECK_STACK_LIMIT
 #define CHECK_STACK_LIMIT (-1)
@@ -4616,6 +4618,150 @@ make_pass_stv (gcc::context *ctxt)
   return new pass_stv (ctxt);
 }
 
+/* Inserting ENDBRANCH instructions.  */
+
+static unsigned int
+rest_of_insert_endbranch (void)
+{
+  timevar_push (TV_MACH_DEP);
+
+  rtx cet_eb;
+  rtx_insn *insn;
+  basic_block bb;
+
+  /* Currently emit EB if it's a tracking function, i.e. 'notrack' is
+     absent among function attributes.  Later an optimization will be
+     introduced to make analysis if an address of a static function is
+     taken.  A static function whose address is not taken will get a
+     notrack attribute.  This will allow to reduce the number of EB.  */
+
+  if (!lookup_attribute ("notrack",
+			 TYPE_ATTRIBUTES (TREE_TYPE (cfun->decl))))
+    {
+      cet_eb = gen_nop_endbr ();
+
+      bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+      insn = BB_HEAD (bb);
+      emit_insn_before (cet_eb, insn);
+    }
+
+  bb = 0;
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
+	   insn = NEXT_INSN (insn))
+	{
+	  if (INSN_P (insn) && GET_CODE (insn) == CALL_INSN)
+	    {
+	      rtx_insn *next_insn = insn;
+
+	      while ((next_insn != BB_END (bb))
+		      && (DEBUG_INSN_P (NEXT_INSN (next_insn))
+			  || NOTE_P (NEXT_INSN (next_insn))
+			  || BARRIER_P (NEXT_INSN (next_insn))))
+		next_insn = NEXT_INSN (next_insn);
+
+	      /* Generate ENDBRANCH after CALL, which can return more than
+		 twice, setjmp-like functions.  */
+	      if (find_reg_note (insn, REG_SETJMP, NULL) != NULL)
+		{
+		  cet_eb = gen_nop_endbr ();
+		  emit_insn_after (cet_eb, next_insn);
+		}
+	      continue;
+	    }
+
+	  if (INSN_P (insn) && JUMP_P (insn) && flag_cet_switch)
+	    {
+	      rtx target = JUMP_LABEL (insn);
+	      if (target == NULL_RTX || ANY_RETURN_P (target))
+		continue;
+
+	      /* Check the jump is a switch table.  */
+	      rtx_insn *label = as_a<rtx_insn *> (target);
+	      rtx_insn *table = next_insn (label);
+	      if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
+		continue;
+
+	      /* For the indirect jump find out all places it jumps and insert
+		 ENDBRANCH there.  It should be done under a special flag to
+		 control ENDBRANCH generation for switch stmts.  */
+	      edge_iterator ei;
+	      edge e;
+	      basic_block dest_blk;
+
+	      FOR_EACH_EDGE (e, ei, bb->succs)
+		{
+		  rtx_insn *insn;
+
+		  dest_blk = e->dest;
+		  insn = BB_HEAD (dest_blk);
+		  gcc_assert (LABEL_P (insn));
+		  cet_eb = gen_nop_endbr ();
+		  emit_insn_after (cet_eb, insn);
+		}
+	      continue;
+	    }
+
+	  if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn))
+	      || (NOTE_P (insn)
+		  && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
+/* TODO.  Check /s bit also.  */
+	    {
+	      cet_eb = gen_nop_endbr ();
+	      emit_insn_after (cet_eb, insn);
+	      continue;
+	    }
+	}
+    }
+
+  timevar_pop (TV_MACH_DEP);
+  return 0;
+}
+
+namespace {
+
+const pass_data pass_data_insert_endbranch =
+{
+  RTL_PASS, /* type.  */
+  "cet", /* name.  */
+  OPTGROUP_NONE, /* optinfo_flags.  */
+  TV_MACH_DEP, /* tv_id.  */
+  0, /* properties_required.  */
+  0, /* properties_provided.  */
+  0, /* properties_destroyed.  */
+  0, /* todo_flags_start.  */
+  0, /* todo_flags_finish.  */
+};
+
+class pass_insert_endbranch : public rtl_opt_pass
+{
+public:
+  pass_insert_endbranch (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_insert_endbranch, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      return (flag_instrument_control_flow && TARGET_IBT);
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return rest_of_insert_endbranch ();
+    }
+
+}; // class pass_insert_endbranch
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_insert_endbranch (gcc::context *ctxt)
+{
+  return new pass_insert_endbranch (ctxt);
+}
+
 /* Return true if a red-zone is in use.  */
 
 bool
@@ -4647,7 +4793,9 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
     { "-msgx",		OPTION_MASK_ISA_SGX },
     { "-mavx5124vnniw", OPTION_MASK_ISA_AVX5124VNNIW },
     { "-mavx5124fmaps", OPTION_MASK_ISA_AVX5124FMAPS },
-    { "-mavx512vpopcntdq", OPTION_MASK_ISA_AVX512VPOPCNTDQ }
+    { "-mavx512vpopcntdq", OPTION_MASK_ISA_AVX512VPOPCNTDQ },
+    { "-mibt",	OPTION_MASK_ISA_IBT },
+    { "-mshstk",	OPTION_MASK_ISA_SHSTK }
   };
   static struct ix86_target_opts isa_opts[] =
   {
@@ -6678,6 +6826,21 @@ ix86_option_override_internal (bool main_args_p,
       free (str);
     }
 
+  /* Do not support control flow instrumentation if CET is not enabled.  */
+  if (opts->x_flag_instrument_control_flow > 0)
+    {
+      if (!(TARGET_IBT_P (opts->x_ix86_isa_flags2)
+	    || TARGET_SHSTK_P (opts->x_ix86_isa_flags2)))
+	{
+	  error ("%<-finstrument-control-flow%> requires CET support "
+		 "on this target. Use -mcet or one of -mibt, -mshstk "
+		 "options to enable CET.");
+	  opts->x_flag_instrument_control_flow = 0;
+	  return false;
+	}
+      opts->x_flag_instrument_control_flow = 2;
+    }
+
   return true;
 }
 
@@ -7083,6 +7246,8 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[],
     IX86_ATTR_ISA ("mpx",	OPT_mmpx),
     IX86_ATTR_ISA ("clwb",	OPT_mclwb),
     IX86_ATTR_ISA ("rdpid",	OPT_mrdpid),
+    IX86_ATTR_ISA ("ibt",	OPT_mibt),
+    IX86_ATTR_ISA ("shstk",	OPT_mshstk),
 
     /* enum options */
     IX86_ATTR_ENUM ("fpmath=",	OPT_mfpmath_),
@@ -19188,6 +19353,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
 	case '!':
 	  if (ix86_bnd_prefixed_insn_p (current_output_insn))
 	    fputs ("bnd ", file);
+	  if (ix86_notrack_prefixed_insn_p (current_output_insn))
+	    fputs ("notrack ", file);
 	  return;
 
 	default:
@@ -32417,8 +32584,12 @@ BDESC_VERIFYS (IX86_BUILTIN__BDESC_MPX_CONST_FIRST,
 	       IX86_BUILTIN__BDESC_MPX_LAST, 1);
 BDESC_VERIFYS (IX86_BUILTIN__BDESC_MULTI_ARG_FIRST,
 	       IX86_BUILTIN__BDESC_MPX_CONST_LAST, 1);
-BDESC_VERIFYS (IX86_BUILTIN_MAX,
+BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_FIRST,
 	       IX86_BUILTIN__BDESC_MULTI_ARG_LAST, 1);
+BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_NORMAL_FIRST,
+	       IX86_BUILTIN__BDESC_CET_LAST, 1);
+BDESC_VERIFYS (IX86_BUILTIN_MAX,
+	       IX86_BUILTIN__BDESC_CET_NORMAL_LAST, 1);
 
 /* Set up all the MMX/SSE builtins, even builtins for instructions that are not
    in the current target ISA to allow the user to compile particular modules
@@ -33079,6 +33250,35 @@ ix86_init_mmx_sse_builtins (void)
   BDESC_VERIFYS (IX86_BUILTIN__BDESC_MULTI_ARG_LAST,
 		 IX86_BUILTIN__BDESC_MULTI_ARG_FIRST,
 		 ARRAY_SIZE (bdesc_multi_arg) - 1);
+
+  /* Add CET inrinsics.  */
+  for (i = 0, d = bdesc_cet; i < ARRAY_SIZE (bdesc_cet); i++, d++)
+    {
+      BDESC_VERIFY (d->code, IX86_BUILTIN__BDESC_CET_FIRST, i);
+      if (d->name == 0)
+	continue;
+
+      ftype = (enum ix86_builtin_func_type) d->flag;
+      def_builtin2 (d->mask, d->name, ftype, d->code);
+    }
+  BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_LAST,
+		 IX86_BUILTIN__BDESC_CET_FIRST,
+		 ARRAY_SIZE (bdesc_cet) - 1);
+
+  for (i = 0, d = bdesc_cet_rdssp;
+       i < ARRAY_SIZE (bdesc_cet_rdssp);
+       i++, d++)
+    {
+      BDESC_VERIFY (d->code, IX86_BUILTIN__BDESC_CET_NORMAL_FIRST, i);
+      if (d->name == 0)
+	continue;
+
+      ftype = (enum ix86_builtin_func_type) d->flag;
+      def_builtin2 (d->mask, d->name, ftype, d->code);
+    }
+  BDESC_VERIFYS (IX86_BUILTIN__BDESC_CET_NORMAL_LAST,
+		 IX86_BUILTIN__BDESC_CET_NORMAL_FIRST,
+		 ARRAY_SIZE (bdesc_cet_rdssp) - 1);
 }
 
 static void
@@ -39246,6 +39446,57 @@ rdseed_step:
       emit_insn (gen_xabort (op0));
       return 0;
 
+    case IX86_BUILTIN_RSTORSSP:
+    case IX86_BUILTIN_CLRSSBSY:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+      icode = (fcode == IX86_BUILTIN_RSTORSSP
+	  ? CODE_FOR_rstorssp
+	  : CODE_FOR_clrssbsy);
+      if (!address_operand (op0, VOIDmode))
+	{
+	  op1 = convert_memory_address (Pmode, op0);
+	  op0 = copy_addr_to_reg (op1);
+	}
+      emit_insn (GEN_FCN (icode) (gen_rtx_MEM (Pmode, op0)));
+      return 0;
+
+    case IX86_BUILTIN_WRSSD:
+    case IX86_BUILTIN_WRSSQ:
+    case IX86_BUILTIN_WRUSSD:
+    case IX86_BUILTIN_WRUSSQ:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = expand_normal (arg0);
+      arg1 = CALL_EXPR_ARG (exp, 1);
+      op1 = expand_normal (arg1);
+      switch (fcode)
+	{
+	case IX86_BUILTIN_WRSSD:
+	  icode = CODE_FOR_wrsssi;
+	  mode = SImode;
+	  break;
+	case IX86_BUILTIN_WRSSQ:
+	  icode = CODE_FOR_wrssdi;
+	  mode = DImode;
+	  break;
+	case IX86_BUILTIN_WRUSSD:
+	  icode = CODE_FOR_wrusssi;
+	  mode = SImode;
+	  break;
+	case IX86_BUILTIN_WRUSSQ:
+	  icode = CODE_FOR_wrussdi;
+	  mode = DImode;
+	  break;
+	}
+      op0 = force_reg (mode, op0);
+      if (!address_operand (op1, VOIDmode))
+	{
+	  op2 = convert_memory_address (Pmode, op1);
+	  op1 = copy_addr_to_reg (op2);
+	}
+      emit_insn (GEN_FCN (icode) (op0, gen_rtx_MEM (mode, op1)));
+      return 0;
+
     default:
       break;
     }
@@ -39548,6 +39799,22 @@ s4fma_expand:
 					    d->flag, d->comparison);
     }
 
+  if (fcode >= IX86_BUILTIN__BDESC_CET_FIRST
+      && fcode <= IX86_BUILTIN__BDESC_CET_LAST)
+    {
+      i = fcode - IX86_BUILTIN__BDESC_CET_FIRST;
+      return ix86_expand_special_args_builtin (bdesc_cet + i, exp,
+					       target);
+    }
+
+  if (fcode >= IX86_BUILTIN__BDESC_CET_NORMAL_FIRST
+      && fcode <= IX86_BUILTIN__BDESC_CET_NORMAL_LAST)
+    {
+      i = fcode - IX86_BUILTIN__BDESC_CET_NORMAL_FIRST;
+      return ix86_expand_args_builtin (bdesc_cet_rdssp + i, exp,
+				       target);
+    }
+
   gcc_unreachable ();
 }
 
@@ -42355,6 +42622,10 @@ 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_instrument_control_flow && TARGET_IBT)
+    emit_insn (gen_nop_endbr ());
+
   /* If VCALL_OFFSET, we'll need THIS in a register.  Might as well
      pull it in now and let DELTA benefit.  */
   if (REG_P (this_param))
@@ -50100,6 +50371,46 @@ ix86_bnd_prefixed_insn_p (rtx insn)
   return chkp_function_instrumented_p (current_function_decl);
 }
 
+/* Return 1 if control tansfer instruction INSN
+   should be encoded with notrack prefix.  */
+
+static bool
+ix86_notrack_prefixed_insn_p (rtx insn)
+{
+  if (!insn || !(flag_instrument_control_flow && TARGET_IBT))
+    return false;
+
+  if (CALL_P (insn))
+    {
+      rtx call = get_call_rtx_from (insn);
+      gcc_assert (call != NULL_RTX);
+      rtx addr = XEXP (call, 0);
+
+      /* Do not emit 'notrack' if it's not an indirect call.  */
+      if (MEM_P (addr)
+	  && GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
+	return false;
+      else
+	return find_reg_note (insn, REG_CALL_NOTRACK, 0);
+    }
+
+  if (JUMP_P (insn) && !flag_cet_switch)
+    {
+      rtx target = JUMP_LABEL (insn);
+      if (target == NULL_RTX || ANY_RETURN_P (target))
+	return false;
+
+      /* Check the jump is a switch table.  */
+      rtx_insn *label = as_a<rtx_insn *> (target);
+      rtx_insn *table = next_insn (label);
+      if (table == NULL_RTX || !JUMP_TABLE_DATA_P (table))
+	return false;
+      else
+	return true;
+    }
+  return false;
+}
+
 /* Calculate integer abs() using only SSE2 instructions.  */
 
 void
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 682745a..b2edede 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -168,6 +168,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_MWAITX_P(x)	TARGET_ISA_MWAITX_P(x)
 #define TARGET_PKU	TARGET_ISA_PKU
 #define TARGET_PKU_P(x)	TARGET_ISA_PKU_P(x)
+#define TARGET_IBT	TARGET_ISA_IBT
+#define TARGET_IBT_P(x)	TARGET_ISA_IBT_P(x)
+#define TARGET_SHSTK	TARGET_ISA_SHSTK
+#define TARGET_SHSTK_P(x)	TARGET_ISA_SHSTK_P(x)
 
 #define TARGET_LP64	TARGET_ABI_64
 #define TARGET_LP64_P(x)	TARGET_ABI_64_P(x)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 5eff4e4..bfb200d 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -63,7 +63,7 @@
 ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
 ;; @ -- print a segment register of thread base pointer load
 ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
-;; ! -- print MPX prefix for jxx/call/ret instructions if required.
+;; ! -- print MPX or NOTRACK prefix for jxx/call/ret instructions if required.
 
 (define_c_enum "unspec" [
   ;; Relocation specifiers
@@ -277,6 +277,17 @@
 
   ;; For RDPID support
   UNSPECV_RDPID
+
+  ;; For CET support
+  UNSPECV_NOP_ENDBR
+  UNSPECV_NOP_RDSSP
+  UNSPECV_INCSSP
+  UNSPECV_SAVEPREVSSP
+  UNSPECV_RSTORSSP
+  UNSPECV_WRSS
+  UNSPECV_WRUSS
+  UNSPECV_SETSSBSY
+  UNSPECV_CLRSSBSY
 ])
 
 ;; Constants to represent rounding modes in the ROUND instruction
@@ -17637,6 +17648,28 @@
   "* return output_probe_stack_range (operands[0], operands[2]);"
   [(set_attr "type" "multi")])
 
+/* Additional processing for builtin_setjmp.  Store the shadow stack pointer
+   as a forth element in jmpbuf.  */
+(define_expand "builtin_setjmp_setup"
+  [(match_operand 0 "address_operand")]
+  "TARGET_SHSTK"
+{
+  if (flag_instrument_control_flow)
+    {
+      rtx mem, reg_ssp;
+
+      mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+					       3 * GET_MODE_SIZE (Pmode)));
+      reg_ssp = gen_reg_rtx (Pmode);
+      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      emit_insn ((Pmode == SImode)
+		  ? gen_rdsspsi (reg_ssp, reg_ssp)
+		  : gen_rdsspdi (reg_ssp, reg_ssp));
+      emit_move_insn (mem, reg_ssp);
+    }
+  DONE;
+})
+
 (define_expand "builtin_setjmp_receiver"
   [(label_ref (match_operand 0))]
   "!TARGET_64BIT && flag_pic"
@@ -17657,6 +17690,83 @@
   DONE;
 })
 
+(define_expand "builtin_longjmp"
+  [(match_operand 0 "address_operand")]
+  "TARGET_SHSTK"
+{
+  rtx fp, lab, stack;
+  rtx jump, label, reg_adj, reg_ssp, reg_minus, mem_buf, tmp, clob;
+  machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
+
+  /* Adjust the shadow stack pointer (ssp) to the value saved in the
+     jmp_buf.  The saving was done in the builtin_setjmp_setup.  */
+  if (flag_instrument_control_flow)
+    {
+      /* Get current shadow stack pointer.  The code below will check if
+	 SHSTK feature is enabled.  If it's not enabled RDSSP instruction
+	 is a NOP.  */
+      reg_ssp = gen_reg_rtx (Pmode);
+      emit_insn (gen_rtx_SET (reg_ssp, const0_rtx));
+      emit_insn ((Pmode == SImode)
+		 ? gen_rdsspsi (reg_ssp, reg_ssp)
+		 : gen_rdsspdi (reg_ssp, reg_ssp));
+      mem_buf = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+						   3 * GET_MODE_SIZE (Pmode))),
+
+      /* Compare through substraction the saved and the current ssp to decide
+	 if ssp has to be adjusted.  */
+      reg_minus = gen_reg_rtx (Pmode);
+      tmp = gen_rtx_SET (reg_minus, gen_rtx_MINUS (Pmode, reg_ssp, mem_buf));
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+      emit_insn (tmp);
+
+      /* Jump over adjustment code.  */
+      label = gen_label_rtx ();
+      tmp = gen_rtx_REG (CCmode, FLAGS_REG);
+      tmp = gen_rtx_EQ (VOIDmode, tmp, const0_rtx);
+      tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+				  gen_rtx_LABEL_REF (VOIDmode, label),
+				  pc_rtx);
+      jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+      JUMP_LABEL (jump) = label;
+
+      /* Adjust the ssp.  */
+      reg_adj = gen_reg_rtx (Pmode);
+      tmp = gen_rtx_SET (reg_adj,
+			 gen_rtx_LSHIFTRT (Pmode, negate_rtx (Pmode, reg_minus),
+					   GEN_INT (3)));
+      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+      tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
+      emit_insn (tmp);
+      emit_insn ((Pmode == SImode)
+		 ? gen_incsspsi (reg_adj)
+		 : gen_incsspdi (reg_adj));
+
+      emit_label (label);
+      LABEL_NUSES (label) = 1;
+    }
+
+  /* This code is the same as in expand_buildin_longjmp.  */
+  fp = gen_rtx_MEM (Pmode, operands[0]);
+  lab = gen_rtx_MEM (Pmode, plus_constant (Pmode, operands[0],
+					   GET_MODE_SIZE (Pmode)));
+  stack = gen_rtx_MEM (sa_mode, plus_constant (Pmode, operands[0],
+					       2 * GET_MODE_SIZE (Pmode)));
+  lab = copy_to_reg (lab);
+
+  emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
+  emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+
+  emit_move_insn (hard_frame_pointer_rtx, fp);
+  emit_stack_restore (SAVE_NONLOCAL, stack);
+
+  emit_use (hard_frame_pointer_rtx);
+  emit_use (stack_pointer_rtx);
+  emit_indirect_jump (lab);
+})
+
+
 ;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
 ;; Do not split instructions with mask registers.
 (define_split
@@ -19299,6 +19409,83 @@
   [(set_attr "length" "2")
    (set_attr "memory" "unknown")])
 
+;; CET instructions
+(define_insn "rdssp<mode>"
+  [(set (match_operand:SWI48x 0 "register_operand" "=r")
+	(unspec_volatile:SWI48x
+	  [(match_operand:SWI48x 1 "register_operand" "0")]
+	  UNSPECV_NOP_RDSSP))]
+  "TARGET_SHSTK"
+  "rdssp<mskmodesuffix>\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "incssp<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")]
+		   UNSPECV_INCSSP)]
+  "TARGET_SHSTK"
+  "incssp<mskmodesuffix>\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "saveprevssp"
+  [(unspec_volatile [(const_int 0)] UNSPECV_SAVEPREVSSP)]
+  "TARGET_SHSTK"
+  "saveprevssp"
+  [(set_attr "length" "5")
+   (set_attr "type" "other")])
+
+(define_insn "rstorssp"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+		   UNSPECV_RSTORSSP)]
+  "TARGET_SHSTK"
+  "rstorssp\t%0"
+  [(set_attr "length" "5")
+   (set_attr "type" "other")])
+
+(define_insn "wrss<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+		     (match_operand:SWI48x 1 "memory_operand" "m")]
+		   UNSPECV_WRSS)]
+  "TARGET_SHSTK"
+  "wrss<mskmodesuffix>\t%0, %1"
+  [(set_attr "length" "3")
+   (set_attr "type" "other")])
+
+(define_insn "wruss<mode>"
+  [(unspec_volatile [(match_operand:SWI48x 0 "register_operand" "r")
+		     (match_operand:SWI48x 1 "memory_operand" "m")]
+		   UNSPECV_WRUSS)]
+  "TARGET_SHSTK"
+  "wruss<mskmodesuffix>\t%0, %1"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "setssbsy"
+  [(unspec_volatile [(const_int 0)] UNSPECV_SETSSBSY)]
+  "TARGET_SHSTK"
+  "setssbsy"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "clrssbsy"
+  [(unspec_volatile [(match_operand 0 "memory_operand" "m")]
+		   UNSPECV_CLRSSBSY)]
+  "TARGET_SHSTK"
+  "clrssbsy\t%0"
+  [(set_attr "length" "4")
+   (set_attr "type" "other")])
+
+(define_insn "nop_endbr"
+  [(unspec_volatile [(const_int 0)] UNSPECV_NOP_ENDBR)]
+  "TARGET_IBT"
+  "*
+{ return (TARGET_64BIT)? \"endbr64\" : \"endbr32\"; }"
+  [(set_attr "length" "4")
+   (set_attr "length_immediate" "0")
+   (set_attr "modrm" "0")])
+
+;; For RTM support
 (define_expand "xbegin"
   [(set (match_operand:SI 0 "register_operand")
 	(unspec_volatile:SI [(const_int 0)] UNSPECV_XBEGIN))]
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index adc75f3..d210ec6 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -931,3 +931,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.
+
+mcet
+Target Report Var(flag_cet) Init(0)
+Support Control-flow  Enforcment Technology (CET) built-in functions
+and code generation.
+
+mibt
+Target Report Mask(ISA_IBT) Var(ix86_isa_flags2) Save
+Specifically enables an indirect branch tracking feature from Control-flow
+Enforcment Technology (CET).
+
+mshstk
+Target Report Mask(ISA_SHSTK) Var(ix86_isa_flags2) Save
+Specifically enables an shadow stack support feature from Control-flow
+Enforcment Technology (CET).
+
+mcet-switch
+Target Report Undocumented Var(flag_cet_switch) Init(0)
+Turn on CET instrumentation for switch statements, which use jump table and
+indirect jump.
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index b52f58e..696cd20 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -90,6 +90,8 @@
 
 #include <xtestintrin.h>
 
+#include <cetintrin.h>
+
 #ifndef __RDRND__
 #pragma GCC push_options
 #pragma GCC target("rdrnd")
diff --git a/gcc/config/i386/linux-common.h b/gcc/config/i386/linux-common.h
index 6380639..6613807 100644
--- a/gcc/config/i386/linux-common.h
+++ b/gcc/config/i386/linux-common.h
@@ -121,3 +121,8 @@ along with GCC; see the file COPYING3.  If not see
 #define CHKP_SPEC "\
 %{!nostdlib:%{!nodefaultlibs:" LIBMPX_SPEC LIBMPXWRAPPERS_SPEC "}}" MPX_SPEC
 #endif
+
+extern void file_end_indicate_exec_stack_and_cet (void);
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_cet
diff --git a/gcc/config/i386/t-cet b/gcc/config/i386/t-cet
new file mode 100644
index 0000000..317f30d
--- /dev/null
+++ b/gcc/config/i386/t-cet
@@ -0,0 +1,21 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+cet.o: $(srcdir)/config/i386/cet.c
+	  $(COMPILE) $<
+	  $(POSTCOMPILE)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-11-06 10:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-18  9:58 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
2017-09-19 15:05 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
2017-10-12 18:50   ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V
2017-10-13  7:03     ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
2017-11-06 10:33 ` 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Uros Bizjak
  -- strict thread matches above, loose matches on Subject: below --
2017-08-01  8:57 0004-Part-4.-Update-x86-backend-to-enable-Intel-CET Tsimbalist, Igor V

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).