Index: testsuite/g++.dg/tm/pr47606.C
===================================================================
--- testsuite/g++.dg/tm/pr47606.C	(revision 0)
+++ testsuite/g++.dg/tm/pr47606.C	(revision 0)
@@ -0,0 +1,65 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm -O2" }
+
+__attribute__((transaction_pure))
+void atomic_exchange_and_add()
+{
+  __asm__ __volatile__     ("");
+}
+
+template<class X> class sp_counted_impl_p
+{
+ public: 
+  X * px_;
+	
+  void weak_release()
+  {
+    atomic_exchange_and_add ();
+  }
+
+  __attribute__((transaction_safe))
+  void release()
+  {
+    weak_release();
+  }
+
+ sp_counted_impl_p( X * px ): px_( px )
+  {
+  }
+
+  __attribute__((transaction_safe))
+  virtual void dispose()
+  {
+    delete px_;
+  }
+};
+
+template<class Y> class shared_count
+{
+ private:     sp_counted_impl_p<Y> * pi_;
+ public:     shared_count(): pi_(0)
+    {
+    }
+  shared_count( Y * p )
+    {
+      pi_ = new sp_counted_impl_p<Y>( p );
+    }
+  ~shared_count()
+    {
+      pi_->release();
+    }
+};
+
+class Entity;
+
+class GradientInfo
+{
+ public:
+  GradientInfo();
+  shared_count<Entity> sources;
+};
+
+void get_grad()
+{
+  shared_count<GradientInfo>(new GradientInfo());
+}
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 170377)
+++ trans-mem.c	(working copy)
@@ -540,6 +540,7 @@ tm_malloc_replacement (tree from)
 #define DIAG_TM_OUTER		1
 #define DIAG_TM_SAFE		2
 #define DIAG_TM_RELAXED		4
+#define DIAG_TM_PURE		8
 
 struct diagnose_tm
 {
@@ -672,9 +673,6 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi
       break;
 
     case GIMPLE_ASM:
-      /* ??? We ought to come up with a way to add attributes to
-	 asm statements, and then add "transaction_safe" to it.
-	 Either that or get the language spec to resurrect __tm_waiver.  */
       if (d->block_flags & DIAG_TM_SAFE)
 	error_at (gimple_location (stmt),
 		  "asm not allowed in atomic transaction");
@@ -682,7 +680,14 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi
         error_at (gimple_location (stmt),
 		  "asm not allowed in %<transaction_safe%> function");
       else
-	d->saw_unsafe = true;
+	{
+	  /* Mark the ASM as allowed if the function it appears in is
+	     marked as TM pure.  */
+	  if (d->func_flags & DIAG_TM_PURE)
+	    gimple_asm_set_tm_safe (stmt, true);
+	  else
+	    d->saw_unsafe = true;
+	}
       break;
 
     case GIMPLE_TRANSACTION:
@@ -758,6 +763,8 @@ diagnose_tm_blocks (void)
     d.func_flags = DIAG_TM_OUTER | DIAG_TM_SAFE;
   else if (is_tm_safe (current_function_decl))
     d.func_flags = DIAG_TM_SAFE;
+  else if (is_tm_pure (current_function_decl))
+    d.func_flags = DIAG_TM_PURE;
   d.summary_flags = d.func_flags;
 
   memset (&wi, 0, sizeof (wi));
@@ -2322,7 +2329,9 @@ expand_block_tm (struct tm_region *regio
 	  break;
 
 	case GIMPLE_ASM:
-	  gcc_unreachable ();
+	  if (!gimple_asm_tm_safe (stmt))
+	    gcc_unreachable ();
+	  break;
 
 	default:
 	  break;
Index: gimple.h
===================================================================
--- gimple.h	(revision 170359)
+++ gimple.h	(working copy)
@@ -101,6 +101,7 @@ enum gimple_rhs_class
 enum gf_mask {
     GF_ASM_INPUT		= 1 << 0,
     GF_ASM_VOLATILE		= 1 << 1,
+    GF_ASM_TM_SAFE		= 1 << 2,
     GF_CALL_CANNOT_INLINE	= 1 << 0,
     GF_CALL_FROM_THUNK		= 1 << 1,
     GF_CALL_RETURN_SLOT_OPT	= 1 << 2,
@@ -2901,6 +2902,30 @@ gimple_asm_input_p (const_gimple gs)
 }
 
 
+/* If TM_SAFE_P is true, mark asm GS as a TM_ASM_TM_SAFE.
+   This is set for GIMPLE_ASM's that appear in a TM pure function.  */
+
+static inline void
+gimple_asm_set_tm_safe (gimple gs, bool tm_safe_p)
+{
+  GIMPLE_CHECK (gs, GIMPLE_ASM);
+  if (tm_safe_p)
+    gs->gsbase.subcode |= GF_ASM_TM_SAFE;
+  else
+    gs->gsbase.subcode &= ~GF_ASM_TM_SAFE;
+}
+
+
+/* Return true if asm GS is a TM_ASM_TM_SAFE.  */
+
+static inline bool
+gimple_asm_tm_safe (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_ASM);
+  return (gs->gsbase.subcode & GF_ASM_TM_SAFE) != 0;
+}
+
+
 /* Return the types handled by GIMPLE_CATCH statement GS.  */
 
 static inline tree
