diff --git a/malloc/malloc.c b/malloc/malloc.c
index b8a43bf..1eed794 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -4150,7 +4150,7 @@ static void malloc_consolidate(mstate av)
     maxfb = &fastbin (av, NFASTBINS - 1);
     fb = &fastbin (av, 0);
     do {
-      p = atomic_exchange_acq (fb, 0);
+      p = atomic_exchange_acq (fb, NULL);
       if (p != 0) {
 	do {
 	  check_inuse_chunk(av, p);
diff --git a/sysdeps/powerpc/atomic-machine.h b/sysdeps/powerpc/atomic-machine.h
index 8b0e1e7..7e6c699 100644
--- a/sysdeps/powerpc/atomic-machine.h
+++ b/sysdeps/powerpc/atomic-machine.h
@@ -27,6 +27,7 @@
  */
 
 #include <stdint.h>
+#include <tls.h>
 
 typedef int32_t atomic32_t;
 typedef uint32_t uatomic32_t;
@@ -78,6 +79,9 @@ typedef uintmax_t uatomic_max_t;
 
 #define atomic_full_barrier()	__asm ("sync" ::: "memory")
 
+/* We can't convert __arch_compare_and_exchange_val_* to compiler built-ins
+   yet because the built-ins expect a pointer to the expected value while
+   our current implementation pass the value directly.  */
 #define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval)	      \
   ({									      \
       __typeof (*(mem)) __tmp;						      \
@@ -112,33 +116,24 @@ typedef uintmax_t uatomic_max_t;
       __tmp;								      \
   })
 
-#define __arch_atomic_exchange_32_acq(mem, value)			      \
+#define __arch_compare_and_exchange_val_32_relaxed(mem, newval, oldval)	      \
   ({									      \
-    __typeof (*mem) __val;						      \
-    __asm __volatile (							      \
-		      "1:	lwarx	%0,0,%2" MUTEX_HINT_ACQ "\n"	      \
-		      "		stwcx.	%3,0,%2\n"			      \
-		      "		bne-	1b\n"				      \
-		      "   " __ARCH_ACQ_INSTR				      \
-		      : "=&r" (__val), "=m" (*mem)			      \
-		      : "b" (mem), "r" (value), "m" (*mem)		      \
-		      : "cr0", "memory");				      \
-    __val;								      \
-  })
-
-#define __arch_atomic_exchange_32_rel(mem, value) \
-  ({									      \
-    __typeof (*mem) __val;						      \
-    __asm __volatile (__ARCH_REL_INSTR "\n"				      \
-		      "1:	lwarx	%0,0,%2" MUTEX_HINT_REL "\n"	      \
-		      "		stwcx.	%3,0,%2\n"			      \
-		      "		bne-	1b"				      \
-		      : "=&r" (__val), "=m" (*mem)			      \
-		      : "b" (mem), "r" (value), "m" (*mem)		      \
-		      : "cr0", "memory");				      \
-    __val;								      \
+      __typeof (*(mem)) __tmp;						      \
+      __typeof (mem)  __memp = (mem);					      \
+      __asm __volatile (						      \
+		        "1:	lwarx	%0,0,%1\n"			      \
+		        "	cmpw	%0,%2\n"			      \
+		        "	bne	2f\n"				      \
+		        "	stwcx.	%3,0,%1\n"			      \
+		        "	bne-	1b\n"				      \
+		        "2:	"					      \
+		        : "=&r" (__tmp)					      \
+		        : "b" (__memp), "r" (oldval), "r" (newval)	      \
+		        : "cr0", "memory");				      \
+      __tmp;								      \
   })
 
+/* The following atomic primitives aren't available as compiler built-ins.  */
 #define __arch_atomic_exchange_and_add_32(mem, value) \
   ({									      \
     __typeof (*mem) __val, __tmp;					      \
@@ -221,10 +216,30 @@ typedef uintmax_t uatomic_max_t;
      __val;								      \
   })
 
+#define __atomic_is_single_thread				\
+  (THREAD_GETMEM (THREAD_SELF, header.multiple_threads) == 0)
+
+#define atomic_compare_and_exchange_val_relaxed(mem, newval, oldval)	      \
+  ({									      \
+    __typeof (*(mem)) __result;						      \
+    if (sizeof (*mem) == 4)						      \
+      __result = __arch_compare_and_exchange_val_32_relaxed(mem, newval,      \
+							    oldval);	      \
+    else if (sizeof (*mem) == 8)					      \
+      __result = __arch_compare_and_exchange_val_64_relaxed(mem, newval,      \
+							    oldval);	      \
+    else								      \
+       abort ();							      \
+    __result;								      \
+  })
+
 #define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
   ({									      \
     __typeof (*(mem)) __result;						      \
-    if (sizeof (*mem) == 4)						      \
+    if (__atomic_is_single_thread)					      \
+      __result = atomic_compare_and_exchange_val_relaxed (mem, newval,	      \
+							  oldval);	      \
+    else if (sizeof (*mem) == 4)					      \
       __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \
     else if (sizeof (*mem) == 8)					      \
       __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \
@@ -236,7 +251,10 @@ typedef uintmax_t uatomic_max_t;
 #define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \
   ({									      \
     __typeof (*(mem)) __result;						      \
-    if (sizeof (*mem) == 4)						      \
+    if (__atomic_is_single_thread)					      \
+      __result = atomic_compare_and_exchange_val_relaxed (mem, newval,	      \
+							  oldval);	      \
+    else if (sizeof (*mem) == 4)					      \
       __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \
     else if (sizeof (*mem) == 8)					      \
       __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \
@@ -245,28 +263,24 @@ typedef uintmax_t uatomic_max_t;
     __result;								      \
   })
 
-#define atomic_exchange_acq(mem, value) \
-  ({									      \
-    __typeof (*(mem)) __result;						      \
-    if (sizeof (*mem) == 4)						      \
-      __result = __arch_atomic_exchange_32_acq (mem, value);		      \
-    else if (sizeof (*mem) == 8)					      \
-      __result = __arch_atomic_exchange_64_acq (mem, value);		      \
-    else 								      \
-       abort ();							      \
-    __result;								      \
+#define atomic_exchange_acq(mem, value)					\
+  ({									\
+    __typeof (value) __ret;						\
+    if (__atomic_is_single_thread)					\
+      __ret = __atomic_exchange_n ((mem), (value), __ATOMIC_RELAXED);	\
+    else								\
+      __ret = __atomic_exchange_n ((mem), (value), __ATOMIC_ACQUIRE);	\
+    __ret;								\
   })
 
-#define atomic_exchange_rel(mem, value) \
-  ({									      \
-    __typeof (*(mem)) __result;						      \
-    if (sizeof (*mem) == 4)						      \
-      __result = __arch_atomic_exchange_32_rel (mem, value);		      \
-    else if (sizeof (*mem) == 8)					      \
-      __result = __arch_atomic_exchange_64_rel (mem, value);		      \
-    else 								      \
-       abort ();							      \
-    __result;								      \
+#define atomic_exchange_rel(mem, value)					\
+  ({									\
+    __typeof (value) __ret;						\
+    if (__atomic_is_single_thread)					\
+      __ret = __atomic_exchange_n ((mem), (value), __ATOMIC_RELAXED);	\
+    else								\
+      __ret = __atomic_exchange_n ((mem), (value), __ATOMIC_RELEASE);	\
+    __ret;								\
   })
 
 #define atomic_exchange_and_add(mem, value) \
@@ -280,6 +294,7 @@ typedef uintmax_t uatomic_max_t;
        abort ();							      \
     __result;								      \
   })
+
 #define atomic_exchange_and_add_acq(mem, value) \
   ({									      \
     __typeof (*(mem)) __result;						      \
@@ -291,6 +306,7 @@ typedef uintmax_t uatomic_max_t;
        abort ();							      \
     __result;								      \
   })
+
 #define atomic_exchange_and_add_rel(mem, value) \
   ({									      \
     __typeof (*(mem)) __result;						      \
@@ -343,3 +359,23 @@ typedef uintmax_t uatomic_max_t;
        abort ();							      \
     __result;								      \
   })
+
+#define catomic_and(mem, arg)						\
+  ({									\
+    __typeof (arg) __ret;						\
+    if (__atomic_is_single_thread)					\
+      __ret = __atomic_fetch_and((mem), arg, __ATOMIC_RELAXED);		\
+    else								\
+      __ret = __atomic_fetch_and((mem), arg, __ATOMIC_ACQUIRE);		\
+    __ret;								\
+  })
+
+#define catomic_or(mem, arg)						\
+  ({									\
+    __typeof (arg) __ret;						\
+    if (__atomic_is_single_thread)					\
+      __ret = __atomic_fetch_or((mem), arg, __ATOMIC_RELAXED);		\
+    else								\
+      __ret = __atomic_fetch_or((mem), arg, __ATOMIC_ACQUIRE);		\
+    __ret;								\
+  })
diff --git a/sysdeps/powerpc/powerpc32/atomic-machine.h b/sysdeps/powerpc/powerpc32/atomic-machine.h
index 1d407b3..c733d43 100644
--- a/sysdeps/powerpc/powerpc32/atomic-machine.h
+++ b/sysdeps/powerpc/powerpc32/atomic-machine.h
@@ -86,6 +86,9 @@
 #define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \
   (abort (), 0)
 
+#define __arch_compare_and_exchange_val_64_relaxed(mem, newval, oldval) \
+  (abort (), (__typeof (*mem)) 0)
+
 #define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \
   (abort (), (__typeof (*mem)) 0)
 
@@ -95,6 +98,9 @@
 #define __arch_atomic_exchange_64_rel(mem, value) \
     ({ abort (); (*mem) = (value); })
 
+#define __arch_atomic_exchange_64_relaxed(mem, value) \
+    ({ abort (); (*mem) = (value); })
+
 #define __arch_atomic_exchange_and_add_64(mem, value) \
     ({ abort (); (*mem) = (value); })
 
diff --git a/sysdeps/powerpc/powerpc64/atomic-machine.h b/sysdeps/powerpc/powerpc64/atomic-machine.h
index 751487a..515572e 100644
--- a/sysdeps/powerpc/powerpc64/atomic-machine.h
+++ b/sysdeps/powerpc/powerpc64/atomic-machine.h
@@ -146,32 +146,22 @@
       __tmp;								      \
   })
 
-#define __arch_atomic_exchange_64_acq(mem, value) \
-    ({									      \
-      __typeof (*mem) __val;						      \
-      __asm __volatile (__ARCH_REL_INSTR "\n"				      \
-			"1:	ldarx	%0,0,%2" MUTEX_HINT_ACQ "\n"	      \
-			"	stdcx.	%3,0,%2\n"			      \
+#define __arch_compare_and_exchange_val_64_relaxed(mem, newval, oldval)	      \
+  ({									      \
+      __typeof (*(mem)) __tmp;						      \
+      __typeof (mem)  __memp = (mem);					      \
+      __asm __volatile ("\n"						      \
+			"1:	ldarx	%0,0,%1\n"			      \
+			"	cmpd	%0,%2\n"			      \
+			"	bne	2f\n"				      \
+			"	stdcx.	%3,0,%1\n"			      \
 			"	bne-	1b\n"				      \
-		  " " __ARCH_ACQ_INSTR					      \
-			: "=&r" (__val), "=m" (*mem)			      \
-			: "b" (mem), "r" (value), "m" (*mem)		      \
+			"2:	"					      \
+			: "=&r" (__tmp)					      \
+			: "b" (__memp), "r" (oldval), "r" (newval)	      \
 			: "cr0", "memory");				      \
-      __val;								      \
-    })
-
-#define __arch_atomic_exchange_64_rel(mem, value) \
-    ({									      \
-      __typeof (*mem) __val;						      \
-      __asm __volatile (__ARCH_REL_INSTR "\n"				      \
-			"1:	ldarx	%0,0,%2" MUTEX_HINT_REL "\n"	      \
-			"	stdcx.	%3,0,%2\n"			      \
-			"	bne-	1b"				      \
-			: "=&r" (__val), "=m" (*mem)			      \
-			: "b" (mem), "r" (value), "m" (*mem)		      \
-			: "cr0", "memory");				      \
-      __val;								      \
-    })
+      __tmp;								      \
+  })
 
 #define __arch_atomic_exchange_and_add_64(mem, value) \
     ({									      \
