diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 37dce30e2fffade1375d2c9db790a254a21c68d0..1e5936ed6a4531df6bfed47b08c6154166657a5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2011-11-30  Richard Henderson  <rth@redhat.com>
+
+	* config/sparc/sparc-opts.h (enum sparc_memory_model_type): New.
+	* config/sparc/sparc.opt (mmemory-model=): New option.
+	* doc/invoke.texi (Sparc Options): Document it.
+	* config/sparc/sparc.c (sparc_option_override): Provide default
+	for sparc_memory_model.
+	(sparc_emit_membar_for_model): Omit barrier combinations that are
+	implied by the memory model.
+
 2011-11-30  Richard Henderson  <rth@redhat.com>
 
 	* config/sparc/sync.md (I124MODE): New mode iterator.
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
index 266cb1403ace2cc493d3b251f6fa7ed180eb67ec..7682eb9d452d2f60aa5ea67bab3c964a3ab6782c 100644
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -47,4 +47,14 @@ enum processor_type {
   PROCESSOR_NATIVE
 };
 
+/* Sparc system memory model.  See Appendix D in the Sparc V9 manual
+   for formal specification, and Appendix J for more discussion.  */
+enum sparc_memory_model_type {
+  SMM_DEFAULT,	/* Uninitialized.  */
+  SMM_RMO,	/* Relaxed Memory Order.  */
+  SMM_PSO,	/* Partial Store Order.  */
+  SMM_TSO,	/* Total Store Order.  */
+  SMM_SC	/* Sequential Consistency.  */
+};
+
 #endif
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 7db216a7c8677908e553f02cdf1c113a890614b2..713db26ee0bac87dd5f24b8f28066dd0c36e5d49 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -1160,6 +1160,17 @@ sparc_option_override (void)
       gcc_unreachable ();
     };
 
+  if (sparc_memory_model == SMM_DEFAULT)
+    {
+      /* Choose the most relaxed model for the processor.  */
+      if (TARGET_V9)
+	sparc_memory_model = SMM_RMO;
+      else if (TARGET_V8)
+	sparc_memory_model = SMM_PSO;
+      else
+	sparc_memory_model = SMM_SC;
+    }
+
 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
   if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
     target_flags |= MASK_LONG_DOUBLE_128;
