Patchwork [i386,MPX,1/X] Support of Intel MPX ISA. 2/2 New registers and instructions

login
register
mail settings
Submitter Ilya Enkovich
Date Sept. 17, 2013, 8:41 a.m.
Message ID <20130917084103.GA12707@msticlxl57.ims.intel.com>
Download mbox | patch
Permalink /patch/275399/
State New
Headers show

Comments

Ilya Enkovich - Sept. 17, 2013, 8:41 a.m.
On 16 Sep 11:24, Uros Bizjak wrote:
> On Fri, Sep 13, 2013 at 12:18 PM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> > 2013/9/11 Uros Bizjak <ubizjak@gmail.com>:
> >>
> >
> > Hi Uros,
> >
> > Thanks a lot for the review!
> >
> >> The x86 part looks mostly OK (I have a couple of comments bellow), but
> >> please first get target-independent changes reviewed and committed.
> >
> > Do you mean I should move bound type and mode declaration into a separate patch?
> 
> Yes, target-independent part (middle end) has to go through the
> separate review to check if this part is OK. The target-dependent part
> uses the infrastructure from the middle end, so it can go into the
> code base only after target-independent parts are committed.

I sent a separate patch for bound type and mode class (http://gcc.gnu.org/ml/gcc-patches/2013-09/msg01268.html). Here is target part of the patch with fixes you mentioned. Does it look OK?

Bootstrapped and checked on linux-x86_64. Still shows incorrect length attribute computation (described here http://gcc.gnu.org/ml/gcc/2013-07/msg00311.html).

Thanks,
Ilya
--

2013-09-16  Ilya Enkovich  <ilya.enkovich@intel.com>

	* config/i386/constraints.md (B): New.
	(Ti): New.
	(Tb): New.
	* config/i386/i386-c.c (ix86_target_macros_internal): Add __MPX__.
	* config/i386/i386-modes.def (BND32): New.
	(BND64): New.
	* config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): New.
	* config/i386/i386.c (isa_opts): Add mmpx.
	(regclass_map): Add bound registers.
	(dbx_register_map): Likewise.
	(dbx64_register_map): Likewise.
	(svr4_dbx_register_map): Likewise.
	(PTA_MPX): New.
	(ix86_option_override_internal): Support MPX ISA.
	(ix86_conditional_register_usage): Support bound registers.
	(print_reg): Likewise.
	(ix86_code_end): Add MPX bnd prefix.
	(output_set_got): Likewise.
	(ix86_output_call_insn): Likewise.
	(ix86_print_operand): Add '!' (MPX bnd) print prefix support.
	(ix86_print_operand_punct_valid_p): Likewise.
	(ix86_print_operand_address): Support UNSPEC_BNDMK_ADDR and
	UNSPEC_BNDMK_ADDR.
	(ix86_class_likely_spilled_p): Add bound regs support.
	(ix86_hard_regno_mode_ok): Likewise.
	(x86_order_regs_for_local_alloc): Likewise.
	(ix86_bnd_prefixed_insn_p): New.
	* config/i386/i386.h (FIRST_PSEUDO_REGISTER): Fix to new value.
	(FIXED_REGISTERS): Add bound registers.
	(CALL_USED_REGISTERS): Likewise.
	(REG_ALLOC_ORDER): Likewise.
	(HARD_REGNO_NREGS): Likewise.
	(TARGET_MPX): New.
	(VALID_BND_REG_MODE): New.
	(FIRST_BND_REG): New.
	(LAST_BND_REG): New.
	(reg_class): Add BND_REGS.
	(REG_CLASS_NAMES): Likewise.
	(REG_CLASS_CONTENTS): Likewise.
	(BND_REGNO_P): New.
	(ANY_BND_REG_P): New.
	(BNDmode): New.
	(HI_REGISTER_NAMES): Add bound registers.
	* config/i386/i386.md (UNSPEC_BNDMK): New.
	(UNSPEC_BNDMK_ADDR): New.
	(UNSPEC_BNDSTX): New.
	(UNSPEC_BNDLDX): New.
	(UNSPEC_BNDLDX_ADDR): New.
	(UNSPEC_BNDCL): New.
	(UNSPEC_BNDCU): New.
	(UNSPEC_BNDCN): New.
	(UNSPEC_MPX_FENCE): New.
	(BND0_REG): New.
	(BND1_REG): New.
	(type): Add mpxmov, mpxmk, mpxchk, mpxld, mpxst.
	(length_immediate): Likewise.
	(prefix_0f): Likewise.
	(memory): Likewise.
	(prefix_rep): Check for bnd prefix.
	(BND): New.
	(bnd_ptr): New.
	(BNDCHECK): New.
	(bndcheck): New.
	(*jcc_1): Add MPX bnd prefix and fix length.
	(*jcc_2): Likewise.
	(jump): Likewise.
	(simple_return_internal): Likewise.
	(simple_return_pop_internal): Likewise.
	(*indirect_jump): Add MPX bnd prefix.
	(*tablejump_1): Likewise.
	(simple_return_internal_long): Likewise.
	(simple_return_indirect_internal): Likewise.
	(<mode>_mk): New.
	(*<mode>_mk): New.
	(mov<mode>): New.
	(*mov<mode>_internal_mpx): New.
	(<mode>_<bndcheck>): New.
	(*<mode>_<bndcheck>): New.
	(<mode>_ldx): New.
	(*<mode>_ldx): New.
	(<mode>_stx): New.
	(*<mode>_stx): New.
	* config/i386/predicates.md (lea_address_operand): Rename to...
	(address_no_seg_operand): ... this.
	(address_mpx_no_base_operand): New.
	(address_mpx_no_index_operand): New.
	(bnd_mem_operator): New.
	* config/i386/i386.opt (mmpx): New.
	* doc/invoke.texi: Add documentation for the flags -mmpx, -mno-mpx.
	* doc/rtl.texi Add documentation for BND32mode and BND64mode.

Patch

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 28e626f..79d02f7 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -18,7 +18,7 @@ 
 ;; <http://www.gnu.org/licenses/>.
 
 ;;; Unused letters:
-;;;     B     H           T
+;;;           H
 ;;;           h jk
 
 ;; Integer register constraints.
@@ -85,6 +85,9 @@ 
 (define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
  "Any SSE register.")
 
+(define_register_constraint "B" "TARGET_MPX ? BND_REGS : NO_REGS"
+ "@internal Any bound register.")
+
 ;; We use the Y prefix to denote any number of conditional register sets:
 ;;  z	First SSE register.
 ;;  i	SSE2 inter-unit moves to SSE register enabled
@@ -226,3 +229,15 @@ 
    to fit that range (for immediate operands in zero-extending x86-64
    instructions)."
   (match_operand 0 "x86_64_zext_immediate_operand"))
