diff --git a/gcc/builtins.c b/gcc/builtins.c
index bd66ff0..8f25086 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5338,6 +5338,7 @@ static enum memmodel
 get_memmodel (tree exp)
 {
   rtx op;
+  int val;
 
   /* If the parameter is not a constant, it's a run time value so we'll just
      convert it to MEMMODEL_SEQ_CST to avoid annoying runtime checking.  */
@@ -5346,7 +5347,10 @@ get_memmodel (tree exp)
 
   op = expand_normal (exp);
 
-  if(INTVAL (op) & ~(MEMMODEL_MASK | targetm.memmodel_mask))
+  val = INTVAL (op);
+  if (targetm.memmodel_check)
+    val = targetm.memmodel_check (val);
+  else if (val & ~MEMMODEL_MASK)
     {
       warning (OPT_Winvalid_memory_model,
 	       "Unknown architecture specifier in memory model to builtin.");
@@ -5361,7 +5365,7 @@ get_memmodel (tree exp)
       return MEMMODEL_SEQ_CST;
     }
 
-  return (enum memmodel) INTVAL (op);
+  return (enum memmodel) val;
 }
 
 /* Expand the __atomic_exchange intrinsic:
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0b6d6be..d17fcac 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -38967,6 +38967,37 @@ ix86_autovectorize_vector_sizes (void)
   return (TARGET_AVX && !TARGET_PREFER_AVX128) ? 32 | 16 : 0;
 }
 
+/* Validate target specific memory model bits in VAL. */
+
+static unsigned int
+ix86_memmodel_check (unsigned val)
+{
+  unsigned model = val & MEMMODEL_MASK;
+  int strong;
+
+  if (val & ~(IX86_HLE_ACQUIRE|IX86_HLE_RELEASE|MEMMODEL_MASK) 
+      || ((val & IX86_HLE_ACQUIRE) && (val & IX86_HLE_RELEASE)))
+    {
+      warning (OPT_Winvalid_memory_model,
+              "Unknown architecture specific memory model");
+      return MEMMODEL_SEQ_CST;
+    }
+  strong = (model == MEMMODEL_ACQ_REL || model == MEMMODEL_SEQ_CST);
+  if (val & IX86_HLE_ACQUIRE && !(model == MEMMODEL_ACQUIRE || strong))
+    {
+      warning (OPT_Winvalid_memory_model,
+	       "HLE_ACQUIRE not used with ACQUIRE or stronger memory model");
+      return MEMMODEL_SEQ_CST | IX86_HLE_ACQUIRE;
+    }
+   if (val & IX86_HLE_RELEASE && !(model == MEMMODEL_RELEASE || strong))
+    {
+      warning (OPT_Winvalid_memory_model,
+	       "HLE_RELEASE not used with RELEASE or stronger memory model");
+      return MEMMODEL_SEQ_CST | IX86_HLE_RELEASE;
+    }
+  return val;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_RETURN_IN_MEMORY
 #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
@@ -39066,8 +39097,8 @@ ix86_autovectorize_vector_sizes (void)
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
 
-#undef TARGET_MEMMODEL_MASK
-#define TARGET_MEMMODEL_MASK (IX86_HLE_ACQUIRE|IX86_HLE_RELEASE)
+#undef TARGET_MEMMODEL_CHECK
+#define TARGET_MEMMODEL_CHECK ix86_memmodel_check
 
 #ifdef HAVE_AS_TLS
 #undef TARGET_HAVE_TLS
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index ee0d700..4c57a9c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -11362,9 +11362,10 @@ MIPS, where add-immediate takes a 16-bit signed value,
 @code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}.  The default value
 is zero, which disables this optimization.  @end deftypevr
 
-@deftypevr {Target Hook} {unsigned HOST_WIDE_INT} TARGET_MEMMODEL_MASK
-Some architectures may prvide additional memory model bits. This hook
-must mask such a bits. @end deftypevr
+@deftypefn {Target Hook} unsigned TARGET_MEMMODEL_CHECK (unsigned @var{val})
+Validate target specific memory model mask bits. When NULL no target specific
+memory model bits are allowed. 
+@end deftypefn
 
 @deftypevr {Target Hook} {unsigned char} TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 This value should be set if the result written by @code{atomic_test_and_set} is not exactly 1, i.e. the @code{bool} @code{true}.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 95eef59..af76e7b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -11242,8 +11242,9 @@ MIPS, where add-immediate takes a 16-bit signed value,
 @code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}.  The default value
 is zero, which disables this optimization.  @end deftypevr
 
-@hook TARGET_MEMMODEL_MASK
-Some architectures may prvide additional memory model bits. This hook
-must mask such a bits. @end deftypevr
+@hook TARGET_MEMMODEL_CHECK
+Validate target specific memory model mask bits. When NULL no target specific
+memory model bits are allowed. 
+@end deftypefn
 
 @hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
diff --git a/gcc/target.def b/gcc/target.def
index f06b6bf..1d74893 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1941,10 +1941,10 @@ DEFHOOKPOD
  unsigned HOST_WIDE_INT, 0)
 
 /* Defines, which target-dependent bits (upper 16) are used by port  */
-DEFHOOKPOD
-(memmodel_mask,
+DEFHOOK
+(memmodel_check,
  "",
- unsigned HOST_WIDE_INT, 0)
+ unsigned, (unsigned val), NULL)
 
 /* Functions relating to calls - argument passing, returns, etc.  */
 /* Members of struct call have no special macro prefix.  */
