@@ -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:
@@ -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
@@ -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}.
@@ -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
@@ -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. */
From: Andi Kleen <ak@linux.intel.com> This is on top of Kirill's latest patch. Based on the earlier discussion. Warn and enforce reasonable memory models for HLE ACQUIRE and RELEASE. It's not useful to have a weaker compiler memory model than what the CPU implements for a transaction. With HLE_ACQUIRE model must be ACQUIRE or stronger. With HLE_RELEASE model must be RELEASE or stronger. I implemented this with a new target hook that replaces the target variable originally added in the earlier patch. Passes bootstrap and test suite on x86_64-linux gcc/: 2012-04-24 Andi Kleen <ak@linux.intel.com> * builtins.c (get_memmodel): Add val. Call target.memmodel_check and return new variable. * config/i386/i386.c (ix86_memmodel_check): Add. (TARGET_MEMMODEL_MASK): Replace with TARGET_MEMMODEL_CHECK. * doc/tm.texi (TARGET_MEMMODEL_MASK): Replace with TARGET_MEMMODEL_CHECK.. * doc/tm.texi.in (TARGET_MEMMODEL_MASK): Replace with TARGET_MEMMODEL_CHECK. * target.def (memmodel_mask): Replace with memmodel_check. --- gcc/builtins.c | 8 ++++++-- gcc/config/i386/i386.c | 35 +++++++++++++++++++++++++++++++++-- gcc/doc/tm.texi | 7 ++++--- gcc/doc/tm.texi.in | 7 ++++--- gcc/target.def | 6 +++--- 5 files changed, 50 insertions(+), 13 deletions(-)