+
+;; T prefix is used for different address constraints
+;;   i - address with no index and no rip
+;;   b - address with no base and no rip
+
+(define_address_constraint "Ti"
+  "MPX address operand without index"
+  (match_operand 0 "address_mpx_no_index_operand"))
+
+(define_address_constraint "Tb"
+  "MPX address operand without base"
+  (match_operand 0 "address_mpx_no_base_operand"))
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 14349be..70b629c 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -360,6 +360,8 @@  ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
     def_or_undef (parse_in, "__SSE_MATH__");
   if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
     def_or_undef (parse_in, "__SSE2_MATH__");
+  if (isa_flag & OPTION_MASK_ISA_MPX)
+    def_or_undef (parse_in, "__MPX__");
 }
 
 
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index e0b8fc8..8bc1b6e 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -87,6 +87,9 @@  VECTOR_MODE (INT, DI, 1);     /*                   V1DI */
 VECTOR_MODE (INT, SI, 1);     /*                   V1SI */
 VECTOR_MODE (INT, QI, 2);     /*                   V2QI */
 
+BOUND_MODE (BND32, 8);
+BOUND_MODE (BND64, 16);
+
 INT_MODE (OI, 32);
 INT_MODE (XI, 64);
 
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 3ab2f3a..fdd98fc 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -239,6 +239,8 @@  extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool);
 extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx);
 extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx);
 
+extern bool ix86_bnd_prefixed_insn_p (rtx);
+
 /* In i386-c.c  */
 extern void ix86_target_macros (void);
 extern void ix86_register_pragmas (void);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a8d70bc..97d8a68 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2032,6 +2032,8 @@  enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
   EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
   EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
   EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS, EVEX_SSE_REGS,
+  /* MPX bound registers */
+  BND_REGS, BND_REGS, BND_REGS, BND_REGS,
 };
 
 /* The "default" register map used in 32bit mode.  */
@@ -2047,6 +2049,7 @@  int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
   -1, -1, -1, -1, -1, -1, -1, -1,	/* extended SSE registers */
   -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 16-23*/
   -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 24-31*/
+  101, 102, 103, 104,			/* bound registers */
 };
 
 /* The "default" register map used in 64bit mode.  */
@@ -2062,6 +2065,7 @@  int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
   25, 26, 27, 28, 29, 30, 31, 32,	/* extended SSE registers */
   67, 68, 69, 70, 71, 72, 73, 74,       /* AVX-512 registers 16-23 */
   75, 76, 77, 78, 79, 80, 81, 82,       /* AVX-512 registers 24-31 */
+  126, 127, 128, 129,			/* bound registers */
 };
 
 /* Define the register numbers to be used in Dwarf debugging information.
@@ -2129,6 +2133,7 @@  int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
   -1, -1, -1, -1, -1, -1, -1, -1,	/* extended SSE registers */
   -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 16-23*/
   -1, -1, -1, -1, -1, -1, -1, -1,       /* AVX-512 registers 24-31*/
+  -1, -1, -1, -1,                       /* bound registers */
 };
 
 /* Define parameter passing and return registers.  */
@@ -2552,6 +2557,7 @@  ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
     { "-mrtm",		OPTION_MASK_ISA_RTM },
     { "-mxsave",	OPTION_MASK_ISA_XSAVE },
     { "-mxsaveopt",	OPTION_MASK_ISA_XSAVEOPT },
+    { "-mmpx",          OPTION_MASK_ISA_MPX },
   };
 
   /* Flag options.  */
@@ -3044,6 +3050,7 @@  ix86_option_override_internal (bool main_args_p)
 #define PTA_AVX512ER		(HOST_WIDE_INT_1 << 41)
 #define PTA_AVX512PF		(HOST_WIDE_INT_1 << 42)
 #define PTA_AVX512CD		(HOST_WIDE_INT_1 << 43)
+#define PTA_MPX			(HOST_WIDE_INT_1 << 44)
 
 /* if this reaches 64, need to widen struct pta flags below */
 
@@ -3577,12 +3584,18 @@  ix86_option_override_internal (bool main_args_p)
 	if (processor_alias_table[i].flags & PTA_AVX512CD
 	    && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AVX512CD))
 	  ix86_isa_flags |= OPTION_MASK_ISA_AVX512CD;
