This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] MIPS: Add option to enable/disable atomic memory primitives.


This is a follow on patch to the atomic memory operations patch. I have added both runtime and configure time options to enable and disable the atomic operations. This is needed to allow systems that lack the underlying ll, sc and sync instructions, to use the atomic operations if there is emulation available.

The Linux kernel has emulation, so I set the default for mips*-linux* to be to use the instructions. It other systems are known to have emulation we can add them in yet another patch.

Note that this patch conflicts slightly with the memory_barrier memory clobber patch, so I will adjust it after I commit the other patch.

So far it is tested by visually inspecting the output when configured with different combinations of --with-llsc=yes, --with-llsc=no, -mllsc -mno-llsc -mips1, -mips32. I will also do a full bootstrap on mipsel-linux and either i686-pc-linux or x86_64-pc-linux.

OK?

2007-09-09 David Daney <ddaney@avtrex.com>

   * doc/invoke.texi: Document new MIPS -mllsc and -mno-llsc options.
   * doc/install.texi: Document new --with-llsc=[yes|no] options.
   * config.gcc: Handle --with-llsc=[yes|no] configure options.
   * config/mips/mips.md (sync): Wrap sync instrunction in %| and %-
   operand codes.
   * config/mips/mips.opt (mllsc): New option.
   * config/mips/mips.c (mips_llsc): Define variable.
   (mips_handle_option): Handle mllsc option.
   (override_options): Set mips_print_operand_punct for '|' and '-'.
   (print_operand): Add new %| and %- operand codes.
   * config/mips/mips.h (mips_llsc_setting): New enum type.
   (mips_llsc): Declare.
   (OPTION_DEFAULT_SPECS): Add llsc handling.
   (ISA_HAS_SYNC_DEFAULT): New macro.
   (ISA_HAS_SYNC): Rewrite.
   (ISA_HAS_LL_SC_DEFAULT): New macro.
   (ISA_HAS_LL_SC): Rewrite.
   (MIPS_COMPARE_AND_SWAP, MIPS_SYNC_OP, MIPS_SYNC_OLD_OP,
   MIPS_SYNC_NEW_OP, MIPS_SYNC_NAND, MIPS_SYNC_OLD_NAND,
   MIPS_SYNC_NEW_NAND, MIPS_SYNC_EXCHANGE): Wrap instructions
   in %| and %- operand codes.

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 128245)
+++ doc/invoke.texi	(working copy)
@@ -627,7 +627,7 @@ Objective-C and Objective-C++ Dialects}.
 -msingle-float  -mdouble-float  -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol
 -msmartmips  -mno-smartmips @gol
 -mpaired-single  -mno-paired-single  -mdmx  -mno-mdmx @gol
--mips3d  -mno-mips3d  -mmt  -mno-mt @gol
+-mips3d  -mno-mips3d  -mmt  -mno-mt -mllsc -mno-llsc @gol
 -mlong64  -mlong32  -msym32  -mno-sym32 @gol
 -G@var{num}  -mlocal-sdata  -mno-local-sdata @gol
 -mextern-sdata  -mno-extern-sdata  -mgpopt  -mno-gopt @gol
@@ -11771,6 +11771,19 @@ operations.
 Assume that the floating-point coprocessor supports double-precision
 operations.  This is the default.
 
+@item -mllsc
+@itemx -mno-llsc
+@opindex mllsc
+@opindex mno-llsc
+Use (do not use) ll, sc, and sync instructions to implement atomic
+memory built-in functions.
+
+The default is usually to use these instructions if they are
+available, but this can be overridden at configure time using
+@option{--with-llsc=yes} or @option{--with-llsc=no}.  For
+@samp{mips*-*-linux*} targets the default is @option{--with-llsc=yes}
+as these instruction are emulated if not available.
+
 @item -mdsp
 @itemx -mno-dsp
 @opindex mdsp
Index: doc/install.texi
===================================================================
--- doc/install.texi	(revision 128245)
+++ doc/install.texi	(working copy)
@@ -1062,6 +1062,24 @@ systems that support conditional traps).
 Division by zero checks use the break instruction.
 @end table
 
+@item --with-llsc=@var{mode}
+Specify if the compiler should generate ll, sc, and sync instructions.
+This option is only supported on the MIPS target.  The default action
+if this option is not specified is to generate these instructions if
+the target architecture supports them or on Linux kernel based systems
+to generate them unconditionally as the kernel will emulate them if
+the cpu does not support them.  The possibilities for @var{mode} are:
+@table @code
+@item yes
+Generate ll, sc and sync instructions even if the target architecture
+does not support them.
+@item no
+Do not generate ll, sc and sync.
+@end table
+
+@item --without-llsc
+This is an alias for @option{--with-llsc=no}.
+
 @item --enable-__cxa_atexit
 Define if you want to use __cxa_atexit, rather than atexit, to
 register C++ destructors for local statics and global objects.