@@ -10863,7 +10874,40 @@ sparc_emit_membar_for_model (enum memmodel model,
   const int LoadStore = 4;
   const int StoreStore = 8;
 
-  int mm = 0;
+  int mm = 0, implied = 0;
+
+  switch (sparc_memory_model)
+    {
+    case SMM_SC:
+      /* Sequential Consistency.  All memory transactions are immediately
+	 visible in sequential execution order.  No barriers needed.  */
+      implied = LoadLoad | StoreLoad | LoadStore | StoreStore;
+      break;
+
+    case SMM_TSO:
+      /* Total Store Ordering: all memory transactions with store semantics
+	 are followed by an implied StoreStore.  */
+      implied |= StoreStore;
+      /* FALLTHRU */
+
+    case SMM_PSO:
+      /* Partial Store Ordering: all memory transactions with load semantics
+	 are followed by an implied LoadLoad | LoadStore.  */
+      implied |= LoadLoad | LoadStore;
+
+      /* If we're not looking for a raw barrer (before+after), then atomic
+	 operations get the benefit of being both load and store.  */
+      if (load_store == 3 && before_after == 2)
+	implied |= StoreLoad | StoreStore;
+      /* FALLTHRU */
+
+    case SMM_RMO:
+      /* Relaxed Memory Ordering: no implicit bits.  */
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
 
   if (before_after & 1)
     {
@@ -10890,6 +10934,9 @@ sparc_emit_membar_for_model (enum memmodel model,
 	}
     }
 
+  /* Remove the bits implied by the system memory model.  */
+  mm &= ~implied;
+
   /* For raw barriers (before+after), always emit a barrier.
      This will become a compile-time barrier if needed.  */
   if (mm || before_after == 3)
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index cb807fdad656abb346e0e0085d089ab03296cb8c..01f3d43b2ca2737c7aea4eb27df1993a05efa416 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -215,3 +215,25 @@ Mask(V9)
 Mask(DEPRECATED_V8_INSNS)
 ;; Generate code that uses the V8 instructions deprecated
 ;; in the V9 architecture.
+
+mmemory-model=
+Target RejectNegative Joined Var(sparc_memory_model) Enum(sparc_memory_model) Init(SMM_DEFAULT)
+Specify the memory model in effect for the program.
+
+Enum
+Name(sparc_memory_model) Type(enum sparc_memory_model_type)
+
+EnumValue
+Enum(sparc_memory_model) String(default) Value(SMM_DEFAULT)
+
+EnumValue
+Enum(sparc_memory_model) String(rmo) Value(SMM_RMO)
+
+EnumValue
+Enum(sparc_memory_model) String(pso) Value(SMM_PSO)
+
+EnumValue
+Enum(sparc_memory_model) String(tso) Value(SMM_TSO)
+
+EnumValue
+Enum(sparc_memory_model) String(sc) Value(SMM_SC)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 265c8f06cba45902e5c1f4634e2c5d1106e2275d..a4a135c9cbd25ae52e0b7784687c267100e46aa6 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -887,6 +887,7 @@ See RS/6000 and PowerPC Options.
 @gccoptlist{-mcpu=@var{cpu-type} @gol
 -mtune=@var{cpu-type} @gol
 -mcmodel=@var{code-model} @gol
+-mmemory-model=@var{mem-model} @gol
 -m32  -m64  -mapp-regs  -mno-app-regs @gol
 -mfaster-structs  -mno-faster-structs  -mflat  -mno-flat @gol
 -mfpu  -mno-fpu  -mhard-float  -msoft-float @gol
@@ -17838,13 +17839,22 @@ an architecture and not an implementation.  These are @samp{v7}, @samp{v8},
 Here is a list of each supported architecture and their supported
 implementations.
 
-@smallexample
-    v7:             cypress
-    v8:             supersparc, hypersparc, leon
-    sparclite:      f930, f934, sparclite86x
-    sparclet:       tsc701
-    v9:             ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4
-@end smallexample
+@table @asis
+@item v7
+cypress
+
+@item v8
+supersparc, hypersparc, leon
+
+@item sparclite
+f930, f934, sparclite86x
+
+@item sparclet
+tsc701
+
+@item v9
+ultrasparc, ultrasparc3, niagara, niagara2, niagara3, niagara4
+@end table
 
 By default (unless configured otherwise), GCC generates code for the V7
 variant of the SPARC architecture.  With @option{-mcpu=cypress}, the compiler
@@ -17979,33 +17989,59 @@ The 32-bit environment sets int, long and pointer to 32 bits.
 The 64-bit environment sets int to 32 bits and long and pointer
 to 64 bits.
 
-@item -mcmodel=medlow
-@opindex mcmodel=medlow
-Generate code for the Medium/Low code model: 64-bit addresses, programs
+@item -mcmodel=@var{which}
+@opindex mcmodel
+Set the code model to one of
+
+@table @samp
+@item medlow
+The Medium/Low code model: 64-bit addresses, programs
 must be linked in the low 32 bits of memory.  Programs can be statically
 or dynamically linked.
 
-@item -mcmodel=medmid
-@opindex mcmodel=medmid
-Generate code for the Medium/Middle code model: 64-bit addresses, programs
+@item medmid
+The Medium/Middle code model: 64-bit addresses, programs
 must be linked in the low 44 bits of memory, the text and data segments must
 be less than 2GB in size and the data segment must be located within 2GB of
 the text segment.
 
-@item -mcmodel=medany
-@opindex mcmodel=medany
-Generate code for the Medium/Anywhere code model: 64-bit addresses, programs
+@item medany
+The Medium/Anywhere code model: 64-bit addresses, programs
 may be linked anywhere in memory, the text and data segments must be less
 than 2GB in size and the data segment must be located within 2GB of the
 text segment.
 
-@item -mcmodel=embmedany
-@opindex mcmodel=embmedany
-Generate code for the Medium/Anywhere code model for embedded systems:
+@item embmedany
+The Medium/Anywhere code model for embedded systems:
 64-bit addresses, the text and data segments must be less than 2GB in
 size, both starting anywhere in memory (determined at link time).  The
 global register %g4 points to the base of the data segment.  Programs
 are statically linked and PIC is not supported.
+@end table
+
+@item -mmemory-model=@var{mem-model}
+@opindex mmemory-model
+Set the memory model in force on the processor to one of
+
+@table @samp
+@item default
+The default memory model for the processor and operating system.
+
+@item rmo
+Relaxed Memory Order
+
+@item pso
+Partial Store Order
+
+@item tso
+Total Store Order
+
+@item sc
+Sequential Consistency
+@end table
+
+These memory models are formally defined in Appendix D of the Sparc V9
+architecture manual, as set in the processor's @code{PSTATE.MM} field.
 
 @item -mstack-bias
 @itemx -mno-stack-bias