+        if (processor_alias_table[i].flags & PTA_MPX
+            && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MPX))
+          ix86_isa_flags |= OPTION_MASK_ISA_MPX;
 	if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE))
 	  x86_prefetch_sse = true;
 
 	break;
       }
 
+  if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX))
+    error ("Intel MPX does not support x32");
+
   if (!strcmp (ix86_arch_string, "generic"))
     error ("generic CPU can be used only for %stune=%s %s",
 	   prefix, suffix, sw);
@@ -4220,6 +4233,11 @@  ix86_conditional_register_usage (void)
   if (! TARGET_AVX512F)
     for (i = FIRST_EXT_REX_SSE_REG; i < LAST_EXT_REX_SSE_REG; i++)
       fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
+
+  /* If MPX is disabled, squash the registers.  */
+  if (! TARGET_MPX)
+    for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+      fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
 }
 
 
@@ -8929,7 +8947,7 @@  ix86_code_end (void)
       xops[0] = gen_rtx_REG (Pmode, regno);
       xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
       output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
-      fputs ("\tret\n", asm_out_file);
+      output_asm_insn ("%!ret", NULL);
       final_end_function ();
       init_insn_lengths ();
       free_after_compilation (cfun);
@@ -8987,7 +9005,7 @@  output_set_got (rtx dest, rtx label)
 
       xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
       xops[2] = gen_rtx_MEM (QImode, xops[2]);
-      output_asm_insn ("call\t%X2", xops);
+      output_asm_insn ("%!call\t%X2", xops);
 
 #if TARGET_MACHO
       /* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here.
@@ -14338,7 +14356,7 @@  print_reg (rtx x, int code, FILE *file)
     case 8:
     case 4:
     case 12:
-      if (! ANY_FP_REG_P (x))
+      if (! ANY_FP_REG_P (x) &&  ! ANY_BND_REG_P (x))
 	putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
       /* FALLTHRU */
     case 16:
@@ -14461,6 +14479,7 @@  get_some_local_dynamic_name (void)
    ~ -- 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.
  */
 
 void
@@ -14955,6 +14974,11 @@  ix86_print_operand (FILE *file, rtx x, int code)
 	    fputs ("addr32 ", file);
 	  return;
 
+	case '!':
+	  if (ix86_bnd_prefixed_insn_p (NULL_RTX))
+	    fputs ("bnd ", file);
+	  return;
+
 	default:
 	    output_operand_lossage ("invalid operand code '%c'", code);
 	}
@@ -15097,7 +15121,7 @@  static bool
 ix86_print_operand_punct_valid_p (unsigned char code)
 {
   return (code == '@' || code == '*' || code == '+' || code == '&'
-	  || code == ';' || code == '~' || code == '^');
+	  || code == ';' || code == '~' || code == '^' || code == '!');
 }
 
 /* Print a memory operand whose address is ADDR.  */
@@ -15127,6 +15151,25 @@  ix86_print_operand_address (FILE *file, rtx addr)
       ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
       code = 'q';
     }
+  else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR)
+    {
+      ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts);
+      gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX);
+      if (parts.base != NULL_RTX)
+	{
+	  parts.index = parts.base;
+	  parts.scale = 1;
+	}
+      parts.base = XVECEXP (addr, 0, 0);
+      addr = XVECEXP (addr, 0, 0);
+    }
+  else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR)
+    {
+      ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+      gcc_assert (parts.index == NULL_RTX);
+      parts.index = XVECEXP (addr, 0, 1);
+      addr = XVECEXP (addr, 0, 0);
+    }
   else
     ok = ix86_decompose_address (addr, &parts);
 
@@ -24094,13 +24137,13 @@  ix86_output_call_insn (rtx insn, rtx call_op)
   if (SIBLING_CALL_P (insn))
     {
       if (direct_p)
-	xasm = "jmp\t%P0";
+	xasm = "%!jmp\t%P0";
       /* SEH epilogue detection requires the indirect branch case
 	 to include REX.W.  */
       else if (TARGET_SEH)
-	xasm = "rex.W jmp %A0";
+	xasm = "%!rex.W jmp %A0";
       else
-	xasm = "jmp\t%A0";
+	xasm = "%!jmp\t%A0";
 
       output_asm_insn (xasm, &call_op);
       return "";
@@ -24137,9 +24180,9 @@  ix86_output_call_insn (rtx insn, rtx call_op)
     }
 
   if (direct_p)
-    xasm = "call\t%P0";
+    xasm = "%!call\t%P0";
   else
-    xasm = "call\t%A0";
+    xasm = "%!call\t%A0";
 
   output_asm_insn (xasm, &call_op);
 
@@ -34098,6 +34141,7 @@  ix86_class_likely_spilled_p (reg_class_t rclass)
       case SSE_FIRST_REG:
       case FP_TOP_REG:
       case FP_SECOND_REG:
+      case BND_REGS:
 	return true;
 
       default:
@@ -34444,6 +34488,8 @@  ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
     return false;
   if (STACK_REGNO_P (regno))
     return VALID_FP_MODE_P (mode);
