diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 02a7f16d8799942c53be12c15ee5e718af218871..d3ca6b516caffa26848b267958778d2bfe1d77c5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2012-02-10  Richard Henderson  <rth@redhat.com>
+
+        * tree-ssa-dce.c (propagate_necessity): Handle GIMPLE_TRANSACTION.
+        * tree-ssa-operands.c (parse_ssa_operands): Add virtual operands
+        for GIMPLE_TRANSACTION.  Tidy if's into a switch.
+
 2012-02-10  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 	    Ira Rosen  <irar@il.ibm.com>
 
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index ccdf14a17027acc3061bcdf16c29f67593b1770e..ace9ef9972d40151cac637c937805017a6dba454 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -965,6 +965,13 @@ propagate_necessity (struct edge_list *el)
 		    mark_aliased_reaching_defs_necessary (stmt, op);
 		}
 	    }
+	  else if (gimple_code (stmt) == GIMPLE_TRANSACTION)
+	    {
+	      /* The beginning of a transaction is a memory barrier.  */
+	      /* ??? If we were really cool, we'd only be a barrier
+		 for the memories touched within the transaction.  */
+	      mark_all_reaching_defs_necessary (stmt);
+	    }
 	  else
 	    gcc_unreachable ();
 
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 0045dd875ec09b516ba28ead5e59332a01180977..ed0d34de2df14a8c2fd050836b96f40a1d8cb5be 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1043,35 +1043,46 @@ static void
 parse_ssa_operands (gimple stmt)
 {
   enum gimple_code code = gimple_code (stmt);
+  size_t i, n, start = 0;
 
-  if (code == GIMPLE_ASM)
-    get_asm_expr_operands (stmt);
-  else if (is_gimple_debug (stmt))
+  switch (code)
     {
+    case GIMPLE_ASM:
+      get_asm_expr_operands (stmt);
+      break;
+
+    case GIMPLE_TRANSACTION:
+      /* The start of a transaction is a memory barrier.  */
+      add_virtual_operand (stmt, opf_def | opf_use);
+      break;
+
+    case GIMPLE_DEBUG:
       if (gimple_debug_bind_p (stmt)
 	  && gimple_debug_bind_has_value_p (stmt))
 	get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt),
 			   opf_use | opf_no_vops);
-    }
-  else
-    {
-      size_t i, start = 0;
+      break;
 
-      if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
-	{
-	  get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def);
-	  start = 1;
-	}
-
-      for (i = start; i < gimple_num_ops (stmt); i++)
-	get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use);
+    case GIMPLE_RETURN:
+      append_vuse (gimple_vop (cfun));
+      goto do_default;
 
+    case GIMPLE_CALL:
       /* Add call-clobbered operands, if needed.  */
-      if (code == GIMPLE_CALL)
-	maybe_add_call_vops (stmt);
+      maybe_add_call_vops (stmt);
+      /* FALLTHRU */
 
-      if (code == GIMPLE_RETURN)
-	append_vuse (gimple_vop (cfun));
+    case GIMPLE_ASSIGN:
+      get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def);
+      start = 1;
+      /* FALLTHRU */
+
+    default:
+    do_default:
+      n = gimple_num_ops (stmt);
+      for (i = start; i < n; i++)
+	get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use);
+      break;
     }
 }