@@ -3610,6 +3628,16 @@ configure for @samp{mipsel-elf} as a wor
 @samp{mips*-*-linux*} target continues to use the MIPS II routines.  More
 work on this is expected in future releases.
 
+The built-in @code{__sync_*} functions are available on MIPS II and
+later systems and others that support the ll, sc and sync
+instructions.  This can be overridden by passing
+@option{--with-llsc=yes} or @option{--with-llsc=no} when configuring
+GCC.  Since the Linux kernel emulates these instructions if they are
+missing, the default for @samp{mips*-*-linux*} targets is
+@option{--with-llsc=yes}.  The @option{--with-llsc=*} configure
+options may be overridden at compile time by passing @option{-mllsc}
+or @option{-mno-llsc} to the compiler.
+
 MIPS systems check for division by zero (unless
 @option{-mno-check-zero-division} is passed to the compiler) by
 generating either a conditional trap or a break instruction.  Using
Index: config.gcc
===================================================================
--- config.gcc	(revision 128245)
+++ config.gcc	(working copy)
@@ -1663,6 +1663,7 @@ mips64*-*-linux*)
 	tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_N32"
 	gnu_ld=yes
 	gas=yes
+	test x$with_llsc != x || with_llsc=llsc
 	;;
 mips*-*-linux*)				# Linux MIPS, either endian.
         tm_file="dbxelf.h elfos.h svr4.h linux.h ${tm_file} mips/linux.h"
@@ -1672,6 +1673,7 @@ mips*-*-linux*)				# Linux MIPS, either 
 		tm_defines="${tm_defines} MIPS_ISA_DEFAULT=32"
                 ;;
         esac
+	test x$with_llsc != x || with_llsc=llsc
 	;;
 mips*-*-openbsd*)
 	tm_defines="${tm_defines} OBSD_HAS_DECLARE_FUNCTION_NAME OBSD_HAS_DECLARE_OBJECT OBSD_HAS_CORRECT_SPECS"
@@ -3008,7 +3010,7 @@ case "${target}" in
 		;;
 
 	mips*-*-*)
-		supported_defaults="abi arch float tune divide"
+		supported_defaults="abi arch float tune divide llsc"
 
 		case ${with_float} in
 		"" | soft | hard)
@@ -3037,6 +3039,23 @@ case "${target}" in
 		*)
 			echo "Unknown division check type use in --with-divide=$with_divide" 1>&2
 			exit 1
+			;;
+		esac
+
+		case ${with_llsc} in
+		yes | llsc)
+			with_llsc=llsc
+			;;
+		no | no-llsc)
+			with_llsc="no-llsc"
+			;;
+		"")
+			# OK
+			;;
+		*)
+			echo "Unknown llsc type used in --with-llsc" 1>&2
+			exit 1
+			;;
 		esac
 		;;
 
@@ -3301,7 +3320,7 @@ case ${target} in
 esac
 
 t=
-all_defaults="abi cpu arch tune schedule float mode fpu divide"
+all_defaults="abi cpu arch tune schedule float mode fpu divide llsc"
 for option in $all_defaults
 do
 	eval "val=\$with_$option"
