This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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 COMMITTED] Add a minor 'cas' atomic optimization on sparc.


When we have an expression that ends up evaluating at compile time to
__arch_compare_and_exchange_val_{32,64}_acq(X, Y, 0) we can use:

	cas{,x}	[%addr_reg], %g0, %newval_reg

instead of:

	cas{,x}	[%addr_reg], %oldval_reg, %newval_reg

and save the compiler from having to allocate and initialize
a register for 'oldval'.

This happens in a bunch of places in nptl, for example
pthread_barrier_wait().

	* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
	(__arch_compare_and_exchange_val_32_acq): Use %g0 as second
	argument of CAS if possible.
	* sysdeps/sparc/sparc64/bits/atomic.h
	(__arch_compare_and_exchange_val_32_acq): Likewise.
	(__arch_compare_and_exchange_val_64_acq): Likewise.
---
 ChangeLog                                   |    9 +++++++++
 sysdeps/sparc/sparc32/sparcv9/bits/atomic.h |   14 ++++++++++----
 sysdeps/sparc/sparc64/bits/atomic.h         |   28 +++++++++++++++++++--------
 3 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 418b932..00f7027 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-01-23  David S. Miller  <davem@davemloft.net>
+
+	* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
+	(__arch_compare_and_exchange_val_32_acq): Use %g0 as second
+	argument of CAS if possible.
+	* sysdeps/sparc/sparc64/bits/atomic.h
+	(__arch_compare_and_exchange_val_32_acq): Likewise.
+	(__arch_compare_and_exchange_val_64_acq): Likewise.
+
 2013-01-23  Pino Toscano  <toscano.pino@tiscali.it>
 
 	* sysdeps/unix/sysv/linux/ulimit.c: Moved to ...
diff --git a/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h b/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
index b1a8958..937d7a1 100644
--- a/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
+++ b/sysdeps/sparc/sparc32/sparcv9/bits/atomic.h
@@ -55,10 +55,16 @@ typedef uintmax_t uatomic_max_t;
 ({									      \
   __typeof (*(mem)) __acev_tmp;						      \
   __typeof (mem) __acev_mem = (mem);					      \
-  __asm __volatile ("cas [%4], %2, %0"					      \
-		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
-		    : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),      \
-		      "0" (newval) : "memory");				      \
+  if (__builtin_constant_p (oldval) && (oldval) == 0)			      \
+    __asm __volatile ("cas [%3], %%g0, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "m" (*__acev_mem), "r" (__acev_mem),		      \
+		        "0" (newval) : "memory");			      \
+  else									      \
+    __asm __volatile ("cas [%4], %2, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),    \
+		        "0" (newval) : "memory");			      \
   __acev_tmp; })
 
 /* This can be implemented if needed.  */
diff --git a/sysdeps/sparc/sparc64/bits/atomic.h b/sysdeps/sparc/sparc64/bits/atomic.h
index 0afbb4b..96611de 100644
--- a/sysdeps/sparc/sparc64/bits/atomic.h
+++ b/sysdeps/sparc/sparc64/bits/atomic.h
@@ -55,20 +55,32 @@ typedef uintmax_t uatomic_max_t;
 ({									      \
   __typeof (*(mem)) __acev_tmp;						      \
   __typeof (mem) __acev_mem = (mem);					      \
-  __asm __volatile ("cas [%4], %2, %0"					      \
-		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
-		    : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),      \
-		      "0" (newval) : "memory");				      \
+  if (__builtin_constant_p (oldval) && (oldval) == 0)			      \
+    __asm __volatile ("cas [%3], %%g0, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "m" (*__acev_mem), "r" (__acev_mem),		      \
+		        "0" (newval) : "memory");			      \
+  else									      \
+    __asm __volatile ("cas [%4], %2, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "r" (oldval), "m" (*__acev_mem), "r" (__acev_mem),    \
+		        "0" (newval) : "memory");			      \
   __acev_tmp; })
 
 #define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
 ({									      \
   __typeof (*(mem)) __acev_tmp;						      \
   __typeof (mem) __acev_mem = (mem);					      \
-  __asm __volatile ("casx [%4], %2, %0"					      \
-		    : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
-		    : "r" ((long) (oldval)), "m" (*__acev_mem),		      \
-		      "r" (__acev_mem), "0" ((long) (newval)) : "memory");    \
+  if (__builtin_constant_p (oldval) && (oldval) == 0)			      \
+    __asm __volatile ("casx [%3], %%g0, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "m" (*__acev_mem), "r" (__acev_mem),		      \
+		        "0" ((long) (newval)) : "memory");		      \
+  else									      \
+    __asm __volatile ("casx [%4], %2, %0"				      \
+		      : "=r" (__acev_tmp), "=m" (*__acev_mem)		      \
+		      : "r" ((long) (oldval)), "m" (*__acev_mem),	      \
+		        "r" (__acev_mem), "0" ((long) (newval)) : "memory");  \
   __acev_tmp; })
 
 #define atomic_exchange_acq(mem, newvalue) \
-- 
1.7.10.4


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