+  if (BND_REGNO_P (regno))
+    return VALID_BND_REG_MODE (mode);
   if (SSE_REGNO_P (regno))
     {
       /* We implement the move patterns for all vector modes into and
@@ -35253,6 +35299,10 @@  x86_order_regs_for_local_alloc (void)
    for (i = FIRST_EXT_REX_SSE_REG; i <= LAST_EXT_REX_SSE_REG; i++)
      reg_alloc_order [pos++] = i;
 
+   /* MPX bound registers.  */
+   for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+     reg_alloc_order [pos++] = i;
+
    /* x87 registers.  */
    if (TARGET_SSE_MATH)
      for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
@@ -41685,6 +41735,18 @@  ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
 		       gen_rtx_MULT (mode, op1, op2));
 }
 
+/* Return 1 if control tansfer instruction INSN
+   should be encoded with bnd prefix.
+   If insn is NULL then return 1 when control
+   transfer instructions should be prefixed with
+   bnd by default for current function.  */
+
+bool
+ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
 /* Expand an insert into a vector register through pinsr insn.
    Return true if successful.  */
 
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e820aa6..4303b56 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -84,6 +84,7 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_FXSR	TARGET_ISA_FXSR
 #define TARGET_XSAVE	TARGET_ISA_XSAVE
 #define TARGET_XSAVEOPT	TARGET_ISA_XSAVEOPT
+#define TARGET_MPX      TARGET_ISA_MPX
 
 #define TARGET_LP64	TARGET_ABI_64
 #define TARGET_X32	TARGET_ABI_X32
@@ -893,7 +894,7 @@  enum target_cpu_default
    eliminated during reloading in favor of either the stack or frame
    pointer.  */
 
-#define FIRST_PSEUDO_REGISTER 69
+#define FIRST_PSEUDO_REGISTER 73
 
 /* Number of hardware registers that go into the DWARF-2 unwind info.
    If not defined, equals FIRST_PSEUDO_REGISTER.  */
@@ -923,7 +924,9 @@  enum target_cpu_default
 /*xmm16,xmm17,xmm18,xmm19,xmm20,xmm21,xmm22,xmm23*/		\
      0,   0,    0,    0,    0,    0,    0,    0,		\
 /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/		\
-     0,   0,    0,    0,    0,    0,    0,    0 }
+     0,   0,    0,    0,    0,    0,    0,    0,		\
+/*   b0, b1, b2, b3*/						\
+     0,  0,  0,  0 }
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -955,7 +958,9 @@  enum target_cpu_default
 /*xmm16,xmm17,xmm18,xmm19,xmm20,xmm21,xmm22,xmm23*/		\
      6,    6,     6,    6,    6,    6,    6,    6,		\
 /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/		\
-     6,    6,     6,    6,    6,    6,    6,    6 }
+     6,    6,     6,    6,    6,    6,    6,    6,		\
+/*   b0, b1, b2, b3*/							\
+     1,  1,  1,  1 }
 
 /* Order in which to allocate registers.  Each register must be
    listed once, even those in FIXED_REGISTERS.  List frame pointer
@@ -971,7 +976,7 @@  enum target_cpu_default
    18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,	\
    33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,  \
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,	\
-   63, 64, 65, 66, 67, 68 }
+   63, 64, 65, 66, 67, 68, 69, 70, 71, 72 }
 
 /* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
    to be rearranged based on a particular function.  When using sse math,
@@ -993,6 +998,7 @@  enum target_cpu_default
 
 #define HARD_REGNO_NREGS(REGNO, MODE)					\
   (STACK_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO)	\
+   || BND_REGNO_P (REGNO)						\
    ? (COMPLEX_MODE_P (MODE) ? 2 : 1)					\
    : ((MODE) == XFmode							\
       ? (TARGET_64BIT ? 2 : 3)						\
@@ -1042,6 +1048,9 @@  enum target_cpu_default
    || (MODE) == V2SImode || (MODE) == SImode				\
    || (MODE) == V4HImode || (MODE) == V8QImode)
 
+#define VALID_BND_REG_MODE(MODE) \
+  (TARGET_64BIT ? (MODE) == BND64mode : (MODE) == BND32mode)
+
 #define VALID_DFP_MODE_P(MODE) \
   ((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)
 
@@ -1141,6 +1150,9 @@  enum target_cpu_default
 #define FIRST_EXT_REX_SSE_REG  (LAST_REX_SSE_REG + 1) /*53*/
 #define LAST_EXT_REX_SSE_REG   (FIRST_EXT_REX_SSE_REG + 15) /*68*/
 
+#define FIRST_BND_REG  (LAST_EXT_REX_SSE_REG + 1) /*69*/
+#define LAST_BND_REG   (FIRST_BND_REG + 3) /*72*/
+
 /* Override this in other tm.h files to cope with various OS lossage
    requiring a frame pointer.  */
 #ifndef SUBTARGET_FRAME_POINTER_REQUIRED
@@ -1221,6 +1233,7 @@  enum reg_class
   SSE_FIRST_REG,
   SSE_REGS,
   EVEX_SSE_REGS,
+  BND_REGS,
   ALL_SSE_REGS,
   MMX_REGS,
   FP_TOP_SSE_REGS,
@@ -1274,6 +1287,7 @@  enum reg_class
    "SSE_FIRST_REG",			\
    "SSE_REGS",				\
    "EVEX_SSE_REGS",			\
+   "BND_REGS",				\
    "ALL_SSE_REGS",			\
    "MMX_REGS",				\
    "FP_TOP_SSE_REGS",			\
@@ -1311,6 +1325,7 @@  enum reg_class
   { 0x200000,       0x0,   0x0 },       /* SSE_FIRST_REG */             \
 { 0x1fe00000,  0x1fe000,   0x0 },       /* SSE_REGS */                  \
        { 0x0,0xffe00000,  0x1f },       /* EVEX_SSE_REGS */             \