Index: config/mips/mips.md
===================================================================
--- config/mips/mips.md	(revision 128245)
+++ config/mips/mips.md	(working copy)
@@ -4270,7 +4270,7 @@ (define_expand "clear_cache"
 (define_insn "sync"
   [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
   "ISA_HAS_SYNC"
-  "sync")
+  "%|sync\n\t%-")
 
 (define_insn "synci"
   [(unspec_volatile [(match_operand 0 "pmode_register_operand" "d")]
Index: config/mips/mips.opt
===================================================================
--- config/mips/mips.opt	(revision 128245)
+++ config/mips/mips.opt	(working copy)
@@ -176,6 +176,10 @@ mips3d
 Target Report RejectNegative Mask(MIPS3D)
 Use MIPS-3D instructions
 
+mllsc
+Target Report
+Use (or don't use) ll, sc and sync instructions
+
 mlocal-sdata
 Target Report Var(TARGET_LOCAL_SDATA) Init(1)
 Use -G for object-local data
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 128245)
+++ config/mips/mips.c	(working copy)
@@ -635,6 +635,9 @@ static GTY(()) int mips16_flipper;
 /* The -mtext-loads setting.  */
 enum mips_code_readable_setting mips_code_readable = CODE_READABLE_YES;
 
+/* The -mllsc setting.  */
+enum mips_llsc_setting mips_llsc = LLSC_DEFAULT;
+
 /* The architecture selected by -mipsN.  */
 static const struct mips_cpu_info *mips_isa_info;
 
@@ -5351,7 +5354,7 @@ mips_set_current_function (tree fndecl A
 /* Implement TARGET_HANDLE_OPTION.  */
 
 static bool
-mips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+mips_handle_option (size_t code, const char *arg, int value)
 {
   switch (code)
     {
@@ -5393,6 +5396,10 @@ mips_handle_option (size_t code, const c
 	return false;
       return true;
 
+    case OPT_mllsc:
+      mips_llsc = value ? LLSC_YES : LLSC_NO;
+      return true;
+
     default:
       return true;
     }
@@ -5675,6 +5682,8 @@ override_options (void)
   mips_print_operand_punct['$'] = 1;
   mips_print_operand_punct['+'] = 1;
   mips_print_operand_punct['~'] = 1;
+  mips_print_operand_punct['|'] = 1;
+  mips_print_operand_punct['-'] = 1;
 
   /* Set up array to map GCC register number to debug register number.
      Ignore the special purpose register numbers.  */
@@ -6037,7 +6046,10 @@ mips_strip_unspec_address (rtx op)
    '^'	Print the name of the pic call-through register (t9 or $25).
    '$'	Print the name of the stack pointer register (sp or $29).
    '+'	Print the name of the gp register (usually gp or $28).
-   '~'	Output a branch alignment to LABEL_ALIGN(NULL).  */
+   '~'	Output a branch alignment to LABEL_ALIGN(NULL).
+   '|'  Print .set push; .set mips2 if mips_llsc == LLSC_YES
+        && !ISA_HAS_LL_SC_DEFAULT.
+   '-'  Print .set pop under the same conditions for '|'.  */
 
 void
 print_operand (FILE *file, rtx op, int letter)
@@ -6167,6 +6179,16 @@ print_operand (FILE *file, rtx op, int l
 	  }
 	  break;
 
+        case '|':
+          if (mips_llsc == LLSC_YES && !ISA_HAS_LL_SC_DEFAULT)
+            fputs (".set\tpush\n\t.set\tmips2\n\t", file);
+          break;
+
+        case '-':
+          if (mips_llsc == LLSC_YES && !ISA_HAS_LL_SC_DEFAULT)
+            fputs (".set\tpop\n\t", file);
+          break;
+
 	default:
 	  error ("PRINT_OPERAND: unknown punctuation '%c'", letter);
 	  break;
Index: config/mips/mips.h
===================================================================
--- config/mips/mips.h	(revision 128245)
+++ config/mips/mips.h	(working copy)
@@ -121,6 +121,14 @@ enum mips_code_readable_setting {
   CODE_READABLE_YES
 };
 
+
+/* Enumerates the setting of the -mllsc option.  */
+enum mips_llsc_setting {
+  LLSC_DEFAULT,
+  LLSC_NO,
+  LLSC_YES
+};
+
 #ifndef USED_FOR_TARGET
 extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */
 extern const char *current_function_file; /* filename current function is in */
@@ -145,6 +153,7 @@ extern const struct mips_cpu_info *mips_
 extern const struct mips_cpu_info *mips_tune_info;
 extern const struct mips_rtx_cost_data *mips_cost;
 extern enum mips_code_readable_setting mips_code_readable;
+extern enum mips_llsc_setting mips_llsc;
 #endif
 
 /* Macros to silence warnings about numbers being signed in traditional
@@ -678,7 +687,8 @@ extern enum mips_code_readable_setting m
   {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
   {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
   {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
-  {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }
+  {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
+  {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }
 
 
 #define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
@@ -882,12 +892,17 @@ extern enum mips_code_readable_setting m
 #define ISA_HAS_SYNCI (ISA_MIPS32R2 && !TARGET_MIPS16)
 
 /* ISA includes sync.  */
-#define ISA_HAS_SYNC ((mips_isa >= 2 || TARGET_MIPS3900) && !TARGET_MIPS16)
+#define ISA_HAS_SYNC_DEFAULT ((mips_isa >= 2 || TARGET_MIPS3900) \
+  && !TARGET_MIPS16)
+#define ISA_HAS_SYNC (mips_llsc == LLSC_YES \
+  || (mips_llsc == LLSC_DEFAULT && ISA_HAS_SYNC_DEFAULT))
 
 /* ISA includes ll and sc.  Note that this implies ISA_HAS_SYNC
    because the expanders use both ISA_HAS_SYNC and ISA_HAS_LL_SC
    instructions.  */
-#define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS16)
+#define ISA_HAS_LL_SC_DEFAULT (mips_isa >= 2 && !TARGET_MIPS16)
+#define ISA_HAS_LL_SC (mips_llsc == LLSC_YES \
+  || (mips_llsc == LLSC_DEFAULT && ISA_HAS_LL_SC_DEFAULT))
 
 /* Add -G xx support.  */
 
@@ -2895,12 +2910,13 @@ while (0)
    and OP is the instruction that should be used to load %3 into a
    register.  */
 #define MIPS_COMPARE_AND_SWAP(SUFFIX, OP)	\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\tbne\t%0,%2,2f\n"				\
   "\t" OP "\t%@,%3\n"				\
-  "\tsc" SUFFIX "\t%@,%1\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%1\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\tnop\n"					\
   "2:%]%>%)"
 
@@ -2911,11 +2927,12 @@ while (0)
    SUFFIX is the suffix that should be added to "ll" and "sc"
    instructions.  */
 #define MIPS_SYNC_OP(SUFFIX, INSN)		\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%@,%0\n"			\
   "\t" INSN "\t%@,%@,%1\n"			\
-  "\tsc" SUFFIX "\t%@,%0\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%0\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\tnop%]%>%)"
 
 /* Return an asm string that atomically:
@@ -2927,11 +2944,12 @@ while (0)
    SUFFIX is the suffix that should be added to "ll" and "sc"
    instructions.  */
 #define MIPS_SYNC_OLD_OP(SUFFIX, INSN)		\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\t" INSN "\t%@,%0,%2\n"			\
-  "\tsc" SUFFIX "\t%@,%1\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%1\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\tnop%]%>%)"
 
 /* Return an asm string that atomically:
@@ -2943,11 +2961,12 @@ while (0)
    SUFFIX is the suffix that should be added to "ll" and "sc"
    instructions.  */
 #define MIPS_SYNC_NEW_OP(SUFFIX, INSN)		\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\t" INSN "\t%@,%0,%2\n"			\
-  "\tsc" SUFFIX "\t%@,%1\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%1\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\t" INSN "\t%0,%0,%2%]%>%)"
 
 /* Return an asm string that atomically:
@@ -2958,12 +2977,13 @@ while (0)
    instructions.  INSN is the and instruction needed to and a register
    with %2.  */
 #define MIPS_SYNC_NAND(SUFFIX, INSN)		\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%@,%0\n"			\
   "\tnor\t%@,%@,%.\n"				\
   "\t" INSN "\t%@,%@,%1\n"			\
-  "\tsc" SUFFIX "\t%@,%0\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%0\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\tnop%]%>%)"
 
 /* Return an asm string that atomically:
@@ -2976,12 +2996,13 @@ while (0)
    instructions.  INSN is the and instruction needed to and a register
    with %2.  */
 #define MIPS_SYNC_OLD_NAND(SUFFIX, INSN)	\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\tnor\t%@,%0,%.\n"				\
   "\t" INSN "\t%@,%@,%2\n"			\
-  "\tsc" SUFFIX "\t%@,%1\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%1\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\tnop%]%>%)"
 
 /* Return an asm string that atomically:
@@ -2994,12 +3015,13 @@ while (0)
    instructions.  INSN is the and instruction needed to and a register
    with %2.  */
 #define MIPS_SYNC_NEW_NAND(SUFFIX, INSN)	\
-  "%(%<%[sync\n"				\
+  "%(%<%[%|sync\n"				\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\tnor\t%0,%0,%.\n"				\
   "\t" INSN "\t%@,%0,%2\n"			\
-  "\tsc" SUFFIX "\t%@,%1\n"			\
-  "\tbeq\t%@,%.,1b\n"				\
+  "\tsc" SUFFIX "\t%@,%1\n\t"			\
+  "%-"						\
+  "beq\t%@,%.,1b\n"				\
   "\t" INSN "\t%0,%0,%2%]%>%)"
 
 /* Return an asm string that atomically:
@@ -3012,11 +3034,11 @@ while (0)
    instructions.  OP is the and instruction that should be used to
    load %2 into a register.  */
 #define MIPS_SYNC_EXCHANGE(SUFFIX, OP)		\
-  "%(%<%[\n"					\
+  "%(%<%[%|\n"					\
   "1:\tll" SUFFIX "\t%0,%1\n"			\
   "\t" OP "\t%@,%2\n"				\
   "\tsc" SUFFIX "\t%@,%1\n"			\
   "\tbeq\t%@,%.,1b\n"				\
   "\tnop\n"					\
-  "\tsync%]%>%)"
+  "\tsync\n\t%-%]%>%)"
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]