+       { 0x0,       0x0, 0x1e0 },       /* BND_REGS */			\
 { 0x1fe00000,0xffffe000,  0x1f },       /* ALL_SSE_REGS */              \
 { 0xe0000000,      0x1f,   0x0 },       /* MMX_REGS */                  \
 { 0x1fe00100,0xffffe000,  0x1f },       /* FP_TOP_SSE_REG */            \
@@ -1319,7 +1334,7 @@  enum reg_class
 {   0x11ffff,    0x1fe0,   0x0 },       /* FLOAT_INT_REGS */            \
 { 0x1ff100ff,0xffffffe0,  0x1f },       /* INT_SSE_REGS */              \
 { 0x1ff1ffff,0xffffffe0,  0x1f },       /* FLOAT_INT_SSE_REGS */        \
-{ 0xffffffff,0xffffffff,  0x1f }                                        \
+{ 0xffffffff,0xffffffff, 0x1ff }                                        \
 }
 
 /* The same information, inverted:
@@ -1393,6 +1408,9 @@  enum reg_class
 #define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
 #define CC_REGNO_P(X) ((X) == FLAGS_REG || (X) == FPSR_REG)
 
+#define BND_REGNO_P(N) IN_RANGE ((N), FIRST_BND_REG, LAST_BND_REG)
+#define ANY_BND_REG_P(X) (REG_P (X) && BND_REGNO_P (REGNO (X)))
+
 /* The class value for index registers, and the one for base regs.  */
 
 #define INDEX_REG_CLASS INDEX_REGS
@@ -1824,6 +1842,9 @@  do {							\
    between pointers and any other objects of this machine mode.  */
 #define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode)
 
+/* Specify the machine mode that bounds have.  */
+#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode)
+
 /* A C expression whose value is zero if pointers that need to be extended
    from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
    greater then zero if they are zero-extended and less then zero if the
@@ -1933,7 +1954,8 @@  do {							\
  "xmm16", "xmm17", "xmm18", "xmm19",					\
  "xmm20", "xmm21", "xmm22", "xmm23",					\
  "xmm24", "xmm25", "xmm26", "xmm27",					\
- "xmm28", "xmm29", "xmm30", "xmm31" }
+ "xmm28", "xmm29", "xmm30", "xmm31",					\
+ "bnd0", "bnd1", "bnd2", "bnd3" }
 
 #define REGISTER_NAMES HI_REGISTER_NAMES
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 3307b08..87cbd77 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -63,6 +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.
 
 (define_c_enum "unspec" [
   ;; Relocation specifiers
@@ -178,6 +179,16 @@ 
   ;; For BMI2 support
   UNSPEC_PDEP
   UNSPEC_PEXT
+
+  UNSPEC_BNDMK
+  UNSPEC_BNDMK_ADDR
+  UNSPEC_BNDSTX
+  UNSPEC_BNDLDX
+  UNSPEC_BNDLDX_ADDR
+  UNSPEC_BNDCL
+  UNSPEC_BNDCU
+  UNSPEC_BNDCN
+  UNSPEC_MPX_FENCE
 ])
 
 (define_c_enum "unspecv" [
@@ -328,6 +339,8 @@ 
    (XMM29_REG			66)
    (XMM30_REG			67)
    (XMM31_REG			68)
+   (BND0_REG			69)
+   (BND1_REG			70)
   ])
 
 ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
@@ -361,7 +374,8 @@ 
    ssecvt,ssecvt1,sseicvt,sseins,
    sseshuf,sseshuf1,ssemuladd,sse4arg,
    lwp,
-   mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
+   mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft,
+   mpxmov,mpxmk,mpxchk,mpxld,mpxst"
   (const_string "other"))
 
 ;; Main data type used by the insn
@@ -390,7 +404,7 @@ 
 ;; The (bounding maximum) length of an instruction immediate.
 (define_attr "length_immediate" ""
   (cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
-			  bitmanip,imulx")
+			  bitmanip,imulx,mpxmk,mpxmov,mpxchk,mpxld,mpxst")
 	   (const_int 0)
 	 (eq_attr "unit" "i387,sse,mmx")
 	   (const_int 0)
@@ -445,13 +459,17 @@ 
 	   (const_int 0)
 	 (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
 	   (const_int 1)
+	 (and (eq_attr "type" "ibr,call,callv")
+	      (match_test "ix86_bnd_prefixed_insn_p (insn)"))
+	   (const_int 1)
 	]
 	(const_int 0)))
 
 ;; Set when 0f opcode prefix is used.
 (define_attr "prefix_0f" ""
   (if_then_else
-    (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip")
+    (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,
+			  mpxmk,mpxmov,mpxchk,mpxld,mpxst")
 	 (eq_attr "unit" "sse,mmx"))
     (const_int 1)
     (const_int 0)))
@@ -600,12 +618,16 @@ 
 (define_attr "memory" "none,load,store,both,unknown"
   (cond [(eq_attr "type" "other,multi,str,lwp")
 	   (const_string "unknown")
-	 (eq_attr "type" "lea,fcmov,fpspc")
+	 (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk")
 	   (const_string "none")
 	 (eq_attr "type" "fistp,leave")
 	   (const_string "both")
 	 (eq_attr "type" "frndint")
 	   (const_string "load")
+	 (eq_attr "type" "mpxld")
+	   (const_string "load")
+	 (eq_attr "type" "mpxst")
+	   (const_string "store")
 	 (eq_attr "type" "push")
 	   (if_then_else (match_operand 1 "memory_operand")
 	     (const_string "both")
@@ -651,7 +673,7 @@ 
 		   fmov,fcmp,fsgn,
 		   sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
 		   sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1,
-		   mmx,mmxmov,mmxcmp,mmxcvt")
+		   mmx,mmxmov,mmxcmp,mmxcvt,mpxmov")
 	      (match_operand 2 "memory_operand"))
 	   (const_string "load")
 	 (and (eq_attr "type" "icmov,ssemuladd,sse4arg")
@@ -875,6 +897,21 @@ 
 (define_mode_iterator DWIH [(SI "!TARGET_64BIT")
 			    (DI "TARGET_64BIT")])
 
+;; Bound modes.
+(define_mode_iterator BND [(BND32 "!TARGET_LP64")
+			   (BND64 "TARGET_LP64")])
+
+;; Pointer mode corresponding to bound mode.
+(define_mode_attr bnd_ptr [(BND32 "SI") (BND64 "DI")])
+
+;; MPX check types
+(define_int_iterator BNDCHECK [UNSPEC_BNDCL UNSPEC_BNDCU UNSPEC_BNDCN])
+
+;; Check name
+(define_int_attr bndcheck [(UNSPEC_BNDCL "cl")
+			   (UNSPEC_BNDCU "cu")
+			   (UNSPEC_BNDCN "cn")])
+
 ;; Instruction suffix for integer modes.
 (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
 
@@ -5239,7 +5276,7 @@ 
 
 (define_insn_and_split "*lea<mode>"
   [(set (match_operand:SWI48 0 "register_operand" "=r")
-	(match_operand:SWI48 1 "lea_address_operand" "p"))]
+	(match_operand:SWI48 1 "address_no_seg_operand" "p"))]
   ""
 {
   if (SImode_address_operand (operands[1], VOIDmode))
@@ -10482,7 +10519,7 @@ 
 		      (label_ref (match_operand 0))
 		      (pc)))]
   ""
-  "%+j%C1\t%l0"
+  "%!%+j%C1\t%l0"
   [(set_attr "type" "ibr")
    (set_attr "modrm" "0")
    (set (attr "length")
@@ -10490,8 +10527,8 @@ 
 				  (const_int -126))
 			      (lt (minus (match_dup 0) (pc))
 				  (const_int 128)))
-	     (const_int 2)
-	     (const_int 6)))])
+	     (plus (const_int 2) (attr "prefix_rep"))
+	     (plus (const_int 6) (attr "prefix_rep"))))])
 
 (define_insn "*jcc_2"
   [(set (pc)
@@ -10500,7 +10537,7 @@ 
 		      (pc)
 		      (label_ref (match_operand 0))))]
   ""
-  "%+j%c1\t%l0"
+  "%!%+j%c1\t%l0"
   [(set_attr "type" "ibr")
    (set_attr "modrm" "0")
    (set (attr "length")
@@ -10508,8 +10545,8 @@ 
 				  (const_int -126))
 			      (lt (minus (match_dup 0) (pc))
 				  (const_int 128)))
-	     (const_int 2)
-	     (const_int 6)))])
+	     (plus (const_int 2) (attr "prefix_rep"))
+	     (plus (const_int 6) (attr "prefix_rep"))))])
 
 ;; In general it is not safe to assume too much about CCmode registers,
 ;; so simplify-rtx stops when it sees a second one.  Under certain
@@ -10966,15 +11003,15 @@ 
   [(set (pc)
 	(label_ref (match_operand 0)))]
   ""
-  "jmp\t%l0"
+  "%!jmp\t%l0"
   [(set_attr "type" "ibr")
    (set (attr "length")
 	   (if_then_else (and (ge (minus (match_dup 0) (pc))
 				  (const_int -126))
 			      (lt (minus (match_dup 0) (pc))
 				  (const_int 128)))
-	     (const_int 2)
-	     (const_int 5)))
+	     (plus (const_int 2) (attr "prefix_rep"))
+	     (plus (const_int 5) (attr "prefix_rep"))))
    (set_attr "modrm" "0")])
 
 (define_expand "indirect_jump"
@@ -10988,7 +11025,7 @@ 
 (define_insn "*indirect_jump"
   [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
   ""
-  "jmp\t%A0"
+  "%!jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
@@ -11037,7 +11074,7 @@ 
   [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
    (use (label_ref (match_operand 1)))]
   ""
-  "jmp\t%A0"
+  "%!jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
@@ -11424,8 +11461,14 @@ 
 (define_insn "simple_return_internal"
   [(simple_return)]
   "reload_completed"
-  "ret"
-  [(set_attr "length" "1")
+  "%!ret"
+  [(set (attr "length")
+          (plus (const_int 1)
+                (attr "prefix_rep")))
+   (set (attr "prefix_rep")
+	(if_then_else (match_test "ix86_bnd_prefixed_insn_p (insn)")
+	  (const_int 1)
+	  (const_int 0)))
    (set_attr "atom_unit" "jeu")
    (set_attr "length_immediate" "0")
    (set_attr "modrm" "0")])
@@ -11437,7 +11480,12 @@ 
   [(simple_return)
    (unspec [(const_int 0)] UNSPEC_REP)]
   "reload_completed"
-  "rep%; ret"
+{
+  if (ix86_bnd_prefixed_insn_p (insn))
+    return "%!ret";
+
+  return "rep%; ret";
+}
   [(set_attr "length" "2")
    (set_attr "atom_unit" "jeu")
    (set_attr "length_immediate" "0")
@@ -11448,8 +11496,14 @@ 
   [(simple_return)
    (use (match_operand:SI 0 "const_int_operand"))]
   "reload_completed"
-  "ret\t%0"
-  [(set_attr "length" "3")
+  "%!ret\t%0"
+  [(set (attr "length")
+          (plus (const_int 3)
+                (attr "prefix_rep")))
+   (set (attr "prefix_rep")
+	(if_then_else (match_test "ix86_bnd_prefixed_insn_p (insn)")
+	  (const_int 1)
+	  (const_int 0)))
    (set_attr "atom_unit" "jeu")
    (set_attr "length_immediate" "2")
    (set_attr "modrm" "0")])
@@ -11458,7 +11512,7 @@ 
   [(simple_return)
    (use (match_operand:SI 0 "register_operand" "r"))]
   "reload_completed"
-  "jmp\t%A0"
+  "%!jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
@@ -17920,6 +17974,131 @@ 
   [(set_attr "type" "other")
    (set_attr "length" "3")])
 
+;; MPX instructions
+
+(define_expand "<mode>_mk"
+  [(set (match_operand:BND 0 "register_operand")
+    (unspec:BND
+      [(mem:<bnd_ptr>
+       (match_par_dup 3
+        [(match_operand:<bnd_ptr> 1 "register_operand")
+	 (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand")]))]
+      UNSPEC_BNDMK))]
+  "TARGET_MPX"
+{
+  operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+						  operands[2]),
+                                UNSPEC_BNDMK_ADDR);
+})
+
+(define_insn "*<mode>_mk"
+  [(set (match_operand:BND 0 "register_operand" "=B")
+    (unspec:BND
+      [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+        [(unspec:<bnd_ptr>
+	   [(match_operand:<bnd_ptr> 1 "register_operand" "r")
+            (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand" "Tb")]
+	   UNSPEC_BNDMK_ADDR)])]
+      UNSPEC_BNDMK))]
+  "TARGET_MPX"
+  "bndmk\t{%3, %0|%0, %3}"
+  [(set_attr "type" "mpxmk")])
+
+(define_expand "mov<mode>"
+  [(set (match_operand:BND 0 "general_operand")
+        (match_operand:BND 1 "general_operand"))]
+  "TARGET_MPX"
+{
+  ix86_expand_move (<MODE>mode, operands);DONE;
+})
+
+(define_insn "*mov<mode>_internal_mpx"
+  [(set (match_operand:BND 0 "nonimmediate_operand" "=B,m")
+        (match_operand:BND 1 "general_operand" "Bm,B"))]
+  "TARGET_MPX"
+  "bndmov\t{%1, %0|%0, %1}"
+  [(set_attr "type" "mpxmov")])
+
+(define_expand "<mode>_<bndcheck>"
+  [(parallel [(unspec [(match_operand:BND 0 "register_operand")
+                       (match_operand:<bnd_ptr> 1 "address_no_seg_operand")] BNDCHECK)
+              (set (match_dup 2)
+                   (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+  "TARGET_MPX"
+{
+  operands[2] = gen_rtx_MEM (BLKmode, operands[1]);
+  MEM_VOLATILE_P (operands[2]) = 1;
+})
+
+(define_insn "*<mode>_<bndcheck>"
+  [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B")
+                       (match_operand:<bnd_ptr> 1 "address_no_seg_operand" "p")] BNDCHECK)
+              (set (match_operand:BLK 2 "bnd_mem_operator")
+                   (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+  "TARGET_MPX"
+  "bnd<bndcheck>\t{%a1, %0|%0, %a1}"
+  [(set_attr "type" "mpxchk")])
+
+(define_expand "<mode>_ldx"
+  [(parallel [(set:BND (match_operand:BND 0 "register_operand")
+                       (unspec:BND
+		         [(mem:<bnd_ptr>
+			   (match_par_dup 3
+			     [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand")
+	                      (match_operand:<bnd_ptr> 2 "register_operand")]))]
+			 UNSPEC_BNDLDX))
+              (use (mem:BLK (match_dup 1)))])]
+  "TARGET_MPX"
+{
+  operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+                                                  operands[2]),
+				UNSPEC_BNDLDX_ADDR);
+})
+
+(define_insn "*<mode>_ldx"
+  [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B")
+                       (unspec:BND
+		         [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+			   [(unspec:<bnd_ptr>
+			     [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand" "Ti")
+	                      (match_operand:<bnd_ptr> 2 "register_operand" "l")]
+			    UNSPEC_BNDLDX_ADDR)])]
+			 UNSPEC_BNDLDX))
+              (use (mem:BLK (match_dup 1)))])]
+  "TARGET_MPX"
+  "bndldx\t{%3, %0|%0, %3}"
+  [(set_attr "type" "mpxld")])
+
+(define_expand "<mode>_stx"
+  [(parallel [(unspec [(mem:<bnd_ptr>
+			 (match_par_dup 3
+			   [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand")
+	                    (match_operand:<bnd_ptr> 1 "register_operand")]))
+	               (match_operand:BND 2 "register_operand")] UNSPEC_BNDSTX)
+              (set (match_dup 4)
+                   (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+  "TARGET_MPX"
+{
+  operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[0],
+                                                  operands[1]),
+				UNSPEC_BNDLDX_ADDR);
+  operands[4] = gen_rtx_MEM (BLKmode, operands[0]);
+  MEM_VOLATILE_P (operands[4]) = 1;
+})
+
+(define_insn "*<mode>_stx"
+  [(parallel [(unspec [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+			 [(unspec:<bnd_ptr>
+			  [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand" "Ti")
+	                   (match_operand:<bnd_ptr> 1 "register_operand" "l")]
+			 UNSPEC_BNDLDX_ADDR)])
+	               (match_operand:BND 2 "register_operand" "B")] UNSPEC_BNDSTX)
+              (set (match_operand:BLK 4 "bnd_mem_operator")
+                   (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+  "TARGET_MPX"
+  "bndstx\t{%2, %3|%3, %2}"
+  [(set_attr "type" "mpxst")])
+
 (include "mmx.md")
 (include "sse.md")
 (include "sync.md")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 5495c29..023fa27 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -665,6 +665,10 @@  mrtm
 Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save
 Support RTM built-in functions and code generation
 
+mmpx
+Target Report Mask(ISA_MPX) Var(ix86_isa_flags) Save
+Support MPX code generation
+
 mstack-protector-guard=
 Target RejectNegative Joined Enum(stack_protector_guard) Var(ix86_stack_protector_guard) Init(SSP_TLS)
 Use given stack-protector guard
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 3959c38..88abd53 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -856,7 +856,7 @@ 
 ;; Return true if op if a valid address for LEA, and does not contain
 ;; a segment override.  Defined as a special predicate to allow
 ;; mode-less const_int operands pass to address_operand.
-(define_special_predicate "lea_address_operand"
+(define_special_predicate "address_no_seg_operand"
   (match_operand 0 "address_operand")
 {
   struct ix86_address parts;
@@ -913,9 +913,74 @@ 
   return true;
 })
 
+;; Return true if op is valid MPX address operand without base
+(define_predicate "address_mpx_no_base_operand"
+  (match_operand 0 "address_operand")
+{
+  struct ix86_address parts;
+  int ok;
+
+  ok = ix86_decompose_address (op, &parts);
+  gcc_assert (ok);
+
+  if (parts.index && parts.base)
+    return false;
+
+  if (parts.seg != SEG_DEFAULT)
+    return false;
+
+  /* Do not support (%rip).  */
+  if (parts.disp && flag_pic && TARGET_64BIT
+      && SYMBOLIC_CONST (parts.disp))
+    {
+      if (GET_CODE (parts.disp) != CONST
+	  || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+	  || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+	  || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+	  || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+	      && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF))
+	return false;
+    }
+
+  return true;
+})
+
+;; Return true if op is valid MPX address operand without index
+(define_predicate "address_mpx_no_index_operand"
+  (match_operand 0 "address_operand")
+{
+  struct ix86_address parts;
+  int ok;
+
+  ok = ix86_decompose_address (op, &parts);
+  gcc_assert (ok);
+
+  if (parts.index)
+    return false;
+
+  if (parts.seg != SEG_DEFAULT)
+    return false;
+
+  /* Do not support (%rip).  */
+  if (parts.disp && flag_pic && TARGET_64BIT
+      && SYMBOLIC_CONST (parts.disp)
+      && (GET_CODE (parts.disp) != CONST
+	  || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+	  || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+	  || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+	  || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+	      && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF)))
+    return false;
+
+  return true;
+})
+
 (define_predicate "vsib_mem_operator"
   (match_code "mem"))
 
+(define_predicate "bnd_mem_operator"
+  (match_code "mem"))
+
 ;; Return true if the rtx is known to be at least 32 bits aligned.
 (define_predicate "aligned_operand"
   (match_operand 0 "general_operand")
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9dfb4d7..bd0fb13 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -651,7 +651,7 @@  Objective-C and Objective-C++ Dialects}.
 -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd @gol
 -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol
 -msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol
--mbmi2 -mrtm -mlwp -mthreads @gol
+-mbmi2 -mrtm -mlwp -mmpx -mthreads @gol
 -mno-align-stringops  -minline-all-stringops @gol
 -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
 -mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} 
@@ -14444,6 +14444,8 @@  preferred alignment to @option{-mpreferred-stack-boundary=2}.
 @itemx -mrtm
 @itemx -mtbm
 @itemx -mno-tbm
+@itemx -mmpx
+@itemx -mno-mpx
 @opindex mmmx
 @opindex mno-mmx
 @opindex msse
@@ -14453,7 +14455,7 @@  preferred alignment to @option{-mpreferred-stack-boundary=2}.
 These switches enable or disable the use of instructions in the MMX, SSE,
 SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD,
 AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM, BMI, BMI2,
-LZCNT, RTM or 3DNow!@:
+LZCNT, RTM, MPX or 3DNow!@:
 extended instruction sets.
 These extensions are also available as built-in functions: see
 @ref{X86 Built-in Functions}, for details of the functions enabled and
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index 02b1214..ad6b84b 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -1295,6 +1295,12 @@  These modes stand for a complex number represented as a pair of integer
 values.  The integer values are in @code{QImode}, @code{HImode},
 @code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode},
 respectively.
+
+@findex BND32mode
+@findex BND64mode
+@item BND32mode BND64mode
+These modes stand for bounds for pointer of 32 and 64 bit size respectively.
+Mode size is double pointer mode size.
 @end table
 
 The machine description defines @code{Pmode} as a C macro which expands